diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000000..ea0fce5d046 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,12 @@ +Tobias Doerffel + +Maintainer, main-development, artwork etc. + + +Sebastian Tilsch + +recording of many samples + + +...may be there're more here in the future... + diff --git a/COPYING b/COPYING new file mode 100644 index 00000000000..eeb586b392a --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 00000000000..108326a1430 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,1124 @@ +2005-09-21 Tobias Doerffel + + * configure.in: + made 0.1.1 release + +2005-09-20 Tobias Doerffel + + * include/about_dialog.h: + * src/core/about_dialog.cpp: + no need for passing parent when creating about-dialog + + * src/core/song_editor.cpp: + - different usage of question-box in songEditor::mayChangeProject() + because of bugs with several qt-versions... + - when exporting song, do use baseName( TRUE ) instead of baseName() + for determining base-name of rendered file + + * src/core/lmms_main_win.cpp: + - display filename before app-name in window-title + - only use basename of filename in window-title + - added message referring to LMMS-homepage when clicking on + Help/Help + + * src/core/export_song_dialog.cpp: + use lmmsMainWin::resetWindowTitle() for resetting window-title + after export is done + + * src/widgets/knob.cpp: + do not add tooltips to knobs - clicking on knob has quite the same + effect so tooltips are just annoying + + * src/core/browser.cpp: + when matching file-name, always convert them to lower case for also + handling files like foo.WAV + + * src/core/config_mgr.cpp: + added setValue(...)-call for saving working-directory after setting + up everything - fixes bug with empty browsers after fresh personal + installation of LMMS + +2005-09-19 Tobias Doerffel + + * configure.in: + made 0.1.0 release + +2005-09-18 Tobias Doerffel + + * src/tracks/bb_track.cpp: + revised paintEvent()-method -> bb-TCO's are now painted with a gradient! + + * src/core/song_editor.cpp: + - call bbEditor::stop before playing to make sure play-button in + bb-editor is properly reset + - call realignTracks() with parameter TRUE in wheelEvent(...) + - some hacks for making pause-button work... + + * src/core/track_container.cpp: + added parameter _complete_update to trackContainer::realignTracks() + to be able to hide and show all tracks which is neccessary e.g. + after having changed pixels-per-tact-property -> zooming in song-editor + works now well + + * src/core/setup_dialog.cpp: + added message-box telling the user to restart LMMS + + * include/midi_alsa_raw.h: + * include/midi_device.h: + * include/midi_oss.h: + * include/midi_dummy.h: + * include/mixer.h: + * include/setup_dialog.h: + * src/core/mixer.cpp: + * src/core/setup_dialog.cpp: + * src/midi/midi_alsa_raw.cpp: + * src/midi/midi_device.cpp: + * src/midi/midi_oss.cpp: + made it possible to select and setup MIDI-device + + * include/knob.h: + * src/widgets/knob.cpp: + - many cleanups, coding style improvements etc. + - added new behaviour for controlling knob -> move cursor up/down for + changing value + - replaced usage of status-bar by text-float-widget + + * include/text_float.h: + * src/widgets/text_float.cpp: + took text-float from Rosegarden + + * include/config_mgr.h: + * src/core/config_mgr.cpp: + - fixed bug in configManager::setValue(): new value-pair was always + pushed back, even if it already existed, so result of value() didn't + change until restart + - moved widget-creation-code from ctor to new method createWidgets() + which fixes problems with unlocalized strings in wizard because + embed::loadTranslation() calls configManager::inst()->localeDir() + for determining path to localization files - this call created all + wizard-widgets before actual localization was loaded... + +2005-09-17 Tobias Doerffel + + * src/core/setup_dialog.cpp: + added switches for disabling tooltips and turning on classical knob- + behaviour + + * include/led_checkbox.h: + * src/widget/led_checkbox.cpp: + added LED-check-box + +2005-09-16 Tobias Doerffel + + * src/core/mixer.cpp: + clear output-buffers in ctor before using them -> avoids awful noises + at startup + + * src/core/mixer.cpp: + * src/lib/sample_buffer.cpp: + * src/tracks/channel_track.cpp: + * src/tracks/sample_track.cpp: + use given frame-parameter in methods playing sample-buffers instead + of mixer::framesPerAudioBuffer() -> no clicks at tact-border because + of odd sample-frame-count + + * src/core/lmms_main_win.cpp: + call presetPreviewPlayHandle::cleanUp() in dtor -> fixes segfault which + which occured at exit if you previewed a channel during session + + * include/preset_preview_play_handle.h: + * src/core/preset_preview_play_handle.cpp: + added cleanUp()-method which deletes blind track-container containing + preset-preview-channel + + * src/soundgenerators/triple_oscillator.cpp: + - unified much code by defining setChecked when compiling with Qt 3 + - also set file-name of user-defined-wave as tool-tip when loading + settings + + * most files in src/: + use new tooltip-system - removes qt3/qt4-compat-code + + * include/tooltip.h: + * src/widget/tooltip.cpp: + added tooltip-namespace with method "add(...)" for allowing transparent + usage of tooltips, so there's no difference to code using tooltips + whether it is compiled with Qt 3 or Qt 4 + +2005-09-14 Tobias Doerffel + + * include/mixer.h: + * include/note_play_handle.h: + * include/play_handle.h: + * src/core/mixer.cpp: + * src/core/note_play_handle.cpp: + * src/tracks/channel_track.cpp: + added play-handle-invalidating-feature making it possible to + invalidate notes of which the objects they depend on do not exist + anymore or things like that. for example channel-track-dtor + invalidates all note-play-handles linked with according channel + -> no segfault when deleting channel-track + + * src/core/track_container.cpp: + pause mixer before removing track -> no segfault + + * src/lib/mmp.cpp: + initialize m_type in mmp::multimediaProject( projectTypes ) + + * src/lib/buffer_allocator.cpp: + added mutex for better protection against parallel accesses from + several threads - fixes some segfaults + + * src/core/lmms_main_win.cpp: + improved ~lmmsMainWin() which now first instructs mixer to quit it's + thread for avoiding spurious usages of objects to be destroyed + afterwards -> no segfault at the end + + * src/core/export_song_dialog.cpp: + * src/tracks/pattern.cpp: + cleaned up exporting/freezing mechanisms by using mixer's new methods + play() and pause() + + * include/mixer.h: + * src/core/mixer.cpp: + cleaned up mixer-thread syncing stuff by reorganizing mutexes and + replacing m_waitMutex by m_safetySyncMutex as well as according methods + lockWaitMutex() and unlockWaitMutex() by play() and pause() + + * src/core/setup_dialog.cpp: + tell config-manager to save it's config-file when setupDialog is + destroyed + +2005-09-13 Stephane Thomas + + * locale/fr.ts: + added French translation + +2005-09-13 Tobias Doerffel + + * src/core/lmms_main_win.cpp: + - show setup-dialog if LMMS is started first time or mixer uses dummy- + audio-driver + - added setup-dialog-entry to settings-menu + + * src/lib/mmp.cpp: + if saving preset, check whether file-name contains suffix ".cs.xml" + and add it if neccessary + + * include/midi_alsa_raw.h: + * src/midi/midi_alsa_raw.cpp: + * src/midi/midi_device.cpp: + - changed everything (including file-names) from midiAlsa to midiALSARaw + - added terminate()-call in dtor for terminating thread properly + + * include/tab_bar.h: + * src/widget/tab_bar.cpp: + - added flag for addTab(...)-method indicating whether to use given + text as caption or just as tooltip + - reduced #ifdef QT4-macros by defining some names when compiling + with Qt3 + + * include/setup_dialog.h: + * src/core/setup_dialog.cpp: + added help-button in audio-setup-tab and improved geometry-stuff + + * include/audio_alsa.h: + * include/audio_oss.h: + * src/audio/audio_alsa.cpp: + * src/audio/audio_oss.cpp: + added probeDevice()-method which eases determining device-name in + either actual audio-class as well as in it's setup-widget + +2005-09-11 Tobias Doerffel + + * src/core/mixer.cpp: + use new audio-settings-technology for opening audio-device + + * include/setup_dialog.h: + * src/core/setup_dialog.cpp: + added setup-dialog for general-, audio- and MIDI-settings + + * include/audio_alsa.h: + * include/audio_device.h: + * include/audio_dummy.h: + * include/audio_jack.h: + * include/audio_oss.h: + * include/audio_sdl.h: + * src/audio/audio_alsa.cpp: + * src/audio/audio_device.cpp: + * src/audio/audio_jack.cpp: + * src/audio/audio_oss.cpp: + * src/audio/audio_sdl.cpp: + added setup-widget-technology making it possible to have audio-device- + specific setup-widgets which can be used in setup-dialog etc. + + * include/lcd_spinbox.h: + * src/widgets/lcd_spinbox.cpp: + added stepping-functionality + + * include/tab_widget.h: + * src/widgets/tab_widget.cpp: + pass caption to constructor instead of using fixed text + + * include/tab_bar.h: + * src/widgets/tab_bar.cpp: + - added direction-parameter in constructor + - added exclusive-property + - addTab(...) returns now pointer to tab-button which gives caller + possibility to modify the button + + * src/core/mixer.cpp: + save frames-per-audio-buffer-value in ctor if not set yet instead + of saving it in dtor + + * src/lib/embed.cpp: + do not return null-pixmap if pixmap not found + +2005-09-10 Tobias Doerffel + + * resources/setup_audio.png: + * resources/setup_general.png: + * resources/setup_midi.png: + added icons to be used in setup-dialog + + * src/audio/audio_alsa.cpp: + * src/audio/audio_sample_recorder.cpp: + use auto-cleaning pointer in createSampleBuffer(...) (fixes memory-leak + in ALSA-driver) + + * include/buffer_allocator.h: + added simple class for auto-cleaning pointers + + * src/core/mixer.cpp: + - added delete-calls in mixer::tryAudioDevices() + - init s_instanceOfMe-member in dtor, otherwise LMMS hangs up + + * locale/: + * artwork/: + moved translations and some artwork-stuff into locale- and artwork- + directory which is going to be installed into + LMMS-data-dir (/usr/share/lmms etc.) and shrinks executable + + * src/lib/embed.cpp: + added possibility to have resources in external files instead of being + linked into executable + + * configure.in: + - use macro AS_HELP_STRING for formatting help-strings + - removed --with-latency option as it is not needed anymore + +2005-09-06 Alireza + + * resources/ir.ts: + added Persian translation + +2005-09-04 Tobias Doerffel + + * src/audio/audio_oss.cpp: + - read device-name from config-file before evaluating environment- + variables etc. + - fixed bugs with device-probing (after dev-file was searched, there + was no open(...)-call again so it always failed if the first open(...) + didn't work + + * src/audio/audio_alsa.cpp: + read device-name from config-file before evaluating environment- + variables or using "default" + + * src/core/lmms_main_win.cpp: + call bufferAllocator::cleanUp( 0 ) for destroying all allocated buffers + + * include/buffer_allocator.h: + * src/lib/buffer_allocator.cpp: + - added clean-up-technique which removes least used buffers if + buffer-size exceeds limits (which depends on mixer's buffer-size) + - added field to bufDesc indicating usage of this buf - used by + alloc-method for determining most used, free and matching buffer + + * include/lcd_spinbox.h: + * src/widgets/lcd_spinbox.cpp: + made lcdSpinBox controlable by scroll-wheel + + * src/widgets/knob.cpp: + do not center knob if width of label is greater than actual knob + + * src/audio/audio_sample_recorder.cpp: + use bufferAllocator instead of new[]/delete[] + + * src/core/mixer.cpp: + - read value for frames-per-audio-buffer out of config-file and save + it at exit + - free buffer at exit + + * include/config_mgr.h: + * src/core/config_mgr.cpp: + added value() and setValue()-method which offers all components of LMMS + an easy way for loading/saving their settings at startup/exit + +2005-09-02 Mario Izquierdo +2005-09-02 Johnny Saenz + + * resources/es.ts: + added Spanish translation + +2005-09-02 Tobias Doerffel + + * most files: + finished changes began on 2005-08-29 + + * include/buffer_allocator.h: + * src/lib/buffer_allocator.cpp: + - only return aligned pointers + - small changes in API + + * resources/de.ts: + completed German translation + +2005-08-29 Tobias Doerffel + + * most files: + begin to use new bufferAllocator instead of old buffer-types and + use mixer-method for determining current number of frames per + audio-buffer + + * include/mixer.h: + types audioBuffer and surroundAudioBuffer don't exist anymore as well + as the constant FRAMES_PER_AUDIO_BUFFER - use + mixer::inst()->framesPerAudioBuffer() instead + +2005-08-28 Tobias Doerffel + + * include/song_editor.h: + * src/core/song_editor.cpp: + replaced QSpinBox by lcdSpinBox for BPM-spinbox + + * include/tab_bar.h: + * src/widgets/tab_bar.cpp: + removed function-parameter _font_size for tabBar::addTab(...) + + * most files: + - replaced QFont::setPointSize()-calls by according pointSize()-calls + which makes LMMS usable at any DPI-resolution + - changes for Qt4-compatibility + + * include/misc.h: + * include/template.h: + moved misc.h to template.h and added template-function pointSize + which sets a DPI-independent size for a given font + + * src/tracks/channel_track.cpp: + use labeling-feature of LCD-spinbox and removed old QLabel and + layouting-stuff + + * include/lcd_spinbox.h: + * src/widgets/lcd_spinbox.cpp: + - fixed bug: when moving mouse up, value was not updated properly + - added labeling-feature + - added valueChanged()-signal + + * src/core/arp_and_chords_tab_widget.cpp: + set m_arpDirection correct when loading older settings + +2005-08-27 Tobias Doerffel + + * include/channel_track.h: + * src/tracks/channel_track.cpp: + use new LCD-spinbox for effect-spinbox + + * include/lcd_spinbox.h: + * src/widgets/lcd_spinbox.cpp: + added LCD-spinbox, an improved QLCDNumber with ability of user-input + + * src/core/main.cpp: + changed highlight- and text-color to dark white instead of glaring green + for many people didn't like it... + + * include/audio_jack.h: + * src/audio/audio_jack.cpp: + - read and observe buf-size from JACK, so that writeBufferToDev() can + wait accordingly to it - now JACK-transport also works if buf-sizes + of LMMS and JACK are different + - also free buffers in destructor and not just throw them out of list + +2005-08-26 Tobias Doerffel + + * include/audio_jack.h: + * src/audio/audio_jack.cpp: + - also work with older versions which do not have jack_client_open() + - fixed bugs + - use bufferAllocator instead of new[] and delete[] in time-critical + functions + + * include/buffer_allocator.h: + * src/lib/buffer_allocator.cpp: + added bufferAllocator which is an optimized internal memory-manager + +2005-08-24 Tobias Doerffel + + * include/audio_jack.h: + * src/audio/audio_jack.cpp: + beginning of support for JACK-transport + + * src/audio/audio_sdl.cpp: + fixed memory leak - m_outputBuffer was not deleted in destructor + + * src/core/arp_and_chords_tab_widget.cpp: + completed usage of switchable groupboxes by saving groupbox-states + and evaluating them in processNote() + +2005-08-22 Tobias Doerffel + + * resources/afp_artwork.png: + small improvements for better usability and internationalization + + * src/soundgenerators/audio_file_processor.cpp: + - cleanups and small improvements concerning painting + - added missing tooltips + - moved open-sample-button right to filename-display-bar + + * src/widgets/pixmap_button.cpp: + changed default-pixmaps to led_yellow.png and led_off.png + + * resources/pattern_bg.png: + resized from 2x43 to 2x25 + + * src/core/name_label.cpp: + decreased default-font + + * include/track.h: + decreased size of track-settings-widget from 256 to 224 + + * include/channel_track.h: + * src/tracks/channel_track.cpp: + - use labeling-feature of knob for labeling volume-knob + - use smaller surroundArea in track-settings-widget and smaller + channel-button with smaller font + + * src/core/surround_area.cpp: + made surroundArea working with different widget-sizes than default size + + * resources/background_artwork.png: + made bg-image more pale + + * include/bb_editor.h: + * src/core/bb_editor.cpp: + changed painting-behaviour and made button-bg-gfx's obsolete by using + specialBgHandlingWidget + + * include/groupbox.h: + * src/widgets/groupbox.cpp: + improved groupbox by adding animation and more + + * src/core/envelope_and_lfo_widget.cpp: + * src/core/envelope_tab_widget.cpp: + - use knobs new labeling-feature + - use new tab-widget for target-widgets + + * include/tab_widget.h: + * src/widgets/tab_widget.cpp: + added own tab-widget which looks much cooler than Qt's one + + * src/core/arp_and_chords_tab_widget.cpp: + - using now new groupbox-widget and reorganized knob/switch-positions + - revised arpeggio-direction-buttons + - use knobs new labeling-feature + - removed obsolete headers + + * include/knob.h: + * src/widgets/knob.cpp: + added labeling-feature for automatically labeling knobs with given + text + + +2005-08-21 Tobias Doerffel + + * src/widgets/side_bar_widget.cpp: + * src/tracks/channel_track.cpp: + * src/core/config_mgr.cpp: + * src/core/piano_roll.cpp: + * src/core/arp_and_chords_tab_widget.cpp: + * src/core/main.cpp: + * src/core/browser.cpp: + replaced painting-device-dependent method setPixelSize by setPointSize + + * src/core/envelope_and_lfo_widget.cpp: + now using new group-box which looks much cooler and is more usable + + * include/groupbox.h: + * src/widgets/groupbox.cpp: + added own groupbox-widget with state-LED + + * src/widgets/pixmap_button.cpp: + delete m_bgPixmap in destructor + + * include/spc_bg_hndl_widget.h: + - made member m_backgroundPixmap to normal QPixmap instead of pointer to + it which also fixes a memory leak as dtor didn't delete the pixmap + - also use erase-pixmap of widget if available + + * include/oscillator.h: + - made shape-functions using phase()-function for determining phase of + sample + - made oscillator::phase() using modff instead of floorf-math which + makes the whole thing up to 20% faster + + * src/core/about_dialog.cpp: + added URL of project-page of LMMS + + * src/core/song_editor.cpp: + create new project if file given in cmd-line is not read-/usable + + * include/export_project_dialog.h: + * include/song_editor.h: + * src/core/main.cpp: + * src/core/song_editor.cpp: + added --render command-line-switch to render file and quit as soon as + job is done - very good for benchmarks + + * src/core/main.cpp: + added --version command-line-switch + +2005-08-20 Tobias Doerffel + + * src/core/lmms_main_win.cpp: + - extended filter for sample-browser + - added home- and root-browser for being able to load songs, presets, + samples etc. from somewhere else than within lmms-working-directory + +2005-07-27 Tobias Doerffel + + * src/core/lmms_main_win.cpp: + * src/core/track_container.cpp: + * src/core/track.cpp: + by completing destructors and fixing some other small bugs there's + finally no seg-fault when quitting app! (the bug annoying for months...) + + * include/track_container.h: + all public-slots were made to normal public and FASTCALLed functions + since they aren't connected to a signal anywhere and it just blows up + qt-moc-code + + * include/sample_track.h: + made method sampleTCO::changeLength(...) FASTCALLed since it's virtual + and method in base-class is also FASTCALLed - eliminates crash when + resizing sample + + * include/track.h: + * src/core/track.cpp: + removed unsused method setTrackWidgetHeight( int ) + +2005-07-26 Pedro Lopez-Cabanillas + + * src/core/browser.cpp: + * src/core/config_mgr.cpp: + * src/core/lmms_main_win.cpp: + * src/core/main.cpp: + * src/core/song_editor.cpp: + * src/lib/mmp.cpp: + * src/tracks/pattern.cpp: + * src/widgets/project_notes.cpp: + small changes for compatibility with Qt 3.1 + + * src/midi/midi_alsa.cpp: + * src/midi/midi_oss.cpp: + added MIDIDEV-environment variable for being able to choose a MIDI + device different from the default one + +2005-07-24 Tobias Doerffel + + * include/midi_mapper.h: + * src/midi/midi_mapper.cpp: + added MIDI-mapper to be used in combination with midiDevice's and/or + MIDI-Out-Plugin which can read MIDI-maps added before + + * midi-maps/*map: + added MIDI-maps from KMid + + * include/midi_dummy.h: + * src/midi/midi_device.cpp: + added dummy MIDI-driver for not crashing if no MIDI-device is available + + * src/core/piano_roll.cpp: + - go to start of pattern when pressing home-key + - added support for zooming + + * src/core/song_editor.cpp: + - fixed bug with loop-points by setting current-frame-var to zero to + force reset of it + - added auto-scrolling ability + - fixed bug which caused horizontal scrollbar to have an undefined + max-value after starting up LMMS + - go to start of pattern when pressing home-key + +2005-07-23 Alexey Kouznetsov + + * resources/ru.ts: + added Russian translation + +2005-07-23 Tobias Doerffel + + * src/core/piano_roll.cpp: + scroll back when stopping and play-position changes to invisible area + + * include/time_line.h: + * src/core/song_editor.cpp: + * src/core/time_line.cpp: + added control-buttons to time-line making it possible to control + things like auto-scrolling, looping and play-position after stop + + * src/midi/midi_device.cpp: + limit volume between 0 and 127 when sending out note-on-event + +2005-07-21 Tobias Doerffel + + * include/nstate_button.h: + * src/widgets/nstate_button.cpp: + added widget nStateButton which is a button able to have n different + states with according pixmaps and tooltips + + * resources/back_to_zero.png: + * resources/keep_stop_position.png: + * resources/back_to_start.png: + * resources/loop_points_off.png: + * resources/loop_points_on.png: + * resources/autoscroll_off.png: + * resources/autoscroll_on.png: + added pixmaps for buttons to be used in time-line as soon as possible + + * lmms-0.1.0rc1.tar.bz2: + release of Release Candidate 1 of LMMS 0.1.0 + +2005-07-20 Tobias Doerffel + + * src/midi/midi_file.cpp: + - proper handling of note-on-events which velocity 0 -> treat like + note-off-events makes it now possible to import a much larger amount + of MIDI-files + - added progress-dialog when importing MIDI-file + + * src/core/song_editor.cpp: + horizontal scrollbar is now placed some pixels above lower edge so that + it doesn't take action when resizing song-editor-window at lower edge + + * src/core/track_container.cpp: + added progress-dialog for loading project and according + qApp->processEvents()-call -> LMMS now isn't blocked anymore while + loading project + + * include/knob.h: + * src/widgets/knob.cpp: + fixed bugs caused by changes made before for scroll-wheel-support + +2005-07-19 Tobias Doerffel + + * include/knob.h: + * src/widgets/knob.cpp: + added better scroll-wheel support which increases/decreases knob-value + by 20th of range (e.g 0.05 if knob is ranged between 0 and 1) + +2005-07-17 Tobias Doerffel + + * projects/: + added "covers"-dir and added "Preludium and Fuge A-Minor" by J.S.Bach + to it as first covered project ;-) + + * src/core/note_play_handle.cpp: + - fixed bad bug in notePlayHandle::play(): instead of directly being + deleted, sub-notes were given to mixer to be removed when they played + completely but since these sub-notes are not known to mixer, it + couldn't delete them + - always call channelTrack::deleteNotePluginData() in + noteplayhandle-dtor even if pointer to note-plugin-data is NULL so + that all plugins are notified when note is done (midiOut-plugin + needs that for sending note-off-events!) + + * include/midi_out.h: + * src/soundgenerators/midi_out.cpp: + new plugin midiOut which sends all notes on this channel out to + external midi-device this is especially cool for playing arpeggio for + key pressed on external midi-device!! + + * src/soundgenerators/plucked_string_synth.cpp: + removed unneccesary inclusion of qpainter-header + + * include/midi_file.h: + * src/midi/midi_file.cpp: + * src/core/lmms_main_win.cpp: + * src/core/song_editor.cpp: + added support for importing MIDI-file (very experimental!!) + + * include/midi.h: + * include/midi_device.h: + moved general MIDI-stuff from midi_device.h to midi.h + + * src/audio/audio_file_device.cpp: + added missing arg()-call to QMessageBox::critical()-call in + audioFileDevice-ctor + +2005-07-16 Tobias Doerffel + + * src/core/config_mgr.cpp: + added shortcuts to navigation-buttons + +2005-07-14 Tobias Doerffel + + * src/core/piano_roll.cpp: + only play notes while editing if we're not in play-mode + + * include/song_editor.h: + * src/core/song_editor.cpp: + when exporting always render one additional tact at the end so that + we don't cut off notes with delay etc. + +2005-07-12 Tobias Doerffel + + - successful compilation with GCC 4.0.1 ;-) + + * src/core/arp_and_chords_tab_widget.cpp: + fixed bug responsible for playing base-notes of chords all time + if any arpeggio selected was selected + +2005-07-11 Tobias Doerffel + + * resources/source/wizard_files.xcf: + * resources/wizard_files.png: + updated project-file-icon in image + + * src/core/config_mgr.cpp: + - ask user whether to re-run setup-wizard if config-file indicates + different version of LMMS + - removed redundant assignment in configManager::loadConfigFile() + - added additional layout for having space at the left and right side + - increased font-size of title + + * Makefile.am: + install LMMS-icon into LMMS-data-dir + + * lmms-0.1.0beta.tar.bz2: + made beta-release of 0.1.0 and announced it on kde-apps.org + +2005-07-10 Tobias Doerffel + + * presets/TripleOscillator/: + added cool Church Organ preset and improved Xylophon preset + + * resources/de.ts: + updated German translations and cleaned up all obsolete translations + and context which shrinks the file by 50K... + + * samples/instruments/: + removed vibraphone01.ogg because of poor quality + + * src/core/piano_roll.cpp: + - do not set what's-this-texts as tooltips for play/stop-button + - added tooltip and what's-this-text to record-button + - display message in piano-roll how to open a pattern if none is opened + - always set window-title, even if no pattern is opened + + * src/core/mixer.cpp: + using iterators in second loop in mixer::run() leads to crashes, so + an optimized version of the old code is used now again... + + * src/core/lmms_main_win.cpp: + added tool-buttons for new project, open/save project etc. and added + popup-menu to new-button containing projects in template-directory + + * include/song_editor.h: + * src/core/song_editor.cpp: + - changed remaining method-names containing "[Ss]ong" to "[Pp]roject" + - toggle channel-button after adding channel-track + + * include/export_project_dialog.h: + * src/core/export_project_dialog.cpp: + renamed from export_song_dialog.ext to export_project_dialog.ext + +2005-07-09 Tobias Doerffel + + * all files: + now all source-code-files but some single exceptions do not have more + than 80 characters per line and also were made to conform one + programming-style + + * include/sgs: + wrote sane soundgenerator-plugin-scanner using bash-scripting which + replaces old, dirty and exaggerated c++-program and is also fully + portable + + * include/lmms_main_win.h: + * include/song_editor.h: + * src/core/lmms_main_win.cpp: + * src/core/song_editor.cpp: + renamed methods newFile, openFile etc. to createNewProject, openProject + etc. + + * resources/source/: + - renamed filenew.png, fileopen.png etc. to project_new.png etc. + - replaced song_file.png by project_file.png which has a new file-icon + with LMMS-logo inside + - replaced preset_file.png by new graphic where the star is inside + of a file-icon + + * resources/source/lmms_logo.svg: + made logo Inkscape 0.41 compatible (had problems with gradients since + logo originally had been made with Inkscape 0.39) + + * src/widgets/project_notes.cpp: + removed unneccessary name-strings for QActions + + * resources/project_notes.png: + replaced 16x16-icon with 22x22-icon to provide big enough icon for + toolbar which needs 22x22-icons + + * src/core/bb_editor.cpp: + * src/core/song_editor.cpp: + * src/tracks/bb_track.cpp: + do not crash if either there're no bb-tracks but bb-editor has tracks + or there're bb-tracks but bb-editor contains no tracks + + * src/core/mixer.cpp: + * src/core/note_play_handle.cpp: + * src/core/track_container.cpp: + * src/tracks/pattern.cpp: + rewrote loops using vectors to use iterators instead of indices etc. + which makes it all a bit smaller and faster since we do not always have + to access the current element using the []-operator + +2005-07-08 Tobias Doerffel + + * src/core/envelope_tab_widget.cpp: + * src/lib/sample_buffer.cpp: + * src/widgets/knob.cpp: + small fixes for making compilable with qt4 + + * configure.in: + * projects/: + added directories "tutorials" and "recorded_loops" + +2005-07-07 Tobias Doerffel + + * include/bb_track.h: + added FASTCALL to moveLocation(...) and changeLength(...) which fixes + crash-bug + + * src/core/song_editor.cpp: + do not confirm overwriting file if new project was just saved + + * samples/: + added a lot of new samples from wikisource and others + +2005-07-06 Tobias Doerffel + + * include/project_notes.h: + * src/core/song_editor.cpp: + * src/widgets/project_notes.cpp: + clear project-notes when clearing song (new/open file etc.) + + * src/tracks/pattern.cpp: + ask user when he tries to freeze a pattern of a muted channel whether he + wants to continue since freezing a pattern of a muted channel makes no + sense (you're rendering silence!) + + * include/piano_roll: + * src/core/piano_roll.cpp: + - added possibility to edit the volume of notes + - removed all bool-variables indicating whether an action is being + performed at the moment and introduced m_action, indicating + one of the actions defined in (also new) enum editActions + - replaced m_startTone and m_startOctave with one variable m_startKey, + which makes a lot of code unneccessary + - rewrote loops using note-vectors to use iterators instead of + indices and vector::size() + - renamed m_evolutionHeight to m_notesEditHeight + - replaced QMouseEvent::pos().[xy]()-calls with QMouseEvent::[xy]() + - pianoRoll::getKey() does now take y-position (int) as parameter + instead of QPoint since it only needs y-position + - use new setKey()/key()-member of note everywhere where it is possible + + * include/note.h: + added setKey()- and key()-member which setting/getting absolute key + of note + +2005-07-05 Tobias Doerffel + + * configure.in: + * projects/: + categorized projects in "cool_songs", "demos", "misc" and "templates" + so that we don't annoy the user with a lot projects in his/her project- + root - have to fill up "templates" with project-templates, e.g. + basic drum-kit, accoustic drum-kit etc. + + * most files: + added FASTCALL-attributes to functions taking at least one parameter + + * include/audio_file_processor.h: + * include/plucked_string_synth.h: + * include/triple_oscillator.h: + moved deleteNotePluginData()-method into according cpp-files which + makes including note_play_handle.h obsolete + + * include/audio_file_processor.h: + * include/sample_buffer.h: + * src/lib/sample_buffer.cpp: + * src/soundgenerators/audio_file_processor.cpp: + added support for saving sample-rate-conversion-state in m_pluginData + of a note which fixes bug making clicks in sound when playing a sample + simultanously at different pitches + + * configure.in: + check whether compiler knows floorf and powf and if not, define them + to floor/pow + +2005-07-04 Tobias Doerffel + + * most files: + made LMMS compiling (and working) with Qt 3.0, GCC 2.95 and other old + libs (compiled it under Knoppix 3.1) + + * include/misc.h: + changed names of abs, min, max, limit to myAbs, myMin etc. for not + conflicting with functions of STL with the same name + + * configure.in: + * src/lib/sample_buffer.cpp: + added support for versions of libsndfile < 1.0.11 since API has changed + in libsndfile 1.0.11 + +2005-07-03 Tobias Doerffel + + * resources/control_env_amount_active.png: + * resources/control_env_amount_inactive.png: + * include/envelope_and_lfo_widget.h: + * src/core/envelope_and_lfo_widget.cpp: + it's now possible to control the amount of an envelope with the + according LFO by toggling new button (otherwise the level of the LFO is + added to the level of the envelope as it always has been) + + * src/core/envelope_and_lfo_widget.cpp: + now you can toggle the amount of an envelope/LFO between 0 and 1 by + clicking on according graph + + * all files: + updated mail-address in header + + * src/audio/audio_device.cpp: + always use SURROUND_CHANNELS as channel-count for libsrc since + resampling is done on surround-buffers - fixes bug which was + responsible for producing useless noise when exporting file in + high-quality-mode + + * src/core/export_song_dialog.cpp: + made "high-quality-mode"-switch working (disabled for some reason + in 0.0.9...) + + * src/core/mixer.cpp: + when restoring audio-device, also restore quality-level + + * include/bb_editor.h: + * src/core/bb_editor.cpp: + cleaned up a lot because there was still much code from times when + the track-technology didn't exist and which isn't now used any more + + * src/audio/audio_alsa.cpp: + added support for 48 KHz soundcards + +2005-07-02 Tobias Doerffel + + * configure.in: + * src/lib/sample_buffer.cpp: + made it possible to compile LMMS without SDL_sound, reorganized + sample-decoding and added libsndfile- and libvorbis-support + + * include/midi_time.h: + added operators "=", "+=", "-=" and implemented copy-ctor + + * include/piano_roll.h: + made currentPattern() a const method and added validPattern() + + * src/tracks/pattern.cpp: + optimized addNote() function which uses m_note.push_back() for notes + beyond last note + + * src/core/piano_roll.cpp: + * src/tracks/pattern.cpp: + when pattern is destroyed it checks whether it is currently opened in + piano-roll and if so pattern lets piano-roll set its pointer to current + pattern to NULL. piano-roll does now always check whether current + pattern is not NULL. in this case it denies any actions. fixes bug which + led to crash when having piano-roll open while deleting pattern (e.g. + creating new file, opening file etc.) + +2005-07-01 Tobias Doerffel + + * all files: + replaced "location" in names of functions/variables by "position" + for more clear and unified names + + * include/piano_roll.h: + * include/timeline.h: + * src/core/piano_roll.cpp: + * src/core/timeline.cpp: + added support for autoscroll in piano-roll when playing/recording + pattern + +2005-06-30 Tobias Doerffel + + * include/channel_track.h: + * include/midi_device.h + * include/mixer.h: + * include/pattern.h: + * src/core/piano_roll.cpp: + * src/midi/midi_device.cpp: + * src/tracks/channel_track.cpp: + added support for recording notes from MIDI-device (e.g. MIDI-keyboard + or virtual channel-piano) in a pattern using the piano-roll + + * include/pattern.h + * src/core/song_editor.cpp: + fixed bug which led to crash: when pattern was played in non-looping + mode song-editor always called pattern::finishFreeze() even if there + actually was no pattern-freezing-process -> added isFreezing() which + is called by song-editor for checking whether pattern is being freezed + before calling finishFreeze() + + * src/core/lmms_main_win.cpp: + * src/lib/sample_buffer.cpp: + when showing open-file-dialog, use QFileDialog::selectedFiles()[0] + instead of QFileDialog::selectedFile() because selectedFile() returns + incorrect file-name if user clicked on the file and then on + "Open"-button instead of double-clicking file + + * src/audio/audio_oss.cpp: + * src/soundgenerators/triple_oscillator.cpp: + * src/tracks/channel_track.cpp: + added #include for solving problems with undeclared + functions getenv() and rand() on some distributions (e.g Slackware) + + * src/core/track.cpp: + * src/soundgenerators/triple_oscillator.cpp: + * src/tracks/channel_track.cpp: + added missing #include "debug.h" for solving problems with undeclared + assert() because of not included assert.h + +2005-06-29 Tobias Doerffel + + * configure.in: + * include/audio_sdl.h: + * src/lib/sample_buffer.cpp: + if SDL/SDL.h does not exist, search for it in SDL10, SDL11 etc. and + include according headers in source-files (solves problems on FreeBSD) + + * README: + updated everything a bit... + +2005-06-28 Tobias Doerffel + + * include/envelope_tab_widget.h: + * src/core/envelope_tab_widget.cpp: + use button instead of knob for turning filter on/off + +2005-06-27 Tobias Doerffel + + * samples/effects/Makefile.am: + don't install effect-samples into directory of basses-samples + + diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000000..b42a17ac464 --- /dev/null +++ b/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000000..240109e3324 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,304 @@ +AUTOMAKE_OPTIONS = foreign 1.4 + +dist-hook: + rm -rf `find $(distdir) -name \*.moc` + + +install-exec-hook: + cd $(DESTDIR)$(bindir) ; \ + strip lmms + + +if HAVE_RPM +$(PACKAGE)-$(VERSION).tar.gz: dist + +# Rule to build RPM distribution package +rpm: $(PACKAGE)-$(VERSION).tar.gz $(PACKAGE).spec + cp $(PACKAGE)-$(VERSION).tar.gz @RPMSOURCEDIR@ + rpmbuild -ba $(PACKAGE).spec +endif + + +noinst_PROGRAMS= bin2res +bin2res_SOURCES = buildtools/bin2res.cpp + + +INCLUDES = -I$(srcdir)/include -I. +bin_PROGRAMS = lmms + + + +AM_CXXFLAGS := $(AM_CXXFLAGS) $(QT_CXXFLAGS) + + +%.moc: $(srcdir)/include/%.h + $(MOC) -o $@ $< + +%.ts: + $(LUPDATE) $(lmms_SOURCES) -ts locale/$@ + +%.qm: %.ts + $(LRELEASE) $< + + + +lmms_MOC = \ + ./about_dialog.moc \ + ./arp_and_chords_tab_widget.moc \ + ./audio_file_processor.moc \ + ./bb_editor.moc \ + ./bb_track.moc \ + ./browser.moc \ + ./channel_track.moc \ + ./config_mgr.moc \ + ./crystal_button.moc \ + ./envelope_and_lfo_widget.moc \ + ./envelope_tab_widget.moc \ + ./export_project_dialog.moc \ + ./kmultitabbar.moc \ + ./group_box.moc \ + ./knob.moc \ + ./lcd_spinbox.moc \ + ./lmms_main_win.moc \ + ./midi_out.moc \ + ./mixer.moc \ + ./name_label.moc \ + ./nstate_button.moc \ + ./pattern.moc \ + ./piano_roll.moc \ + ./piano_widget.moc \ + ./pixmap_button.moc \ + ./plucked_string_synth.moc \ + ./project_notes.moc \ + ./rename_dialog.moc \ + ./sample_buffer.moc \ + ./sample_track.moc \ + ./setup_dialog.moc \ + ./side_bar.moc \ + ./side_bar_widget.moc \ + ./song_editor.moc \ + ./sound_generator.moc \ + ./surround_area.moc \ + ./tab_bar.moc \ + ./tab_button.moc \ + ./tab_widget.moc \ + ./timeline.moc \ + ./track_container.moc \ + ./track.moc \ + ./triple_oscillator.moc \ + ./visualization_widget.moc + + +BUILT_SOURCES = $(lmms_MOC) + +#lmms_TRANSLATIONS = $(wildcard $(srcdir)/locale/*.qm $(srcdir)/locale/*.ts) + +lmms_EMBEDDED_RESOURCES = $(wildcard $(srcdir)/resources/*png AUTHORS COPYING) + +./embedded_resources.h: $(lmms_EMBEDDED_RESOURCES) bin2res + $(top_builddir)/bin2res $(lmms_EMBEDDED_RESOURCES) > $@ + +./embed.o: ./embedded_resources.h + + +lmms_SOURCES = \ + $(srcdir)/src/audio/audio_alsa.cpp \ + $(srcdir)/src/audio/audio_device.cpp \ + $(srcdir)/src/audio/audio_file_device.cpp \ + $(srcdir)/src/audio/audio_file_ogg.cpp \ + $(srcdir)/src/audio/audio_file_wave.cpp \ + $(srcdir)/src/audio/audio_jack.cpp \ + $(srcdir)/src/audio/audio_oss.cpp \ + $(srcdir)/src/audio/audio_sample_recorder.cpp \ + $(srcdir)/src/audio/audio_sdl.cpp \ + $(srcdir)/src/core/about_dialog.cpp \ + $(srcdir)/src/core/arp_and_chords_tab_widget.cpp \ + $(srcdir)/src/core/bb_editor.cpp \ + $(srcdir)/src/core/browser.cpp \ + $(srcdir)/src/core/config_mgr.cpp \ + $(srcdir)/src/core/envelope_and_lfo_widget.cpp \ + $(srcdir)/src/core/envelope_tab_widget.cpp \ + $(srcdir)/src/core/export_project_dialog.cpp \ + $(srcdir)/src/core/lmms_main_win.cpp \ + $(srcdir)/src/core/main.cpp \ + $(srcdir)/src/core/mixer.cpp \ + $(srcdir)/src/core/name_label.cpp \ + $(srcdir)/src/core/note.cpp \ + $(srcdir)/src/core/note_play_handle.cpp \ + $(srcdir)/src/core/piano_roll.cpp \ + $(srcdir)/src/core/piano_widget.cpp \ + $(srcdir)/src/core/plugin_management.cpp \ + $(srcdir)/src/core/preset_preview_play_handle.cpp \ + $(srcdir)/src/core/sample_play_handle.cpp \ + $(srcdir)/src/core/setup_dialog.cpp \ + $(srcdir)/src/core/song_editor.cpp \ + $(srcdir)/src/core/sound_generator.cpp \ + $(srcdir)/src/core/track.cpp \ + $(srcdir)/src/core/track_container.cpp \ + $(srcdir)/src/core/surround_area.cpp \ + $(srcdir)/src/core/timeline.cpp \ + $(srcdir)/src/lib/buffer_allocator.cpp \ + $(srcdir)/src/lib/clipboard.cpp \ + $(srcdir)/src/lib/embed.cpp \ + $(srcdir)/src/lib/mmp.cpp \ + $(srcdir)/src/lib/oscillator.cpp \ + $(srcdir)/src/lib/sample_buffer.cpp \ + $(srcdir)/src/midi/midi_alsa_raw.cpp \ + $(srcdir)/src/midi/midi_device.cpp \ + $(srcdir)/src/midi/midi_file.cpp \ + $(srcdir)/src/midi/midi_mapper.cpp \ + $(srcdir)/src/midi/midi_oss.cpp \ + $(srcdir)/src/soundgenerators/audio_file_processor.cpp \ + $(srcdir)/src/soundgenerators/midi_out.cpp \ + $(srcdir)/src/soundgenerators/plucked_string_synth.cpp \ + $(srcdir)/src/soundgenerators/triple_oscillator.cpp \ + $(srcdir)/src/tracks/bb_track.cpp \ + $(srcdir)/src/tracks/channel_track.cpp \ + $(srcdir)/src/tracks/pattern.cpp \ + $(srcdir)/src/tracks/sample_track.cpp \ + $(srcdir)/src/widgets/crystal_button.cpp \ + $(srcdir)/src/widgets/group_box.cpp \ + $(srcdir)/src/widgets/kmultitabbar.cpp \ + $(srcdir)/src/widgets/knob.cpp \ + $(srcdir)/src/widgets/lcd_spinbox.cpp \ + $(srcdir)/src/widgets/led_checkbox.cpp \ + $(srcdir)/src/widgets/nstate_button.cpp \ + $(srcdir)/src/widgets/pixmap_button.cpp \ + $(srcdir)/src/widgets/project_notes.cpp \ + $(srcdir)/src/widgets/rename_dialog.cpp \ + $(srcdir)/src/widgets/side_bar_widget.cpp \ + $(srcdir)/src/widgets/tab_bar.cpp \ + $(srcdir)/src/widgets/tab_widget.cpp \ + $(srcdir)/src/widgets/text_float.cpp \ + $(srcdir)/src/widgets/tooltip.cpp \ + $(srcdir)/src/widgets/visualization_widget.cpp \ + $(srcdir)/include/pch.h \ + $(srcdir)/include/debug.h \ + $(srcdir)/include/lmms_main_win.h \ + $(srcdir)/include/audio_alsa.h \ + $(srcdir)/include/audio_device.h \ + $(srcdir)/include/audio_dummy.h \ + $(srcdir)/include/audio_file_device.h \ + $(srcdir)/include/audio_file_ogg.h \ + $(srcdir)/include/audio_file_wave.h \ + $(srcdir)/include/audio_jack.h \ + $(srcdir)/include/audio_oss.h \ + $(srcdir)/include/audio_sample_recorder.h \ + $(srcdir)/include/audio_sdl.h \ + $(srcdir)/include/interpolation.h \ + $(srcdir)/include/mixer.h \ + $(srcdir)/include/pattern.h \ + $(srcdir)/include/channel_track.h \ + $(srcdir)/include/note.h \ + $(srcdir)/include/volume.h \ + $(srcdir)/include/panning.h \ + $(srcdir)/include/song_editor.h \ + $(srcdir)/include/sound_generator.h \ + $(srcdir)/include/audio_file_processor.h \ + $(srcdir)/include/midi_time.h \ + $(srcdir)/include/bb_editor.h \ + $(srcdir)/include/piano_widget.h \ + $(srcdir)/include/effect_board.h \ + $(srcdir)/include/pixmap_button.h \ + $(srcdir)/include/triple_oscillator.h \ + $(srcdir)/include/settings.h \ + $(srcdir)/include/plucked_string_synth.h \ + $(srcdir)/include/rename_dialog.h \ + $(srcdir)/include/export_project_dialog.h \ + $(srcdir)/include/note_play_handle.h \ + $(srcdir)/include/piano_roll.h \ + $(srcdir)/include/basic_filters.h \ + $(srcdir)/include/envelope_tab_widget.h \ + $(srcdir)/include/envelope_and_lfo_widget.h \ + $(srcdir)/include/about_dialog.h \ + $(srcdir)/include/oscillator.h \ + $(srcdir)/include/crystal_button.h \ + $(srcdir)/include/arp_and_chords_tab_widget.h \ + $(srcdir)/include/export.h \ + $(srcdir)/include/group_box.h \ + $(srcdir)/include/tab_widget.h \ + $(srcdir)/include/knob.h \ + $(srcdir)/include/browser.h \ + $(srcdir)/include/templates.h \ + $(srcdir)/include/surround_area.h \ + $(srcdir)/include/kmultitabbar.h \ + $(srcdir)/include/side_bar.h \ + $(srcdir)/include/side_bar_widget.h \ + $(srcdir)/include/track.h \ + $(srcdir)/include/track_container.h \ + $(srcdir)/include/bb_track.h \ + $(srcdir)/include/sample_track.h \ + $(srcdir)/include/sample_buffer.h \ + $(srcdir)/include/name_label.h \ + $(srcdir)/include/play_handle.h \ + $(srcdir)/include/mmp.h \ + $(srcdir)/include/midi_device.h \ + $(srcdir)/include/midi_file.h \ + $(srcdir)/include/midi_alsa_raw.h \ + $(srcdir)/include/midi_oss.h \ + $(srcdir)/include/clipboard.h \ + $(srcdir)/include/types.h \ + $(srcdir)/include/qt3support.h \ + $(srcdir)/include/embed.h \ + $(srcdir)/include/timeline.h \ + $(srcdir)/include/config_mgr.h \ + $(srcdir)/include/spc_bg_hndl_widget.h \ + $(srcdir)/include/tab_bar.h \ + $(srcdir)/include/tab_button.h \ + $(srcdir)/include/project_notes.h \ + $(srcdir)/include/visualization_widget.h \ + $(srcdir)/include/endian_handling.h \ + $(srcdir)/include/preset_preview_play_handle.h \ + $(srcdir)/include/sample_play_handle.h \ + $(srcdir)/include/midi.h \ + $(srcdir)/include/midi_out.h \ + $(srcdir)/include/nstate_button.h \ + $(srcdir)/include/midi_dummy.h \ + $(srcdir)/include/midi_mapper.h \ + $(srcdir)/include/buffer_allocator.h \ + $(srcdir)/include/lcd_spinbox.h \ + $(srcdir)/include/tooltip.h \ + $(srcdir)/include/led_checkbox.h \ + $(srcdir)/include/text_float.h \ + $(srcdir)/include/setup_dialog.h + + +EXTRA_DIST = \ + $(lmms_EMBEDDED_RESOURCES) \ + $(srcdir)/include/sgs + + +CLEANFILES = $(lmms_MOC) ./embedded_resources.h + +if HAVE_LIBSDL +LIB_SDL_LDADD = -lSDL +endif + +if HAVE_LIBSDL_SOUND +LIB_SDL_SOUND_LDADD = -lSDL_sound +endif + +if HAVE_LIBASOUND +LIB_ASOUND_LDADD = -lasound +endif + +if HAVE_LIBJACK +LIB_JACK_LDADD = -ljack +endif + +if HAVE_LIBVORBIS +LIB_VORBIS_LDADD = -lvorbis -lvorbisenc -lvorbisfile +endif + +if HAVE_LIBSRC +LIB_SRC_LDADD = -lsamplerate +endif + +if HAVE_LIBSF +LIB_SF_LDADD = -lsndfile +endif + +lmms_LDADD = $(QT_LDADD) $(LIB_SDL_LDADD) $(LIB_ASOUND_LDADD) $(LIB_JACK_LDADD) $(LIB_SDL_SOUND_LDADD) $(LIB_VORBIS_LDADD) $(LIB_SRC_LDADD) $(LIB_SF_LDADD) + +SUBDIRS = artwork locale midi-maps presets projects samples + diff --git a/README b/README new file mode 100644 index 00000000000..bed7ce9ac42 --- /dev/null +++ b/README @@ -0,0 +1,97 @@ +Linux MultiMedia Studio 0.1.0 +============================= + +Copyright (c) 2004-2005 by Tobias Doerffel + + +The whole program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2 of the License, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place - Suite 330, Boston, MA 02111-1307, USA + + + +What is LMMS?? +-------------- + +LMMS aims to be a free alternative to popular (but commercial and closed- +source) programs like FruityLoops, Cubase and Logic giving you the ability of +producing music with your computer by creating/synthesizing sounds, arranging +samples, playing live with keyboard and much more... + +LMMS combines the features of a tracker-/sequencer-program (pattern-/channel-/ +sample-/song-/effect-management) and those of powerful synthesizers and +samplers in a modern, user-friendly and easy to use graphical user-interface. + +LMMS is still in heavy development, so with this version please don't expect a +complete, ready and bugfree program!! + + + +Requirements +------------ + +The most important requirement is for sure a fast computer, so don't try to get +LMMS working on a pentium one with 60 MHz... ;-) So you should have at least +500 MHz, but for really enjoying LMMS less than 1 GHz makes no sense... +(LMMS is currently developed on a PIII 450 MHz...!!) + +Required libraries are: + +- Qt 3.2 or higher (tested up to 4.0.0) with devel-files +- SDL_sound (tested with 0.1.5 & 1.0.1) with devel-files + +Optional, but strongly recommended: +- libvorbis with devel-files +- libalsa with devel-files +- SDL with devel-files +- libsamplerate with devel-files + +For compiling you should have an up to date GCC with g++. +LMMS has been (successfully) tested under Debian Sarge 3.1, Fedora Core 2-4, +and SuSE Linux 9.0-9.3 with Qt 3.[23].x and Qt 4.0.0. +It was compiled using GCC 3.3.x, GCC 3.4.x and GCC 4.0.0. + +If you have problems with compiling or running LMMS, find any bug or have +suggestions and so on, please feel free to e-mail me (for mail-address see +below)! + + + + +Help developing LMMS +-------------------- + +If you are interested in LMMS, it's programming, artwork, testing, writing +demo-songs, (and improving this f**** README...) or something like that, +you're welcome to participate on the development of LMMS! + +Just e-mail me: tobydox@users.sourceforge.net + +The project-homepage of LMMS and mailingslists can be found at +http://lmms.sourceforge.net + + +Before coding a new big feature, please always post your idea and suggestions +about your feature and about the actual implementation to the +LMMS-devel-mailinglist (lmms-devel@lists.sourceforge.net) and wait for replies +or email me! Maybe there're different ideas, improvements, hints or maybe your +feature is not welcome/needed at the moment (but for sure this will be very +seldom). + +If you coded your feature, make sure, that it is running properly with the +newest available version of LMMS and that it also runs with different +configurations (e.g. different latency, disabled surround-support, missing +package(s) etc.). Important is also, that you comment your +source so that other people can fix bugs or improve your feature! + + diff --git a/TODO b/TODO new file mode 100644 index 00000000000..043e3f619e1 --- /dev/null +++ b/TODO @@ -0,0 +1,40 @@ +- make usable with Qt4 +- make LMMS an ALSA-sequencer-client +- adchannel-toolbutton -> popup-menu with available soundgenerator-plugins +- tempo-based arpeggio +- pre-listen when opening sample with QFileDialog +- level-meters in output-graph and channel-track +- panning-editing in piano-roll +- use midi-maps +- process program-/channel-change-events from MIDI-files +- setup MIDI-channel and -program in MIDI-Out +- speed up painting of sampleTCO +- save window-positions, -states and -sizes in files +- solve problems with different keyboard-layouts when playing channel-track with pc-keyboard +- balance env+lfo +- autosave every 1 minute +- audioDummy: always wait until the stuff normally would have been written (=simulate blocking IO) +- plucked-string-synth: knob for metallic -> use noise as wave-shape +- finish qt4-port and make LMMS usable when compiling with Qt4 +- rewrite export-project-dialog using layout-mechanism +- dynamic pitch-change +- make piano-roll use the global clipboard?? +- add languages: + - Dutch + - Italian + - ...any other welcome + + + +Things to be done anytime in the future +- effect-board -> live-fx from input +- event-system +- chord-editor? +- WAVE/OGG/MP3-Import -> FFT-analysis -> write notes +- FLP-Import +- classical note-edit-window -> also ability of printing and maybe later scanning & recognition of notes +- add FLAC as export-format? +- support of LADSPA for all plugins +- better commented source... +- optimize, optimize, optimize..... + diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 00000000000..051df50520c --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,266 @@ +# Check for Qt compiler flags, linker flags, and binary packages +AC_DEFUN([gw_CHECK_QT], +[ +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([AC_PATH_X]) + +AC_MSG_CHECKING([QTDIR]) +AC_ARG_WITH([qtdir], [ --with-qtdir=DIR Qt installation directory [default=$QTDIR]], QTDIR=$withval) +# Check that QTDIR is defined or that --with-qtdir given +if test x"$QTDIR" = x ; then + # some usual Qt-locations + QT_SEARCH="/usr /usr/lib/qt /usr/lib/qt3 /usr/lib/qt31 /usr/lib/qt32 /usr/lib/qt33 /usr/lib/qt-3.0 /usr/lib/qt-3.1 /usr/lib/qt-3.2 /usr/lib/qt-3.3 usr/local/qt /usr/local/qt3 /usr/local/qt31/ /usr/local/qt32 /usr/local/qt33 /usr/X11R6 /usr/local/Trolltech/Qt-4.0.0" +else + QT_SEARCH=$QTDIR + QTDIR="" +fi +for i in $QT_SEARCH ; do + QT_INCLUDE_SEARCH="include include/qt include/qt3 include/Qt" + for j in $QT_INCLUDE_SEARCH ; do + if test -f $i/$j/qglobal.h -a x$QTDIR = x ; then + QTDIR=$i + QT_INCLUDES=$i/$j + fi + done +done +if test x"$QTDIR" = x ; then + AC_MSG_ERROR([*** QTDIR must be defined, or --with-qtdir option given]) +fi +AC_MSG_RESULT([$QTDIR]) + +# Change backslashes in QTDIR to forward slashes to prevent escaping +# problems later on in the build process, mainly for Cygwin build +# environment using MSVC as the compiler +# TODO: Use sed instead of perl +QTDIR=`echo $QTDIR | perl -p -e 's/\\\\/\\//g'` + +AC_MSG_CHECKING([Qt includes]) +# Check where includes are located +if test x"$QT_INCLUDES" = x ; then + AC_MSG_ERROR([*** could not find Qt-includes! Make sure you have the Qt-devel-files installed!]) +fi +AC_MSG_RESULT([$QT_INCLUDES]) + +# Figure out which version of Qt we are using +AC_MSG_CHECKING([Qt version]) +QT_VER=`grep 'define.*QT_VERSION_STR\W' $QT_INCLUDES/qglobal.h | perl -p -e 's/\D//g'` +case "${QT_VER}" in + 2*) + AC_MSG_ERROR([*** Qt 2 is not supported by iTALC. Please upgrade to Qt3!]) + ;; + 3*) + QT_MAJOR="3" + ;; + 4*) + QT_MAJOR="4" + ;; + *) + AC_MSG_ERROR([*** Don't know how to handle this Qt major version]) + ;; +esac +AC_MSG_RESULT([$QT_VER ($QT_MAJOR)]) + +# Check that moc is in path +AC_CHECK_PROG(MOC, moc, $QTDIR/bin/moc,,$QTDIR/bin/) +if test x$MOC = x ; then + AC_CHECK_PROG(MOC, moc-qt3, $QTDIR/bin/moc-qt3,,$QTDIR/bin/) + if test x$MOC = x ; then + AC_MSG_ERROR([*** not found! Make sure you have Qt-devel-tools installed!]) + fi +fi + +# uic is the Qt user interface compiler +AC_CHECK_PROG(UIC, uic, $QTDIR/bin/uic,,$QTDIR/bin/) +if test x$UIC = x ; then + AC_MSG_WARN([*** not found! It's currently not needed but should be part of a proper Qt-devel-tools-installation!]) +fi + +# qembed is the Qt data embedding utility. +#AC_CHECK_PROG(QEMBED, qembed, $QTDIR/bin/qembed,,$QTDIR/bin/) +#if test x$QEMBED = x ; then +# AC_MSG_ERROR([*** not found! Make sure you have Qt-devel-tools/Qt-extensions installed! On some distributions (e.g. SuSE) the package, containing qembed is also called qt3-extensions.]) +#fi + +# lupdate is the Qt translation-update utility. +AC_CHECK_PROG(LUPDATE, lupdate, $QTDIR/bin/lupdate,,$QTDIR/bin/) +if test x$LUPDATE = x ; then + AC_MSG_WARN([*** not found! It's not needed just for compiling but should be part of a proper Qt-devel-tools-installation!]) +fi + +# lrelease is the Qt translation-release utility. +AC_CHECK_PROG(LRELEASE, lrelease, $QTDIR/bin/lrelease,,$QTDIR/bin/) +if test x$LRELEASE = x ; then + AC_MSG_WARN([*** not found! It's not needed just for compiling but should be part of a proper Qt-devel-tools-installation!]) +fi + +# Calculate Qt include path +QT_CXXFLAGS="-I$QT_INCLUDES" +if test "$QT_MAJOR" = "4" ; then + QT_CXXFLAGS="$QT_CXXFLAGS -I$QTDIR/include" +fi + + +QT_IS_EMBEDDED="no" +# On unix, figure out if we're doing a static or dynamic link +case "${host}" in + *-cygwin) + AC_DEFINE_UNQUOTED(WIN32, "", Defined if on Win32 platform) + if test -f "$QTDIR/lib/qt.lib" ; then + QT_LIB="qt.lib" + QT_IS_STATIC="yes" + QT_IS_MT="no" + elif test -f "$QTDIR/lib/qt-mt.lib" ; then + QT_LIB="qt-mt.lib" + QT_IS_STATIC="yes" + QT_IS_MT="yes" + elif test -f "$QTDIR/lib/qt$QT_VER.lib" ; then + QT_LIB="qt$QT_VER.lib" + QT_IS_STATIC="no" + QT_IS_MT="no" + elif test -f "$QTDIR/lib/qt-mt$QT_VER.lib" ; then + QT_LIB="qt-mt$QT_VER.lib" + QT_IS_STATIC="no" + QT_IS_MT="yes" + fi + ;; + + *) + QT_IS_STATIC=`ls $QTDIR/lib/*.a 2> /dev/null` + if test "x$QT_IS_STATIC" = x; then + QT_IS_STATIC="no" + else + QT_IS_STATIC="yes" + fi + if test x$QT_IS_STATIC = xno ; then + QT_IS_DYNAMIC=`ls $QTDIR/lib/*.so 2> /dev/null` + if test "x$QT_IS_DYNAMIC" = x; then + AC_MSG_ERROR([*** Couldn't find any Qt libraries]) + fi + fi + if test "$QT_MAJOR" = "4" ; then + QT_IS_MT="yes" + QT_LIB="-lQtCore -lQtGui -lQtXml -lQt3Support" + else + if test "x`ls $QTDIR/lib/libqt-mt.* 2> /dev/null`" != x ; then + QT_LIB="-lqt-mt" + QT_IS_MT="yes" + elif test "x`ls $QTDIR/lib/libqt.* 2> /dev/null`" != x ; then + QT_LIB="-lqt" + QT_IS_MT="no" + elif test "x`ls $QTDIR/lib/libqte.* 2> /dev/null`" != x ; then + QT_LIB="-lqte" + QT_IS_MT="no" + QT_IS_EMBEDDED="yes" + elif test "x`ls $QTDIR/lib/libqte-mt.* 2> /dev/null`" != x ; then + QT_LIB="-lqte-mt" + QT_IS_MT="yes" + QT_IS_EMBEDDED="yes" + fi + fi + ;; +esac +AC_MSG_CHECKING([if Qt is static]) +AC_MSG_RESULT([$QT_IS_STATIC]) +AC_MSG_CHECKING([if Qt is multithreaded]) +if test "$QT_IS_MT" = "no"; then + AC_MSG_ERROR([*** your Qt is not multithreaded. That's bad, because multithreading is required for compiling... Please install Qt-mt!]) +fi +AC_MSG_RESULT([$QT_IS_MT]) +AC_MSG_CHECKING([if Qt is embedded]) +AC_MSG_RESULT([$QT_IS_EMBEDDED]) + +QT_GUILINK="" +QASSISTANTCLIENT_LDADD="-lqassistantclient" +QT_LIBS="$QT_LIB" + +case "${host}" in + *irix*) + QT_LIBS="$QT_LIB" + if test $QT_IS_STATIC = yes ; then + QT_LIBS="$QT_LIBS -L$x_libraries -lXext -lX11 -lm -lSM -lICE" + fi + ;; + + *linux*) + QT_LIBS="$QT_LIB" + if test $QT_IS_STATIC = yes && test $QT_IS_EMBEDDED = no; then + QT_LIBS="$QT_LIBS -L$x_libraries -lXext -lX11 -lm -lSM -lICE -ldl -ljpeg" + fi + ;; + + + *osf*) + # Digital Unix (aka DGUX aka Tru64) + QT_LIBS="$QT_LIB" + if test $QT_IS_STATIC = yes ; then + QT_LIBS="$QT_LIBS -L$x_libraries -lXext -lX11 -lm -lSM -lICE" + fi + ;; + + *solaris*) + QT_LIBS="$QT_LIB" + if test $QT_IS_STATIC = yes ; then + QT_LIBS="$QT_LIBS -L$x_libraries -lXext -lX11 -lm -lSM -lICE -lresolv -lsocket -lnsl" + fi + ;; + + + *win*) + # linker flag to suppress console when linking a GUI app on Win32 + QT_GUILINK="/subsystem:windows" + + if test $QT_MAJOR = "3" ; then + if test $QT_IS_MT = yes ; then + QT_LIBS="/nodefaultlib:libcmt" + else + QT_LIBS="/nodefaultlib:libc" + fi + fi + + if test $QT_IS_STATIC = yes ; then + QT_LIBS="$QT_LIBS $QT_LIB kernel32.lib user32.lib gdi32.lib comdlg32.lib ole32.lib shell32.lib imm32.lib advapi32.lib wsock32.lib winspool.lib winmm.lib netapi32.lib" + if test $QT_MAJOR = "3" ; then + QT_LIBS="$QT_LIBS qtmain.lib" + fi + else + QT_LIBS="$QT_LIBS $QT_LIB" + if test $QT_MAJOR = "3" ; then + QT_CXXFLAGS="$QT_CXXFLAGS -DQT_DLL" + QT_LIBS="$QT_LIBS qtmain.lib qui.lib user32.lib netapi32.lib" + fi + fi + QASSISTANTCLIENT_LDADD="qassistantclient.lib" + ;; + +esac + + +if test x"$QT_IS_EMBEDDED" = "xyes" ; then + QT_CXXFLAGS="-DQWS $QT_CXXFLAGS" +fi + +if test x"$QT_IS_MT" = "xyes" ; then + QT_CXXFLAGS="$QT_CXXFLAGS -D_REENTRANT -DQT_THREAD_SUPPORT" + QT_LIBS="$QT_LIBS -lpthread" +fi + +QT_LDADD="-L$QTDIR/lib $QT_LIBS" + +#if test x$QT_IS_STATIC = xyes ; then +# OLDLIBS="$LIBS" +# LIBS="$QT_LDADD" +# AC_CHECK_LIB(Xft, XftFontOpen, QT_LDADD="$QT_LDADD -lXft") +# LIBS="$LIBS" +#fi + +AC_MSG_CHECKING([QT_CXXFLAGS]) +AC_MSG_RESULT([$QT_CXXFLAGS]) +AC_MSG_CHECKING([QT_LDADD]) +AC_MSG_RESULT([$QT_LDADD]) + +AC_SUBST(QT_CXXFLAGS) +AC_SUBST(QT_LDADD) +AC_SUBST(QT_GUILINK) +AC_SUBST(QASSISTANTCLIENT_LDADD) + +]) diff --git a/buildtools/bin2res.cpp b/buildtools/bin2res.cpp new file mode 100644 index 00000000000..9680c699cc8 --- /dev/null +++ b/buildtools/bin2res.cpp @@ -0,0 +1,210 @@ +/* + * bin2res.cpp - generate embedded resources from binary data (based on qembed) + * + * Copyright (c) 2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include +#include +#include +#include + +static void embedData( const char * _input, int _size, std::ostream & _output ); +static std::string convertFileNameToCIdentifier( const std::string & _s ); + + +struct embed +{ + unsigned int size; + std::string name; + std::string cname; +} ; + +typedef std::vector stringlist; + +const int MAX_FILE_SIZE = 256*256*256; // = 16 MB + + +int main( int argc, char * * argv ) +{ + if( argc < 2 ) + { + std::cerr << "Usage:" << std::endl << "\t" << argv[0] << + " files" << std::endl; + return( 1 ); + } + + std::cout << "// Generated by bin2res" << std::endl; + + std::vector embedded_data; + + std::cout << "#ifndef _EMBEDDED_RESOURCES_H" << std::endl; + std::cout << "#define _EMBEDDED_RESOURCES_H" << std::endl; + + stringlist files; + for( int i = 1; i < argc; ++i ) + { + files.push_back( argv[i] ); + } + for( stringlist::iterator it = files.begin(); it != files.end(); ++it ) + { + std::ifstream f( it->c_str() ); + if( f.fail() ) + { + std::cerr << "Cannot open file " << *it << + ", ignoring it" << std::endl; + continue; + } + f.seekg( 0, std::ios::end ); + int fsize = f.tellg(); + f.seekg( 0 ); + if( fsize == 0 || fsize > MAX_FILE_SIZE ) + { + std::cerr << "File " << *it << " has zero size or is " + "too large to be processed with bin2res." << + std::endl; + } + char * data = new char[fsize]; + f.read( data, fsize ); + embed * e = new embed; + e->size = fsize; + if( it->rfind( '/' ) != std::string::npos ) + { + e->name = std::string( it->c_str() + + it->rfind( '/' ) + 1 ); + } + else + { + e->name = *it; + } + e->cname = convertFileNameToCIdentifier( e->name ); + embedded_data.push_back( e ); + std::string s; + std::cout << "static const unsigned char " << e->cname << + "_data[] = {"; + embedData( data, fsize, std::cout ); + std::cout << std::endl << "};" << std::endl << std::endl; + delete[] data; + } + + if( embedded_data.size() > 0 ) + { + std::cout << "static const unsigned char dummy_data[] =" + "{ 0x00 };" << std::endl << std::endl; + embed * dummy = new embed; + dummy->size = 1; + dummy->name = "dummy"; + dummy->cname = convertFileNameToCIdentifier( "dummy" ); + embedded_data.push_back( dummy ); + + std::cout << "#include " << std::endl; + std::cout << "static struct embedDesc" << std::endl + << "{" << std::endl + << " int size;" << std::endl + << " const unsigned char * data;" << + std::endl + << " const char * name;" << std::endl + << "} embed_vec[] = {" << std::endl; + while( embedded_data.size() > 0 ) + { + embed * e = embedded_data[0]; + std::cout << " { " << e->size << ", " << e->cname << + "_data, " << "\"" << e->name << + "\" }," << std::endl; + delete e; + embedded_data.erase( embedded_data.begin() ); + } + std::cout << " { 0, 0, 0 }" << std::endl << "};" << std::endl + << std::endl + << "static const embedDesc & findEmbeddedData( " + "const char * _name )" << std::endl + << "{" << std::endl + << " for( int i = 0; embed_vec[i].data; " + "i++ )" << std::endl + << " {" << std::endl + << " if( strcmp( embed_vec[i].name, " + "_name ) == 0 )" << std::endl + << " {" << std::endl + << " return( " + "embed_vec[i] );" << std::endl + << " }" << std::endl + << " }" << std::endl +/* << " printf( \"warning: embedded resource " + "%s not found!\\n\", _name );" + << std::endl*/ + << " return( findEmbeddedData( " + "\"dummy\" ) );" << std::endl + << "}" << std::endl << std::endl; + } + std::cout << "#endif" << std::endl; + return( 0 ); +} + + + + +std::string convertFileNameToCIdentifier( const std::string & _s ) +{ + std::string r = _s; + int len = r.length(); + if ( len > 0 && !isalpha( (char)r[0] ) ) + { + r[0] = '_'; + } + for ( int i = 1; i < len; i++ ) + { + if ( !isalnum( (char)r[i] ) ) + { + r[i] = '_'; + } + } + return( r ); +} + + + + +void embedData( const char * _input, int _nbytes, std::ostream & _output ) +{ + static const char hexdigits[] = "0123456789abcdef"; + std::string s; + for( int i = 0; i < _nbytes; i++ ) + { + if( ( i%14 ) == 0 ) + { + s += "\n "; + _output << s; + s = ""; + } + unsigned int v = _input[i]; + s += "0x"; + s += hexdigits[(v >> 4) & 15]; + s += hexdigits[v & 15]; + if( i < _nbytes-1 ) + { + s += ','; + } + } + if ( s.length() ) + { + _output << s; + } +} + diff --git a/configure.in b/configure.in new file mode 100644 index 00000000000..2069236c885 --- /dev/null +++ b/configure.in @@ -0,0 +1,496 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.50) +AC_INIT(lmms, 0.1.1, tobydox@users.sourceforge.net) +#AC_INIT(acinclude.m4) +AM_INIT_AUTOMAKE(lmms, 0.1.1) + +AM_CONFIG_HEADER(config.h) + +# Checks for programs. +AC_PROG_CXX +AC_PROG_CC +AC_PROG_LN_S + + +AC_PATH_XTRA +gw_CHECK_QT + + +# checks for header files. +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS([fcntl.h memory.h string.h sys/ioctl.h unistd.h stdlib.h]) + +# checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_INLINE +AC_TYPE_SIZE_T +AC_HEADER_TIME +AC_STRUCT_TM +AC_C_VOLATILE +AC_C_BIGENDIAN + +# checks for library functions. +AC_FUNC_ALLOCA +AC_PROG_GCC_TRADITIONAL +AC_FUNC_MALLOC +AC_FUNC_MEMCMP +AC_TYPE_SIGNAL + +AC_CHECK_FUNCS([usleep]) + + +# search for include-path of SDL (just for supporting the FreeBSD-guys.... ;-) +for i in SDL SDL10 SDL11 SDL12 ; do + FOUND="" + AC_CHECK_HEADER($i/SDL.h, FOUND="true") + if test "$FOUND" = "true" ; then + SDL_INC_PATH="$i" + break + fi +done + + +AH_TEMPLATE(SDL_SDL_H, [Define to location of SDL.h]) +AH_TEMPLATE(SDL_SDL_AUDIO_H, [Define to location of SD_audio.h]) +AH_TEMPLATE(SDL_SDL_SOUND_H, [Define to location of SDL_sound.h]) + +OLD_LIBS="$LIBS" +LIBS="$LIBS -lpthread" + +# check for SDL-lib +AC_ARG_WITH(sdl, + AS_HELP_STRING([--without-sdl], + [disable support for SDL-audio-output]), , + [ with_sdlaudio=yes ]) +AH_TEMPLATE(HAVE_SDL_SDL_AUDIO_H, [Define to 1 if you have the $SDL_INC_PATH/SDL_audio.h header file.]) +if test "x$with_sdlaudio" = "xyes" -a ! -z "$SDL_INC_PATH"; then + AC_CHECK_HEADER($SDL_INC_PATH/SDL_audio.h, HAVE_SDL_SDL_AUDIO_H="true") + AC_CHECK_LIB([SDL], [SDL_OpenAudio], HAVE_LIBSDL="true", HAVE_SDL_SDL_AUDIO_H="") +fi +if test ! -z "$HAVE_SDL_SDL_AUDIO_H" ; then + AC_DEFINE_UNQUOTED(SDL_SDL_H, <$SDL_INC_PATH/SDL.h>) + AC_DEFINE_UNQUOTED(SDL_SDL_AUDIO_H, <$SDL_INC_PATH/SDL_audio.h>) + AC_DEFINE(HAVE_SDL_SDL_AUDIO_H) +fi +AM_CONDITIONAL(HAVE_LIBSDL, test ! -z "$HAVE_SDL_SDL_AUDIO_H") + + +# check for SDL_sound-lib +AC_ARG_WITH(sdlsound, + AS_HELP_STRING([--without-sdlsound], + [disable support for reading samples via SDL_sound]), , + [ with_sdlsound=yes ]) +AH_TEMPLATE(HAVE_SDL_SDL_SOUND_H, [Define to 1 if you have the $SDL_INCL_PATH/SDL_sound.h header file.]) +if test "x$with_sdlsound" = "xyes" -a ! -z "$SDL_INC_PATH"; then + AC_CHECK_HEADER($SDL_INC_PATH/SDL_sound.h, HAVE_SDL_SDL_SOUND_H="true") + AC_CHECK_LIB([SDL_sound], [Sound_Init], HAVE_LIBSDL_SOUND="true", HAVE_SDL_SDL_SOUND_H="") +fi +if test ! -z "$HAVE_SDL_SDL_SOUND_H" ; then + AC_DEFINE_UNQUOTED(SDL_SDL_SOUND_H, <$SDL_INC_PATH/SDL_sound.h>) + AC_DEFINE(HAVE_SDL_SDL_SOUND_H) +fi + +AM_CONDITIONAL(HAVE_LIBSDL_SOUND, test ! -z "$HAVE_LIBSDL_SOUND") + +LIBS="$OLD_LIBS" + + +# check for ALSA-lib +AC_ARG_WITH(asound, + AS_HELP_STRING([--without-asound], + [disable support for ALSA-sound-output]), , + [ with_asound=yes ]) +AH_TEMPLATE(HAVE_ALSA_ASOUNDLIB_H, [Define to 1 if you have the alsa/asoundlib.h header file.]) +if test "x$with_asound" = "xyes" ; then + AC_CHECK_HEADER(alsa/asoundlib.h, HAVE_ALSA_ASOUNDLIB_H="true") + AC_CHECK_LIB([asound], [snd_pcm_open], HAVE_LIBASOUND="true", HAVE_ALSA_ASOUNDLIB_H="") +fi +if test ! -z "$HAVE_ALSA_ASOUNDLIB_H" ; then + AC_DEFINE(HAVE_ALSA_ASOUNDLIB_H) +fi +AM_CONDITIONAL(HAVE_LIBASOUND, test ! -z "$HAVE_ALSA_ASOUNDLIB_H") + + +# check for JACK +AC_ARG_WITH(jack, + AS_HELP_STRING([--without-jack], + [disable support for JACK-transport]), , + [ with_jack=yes ]) +AH_TEMPLATE(HAVE_JACK_JACK_H, [Define to 1 if you have the jack/jack.h header file.]) +AH_TEMPLATE(OLD_JACK, [Define to 1 if your JACK-version doesnt know about jack_client_open() etc.]) +if test "x$with_jack" = "xyes" ; then + AC_CHECK_HEADER(jack/jack.h, HAVE_JACK_JACK_H="true") + AC_CHECK_LIB([jack], [jack_client_new], HAVE_LIBJACK="true", HAVE_JACK_JACK_H="") + AC_CHECK_LIB([jack], [jack_client_open], JACK_CLIENT_OPEN="true") + if test -z "$JACK_CLIENT_OPEN" ; then + AC_DEFINE(OLD_JACK) + fi +fi +if test ! -z "$HAVE_JACK_JACK_H" ; then + AC_DEFINE(HAVE_JACK_JACK_H) +fi +AM_CONDITIONAL(HAVE_LIBJACK, test ! -z "$HAVE_JACK_JACK_H") + + +# check for vorbis-lib +AC_ARG_WITH(vorbis, + AS_HELP_STRING([--without-vorbis], + [disable support for exporting song to OGG-files]), , + [ with_vorbis=yes ]) +AH_TEMPLATE(HAVE_VORBIS_CODEC_H, [Define to 1 if you have the vorbis/codec.h header file.]) +AH_TEMPLATE(HAVE_VORBIS_VORBISENC_H, [Define to 1 if you have the vorbis/vorbisenc.h header file.]) +AH_TEMPLATE(HAVE_VORBIS_VORBISFILE_H, [Define to 1 if you have the vorbis/vorbisfile.h header file.]) +if test "x$with_vorbis" = "xyes" ; then + OGG_SUPPORT="true" + AC_CHECK_HEADER(vorbis/codec.h, HAVE_VORBIS_CODEC_H="true",OGG_SUPPORT="") + AC_CHECK_HEADER(vorbis/vorbisenc.h, HAVE_VORBIS_VORBISENC_H="true",OGG_SUPPORT="") + AC_CHECK_HEADER(vorbis/vorbisfile.h, HAVE_VORBIS_VORBISFILE_H="true",OGG_SUPPORT="") + AC_CHECK_LIB([vorbis], [vorbis_analysis], HAVE_LIBVORBIS="true", OGG_SUPPORT="") +fi +if test ! -z "$OGG_SUPPORT" ; then + AC_DEFINE(HAVE_VORBIS_CODEC_H) + AC_DEFINE(HAVE_VORBIS_VORBISENC_H) + AC_DEFINE(HAVE_VORBIS_VORBISFILE_H) +fi +AM_CONDITIONAL(HAVE_LIBVORBIS, test ! -z "$OGG_SUPPORT") + + +# check for libsamplerate +AC_ARG_WITH(src, + AS_HELP_STRING([--without-libsrc], + [disable support for resampling via libsamplerate]), , + [ with_libsrc=yes ]) +AH_TEMPLATE(HAVE_SAMPLERATE_H, [Define to 1 if you have the samplerate.h header file.]) +if test "x$with_libsrc" = "xyes" ; then + AC_CHECK_HEADER(samplerate.h, HAVE_SAMPLERATE_H="true") + AC_CHECK_LIB([samplerate], [src_simple], HAVE_LIBSRC="true", HAVE_SAMPLERATE_H="") +fi +if test ! -z "$HAVE_SAMPLERATE_H" ; then + AC_DEFINE(HAVE_SAMPLERATE_H) +fi +AM_CONDITIONAL(HAVE_LIBSRC, test ! -z "$HAVE_SAMPLERATE_H") + + +# libsndfile-stuff +AC_ARG_WITH(src, + AS_HELP_STRING([--without-libsf], + [disable support for importing files via libsndfile]), , + [ with_libsf=yes ]) +AH_TEMPLATE(HAVE_SNDFILE_H, [Define to 1 if you have the sndfile.h header file.]) +if test "x$with_libsf" = "xyes" ; then + AC_CHECK_HEADER(sndfile.h, HAVE_SNDFILE_H="true") + AC_CHECK_LIB([sndfile], [sf_command], HAVE_LIBSF="true", HAVE_SNDFILE_H="") + AC_MSG_CHECKING([version of libsndfile]) + AH_TEMPLATE(OLD_SNDFILE, [Define to 1 if libsndfile < 1.0.11]) + OLD_LIBS="$LIBS" + LIBS="$LIBS -lsndfile" + AC_RUN_IFELSE([ #include + int main( void ) + { + SF_INFO si; + ( void )sf_open( "", SFM_READ, &si ); + return 0; + }], + AC_MSG_RESULT([>= 1.0.11]), + AC_MSG_RESULT([< 1.0.11]) + AC_DEFINE(OLD_SNDFILE) + ) + LIBS="$OLD_LIBS" +fi +if test ! -z "$HAVE_SNDFILE_H" ; then + AC_DEFINE(HAVE_SNDFILE_H) +fi +AM_CONDITIONAL(HAVE_LIBSF, test ! -z "$HAVE_SNDFILE_H") + +AC_ARG_WITH(nosmpdecs, + AS_HELP_STRING([--without-sample-decoders], + [force compiling LMMS even if libraries for sample-decoding were found]), + [ with_smpdecs=yes ]) + +if test -z "$HAVE_SND_FILE" -a -z "$HAVE_SDL_SDL_SOUND_H" -a -z "$OGG_SUPPORT" -a ! -z "$with_smpdecs"; then + AC_MSG_ERROR([*** neither libsndfile nor SDL_sound nor libvorbis (or according devel-files) were found which would make LMMS unable to load any samples, so please install at least one of the packages and try again! Use --without-sample-decoders to force compiling LMMS.]) +fi + + + +# check whether to disable surround-support +AC_MSG_CHECKING([whether to disable surround-support]) +AH_TEMPLATE(DISABLE_SURROUND, [Define if you want to disable surround-support in LMMS.]) +AC_ARG_ENABLE([surround], + AS_HELP_STRING([--disable-surround], + [compile LMMS without surround-support]), + DISABLE_SURROUND="yes") +if test "x$DISABLE_SURROUND" = "xyes" ; then + AC_MSG_RESULT(yes) + AC_DEFINE(DISABLE_SURROUND) +else + AC_MSG_RESULT(no) +fi + + +# check whether to enable high-quality sinc-resampling +AC_MSG_CHECKING([whether to enable high quality sinc-resampling]) +AH_TEMPLATE(HQ_SINC, [Define if you want to enable high quality sinc-resampling.]) +AC_ARG_ENABLE([hqsinc], + AS_HELP_STRING([--enable-hqsinc], + [enable high quality sinc-resampling]), HQ_SINC="yes") +if test "x$HQ_SINC" = "xyes" ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HQ_SINC) +else + AC_MSG_RESULT(no) +fi + + +# check whether compiler of current platform supports attribute regparm(x) +AC_MSG_CHECKING([whether we can use function-attribute regparm(x) on current platform]) +AH_TEMPLATE(FASTCALL, [Define to any attribute, speeding up function-calls]) +AC_RUN_IFELSE([ int __attribute__((regparm(3))) foo( int a, int b, int c ) + { return( a=b=c ); } + int __attribute__((regparm(3))) main( void ) + { return( foo(2,1,0) ); }], + AC_MSG_RESULT(yes) + AC_DEFINE(FASTCALL, [__attribute__((regparm(3)))]), + AC_MSG_RESULT(no) + AC_DEFINE_UNQUOTED(FASTCALL,[]) + ) + + +AC_MSG_CHECKING([whether floorf is known by compiler]) +AH_TEMPLATE(floorf, [Define to floor if floorf is not known]) +AC_TRY_LINK([#include ], [ floorf ], + AC_MSG_RESULT(yes), + AC_MSG_RESULT([no - will use floor instead]) + AC_DEFINE(floorf, floor) + ) + +AC_MSG_CHECKING([whether powf is known by compiler]) +AH_TEMPLATE(powf, [Define to pow if powf is not known]) +AC_TRY_LINK([#include ], [ powf ], + AC_MSG_RESULT(yes), + AC_MSG_RESULT([no - will use pow instead]) + AC_DEFINE(powf, pow) + ) + +AC_MSG_CHECKING([whether fabsf is known by compiler]) +AH_TEMPLATE(fabsf, [Define to pow if fabsf is not known]) +AC_TRY_LINK([#include ], [ fabsf ], + AC_MSG_RESULT(yes), + AC_MSG_RESULT([no - will use fabs instead]) + AC_DEFINE(fabsf, fabs) + ) + + +# check whether to enable debugging-code +AC_MSG_CHECKING([whether to enable debugging-code]) +AH_TEMPLATE(LMMS_DEBUG, [Define if you want to disable debbuging-code in LMMS.]) +AC_ARG_ENABLE([debug], + AS_HELP_STRING([--enable-debug], + [compile LMMS with additional debugging support]), DEBUG="yes") +if test "x$DEBUG" = "xyes" ; then + AC_MSG_RESULT(yes) + AC_DEFINE(LMMS_DEBUG) +else + AC_MSG_RESULT(no) +fi + + +# check for rpm SOURCES path +echo -n "checking for rpm sources path... " +RPMSOURCEDIR="NOT-FOUND" +for directory in packages OpenLinux redhat RedHat rpm RPM "" ; do + if test -d /usr/src/${directory}/SOURCES ; then + RPMSOURCEDIR="/usr/src/${directory}/SOURCES/" + fi +done +echo "$RPMSOURCEDIR" +AM_CONDITIONAL(HAVE_RPM, test "$RPMSOURCEDIR" != "NOT-FOUND") +AC_SUBST(RPMSOURCEDIR) + +lmmsdatadir="$datadir/$PACKAGE" +AC_SUBST(lmmsdatadir) + + +CXXFLAGS="$CXXFLAGS -g0" +if test $CXX == "g++" ; then + CXXFLAGS="$CXXFLAGS -ansi -Wall -fno-exceptions" +fi + + +AC_CONFIG_FILES([Makefile + artwork/Makefile + locale/Makefile + midi-maps/Makefile + presets/Makefile + presets/AudioFileProcessor/Makefile + presets/MIDI-Out/Makefile + presets/PluckedStringSynth/Makefile + presets/TripleOscillator/Makefile + projects/Makefile + projects/cool_songs/Makefile + projects/covers/Makefile + projects/demos/Makefile + projects/misc/Makefile + projects/recorded_loops/Makefile + projects/templates/Makefile + projects/tutorials/Makefile + samples/Makefile + samples/basses/Makefile + samples/bassloopes/Makefile + samples/beats/Makefile + samples/drums/Makefile + samples/effects/Makefile + samples/instruments/Makefile + samples/latin/Makefile + samples/misc/Makefile + samples/shapes/Makefile + samples/stringsnpads/Makefile + lmms.spec]) +AC_OUTPUT + +with_warnings="false" + +echo +echo + + +if test -z "$OGG_SUPPORT" ; then + echo " ========================" + echo " === LMMS - WARNING =======================================================" + echo " ========================" + echo " =" + echo " = You don't seem to have libvorbis installed and/or libvorbis-development-" + echo " = package is missing. This will disable support for exporting songs to" + echo " = OGG-files! If also SDL_sound is missing, you'll not be able to use the " + echo " = samples coming with LMMS since libsndfile currently has no OGG-support!" + echo " = Consider installing the missing packages for using the full power of LMMS." + echo " =" + with_warnings="true" +fi + + + +if test -z "$HAVE_ALSA_ASOUNDLIB_H" ; then + echo " ========================" + echo " === LMMS - WARNING =======================================================" + echo " ========================" + echo " =" + echo " = You don't seem to have ALSA-library installed and/or ALSA-lib-development-" + echo " = package is missing. This will disable support for sound-output via ALSA!" + echo " = If you use ALSA-driver for your soundcard there will be no sound-output!" + echo " = Consider installing the missing packages for using the full power of LMMS." + echo " =" + with_warnings="true" +fi + + + +if test -z "$HAVE_JACK_JACK_H" ; then + echo " ========================" + echo " === LMMS - WARNING =======================================================" + echo " ========================" + echo " =" + echo " = You don't seem to have JACK-library installed and/or JACK-lib-development-" + echo " = package is missing. This will disable support for JACK-transport." + echo " = This is no problem but you'll miss the great possibilities of interacting" + echo " = with other sound-applications in realtime!" + echo " = Consider installing the missing packages for using the full power of LMMS." + echo " =" + with_warnings="true" +fi + + + +if test -z "$HAVE_SDL_SDL_AUDIO_H" ; then + echo " ========================" + echo " === LMMS - WARNING =======================================================" + echo " ========================" + echo " =" + echo " = You don't seem to have SDL-library installed and/or SDL-lib-development-" + echo " = package is missing. This will disable support for sound-output via SDL, " + echo " = which is important, if you're using sound-daemons (arts, ESD, JACK etc.)" + echo " = When compiling without SDL, you'll always have to kill your sound-daemon" + echo " = before using LMMS...!" + echo " = Consider installing the missing packages for using the full power of LMMS." + echo " =" + with_warnings="true" +fi + + + + +if test -z "$HAVE_SDL_SDL_SOUND_H" ; then + echo " ========================" + echo " === LMMS - WARNING =======================================================" + echo " ========================" + echo " =" + echo " = You don't seem to have SDL_sound-library installed and/or SDL_sound-" + echo " = development-package is missing. This means that you can only load samples" + echo " = within LMMS if you have libsndfile and libvorbis installed!" + echo " = Consider installing the missing packages for using the full power of LMMS." + echo " =" + with_warnings="true" +fi + + + + +if test -z "$HAVE_SNDFILE_H" ; then + echo " ========================" + echo " === LMMS - WARNING =======================================================" + echo " ========================" + echo " =" + echo " = You don't seem to have libsndfile installed and/or libsndfile-development-" + echo " = package is missing. This is not that fatal as long as you have SDL_sound" + echo " = installed. Otherwise it's strongly recommended to install libsndfile and" + echo " = libvorbis for being able to use samples within LMMS." + echo " = Consider installing the missing packages for using the full power of LMMS." + echo " =" + with_warnings="true" +fi + + + + +if test -z "$HAVE_SAMPLERATE_H" ; then + echo " ========================" + echo " === LMMS - WARNING =======================================================" + echo " ========================" + echo " =" + echo " = You don't seem to have libsamplerate installed and/or libsamplerate-" + echo " = development-package is missing. This will disable resampling with" + echo " = libsamplerate and results in worse quality! Currently LMMS will also" + echo " = crash more often, because internal sample-rate-converter has some bugs..." + echo " = Consider installing the missing packages for using the full power of LMMS." + echo " =" + with_warnings="true" +fi + + + + +echo +echo +echo " ============================" +echo " === LMMS - INFORMATION ===================================================" +echo " ============================" +echo " =" +if test "$with_warnings" = "false" ; then + echo " = LMMS has been configured successfully. Now you can build it by typing 'make'." + echo " = After the compilation-process has finished, you can install LMMS by" + echo " = typing 'make install'." +else + echo " = LMMS has been configured, but there were one or more warnings you should" + echo " = not ignore. First try to solve the mentioned problems before" + echo " = proceeding. Otherwise don't complain, if LMMS doesn't run the way" + echo " = you might expect..." +fi +echo " =" +echo " = If there're problems while compiling LMMS, please send a mail to " +echo " = tobydox@users.sourceforge.net!" +echo " =" +echo + diff --git a/include/about_dialog.h b/include/about_dialog.h new file mode 100644 index 00000000000..5a9051d0756 --- /dev/null +++ b/include/about_dialog.h @@ -0,0 +1,69 @@ +/* + * about_dialog.h - declaration of class aboutDialog + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _ABOUT_DIALOG_H +#define _ABOUT_DIALOG_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +class QPushButton; +class QLabel; +class QTabWidget; + + +class aboutDialog : public QDialog +{ + Q_OBJECT +public: + aboutDialog( void ); + ~aboutDialog(); + + +protected: + void keyPressEvent( QKeyEvent * _ke ); + void resizeEvent( QResizeEvent * _re ); + + +private: + QPushButton * m_okBtn; + QLabel * m_iconLbl; + QLabel * m_appNameLbl; + QTabWidget * m_aboutTabs; + +} ; + + +#endif + diff --git a/include/arp_and_chords_tab_widget.h b/include/arp_and_chords_tab_widget.h new file mode 100644 index 00000000000..a431e07373b --- /dev/null +++ b/include/arp_and_chords_tab_widget.h @@ -0,0 +1,138 @@ +/* + * arp_and_chords_tab_widget.h - declaration of class arpAndChordWidget which + * provides code for using arpeggio and chords + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _ARP_AND_CHORDS_TAB_WIDGET_H +#define _ARP_AND_CHORDS_TAB_WIDGET_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "settings.h" +#include "types.h" + + +class channelTrack; +class groupBox; +class knob; +class pixmapButton; +class QComboBox; +class QPixmap; +class notePlayHandle; + + +const int MAX_CHORD_POLYPHONY = 10; + + +class arpAndChordsTabWidget : public QWidget, public settings +{ + Q_OBJECT +public: + arpAndChordsTabWidget( channelTrack * _channel_track, + QWidget * _parent ); + ~arpAndChordsTabWidget(); + + static struct chord + { + const QString name; + Sint8 interval[MAX_CHORD_POLYPHONY]; + } s_chords[]; + + void FASTCALL processNote( notePlayHandle * _n ); + static inline int getChordSize( chord & _c ) + { + int idx = 0; + while( _c.interval[idx] != -1 ) + { + ++idx; + } + return( idx ); + } + + + virtual void FASTCALL saveSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void FASTCALL loadSettings( const QDomElement & _this ); + inline virtual QString nodeName( void ) const + { + return( "arpandchords" ); + } + + + +protected slots: +// void arpOffToggled( bool ); + void arpUpToggled( bool ); + void arpDownToggled( bool ); + void arpUpAndDownToggled( bool ); + void arpRandomToggled( bool ); + + +private: + + enum arpDirections + { + OFF, + UP, + DOWN, + UP_AND_DOWN, + RANDOM + } m_arpDirection; + + channelTrack * m_channelTrack; + + // chord-stuff + groupBox * m_chordsGroupBox; + QComboBox * m_chordsComboBox; + knob * m_chordRangeKnob; + + // arpeggio-stuff + groupBox * m_arpGroupBox; + QComboBox * m_arpComboBox; + knob * m_arpRangeKnob; + knob * m_arpTimeKnob; + knob * m_arpGateKnob; + QLabel * m_arpDirectionLbl; + //pixmapButton * m_arpOffBtn; + pixmapButton * m_arpUpBtn; + pixmapButton * m_arpDownBtn; + pixmapButton * m_arpUpAndDownBtn; + pixmapButton * m_arpRandomBtn; + +} ; + +#endif diff --git a/include/audio_alsa.h b/include/audio_alsa.h new file mode 100644 index 00000000000..80b5f927b59 --- /dev/null +++ b/include/audio_alsa.h @@ -0,0 +1,102 @@ +/* + * audio_alsa.h - device-class that implements ALSA-PCM-output + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _AUDIO_ALSA_H +#define _AUDIO_ALSA_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_ALSA_ASOUNDLIB_H + +#ifndef ALSA_SUPPORT +#define ALSA_SUPPORT +#endif + +#include + +#include "audio_device.h" + + +class lcdSpinBox; +class QLineEdit; + + +class audioALSA : public audioDevice +{ +public: + audioALSA( Uint32 _sample_rate, bool & _success_ful ); + ~audioALSA(); + + inline static QString name( void ) + { + return( setupWidget::tr( "ALSA (Advanced Linux Sound " + "Architecture)" ) ); + } + + static QString probeDevice( void ); + + + class setupWidget : public audioDevice::setupWidget + { + public: + setupWidget( QWidget * _parent ); + virtual ~setupWidget(); + + virtual void saveSettings( void ); + + private: + QLineEdit * m_device; + lcdSpinBox * m_channels; + + } ; + + +private: + virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab, + Uint32 _frames, + float _master_output ); + + int FASTCALL setHWParams( Uint32 _sample_rate, Uint32 _channels, + snd_pcm_access_t _access ); + int setSWParams( void ); + int FASTCALL handleError( int _err ); + + + snd_pcm_t * m_handle; + + snd_pcm_uframes_t m_bufferSize; + snd_pcm_uframes_t m_periodSize; + + snd_pcm_hw_params_t * m_hwParams; + snd_pcm_sw_params_t * m_swParams; + + bool m_littleEndian; + +} ; + +#endif + +#endif diff --git a/include/audio_device.h b/include/audio_device.h new file mode 100644 index 00000000000..28f612e0799 --- /dev/null +++ b/include/audio_device.h @@ -0,0 +1,143 @@ +/* + * audio_device.h - base-class for audio-devices, used by LMMS-mixer + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _AUDIO_DEVICE_H +#define _AUDIO_DEVICE_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SAMPLERATE_H +#include +#endif + + +#include "mixer.h" +#include "tab_widget.h" + + +class audioDevice +{ +public: + audioDevice( Uint32 _sample_rate, Uint8 _channels ); + virtual ~audioDevice(); + + inline void lock( void ) + { + m_devMutex.lock(); + } + + inline void unlock( void ) + { + m_devMutex.unlock(); + } + + void FASTCALL writeBuffer( surroundSampleFrame * _ab, Uint32 _frames, + Uint32 _src_sample_rate, + float _master_output ); + + inline Uint32 sampleRate( void ) const + { + return( m_sampleRate ); + } + + Uint8 channels( void ) const + { + return( m_channels ); + } + + + + class setupWidget : public tabWidget + { + public: + setupWidget( const QString & _caption, QWidget * _parent ) : + tabWidget( tabWidget::tr( "Settings for %1" ).arg( + _caption ), _parent ) + { + } + + virtual ~setupWidget() + { + } + + virtual void saveSettings( void ) = 0; + + } ; + + + +protected: + virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab, + Uint32 _frames, + float _master_output ) = 0; + + // convert a given audio-buffer to a buffer in signed 16-bit samples + // returns num of bytes in outbuf + int FASTCALL convertToS16( surroundSampleFrame * _ab, Uint32 _frames, + float _master_output, + outputSampleType * _output_buffer, + bool _convert_endian = FALSE ); + + // clear given signed-int-16-buffer + void FASTCALL clearS16Buffer( outputSampleType * _outbuf, + Uint32 _frames ); + + // resample given buffer from samplerate _src_src to samplerate _dst_src + void FASTCALL resample( surroundSampleFrame * _src, Uint32 _frames, + surroundSampleFrame * _dst, + Uint32 _src_sr, Uint32 _dst_sr ); + inline void setSampleRate( Uint32 _new_sr ) + { + m_sampleRate = _new_sr; + } + + +private: + Uint32 m_sampleRate; + Uint8 m_channels; + QMutex m_devMutex; + +#ifdef HAVE_SAMPLERATE_H + SRC_DATA m_srcData; + SRC_STATE * m_srcState; +#endif + +} ; + + +#endif diff --git a/include/audio_dummy.h b/include/audio_dummy.h new file mode 100644 index 00000000000..0b7ff86f593 --- /dev/null +++ b/include/audio_dummy.h @@ -0,0 +1,80 @@ +/* + * audio_dummy.h - dummy-audio-device + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _AUDIO_DUMMY_H +#define _AUDIO_DUMMY_H + +#include "audio_device.h" + + +class audioDummy : public audioDevice +{ +public: + audioDummy( Uint32 _sample_rate, bool & _success_ful ) : + audioDevice( _sample_rate, DEFAULT_CHANNELS ) + { + _success_ful = TRUE; + } + + virtual ~audioDummy() + { + } + + inline static QString name( void ) + { + return( setupWidget::tr( "Dummy (no sound output)" ) ); + } + + + class setupWidget : public audioDevice::setupWidget + { + public: + setupWidget( QWidget * _parent ) : + audioDevice::setupWidget( audioDummy::name(), _parent ) + { + } + + virtual ~setupWidget() + { + } + + virtual void saveSettings( void ) + { + } + + } ; + + +private: + virtual void FASTCALL writeBufferToDev( surroundSampleFrame *, + Uint32 /*_frames*/, float ) + { + //usleep( (Uint32)( _frames * 1000.0f * 1000.0f / + // DEFAULT_SAMPLE_RATE ) ); + } + +} ; + + +#endif diff --git a/include/audio_file_device.h b/include/audio_file_device.h new file mode 100644 index 00000000000..a958322509b --- /dev/null +++ b/include/audio_file_device.h @@ -0,0 +1,94 @@ +/* + * audio_file_device.h - base-class for audio-device-classes which write + * their output into a file + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _AUDIO_FILE_DEVICE_H +#define _AUDIO_FILE_DEVICE_H + + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +#include "audio_device.h" + + + +class audioFileDevice : public audioDevice +{ +public: + audioFileDevice( Uint32 _sample_rate, Uint8 _channels, + const QString & _file, bool _use_vbr, + Uint16 _nom_bitrate, Uint16 _min_bitrate, + Uint16 _max_bitrate ); + virtual ~audioFileDevice(); + + +protected: + int FASTCALL writeData( const void * _data, int _len ); + void seekToBegin( void ); + + inline bool useVBR( void ) const + { + return( m_useVbr ); + } + inline Uint16 nominalBitrate( void ) const + { + return( m_nomBitrate ); + } + inline Uint16 minBitrate( void ) const + { + return( m_minBitrate ); + } + inline Uint16 maxBitrate( void ) const + { + return( m_maxBitrate ); + } + inline bool outputFileOpened( void ) const + { + return( m_outputFile.isOpen() ); + } + + +private: + QFile m_outputFile; + + bool m_useVbr; + + Uint16 m_nomBitrate; + Uint16 m_minBitrate; + Uint16 m_maxBitrate; + +} ; + + +#endif diff --git a/include/audio_file_ogg.h b/include/audio_file_ogg.h new file mode 100644 index 00000000000..2a1ae256c2e --- /dev/null +++ b/include/audio_file_ogg.h @@ -0,0 +1,102 @@ +/* + * audio_file_ogg.h - Audio-device which encodes wave-stream and writes it + * into an OGG-file. This is used for song-export. + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _AUDIO_FILE_OGG_H +#define _AUDIO_FILE_OGG_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_VORBIS_CODEC_H + +#include + +#include "audio_file_device.h" + + + +class audioFileOgg : public audioFileDevice +{ +public: + audioFileOgg( Uint32 _sample_rate, Uint32 _channels, + bool & _success_ful, const QString & _file, + bool _use_vbr, Uint16 _nom_bitrate, + Uint16 _min_bitrate, Uint16 _max_bitrate ); + ~audioFileOgg(); + + static audioDevice * getInst( Uint32 _sample_rate, Uint32 _channels, + bool & _success_ful, + const QString & _file, + bool _use_vbr, + Uint16 _nom_bitrate, + Uint16 _min_bitrate, + Uint16 _max_bitrate ) + { + return( new audioFileOgg( _sample_rate, _channels, _success_ful, + _file, _use_vbr, _nom_bitrate, + _min_bitrate, _max_bitrate ) ); + } + + +private: + virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab, + Uint32 _frames, + float _master_output ); + + bool startEncoding( void ); + void finishEncoding( void ); + inline int writePage( void ); + + + + int m_channels; + long m_rate; + + // Various bitrate/quality options + int m_managed; + int m_bitrate; + int m_minBitrate; + int m_maxBitrate; + + unsigned int m_serialNo; + + vorbis_comment * m_comments; + + // encoding setup - init by init_ogg_encoding + ogg_stream_state m_os; + ogg_page m_og; + ogg_packet m_op; + + vorbis_dsp_state m_vd; + vorbis_block m_vb; + vorbis_info m_vi; + +} ; + + +#endif + +#endif diff --git a/include/audio_file_wave.h b/include/audio_file_wave.h new file mode 100644 index 00000000000..c8e95a033a7 --- /dev/null +++ b/include/audio_file_wave.h @@ -0,0 +1,90 @@ +/* + * audio_file_wave.h - Audio-device which encodes wave-stream and writes it + * into an WAVE-file. This is used for song-export. + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _AUDIO_FILE_WAVE_H +#define _AUDIO_FILE_WAVE_H + + +#include "audio_file_device.h" + + + +class audioFileWave : public audioFileDevice +{ +public: + audioFileWave( Uint32 _sample_rate, Uint32 _channels, + bool & _success_ful, const QString & _file, + bool _use_vbr, Uint16 _nom_bitrate, + Uint16 _min_bitrate, Uint16 _max_bitrate ); + virtual ~audioFileWave(); + + static audioDevice * getInst( Uint32 _sample_rate, Uint32 _channels, + bool & _success_ful, + const QString & _file, bool _use_vbr, + Uint16 _nom_bitrate, + Uint16 _min_bitrate, + Uint16 _max_bitrate ) + { + return( new audioFileWave( _sample_rate, _channels, + _success_ful, _file, _use_vbr, + _nom_bitrate, _min_bitrate, + _max_bitrate ) ); + } + + +private: + virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab, + Uint32 _frames, + float _master_output ); + + bool startEncoding( void ); + void finishEncoding( void ); + + + int m_bytesWritten; + + struct waveFileHeader + { + char riff_id[4]; // "RIFF" + Uint32 total_bytes; // total filesize-8 + char wave_fmt_str[8]; // "WAVEfmt" + Uint32 bitrate_1; // bitrate, e.g. 16 + Uint16 uncompressed; // 1 if PCM + Uint16 channels; // 1 = mono 2 = stereo + Uint32 sample_rate; // sample-rate e.g. 44100 + Uint32 bytes_per_second; // sample-rate*channels* + // (bitrate/8) + Uint16 block_alignment; // channels*(bitrate/8) + Uint16 bitrate_2; // bitrate, e.g. 16 + char data_chunk_id[4]; // "data" + Uint32 data_bytes; // total size of sample-data + } m_waveFileHeader; + + //outputSampleType * m_outputBuffer; + +} ; + + +#endif diff --git a/include/audio_jack.h b/include/audio_jack.h new file mode 100644 index 00000000000..df7eaa9431c --- /dev/null +++ b/include/audio_jack.h @@ -0,0 +1,122 @@ +/* + * audio_jack.h - support for JACK-transport + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _AUDIO_JACK_H +#define _AUDIO_JACK_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_JACK_JACK_H + +#define JACK_SUPPORT + +#include + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include +#include + +#endif + + +#include "audio_device.h" +#include "tab_widget.h" + + +class QLineEdit; +class lcdSpinBox; + + +class audioJACK : public audioDevice +{ +public: + audioJACK( Uint32 _sample_rate, bool & _success_ful ); + ~audioJACK(); + + inline static QString name( void ) + { + return( setupWidget::tr( "JACK (Jack Audio Connection Kit)" ) ); + } + + + class setupWidget : public audioDevice::setupWidget + { + public: + setupWidget( QWidget * _parent ); + virtual ~setupWidget(); + + virtual void saveSettings( void ); + + private: + QLineEdit * m_clientName; + lcdSpinBox * m_channels; + + } ; + + +private: + virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab, + Uint32 _frames, + float _master_output ); + + void clearBuffer( void ); + + static int processCallback( jack_nframes_t _nframes, void * _udata ); + static int bufSizeCallback( jack_nframes_t _nframes, void * _udata ); + + + jack_client_t * m_client; + vvector m_outputPorts; + struct bufset + { + sampleType * buf; + Uint32 frames; + } ; + + vlist > m_bufferSets; + Uint32 m_framesDoneInCurBuf; + volatile Uint32 m_frameSync; + + Uint32 m_jackBufSize; + + QMutex m_bufMutex; + +} ; + +#endif + +#endif diff --git a/include/audio_oss.h b/include/audio_oss.h new file mode 100644 index 00000000000..f15a3bde108 --- /dev/null +++ b/include/audio_oss.h @@ -0,0 +1,79 @@ +/* + * audio_oss.h - device-class that implements OSS-PCM-output + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _AUDIO_OSS_H +#define _AUDIO_OSS_H + +#include "audio_device.h" +#include "tab_widget.h" + +#define OSS_SUPPORT + + +class lcdSpinBox; +class QLineEdit; + + +class audioOSS : public audioDevice +{ +public: + audioOSS( Uint32 _sample_rate, bool & _success_ful ); + ~audioOSS(); + + inline static QString name( void ) + { + return( setupWidget::tr( "OSS (Open Sound System)" ) ); + } + + static QString probeDevice( void ); + + + class setupWidget : public audioDevice::setupWidget + { + public: + setupWidget( QWidget * _parent ); + virtual ~setupWidget(); + + virtual void saveSettings( void ); + + private: + QLineEdit * m_device; + lcdSpinBox * m_channels; + + } ; + + +private: + virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab, + Uint32 _frames, + float _master_output ); + + int m_audioFD; + + bool m_convertEndian; + +} ; + + +#endif diff --git a/include/audio_sample_recorder.h b/include/audio_sample_recorder.h new file mode 100644 index 00000000000..8bbfc47d0aa --- /dev/null +++ b/include/audio_sample_recorder.h @@ -0,0 +1,74 @@ +/* + * audio_sample_recorder.h - device-class that implements recording + * surround-audio-buffers into RAM, maybe later + * also harddisk + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _AUDIO_SAMPLE_RECORDER_H +#define _AUDIO_SAMPLE_RECORDER_H + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + + +#include "audio_device.h" + + +class sampleBuffer; + + +class audioSampleRecorder : public audioDevice +{ +public: + audioSampleRecorder( Uint32 _sample_rate, Uint32 _channels, + bool & _success_ful ); + ~audioSampleRecorder(); + + Uint32 framesRecorded( void ) const; + void FASTCALL createSampleBuffer( sampleBuffer * * _sample_buf ) const; + + +private: + virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab, + Uint32 _frames, + float _master_output ); + + typedef vvector > bufferVector; + bufferVector m_buffers; + +} ; + + +#endif diff --git a/include/audio_sdl.h b/include/audio_sdl.h new file mode 100644 index 00000000000..1f86702524a --- /dev/null +++ b/include/audio_sdl.h @@ -0,0 +1,110 @@ +/* + * audio_sdl.h - device-class that performs PCM-output via SDL + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _AUDIO_SDL_H +#define _AUDIO_SDL_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SDL_SDL_AUDIO_H + +#ifndef SDL_AUDIO_SUPPORT +#define SDL_AUDIO_SUPPORT +#endif + + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + +#include SDL_SDL_H +#include SDL_SDL_AUDIO_H + + +#include "audio_device.h" +#include "tab_widget.h" + + +class QLineEdit; + + +class audioSDL : public audioDevice +{ +public: + audioSDL( Uint32 _sample_rate, bool & _success_ful ); + ~audioSDL(); + + inline static QString name( void ) + { + return( setupWidget::tr( "SDL (Simple DirectMedia Layer)" ) ); + } + + + class setupWidget : public audioDevice::setupWidget + { + public: + setupWidget( QWidget * _parent ); + virtual ~setupWidget(); + + virtual void saveSettings( void ); + + private: + QLineEdit * m_device; + + } ; + + +private: + virtual void FASTCALL writeBufferToDev( surroundSampleFrame * _ab, + Uint32 _frames, + float _master_output ); + + void clearBuffer( void ); + + static void sdlAudioCallback( void * _udata, Uint8 * _buf, int _len ); + + SDL_AudioSpec m_audioHandle; + + outputSampleType * m_buffer; + + QMutex m_bufMutex; + QMutex m_callbackMutex; + + bool m_convertEndian; + +} ; + +#endif + +#endif diff --git a/include/basic_filters.h b/include/basic_filters.h new file mode 100644 index 00000000000..d9da2e7905b --- /dev/null +++ b/include/basic_filters.h @@ -0,0 +1,258 @@ +/* + * basic_filters.h - simple but powerful filter-class with most used filters + * + * original file by ??? + * modified and enhanced by Tobias Doerffel, 2004 + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _BASIC_FILTERS_H +#define _BASIC_FILTERS_H + +#ifndef __USE_XOPEN +#define __USE_XOPEN +#endif + +#include + +#include "types.h" +#include "mixer.h" +#include "templates.h" + + +template +class basicFilters +{ +public: + + enum filterTypes + { + LOWPASS, + HIPASS, + BANDPASS_CSG, + BANDPASS_CZPG, + NOTCH, + ALLPASS, + MOOG, + DOUBLE_LOWPASS, + DOUBLE_MOOG + } ; + + inline basicFilters( const float _sampleRate ) : + m_b0a0( 0.0f ), + m_b1a0( 0.0f ), + m_b2a0( 0.0f ), + m_a1a0( 0.0f ), + m_a2a0( 0.0f ), + m_sampleRate( _sampleRate ), + m_subFilter( NULL ) + { + // reset in/out history + for( Uint8 _chnl = 0; _chnl < CHANNELS; ++_chnl ) + { + // reset in/out history for simple filters + m_ou1[_chnl] = m_ou2[_chnl] = m_in1[_chnl] = + m_in2[_chnl] = 0.0f; + // reset in/out historey for moog-filter + m_y1[_chnl] = m_y2[_chnl] = m_y3[_chnl] = m_y4[_chnl] = + m_oldx[_chnl] = m_oldy1[_chnl] = + m_oldy2[_chnl] = m_oldy3[_chnl] = 0.0f; + } + } + + inline ~basicFilters() + { + delete m_subFilter; + } + + inline sampleType update( sampleType _in0, Uint8 _chnl ) + { + sampleType out; + if( m_type != MOOG ) + { + // filter + out = m_b0a0*_in0 + m_b1a0*m_in1[_chnl] + + m_b2a0*m_in2[_chnl] - m_a1a0*m_ou1[_chnl] - + m_a2a0*m_ou2[_chnl]; + + // push in/out buffers + m_in2[_chnl] = m_in1[_chnl]; + m_in1[_chnl] = _in0; + m_ou2[_chnl] = m_ou1[_chnl]; + + m_ou1[_chnl] = out; + } + else + { + sampleType x = _in0 - m_r*m_y4[_chnl]; + + // Four cascaded onepole filters (bilinear transform) + m_y1[_chnl] = x*m_p + m_oldx[_chnl]*m_p - + m_k*m_y1[_chnl]; + m_y2[_chnl] = m_y1[_chnl]*m_p+m_oldy1[_chnl]*m_p - + m_k*m_y2[_chnl]; + m_y3[_chnl] = m_y2[_chnl]*m_p+m_oldy2[_chnl]*m_p - + m_k*m_y3[_chnl]; + m_y4[_chnl] = m_y3[_chnl]*m_p+m_oldy3[_chnl]*m_p - + m_k*m_y4[_chnl]; + + m_oldx[_chnl] = x; + m_oldy1[_chnl] = m_y1[_chnl]; + m_oldy2[_chnl] = m_y2[_chnl]; + m_oldy3[_chnl] = m_y3[_chnl]; + out = m_y4[_chnl] - m_y4[_chnl] * m_y4[_chnl] * + m_y4[_chnl] * ( 1.0f/6.0f ); + } + if( m_subFilter != NULL ) + { + return( m_subFilter->update( out, _chnl ) ); + } + // Clipper band limited sigmoid + return( out ); + } + + + inline void calcFilterCoeffs( const filterTypes _type, float _freq, + const float _q + /*, const bool _q_is_bandwidth = FALSE*/ ) + { + // temp coef vars + m_type = _type; + _freq = tMax( _freq, 0.01f );// limit freq for not getting + // bad noise out of the filter... + + if( m_type == MOOG || m_type == DOUBLE_MOOG ) + { + const float f = 2 * _freq / m_sampleRate; // [0 - 1] + m_k = 3.6f*f - 1.6f*f*f - 1; // (Empirical tunning) + m_p = (m_k+1)*0.5f; + m_r = _q*powf( M_E, ( ( 1-m_p ) * 1.386249f ) ); + if( m_type == DOUBLE_MOOG ) + { + if( m_subFilter == NULL ) + { + m_subFilter = + new basicFilters( + m_sampleRate ); + } + m_subFilter->calcFilterCoeffs( MOOG, _freq, + _q ); + } + } + else + { + // other filters + const float omega = 2.0f * M_PI * _freq / + m_sampleRate; + const float tsin = sinf( omega ); + const float tcos = cosf( omega ); + //float alpha; + + //if (q_is_bandwidth) + //alpha = tsin*sinhf(logf(2.0f)/2.0f*q*omega/tsin); + //else + const float alpha = tsin / ( 2.0f*_q ); + + const float a0 = 1.0f / ( 1.0f+alpha ); + + if( m_type == LOWPASS || m_type == DOUBLE_LOWPASS ) + { + m_b0a0 = ((1.0f-tcos)/2.0f)*a0; + m_b1a0 = (1.0f-tcos)*a0; + m_b2a0 = m_b0a0;//((1.0f-tcos)/2.0f)*a0; + m_a1a0 = (-2.0f*tcos)*a0; + if( m_type == DOUBLE_LOWPASS ) + { + if( m_subFilter == NULL ) + { + m_subFilter = + new basicFilters( m_sampleRate ); + } + m_subFilter->calcFilterCoeffs( LOWPASS, + _freq, + _q ); + } + } + else if( m_type == HIPASS ) + { + m_b0a0 = ((1.0f+tcos)/2.0f)*a0; + m_b1a0 = (-1.0f-tcos)*a0; + m_b2a0 = m_b0a0;//((1.0f+tcos)/2.0f)*a0; + m_a1a0 = (-2.0f*tcos)*a0; + } + else if( m_type == BANDPASS_CSG ) + { + m_b0a0 = (tsin/2.0f)*a0; + m_b1a0 = 0.0f; + m_b2a0 = (-tsin/2.0f)*a0; + m_a1a0 = (-2.0f*tcos)*a0; + } + else if( m_type == BANDPASS_CZPG ) + { + m_b0a0 = alpha*a0; + m_b1a0 = 0.0f; + m_b2a0 = (-alpha)*a0; + m_a1a0 = (-2.0f*tcos)*a0; + } + else if( m_type == NOTCH ) + { + m_b0a0 = a0; + m_b1a0 = (-2.0f*tcos)*a0; + m_b2a0 = a0; + m_a1a0 = m_b1a0;//(-2.0f*tcos)*a0; + } + else if( m_type == ALLPASS ) + { + m_b0a0 = (1.0f-alpha)*a0; + m_b1a0 = (-2.0f*tcos)*a0; + m_b2a0 = 1.0;//(1.0f+alpha)*a0; + m_a1a0 = m_b1a0;//(-2.0f*tcos)*a0; + //m_a2a0 = m_b0a0;//(1.0f-alpha)*a0; + } + m_a2a0 = (1.0f-alpha)*a0; + } + } + + +private: + // filter coeffs + float m_b0a0, m_b1a0, m_b2a0, m_a1a0, m_a2a0; + + // coeffs for moog-filter + float m_r, m_p, m_k; + + typedef sampleType frame[CHANNELS]; + + // in/out history + frame m_ou1, m_ou2, m_in1, m_in2; + + // in/out history for moog-filter + frame m_y1, m_y2, m_y3, m_y4, m_oldx, m_oldy1, m_oldy2, m_oldy3; + + filterTypes m_type; + + float m_sampleRate; + basicFilters * m_subFilter; +} ; + + +#endif diff --git a/include/bb_editor.h b/include/bb_editor.h new file mode 100644 index 00000000000..eea12f814eb --- /dev/null +++ b/include/bb_editor.h @@ -0,0 +1,119 @@ +/* + * bb_editor.h - declaration of class bbEditor, a basic-component of LMMS + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _BB_EDITOR_H +#define _BB_EDITOR_H + +#include "qt3support.h" + + +#include "track_container.h" +#include "lmms_main_win.h" + + +class pixmapButton; +class songEditor; +class QPixmap; + + +class bbEditor : public trackContainer +{ + Q_OBJECT +public: + static inline bbEditor * inst( void ) + { + if( s_instanceOfMe == NULL ) + { + s_instanceOfMe = new bbEditor(); + } + return( s_instanceOfMe ); + } + + virtual bool FASTCALL play( midiTime _start, Uint32 _start_frame, + Uint32 _frames, Uint32 _frame_base, + Sint16 _tco_num = -1 ); + + virtual void FASTCALL saveSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void FASTCALL loadSettings( const QDomElement & _this ); + virtual void updateAfterTrackAdd( void ); + + inline virtual QString nodeName( void ) const + { + return( "bbeditor" ); + } + + virtual inline bool fixedTCOs( void ) const + { + return( TRUE ); + } + + csize currentBB( void ) const; + void FASTCALL setCurrentBB( csize _bb ); + tact FASTCALL lengthOfBB( csize _bb ); + inline tact lengthOfCurrentBB( void ) + { + return( lengthOfBB( currentBB() ) ); + } + void FASTCALL removeBB( csize _bb ); + csize numOfBBs( void ) const; + + void FASTCALL swapBB( csize _bb1, csize _bb2 ); + + +protected: + void closeEvent( QCloseEvent * _ce ); + void keyPressEvent (QKeyEvent * _ke); + void wheelEvent( QWheelEvent * _we ); + void resizeEvent( QResizeEvent * _re ); + void updateBackground( void ); + + +protected slots: + void play( void ); + void stop( void ); + + +private: + bbEditor(); + //bbEditor( const bbEditor & ); + ~bbEditor(); + + void FASTCALL createTCOsForBB( csize _bb ); + + + static bbEditor * s_instanceOfMe; + static QPixmap * s_titleArtwork; + + pixmapButton * m_playButton; + pixmapButton * m_stopButton; + + + friend class songEditor; + friend lmmsMainWin::~lmmsMainWin(); + +} ; + + +#endif diff --git a/include/bb_track.h b/include/bb_track.h new file mode 100644 index 00000000000..b0436ca5ac6 --- /dev/null +++ b/include/bb_track.h @@ -0,0 +1,150 @@ +/* + * bb_track.h - class bbTrack, a wrapper for using bbEditor + * (which is a singleton-class) as track + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _BB_TRACK_H +#define _BB_TRACK_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + + +#include "track.h" + +class nameLabel; +class trackContainer; + + +class bbTCO : public trackContentObject +{ + Q_OBJECT +public: + bbTCO( track * _track, const QColor & _c = QColor() ); + virtual ~bbTCO(); + + virtual void FASTCALL movePosition( const midiTime & _pos ); + virtual void FASTCALL changeLength( const midiTime & _length ); + + virtual void FASTCALL saveSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void FASTCALL loadSettings( const QDomElement & _this ); + inline virtual QString nodeName( void ) const + { + return( "bbtco" ); + } + + const QColor & color( void ) const + { + return( m_color ); + } + + +protected slots: + void openInBBEditor( bool _c ); + void openInBBEditor( void ); + void resetName( void ); + void changeName( void ); + void changeColor( void ); + + +protected: + void paintEvent( QPaintEvent * ); + void mouseDoubleClickEvent( QMouseEvent * _me ); + virtual void constructContextMenu( QMenu * ); + + +private: + QString m_name; + QColor m_color; + +} ; + + + +class bbTrack : public QObject, public track +{ + Q_OBJECT +public: + bbTrack( trackContainer * _tc ); + virtual ~bbTrack(); + + virtual trackTypes trackType( void ) const; + virtual bool FASTCALL play( const midiTime & _start, + Uint32 _start_frame, Uint32 _frames, + Uint32 _frame_base, + Sint16 _tco_num = -1 ); + virtual trackContentObject * FASTCALL createTCO( const midiTime & + _pos ); + + virtual void FASTCALL saveTrackSpecificSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void FASTCALL loadTrackSpecificSettings( const QDomElement & + _this ); + + static bbTrack * FASTCALL findBBTrack( csize _bb_num ); + static csize FASTCALL numOfBBTrack( track * _track ); + static void FASTCALL swapBBTracks( track * _track1, track * _track2 ); + + inline nameLabel * trackLabel( void ) + { + return( m_trackLabel ); + } + + +public slots: + void clickedTrackLabel( void ); + + +protected: + inline virtual QString nodeName( void ) const + { + return( "bbtrack" ); + } + + +private: + nameLabel * m_trackLabel; + + struct bbInfoStruct + { + csize num; + QString name; + } ; + static QMap s_bbNums; + +} ; + + +#endif diff --git a/include/buffer_allocator.h b/include/buffer_allocator.h new file mode 100644 index 00000000000..24f84c1699e --- /dev/null +++ b/include/buffer_allocator.h @@ -0,0 +1,78 @@ +/* + * buffer_allocator.h - namespace bufferAllocator providing routines for own + * optimized memory-management for audio-buffers + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _BUFFER_ALLOCATOR_H +#define _BUFFER_ALLOCATOR_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "types.h" + + + + +namespace bufferAllocator +{ + void * FASTCALL allocBytes( Uint32 _bytes ); + + template + inline T * FASTCALL alloc( Uint32 _n ) + { + return( (T *) allocBytes( sizeof( T ) * _n ) ); + } + + void FASTCALL free( void * _buf ); + + void FASTCALL cleanUp( Uint16 _level ); + + + // simple class for automatically freeing buffer in complex functions + template + class autoCleaner + { + public: + autoCleaner( T * _ptr ) : + m_ptr( _ptr ) + { + } + ~autoCleaner() + { + bufferAllocator::free( m_ptr ); + } + inline const T * ptr( void ) const + { + return( m_ptr ); + } + + private: + T * m_ptr; + } ; + +} ; + + +#endif diff --git a/include/clipboard.h b/include/clipboard.h new file mode 100644 index 00000000000..01f269b5cea --- /dev/null +++ b/include/clipboard.h @@ -0,0 +1,59 @@ +/* + * clipboard.h - the clipboard for patterns, notes etc. + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _CLIPBOARD_H +#define _CLIPBOARD_H + +#ifdef HAVE_CONFIG_H +#include +#endif + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + + +class settings; + +namespace clipboard +{ + typedef QMap map; + extern map content; + + void FASTCALL copy( settings * _settings_object ); + const QDomElement * FASTCALL getContent( const QString & _node_name ); +} ; + +#endif diff --git a/include/config_mgr.h b/include/config_mgr.h new file mode 100644 index 00000000000..0143aac2861 --- /dev/null +++ b/include/config_mgr.h @@ -0,0 +1,187 @@ +/* + * config_mgr.h - class configManager, a class for managing LMMS-configuration + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _CONFIG_MGR_H +#define _CONFIG_MGR_H + +#ifdef HAVE_CONFIG_H +#include +#endif + + +#include "qt3support.h" + + +#ifdef QT4 + +#include +#include +#include +#include + +#else + +#include +#include +#include +#include + +#endif + + +#include "lmms_main_win.h" + + +class QLineEdit; +class QLabel; +class QRadioButton; +class QHBoxLayout; +class QVBoxLayout; +class QFrame; + + +const QString PROJECTS_PATH = "projects/"; +const QString PRESETS_PATH = "presets/"; +const QString SAMPLES_PATH = "samples/"; +const QString ARTWORK_PATH = "artwork/"; +const QString LOCALE_PATH = "locale/"; + + +class configManager : public QDialog +{ + Q_OBJECT +public: + static inline configManager * inst( void ) + { + if( s_instanceOfMe == NULL ) + { + s_instanceOfMe = new configManager(); + } + return( s_instanceOfMe ); + } + + const QString & lmmsWorkingDir( void ) const + { + return( m_lmmsWorkingDir ); + } + QString projectsDir( void ) const + { + return( m_lmmsWorkingDir + PROJECTS_PATH ); + } + QString presetsDir( void ) const + { + return( m_lmmsWorkingDir + PRESETS_PATH ); + } + QString samplesDir( void ) const + { + return( m_lmmsWorkingDir + SAMPLES_PATH ); + } + QString artworkDir( void ) const + { + return( m_lmmsDataDir + ARTWORK_PATH ); + } + QString localeDir( void ) const + { + return( m_lmmsDataDir + LOCALE_PATH ); + } + + const QString & value( const QString & _class, + const QString & _attribute ) const; + void setValue( const QString & _class, const QString & _attribute, + const QString & _value ); + + bool loadConfigFile( void ); + void saveConfigFile( void ); + + +protected slots: + void openWorkingDir( void ); + void setWorkingDir( const QString & _wd ); + + virtual void accept( void ); + + void backButtonClicked( void ); + void nextButtonClicked( void ); + void switchPage( csize _pg ); + void switchPage( QWidget * _pg ); + + +private: + static configManager * s_instanceOfMe; + + configManager( void ); + configManager( const configManager & _c ); + ~configManager(); + + void createWidgets( void ); + + + void FASTCALL addPage( QWidget * _w, const QString & _title ); + + static void processFilesRecursively( const QString & _src_dir, + const QString & _dst_dir, + void( * _proc_func )( const QString & _src, const QString & + _dst ) ); + + + const QString m_lmmsRcFile; + QString m_lmmsWorkingDir; + QString m_lmmsDataDir; + + typedef vvector > stringPairVector; + typedef QMap settingsMap; + settingsMap m_settings; + + + QWidget * m_pageIntro; + QWidget * m_pageWorkingDir; + QWidget * m_pageFiles; + + QRadioButton * m_samplesCopyRB; + QRadioButton * m_presetsCopyRB; + QRadioButton * m_projectsCopyRB; + + QLineEdit * m_wdLineEdit; + + // wizard stuff + vlist > m_pages; + csize m_currentPage; + QFrame * m_hbar; + QWidget * m_contentWidget; + QLabel * m_title; + QPushButton * m_cancelButton; + QPushButton * m_backButton; + QPushButton * m_nextButton; + QPushButton * m_finishButton; + QHBoxLayout * m_buttonLayout; + QHBoxLayout * m_mainLayout; + QVBoxLayout * m_contentLayout; + + + // lmmsMainWin-dtor is allowed to destroy us... + friend lmmsMainWin::~lmmsMainWin(); + +} ; + +#endif diff --git a/include/debug.h b/include/debug.h new file mode 100644 index 00000000000..0e3c3559e79 --- /dev/null +++ b/include/debug.h @@ -0,0 +1,41 @@ +/* + * debug.h - header file to be included for debugging purposes + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _DEBUG_H +#define _DEBUG_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +// set whether debug-stuff (like messages on the console, asserts and other +// additional range-checkings) should be compiled + +#ifdef LMMS_DEBUG +#include +#include +#endif + + +#endif diff --git a/include/effect_board.h b/include/effect_board.h new file mode 100644 index 00000000000..d78dfb12d13 --- /dev/null +++ b/include/effect_board.h @@ -0,0 +1,31 @@ +/* + * effect_board.h - stuff for effect-board + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _EFFECT_BOARD_H +#define _EFFECT_BOARD_H + +const int MIN_EFFECT_CHANNEL = 0; +const int MAX_EFFECT_CHANNEL = 63; +const int DEFAULT_EFFECT_CHANNEL = (MIN_EFFECT_CHANNEL); + +#endif diff --git a/include/embed.h b/include/embed.h new file mode 100644 index 00000000000..314c8ccd4bf --- /dev/null +++ b/include/embed.h @@ -0,0 +1,51 @@ +/* + * embed.h - misc. stuff for using embedded data (resources linked into binary) + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _EMBED_H +#define _EMBED_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + +namespace embed +{ + +QPixmap getIconPixmap( const char * _name, int _w = -1, int _h = -1 ); +QString getText( const char * _name ); +void loadTranslation( const QString & _tname ); + +} + +#endif diff --git a/include/endian_handling.h b/include/endian_handling.h new file mode 100644 index 00000000000..8254e9db499 --- /dev/null +++ b/include/endian_handling.h @@ -0,0 +1,59 @@ +/* + * endian.h - handle endianess-problems + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _ENDIAN_HANDLING_H +#define _ENDIAN_HANDLING_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "types.h" + + +inline bool isLittleEndian( void ) +{ +#ifdef WORDS_BIGENDIAN + return( FALSE ); +#else + return( TRUE ); +#endif +} + + +inline Sint16 swap16IfBE( Sint16 _i ) +{ + return( isLittleEndian() ? _i : ( ( _i & 0xFF ) << 8) | ( ( _i >> 8 ) & 0xFF ) ); +} + + +inline Sint32 swap32IfBE( Sint32 _i ) +{ + return( isLittleEndian() ? _i : ( ( _i & 0xff000000 ) >> 24 ) | + ( ( _i & 0x00ff0000 ) >> 8 ) | + ( ( _i & 0x0000ff00 ) << 8 ) | + ( ( _i & 0x000000ff ) << 24 ) ); +} + +#endif diff --git a/include/envelope_and_lfo_widget.h b/include/envelope_and_lfo_widget.h new file mode 100644 index 00000000000..b9760d9c19d --- /dev/null +++ b/include/envelope_and_lfo_widget.h @@ -0,0 +1,174 @@ +/* + * envelope_and_lfo_widget.h - declaration of class envelopeAndLFOWidget which + * is used by envelope/lfo/filter-tab of + * channel-window + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _ENVELOPE_AND_LFO_WIDGET_H +#define _ENVELOPE_AND_LFO_WIDGET_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +#include "settings.h" +#include "types.h" +#include "spc_bg_hndl_widget.h" + + +class envelopeTabWidget; +class pixmapButton; +class knob; +class QPaintEvent; +class QPixmap; + + + +class envelopeAndLFOWidget : public QWidget, public settings, + public specialBgHandlingWidget +{ + Q_OBJECT +public: + envelopeAndLFOWidget( float _value_for_zero_amount, QWidget * _parent ); + ~envelopeAndLFOWidget(); + + static inline float expKnobVal( float val ) + { + return( ( ( val < 0 ) ? -1 : 1 ) * val*val ); + } + static void triggerLFO( void ); + static void resetLFO( void ); + + float FASTCALL level( Uint32 _frame, Uint32 _release_begin, + Uint32 _frame_offset ) const; + + inline bool used( void ) const + { + return( m_used ); + } + + + virtual void FASTCALL saveSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void FASTCALL loadSettings( const QDomElement & _this ); + inline virtual QString nodeName( void ) const + { + return( "el" ); + } + + +public slots: + void updateSampleVars( void ); + + +protected: + void paintEvent( QPaintEvent * _pe ); + void mousePressEvent( QMouseEvent * _me ); + + float FASTCALL lfoLevel( Uint32 _frame, Uint32 _frame_offset ) const; + + +protected slots: + void updateAfterKnobChange( float ); + void lfoSinWaveCh( bool ); + void lfoTriangleWaveCh( bool ); + void lfoSawWaveCh( bool ); + void lfoSquareWaveCh( bool ); + void x100Toggled( bool ); + + +private: + static Uint32 s_lfoFrame; + + bool m_used; + + // envelope-stuff + knob * m_predelayKnob; + knob * m_attackKnob; + knob * m_holdKnob; + knob * m_decayKnob; + knob * m_sustainKnob; + knob * m_releaseKnob; + knob * m_amountKnob; + static QPixmap * s_envGraph; + + float m_sustainLevel; + float m_amount; + float m_valueForZeroAmount; + float m_amountAdd; + Uint32 m_pahdFrames; + Uint32 m_rFrames; + float * m_pahdEnv; + float * m_rEnv; + + // LFO-stuff + knob * m_lfoPredelayKnob; + knob * m_lfoAttackKnob; + knob * m_lfoSpeedKnob; + knob * m_lfoAmountKnob; + pixmapButton * m_sinLfoBtn; + pixmapButton * m_triangleLfoBtn; + pixmapButton * m_sawLfoBtn; + pixmapButton * m_sqrLfoBtn; + static QPixmap * s_lfoGraph; + + pixmapButton * m_x100Btn; + pixmapButton * m_controlEnvAmountBtn; + + Uint32 m_lfoPredelayFrames; + Uint32 m_lfoAttackFrames; + Uint32 m_lfoOscillationFrames; + float m_lfoAmount; + bool m_lfoAmountIsZero; + float * m_lfoShapeData; + + enum lfoShapes + { + SIN, + TRIANGLE, + SAW, + SQUARE + } m_lfoShape; + + volatile bool m_busy; + + + + friend class envelopeTabWidget; + +} ; + +#endif diff --git a/include/envelope_tab_widget.h b/include/envelope_tab_widget.h new file mode 100644 index 00000000000..d7276b3cfea --- /dev/null +++ b/include/envelope_tab_widget.h @@ -0,0 +1,107 @@ +/* + * envelope_tab_widget.h - declaration of class envelopeTabWidget which + * provides UI- and DSP-code for using envelopes, LFOs + * and a filter + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _ENVELOPE_TAB_WIDGET_H +#define _ENVELOPE_TAB_WIDGET_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +#include "settings.h" +#include "basic_filters.h" +#include "envelope_and_lfo_widget.h" + + +class QComboBox; +class groupBox; +class tabWidget; +class QLabel; +class knob; +class pixmapButton; +class channelTrack; +class notePlayHandle; + + +class envelopeTabWidget : public QWidget, public settings +{ + Q_OBJECT +public: + envelopeTabWidget( channelTrack * _channel_track, QWidget * parent ); + ~envelopeTabWidget(); + + void FASTCALL processAudioBuffer( sampleFrame * _ab, Uint32 _frames, + notePlayHandle * _n ); + + enum targets + { + VOLUME, +/* PANNING, + PITCH,*/ + CUT, + RES, + TARGET_COUNT + } ; + + Uint32 envFrames( void ); + Uint32 releaseFrames( void ); + + float FASTCALL volumeLevel( notePlayHandle * _n, Uint32 _frame ); + + + virtual void FASTCALL saveSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void FASTCALL loadSettings( const QDomElement & _this ); + inline virtual QString nodeName( void ) const + { + return( "eldata" ); + } + + +private: + channelTrack * m_channelTrack; + + tabWidget * m_targetsTabWidget; + envelopeAndLFOWidget * m_envLFOWidgets[TARGET_COUNT]; + + // filter-stuff + groupBox * m_filterGroupBox; + QComboBox * m_filterComboBox; + knob * m_filterCutKnob; + knob * m_filterResKnob; + +} ; + +#endif diff --git a/include/export.h b/include/export.h new file mode 100644 index 00000000000..dc983101343 --- /dev/null +++ b/include/export.h @@ -0,0 +1,61 @@ +/* + * export.h - header which is needed for song-export + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _EXPORT_H +#define _EXPORT_H + +#include "types.h" + +class audioDevice; + + +typedef audioDevice * ( * getDeviceInst)( Uint32 _sample_rate, + Uint32 _channels, + bool & _success_ful, + const QString & _file, + bool _use_vbr, + Uint16 _nom_bitrate, + Uint16 _min_bitrate, + Uint16 _max_bitrate ); + + +enum fileTypes +{ + WAVE_FILE, + OGG_FILE, + NULL_FILE = 0xFF +} ; + + +struct fileEncodeDevice +{ + fileTypes m_fileType; + const char * m_description; + const char * m_extension; + getDeviceInst m_getDevInst; +} ; + +extern fileEncodeDevice fileEncodeDevices[]; + + +#endif diff --git a/include/export_project_dialog.h b/include/export_project_dialog.h new file mode 100644 index 00000000000..0789b5a9433 --- /dev/null +++ b/include/export_project_dialog.h @@ -0,0 +1,111 @@ +/* + * export_project_dialog.h - declaration of class exportProjectDialog which is + * responsible for exporting project + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _EXPORT_PROJECT_DIALOG_H +#define _EXPORT_PROJECT_DIALOG_H + +#ifdef HAVE_CONFIG_H +#include +#endif + + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +#include "export.h" + + +class QLabel; +class QPushButton; +class QComboBox; +class QProgressBar; +class QCheckBox; +class pixmapButton; + + +class exportProjectDialog : public QDialog +{ + Q_OBJECT +public: + exportProjectDialog( const QString & _file_name, QWidget * _parent ); + ~exportProjectDialog(); + void FASTCALL updateProgressBar( int _new_val ); + + +public slots: + void exportBtnClicked( void ); + + +protected: + void keyPressEvent( QKeyEvent * _ke ); + void closeEvent( QCloseEvent * _ce ); + + +private slots: + void changedType( const QString & ); + void cancelBtnClicked( void ); + void redrawProgressBar( void ); + + +private: + QString m_fileName; + QLabel * m_typeLbl; + QComboBox * m_typeCombo; + QLabel * m_kbpsLbl; + QComboBox * m_kbpsCombo; + QCheckBox * m_vbrCb; + QCheckBox * m_hqmCb; + QLabel * m_hourglassLbl; + QPushButton * m_exportBtn; + QPushButton * m_cancelBtn; + QProgressBar * m_exportProgressBar; + fileTypes m_fileType; + bool m_deleteFile; + int m_oldProgressVal; + int m_progressVal; + + QTimer * m_progressBarUpdateTimer; + + static Sint16 s_availableBitrates[]; + + void finishProjectExport( void ); + void abortProjectExport( void ); + + static fileTypes FASTCALL getFileTypeFromExtension( const QString & + _ext ); + +} ; + +#endif diff --git a/include/group_box.h b/include/group_box.h new file mode 100644 index 00000000000..565701a2af4 --- /dev/null +++ b/include/group_box.h @@ -0,0 +1,85 @@ +/* + * group_box.h - LMMS-groupbox + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _GROUP_BOX_H +#define _GROUP_BOX_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + +#include "pixmap_button.h" + +class QPixmap; + + +class groupBox : public QWidget +{ + Q_OBJECT +public: + groupBox( const QString & _caption, QWidget * _parent ); + ~groupBox(); + + bool isActive( void ) const + { +#ifdef QT4 + return( m_led->isChecked() ); +#else + return( m_led->isOn() ); +#endif + } + + +public slots: + void setState( bool _on, bool _anim = FALSE ); + void animate( void ); + + +protected: + virtual void resizeEvent( QResizeEvent * _re ); + virtual void mousePressEvent( QMouseEvent * _me ); + + +private: + void updatePixmap( void ); + + static QPixmap * s_ledBg; + + pixmapButton * m_led; + QString m_caption; + + int m_origHeight; + bool m_animating; + +} ; + +#endif diff --git a/include/interpolation.h b/include/interpolation.h new file mode 100644 index 00000000000..dfce10a0ad7 --- /dev/null +++ b/include/interpolation.h @@ -0,0 +1,93 @@ +/* + * interpolation.h - fast implementations of several interpolation-algorithms + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _INTERPOLATION_H +#define _INTERPOLATION_H + +#ifndef __USE_XOPEN +#define __USE_XOPEN +#endif + +#include + + +inline float hermiteInterpolate( float x0, float x1, float x2, float x3, + float frac_pos ) +{ + const float frsq = frac_pos*frac_pos; + const float frsq2 = 2*frsq; + return( ( (x2-x0) *0.5f ) * ( frac_pos * (frsq+1) -frsq2 ) + + ( frsq2*frac_pos - 3*frsq ) * ( x1-x2 ) + + frsq2 * (frac_pos-1) * ( ( x3-x1 ) * 0.25f ) + x1 ); + +/* + const float frsq = frac_pos*frac_pos; + //const float frsq2 = 2*frsq; + frac_pos *= 0.5; + const float frcu = frsq*frac_pos; + return ( + + (frcu - frsq + frac_pos) * ((x2 - x0)) + + + (4*frcu - 3*frsq) * (x1 - x2) + //frsq*(2*frac_pos-3) * (x1 - x2) + + + (frcu - 0.5*frsq)*((x3 - x1)) + + + x1 + + ); +*/ +} + + + +inline float cubicInterpolate( float v0, float v1, float v2, float v3, float x ) +{ + float frsq = x*x; + float frcu = frsq*v0; + float t1 = v3 + 3*v1; + + return( v1 + 0.5f * frcu + x * ( v2 - frcu * ( 1.0f/6.0f ) - + t1 * ( 1.0f/6.0f ) - v0 / 3.0f ) + frsq * x * ( t1 * + ( 1.0f/6.0f ) - 0.5f * v2 ) + frsq * ( 0.5f * v2 - v1 ) ); +} + + + +inline float cosinusInterpolate( float v0, float v1, float x ) +{ + float f = cosf( x * ( M_PI*0.5f ) ); + return( v0*f + v1*( 1.0f-f ) ); +} + + + +inline float linearInterpolate( float v0, float v1, float x ) +{ + return( v0*( 1.0f-x ) + v1*x ); +} + + +#endif diff --git a/include/kmultitabbar.h b/include/kmultitabbar.h new file mode 100644 index 00000000000..070f9924c43 --- /dev/null +++ b/include/kmultitabbar.h @@ -0,0 +1,320 @@ +/*************************************************************************** + kmultitabbar.h - description + ------------------- + begin : 2001 + copyright : (C) 2001,2002,2003 by Joseph Wenninger + ***************************************************************************/ + +/*************************************************************************** + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + ***************************************************************************/ + +#ifndef _KMultitabbar_h_ +#define _KMultitabbar_h_ + +#include "qt3support.h" + +class KMultiTabBarButton; +class KMultiTabBarTab; + +#ifdef QT4 + +#include +#include +//#include +#include +#include +#include +#include +#include + +typedef QList buttonList; +typedef QList tabList; + +#else + +#include +#include +#include +#include +#include +#include +#include + +typedef QPtrList buttonList; +typedef QPtrList tabList; + +#endif + + +class QPixmap; +class QPainter; +class QFrame; + +class KMultiTabBarPrivate; +class KMultiTabBarTabPrivate; +class KMultiTabBarButtonPrivate; +class KMultiTabBarInternal; + +/** + * A Widget for horizontal and vertical tabs. + * It is possible to add normal buttons to the top/left + * The handling if only one tab at a time or multiple tabs + * should be raisable is left to the "user". + *@author Joseph Wenninger + */ +class KMultiTabBar: public QWidget +{ + Q_OBJECT +public: + //enum KMultiTabBarMode{ Horizontal, Vertical }; + enum KMultiTabBarPosition{DockLeft, DockRight, DockTop, DockBottom}; + + /** + * VSNET == Visual Studio .Net like (only show the text of active tabs + * KDEV3 == Kdevelop 3 like (always show the text) + * KONQSBC == konqy's classic sidebar style (unthemed), this one is disabled + * at the moment, but will be renabled soon too + */ + enum KMultiTabBarStyle{VSNET=0, KDEV3=1, KONQSBC=2, KDEV3ICON=3,STYLELAST=0xffff}; + + KMultiTabBar(Qt::Orientation o,QWidget *parent=0); + virtual ~KMultiTabBar(); + + /** + * append a new button to the button area. The button can later on be accessed with button(ID) + * eg for connecting signals to it + * @param pic a pixmap for the button + * @param id an arbitraty ID value. It will be emitted in the clicked signal for identifying the button + * if more than one button is connected to a signals. + * @param popup A popup menu which should be displayed if the button is clicked + * @param not_used_yet will be used for a popup text in the future + */ + int appendButton(const QPixmap &pic,int id=-1,QMenu* popup=0,const QString& not_used_yet=QString::null); + /** + * remove a button with the given ID + */ + void removeButton(int id); + /** + * append a new tab to the tab area. It can be accessed lateron with tabb(id); + * @param pic a bitmap for the tab + * @param id an arbitrary ID which can be used later on to identify the tab + * @param text if a mode with text is used it will be the tab text, otherwise a mouse over hint + */ + int appendTab(const QPixmap &pic,int id=-1,const QString& text=QString::null); + /** + * remove a tab with a given ID + */ + void removeTab(int id); + /** + * set a tab to "raised" + * @param id The ID of the tab to manipulate + * @param state true == activated/raised, false == not active + */ + void setTab(int id ,bool state); + /** + * return the state of a tab, identified by it's ID + */ + bool isTabRaised(int id) const; + /** + * get a pointer to a button within the button area identified by its ID + */ + class KMultiTabBarButton *button(int id) const; + + /** + * get a pointer to a tab within the tab area, identiifed by its ID + */ + class KMultiTabBarTab *tab(int id) const; + /** + * set the real position of the widget. + * @param pos if the mode is horizontal, only use top, bottom, if it is vertical use left or right + */ + void setPosition(KMultiTabBarPosition pos); + /** + * set the display style of the tabs + */ + void setStyle(KMultiTabBarStyle style); + /** + * be carefull, don't delete tabs yourself and don't delete the list itself + */ + tabList * tabs(); + /** + * be carefull, don't delete buttons yourself and don't delete the list itself + */ + buttonList * buttons(); + + /** + * might vanish, not sure yet + */ + void showActiveTabTexts(bool show=true); +protected: + friend class KMultiTabBarButton; + virtual void fontChange( const QFont& ); + void updateSeparator(); +private: + class KMultiTabBarInternal *m_internal; + QBoxLayout *m_l; + QFrame *m_btnTabSep; + buttonList m_buttons; + KMultiTabBarPosition m_position; + KMultiTabBarPrivate *d; +}; + +/** + * This class should never be created except with the appendButton call of KMultiTabBar + */ +class KMultiTabBarButton: public QPushButton +{ + Q_OBJECT +public: + KMultiTabBarButton(const QPixmap& pic,const QString&, QMenu *popup, + int id,QWidget *parent, KMultiTabBar::KMultiTabBarPosition pos, KMultiTabBar::KMultiTabBarStyle style); + KMultiTabBarButton(const QString&, QMenu *popup, + int id,QWidget *parent, KMultiTabBar::KMultiTabBarPosition pos, KMultiTabBar::KMultiTabBarStyle style); + virtual ~KMultiTabBarButton(); + int id() const; + +public slots: + /** + * this is used internaly, but can be used by the user, if (s)he wants to + * It the according call of KMultiTabBar is invoked though this modifications will be overwritten + */ + void setPosition(KMultiTabBar::KMultiTabBarPosition); + /** + * this is used internaly, but can be used by the user, if (s)he wants to + * It the according call of KMultiTabBar is invoked though this modifications will be overwritten + */ + void setStyle(KMultiTabBar::KMultiTabBarStyle); + + /** + * modify the text of the button + */ + void setText(const QString &); + + QSize sizeHint() const; + +protected: + KMultiTabBar::KMultiTabBarPosition m_position; + KMultiTabBar::KMultiTabBarStyle m_style; + QString m_text; + virtual void hideEvent( class QHideEvent*); + virtual void showEvent( class QShowEvent*); +private: + int m_id; + KMultiTabBarButtonPrivate *d; +signals: + /** + * this is emitted if the button is clicked + * @param id the ID identifying the button + */ + void clicked(int id); +protected slots: + virtual void slotClicked(); +}; + +/** + * This class should never be created except with the appendTab call of KMultiTabBar + */ +class KMultiTabBarTab: public KMultiTabBarButton +{ + Q_OBJECT +public: + KMultiTabBarTab(const QPixmap& pic,const QString&,int id,QWidget *parent, + KMultiTabBar::KMultiTabBarPosition pos,KMultiTabBar::KMultiTabBarStyle style); + virtual ~KMultiTabBarTab(); + /** + * set the active state of the tab + * @param state true==active false==not active + */ + void setState(bool state); + /** + * choose if the text should always be displayed + * this is only used in classic mode if at all + */ + void showActiveTabText(bool show); + void resize(){ setSize( neededSize() ); } +#ifndef QT4 + virtual inline const QColorGroup & palette( void ) const + { + return( colorGroup() ); + } +#endif +private: + bool m_showActiveTabText; + int m_expandedSize; + KMultiTabBarTabPrivate *d; +protected: + friend class KMultiTabBarInternal; + void setSize(int); + int neededSize(); + void updateState(); + virtual void drawButton(QPainter *); + virtual void drawButtonLabel(QPainter *); + void drawButtonStyled(QPainter *); + void drawButtonClassic(QPainter *); +protected slots: + virtual void slotClicked(); + void setTabsPosition(KMultiTabBar::KMultiTabBarPosition); + +public slots: + virtual void setIcon(const QString&); + virtual void setIcon(const QPixmap&); +}; + + + +class KMultiTabBarInternal: public Q3ScrollView +{ + Q_OBJECT +public: + KMultiTabBarInternal(QWidget *parent,Qt::Orientation o); + int appendTab(const QPixmap &,int=-1,const QString& =QString::null); + KMultiTabBarTab *tab(int) const; + void removeTab(int); + void setPosition(enum KMultiTabBar::KMultiTabBarPosition pos); + void setStyle(enum KMultiTabBar::KMultiTabBarStyle style); + void showActiveTabTexts(bool show); + tabList * tabs(){return &m_tabs;} +#ifndef QT4 + virtual inline const QColorGroup & palette( void ) const + { + return( colorGroup() ); + } +#endif +private: + friend class KMultiTabBar; + QWidget *box; + QBoxLayout *mainLayout; + tabList m_tabs; + enum KMultiTabBar::KMultiTabBarPosition m_position; + bool m_showActiveTabTexts; + enum KMultiTabBar::KMultiTabBarStyle m_style; + int m_expandedTabSize; + int m_lines; +protected: + virtual void drawContents ( QPainter *, int, int, int, int); + + /** + * [contentsM|m]ousePressEvent are reimplemented from QScrollView + * in order to ignore all mouseEvents on the viewport, so that the + * parent can handle them. + */ + virtual void contentsMousePressEvent(QMouseEvent *); + virtual void mousePressEvent(QMouseEvent *); + virtual void resizeEvent(QResizeEvent *); +}; + +#endif diff --git a/include/knob.h b/include/knob.h new file mode 100644 index 00000000000..feff4061cfe --- /dev/null +++ b/include/knob.h @@ -0,0 +1,191 @@ +/* + * knob.h - powerful knob-widget + * + * This file is based on the knob-widget of the Qwt Widget Library by Josef Wilgen + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _KNOB_H +#define _KNOB_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + + +#include "templates.h" + + +class QPixmap; +class textFloat; + + +enum knobTypes +{ + knobDark_28, knobBright_26, knobSmall_17 +} ; + + + +class knob : public QWidget +{ + Q_OBJECT +public: + knob( int _knob_num, QWidget * _parent, const QString & _name ); + virtual ~knob(); + + enum ScrollMode + { + ScrNone, + ScrMouse, + ScrTimer, + ScrDirect, + ScrPage + } ; + + void setTracking( bool _enable ); + void setHintText( const QString & _txt_before, + const QString & _txt_after ); + void setLabel( const QString & _txt ); + + void setTotalAngle( float _angle ); + + void setRange( float _vmin, float _vmax, float _vstep = 0.0, + int _pagesize = 1 ); + + inline float value( void ) const + { + return( m_value ); + } + + void setStep( float ); + + inline float maxValue( void ) const + { + return( m_maxValue ); + } + inline float minValue( void ) const + { + return( m_minValue ); + } + + inline void incPages( int _n_pages ) + { + setNewValue( m_value + float( _n_pages ) * m_pageSize, 1 ); + } + + + +public slots: + void setValue( float _val, bool _is_init_value = FALSE ); + void fitValue( float _val ); + void incValue( int _steps ); + void reset( void ); + void copyValue( void ); + void pasteValue( void ); + void connectToMidiDevice( void ); + void displayHelp( void ); + + +signals: + void valueChanged( float value ); + void sliderPressed( void ); + void sliderReleased( void ); + void sliderMoved( float value ); + + +protected: + virtual void paintEvent( QPaintEvent * _me ); + virtual void resizeEvent( QResizeEvent * _me ); + virtual void mousePressEvent( QMouseEvent * _me ); + virtual void mouseReleaseEvent( QMouseEvent * _me ); + virtual void mouseMoveEvent( QMouseEvent * _me ); + virtual void wheelEvent( QWheelEvent * _me ); + virtual void contextMenuEvent( QContextMenuEvent * _me ); + + void drawKnob( QPainter * _p ); + void setPosition( const QPoint & _p ); + + +private: + void layoutKnob( bool _update = TRUE ); + float getValue( const QPoint & _p ); + void getScrollMode( const QPoint & _p, int & _scroll_mode, + int & _direction ); + void recalcAngle( void ); + + void valueChange( void ); + void rangeChange( void ); + + + void buttonReleased( void ); + + void setNewValue( float x, int align = 0 ); + + + static float s_copiedValue; + static textFloat * s_textFloat; + + + int m_knobWidth; + int m_scrollMode; + float m_mouseOffset; + int m_direction; + int m_tracking; + QPoint m_origMousePos; + + + float m_angle; + float m_oldAngle; + float m_totalAngle; + float m_nTurns; + + QPixmap * m_knobPixmap; + int m_knobNum; + QString m_hintTextBeforeValue; + QString m_hintTextAfterValue; + QString m_label; + + + float m_minValue; + float m_maxValue; + float m_step; + float m_pageSize; + float m_value; + float m_exactValue; + float m_exactPrevValue; + float m_prevValue; + float m_initValue; + +} ; + +#endif diff --git a/include/lcd_spinbox.h b/include/lcd_spinbox.h new file mode 100644 index 00000000000..1a92975e0d5 --- /dev/null +++ b/include/lcd_spinbox.h @@ -0,0 +1,84 @@ +/* + * lcd_spinbox.h - class lcdSpinBox, an improved QLCDNumber + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _LCD_SPINBOX_H +#define _LCD_SPINBOX_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + + +class lcdSpinBox : public QWidget +{ + Q_OBJECT +public: + lcdSpinBox( int _min, int _max, int _num_digits, QWidget * _parent ); + virtual ~lcdSpinBox(); + + void setStep( int _step ); + + inline int value( void ) const + { + return( m_number->intValue() ); + } + + void setValue( int _value ); + void setLabel( const QString & _txt ); + + +protected: + virtual void mousePressEvent( QMouseEvent * _me ); + virtual void mouseMoveEvent( QMouseEvent * _me ); + virtual void mouseReleaseEvent( QMouseEvent * _me ); + virtual void wheelEvent( QWheelEvent * _we ); + + +private: + int m_value; + int m_minValue; + int m_maxValue; + int m_step; + + QLCDNumber * m_number; + QLabel * m_label; + + QPoint m_origMousePos; + + +signals: + void valueChanged( int ); + +} ; + +#endif diff --git a/include/led_checkbox.h b/include/led_checkbox.h new file mode 100644 index 00000000000..53711a436c3 --- /dev/null +++ b/include/led_checkbox.h @@ -0,0 +1,67 @@ +/* + * led_checkbox.h - class ledCheckBox, an improved QCheckBox + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _LED_CHECKBOX_H +#define _LED_CHECKBOX_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +class QPixmap; + + +class ledCheckBox : public QCheckBox +{ +public: + enum ledColors + { + YELLOW, GREEN, TOTAL_COLORS + } ; + + ledCheckBox( const QString & _txt, QWidget * _parent, + ledColors _color = YELLOW ); + virtual ~ledCheckBox(); + + +protected: + virtual void paintEvent( QPaintEvent * _pe ); + + +private: + QPixmap * m_ledOnPixmap; + QPixmap * m_ledOffPixmap; + +} ; + +#endif diff --git a/include/midi.h b/include/midi.h new file mode 100644 index 00000000000..5c2ccee3140 --- /dev/null +++ b/include/midi.h @@ -0,0 +1,107 @@ +/* + * midi.h - constants, structs etc. concerning MIDI + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _MIDI_H +#define _MIDI_H + + +#include "types.h" + + + +enum midiEventTypes +{ + // messages + NOTE_OFF = 0x80, + NOTE_ON = 0x90, + KEY_PRESSURE = 0xA0, + CONTROL_CHANGE = 0xB0, + PROGRAM_CHANGE = 0xC0, + CHANNEL_PRESSURE = 0xD0, + PITCH_BEND = 0xE0, + // system exclusive + MIDI_SYSEX = 0xF0, + // system common - never in midi files + MIDI_TIME_CODE = 0xF1, + MIDI_SONG_POSITION = 0xF2, + MIDI_SONG_SELECT = 0xF3, + MIDI_TUNE_REQUEST = 0xF6, + MIDI_EOX = 0xF7, + // system real-time - never in midi files + MIDI_SYNC = 0xF8, + MIDI_TICK = 0xF9, + MIDI_START = 0xFA, + MIDI_CONTINUE = 0xFB, + MIDI_STOP = 0xFC, + MIDI_ACTIVE_SENSING = 0xFE, + MIDI_SYSTEM_RESET = 0xFF, + // meta event - for midi files only + MIDI_META_EVENT = 0xFF +} ; + + + +struct midiEvent +{ + midiEvent( midiEventTypes _type = MIDI_ACTIVE_SENSING, + Uint8 _channel = 0, + Uint16 _param1 = 0, + Uint16 _param2 = 0 ) : + m_type( _type ), + m_channel( _channel ), + m_sysExData( NULL ) + { + m_data.m_param[0] = _param1; + m_data.m_param[1] = _param2; + } + midiEvent( midiEventTypes _type, char * _sysex_data, int _data_len ) : + m_type( _type ), + m_channel( 0 ), + m_sysExData( _sysex_data ) + { + m_data.m_sysExDataLen = _data_len; + } + inline Uint16 key( void ) const + { + return( m_data.m_param[0] ); + } + inline Uint32 velocity( void ) const + { + return( m_data.m_param[1] ); + } + + midiEventTypes m_type; // MIDI event type + Uint8 m_channel; // MIDI channel + union + { + Uint16 m_param[2]; // first/second parameter (key/velocity) + int m_sysExDataLen; // len of m_sysExData + } m_data; + + char * m_sysExData; + +} ; + + +#endif diff --git a/include/midi_alsa_raw.h b/include/midi_alsa_raw.h new file mode 100644 index 00000000000..988268df1e4 --- /dev/null +++ b/include/midi_alsa_raw.h @@ -0,0 +1,107 @@ +/* + * midi_alsa_raw.h - midi-device-driver for RawMIDI via ALSA + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _MIDI_ALSA_RAW_H +#define _MIDI_ALSA_RAW_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_ALSA_ASOUNDLIB_H + +#ifndef ALSA_SUPPORT +#define ALSA_SUPPORT +#endif + +#include + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +#include "midi_device.h" + + +struct pollfd; +class QLineEdit; + + +class midiALSARaw : public midiDevice, public QThread +{ +public: + midiALSARaw( channelTrack * _ct = NULL ); + ~midiALSARaw(); + + static QString probeDevice( void ); + + + inline static QString name( void ) + { + return( setupWidget::tr( "ALSA Raw-MIDI (Advanced Linux Sound " + "Architecture)" ) ); + } + + + class setupWidget : public midiDevice::setupWidget + { + public: + setupWidget( QWidget * _parent ); + virtual ~setupWidget(); + + virtual void saveSettings( void ); + + private: + QLineEdit * m_device; + + } ; + + +protected: + virtual void FASTCALL sendByte( Uint8 _c ); + virtual void FASTCALL run( void ); + + +private: + snd_rawmidi_t * m_input, * * m_inputp; + snd_rawmidi_t * m_output, * * m_outputp; + int m_npfds; + pollfd * m_pfds; + + volatile bool m_quit; + +} ; + +#endif + +#endif diff --git a/include/midi_dummy.h b/include/midi_dummy.h new file mode 100644 index 00000000000..e8276bc7aec --- /dev/null +++ b/include/midi_dummy.h @@ -0,0 +1,77 @@ +/* + * midi_dummy.h - dummy MIDI-driver + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _MIDI_DUMMY_H +#define _MIDI_DUMMY_H + + +#include "midi_device.h" +#include "tab_widget.h" + + +class midiDummy : public midiDevice +{ +public: + midiDummy() : + midiDevice() + { + } + ~midiDummy() + { + } + + inline static QString name( void ) + { + return( setupWidget::tr( "Dummy (no MIDI support)" ) ); + } + + + class setupWidget : public midiDevice::setupWidget + { + public: + setupWidget( QWidget * _parent ) : + midiDevice::setupWidget( midiDummy::name(), _parent ) + { + } + + virtual ~setupWidget() + { + } + + virtual void saveSettings( void ) + { + } + + } ; + + +protected: + virtual void FASTCALL sendByte( Uint8 ) + { + } + +} ; + + +#endif diff --git a/include/midi_mapper.h b/include/midi_mapper.h new file mode 100644 index 00000000000..ab595acd7e1 --- /dev/null +++ b/include/midi_mapper.h @@ -0,0 +1,112 @@ +/* + * midi_mapper.h - MIDI-mapper for any midiDevice + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _MIDI_MAPPER_H +#define _MIDI_MAPPER_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + + +#include "types.h" + + +const Uint8 MIDI_PROGRAMS = 128; +const Uint8 MIDI_KEYS = 128; +const Uint8 MIDI_CHANNELS = 16; + +class midiMapper +{ +public: + midiMapper( const QString & _map ); + ~midiMapper(); + + inline const QString & programName( Uint8 _program ) const + { + return( m_patchMap[_program].second ); + } + + inline Uint8 mappedProgramNumber( Uint8 _program ) const + { + return( m_patchMap[_program].first ); + } + + inline const QString & drumsetKeyName( Uint8 _key ) const + { + return( m_drumsetKeyMap[_key].second ); + } + inline Uint8 keyForDrumName( const QString & _name ) const + { + for( Uint8 i = 0; i < MIDI_KEYS; ++i ) + { + if( m_drumsetKeyMap[i].second == _name ) + { + return( i ); + } + } + return( 0 ); + } + + inline Uint8 drumsetChannel( void ) const + { + return( m_drumsetChannel ); + } + + inline Uint8 drumsetPatch( void ) const + { + return( m_drumsetPatch ); + } + + inline Uint8 mappedChannel( Uint8 _channel ) const + { + return( m_channelMap[_channel] ); + } + + +private: + void readPatchMap( QFile & _f ); + void readDrumsetKeyMap( QFile & _f ); + void readChannelMap( QFile & _f ); + + QPair m_patchMap[MIDI_PROGRAMS]; + QPair m_drumsetKeyMap[MIDI_KEYS]; + Uint8 m_channelMap[MIDI_CHANNELS]; + Uint8 m_drumsetChannel; + Uint8 m_drumsetPatch; + +} ; + + +#endif diff --git a/include/midi_oss.h b/include/midi_oss.h new file mode 100644 index 00000000000..c08b93fa9e3 --- /dev/null +++ b/include/midi_oss.h @@ -0,0 +1,79 @@ +/* + * midi_oss.h - OSS-driver for MIDI-port + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _MIDI_OSS_H +#define _MIDI_OSS_H + +#include +#include + +#include "midi_device.h" + + +class QLineEdit; + + +class midiOSS : public midiDevice, public QThread +{ +public: + midiOSS( channelTrack * _ct = NULL ); + ~midiOSS(); + + static QString probeDevice( void ); + + + inline static QString name( void ) + { + return( setupWidget::tr( "OSS Raw-MIDI (Open Sound System)" ) ); + } + + + class setupWidget : public midiDevice::setupWidget + { + public: + setupWidget( QWidget * _parent ); + virtual ~setupWidget(); + + virtual void saveSettings( void ); + + private: + QLineEdit * m_device; + + } ; + + +protected: + virtual void FASTCALL sendByte( Uint8 _c ); + virtual void FASTCALL run( void ); + + +private: + QFile m_midiDev; + + volatile bool m_quit; + +} ; + + +#endif diff --git a/include/midi_time.h b/include/midi_time.h new file mode 100644 index 00000000000..74abfba1f09 --- /dev/null +++ b/include/midi_time.h @@ -0,0 +1,122 @@ +/* + * midi_time.h - declaration of class midiTime which provides data-type for + * position- and length-variables + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _MIDI_TIME_H +#define _MIDI_TIME_H + +#include "types.h" + + +class midiTime +{ +public: + inline midiTime( tact _tact, tact64th _tact_64th ) : + m_tact( _tact ), + m_tact64th( _tact_64th ) + { + } + + inline midiTime( Sint32 _abs = 0 ) : + m_tact( _abs / 64 ), + m_tact64th( _abs % 64 ) + { + } + + inline midiTime( const midiTime & _t ) + { + *this = _t; + } + + inline midiTime & operator=( const midiTime & _t ) + { + m_tact = _t.m_tact; + m_tact64th = _t.m_tact64th; + return( *this ); + } + + inline midiTime & operator+=( const midiTime & _t ) + { + return( *this = static_cast( *this ) + + static_cast( _t ) ); + } + + inline midiTime & operator-=( const midiTime & _t ) + { + return( *this = static_cast( *this ) - + static_cast( _t ) ); + } + + inline void setTact( tact _t ) + { + m_tact = _t; + } + + inline tact getTact( void ) const + { + return( m_tact ); + } + + inline void setTact64th( tact64th _t ) + { + m_tact64th = _t; + } + + inline tact64th getTact64th( void ) const + { + return( m_tact64th ); + } + + // converts time-class in an absolute value, useful for calculations, + // comparisons and so on... + inline operator Sint32( void ) const + { + return( static_cast( m_tact ) * 64 + + static_cast( m_tact64th ) ); + } + + // calculate number of frame that are needed this time + inline Uint32 frames( float _frames_per_tact ) const + { + if( m_tact >= 0 ) + { + return( static_cast( m_tact * + _frames_per_tact + + m_tact64th * + _frames_per_tact / + 64.0f ) ); + } + return( 0 ); + } + + +private: + tact m_tact; + tact64th m_tact64th; + +} ; + + +#endif + diff --git a/include/mixer.h b/include/mixer.h new file mode 100644 index 00000000000..eceda1ef748 --- /dev/null +++ b/include/mixer.h @@ -0,0 +1,341 @@ +/* + * mixer.h - audio-device-independent mixer for LMMS + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _MIXER_H +#define _MIXER_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include +#include +#include + +#endif + + +#include "types.h" +#include "volume.h" +#include "panning.h" +#include "note.h" +#include "play_handle.h" + + +class audioDevice; +class midiDevice; +class lmmsMainWin; + + +const int DEFAULT_BUFFER_SIZE = 512; + +const Uint16 MAX_SAMPLE_PACKETS = 256; // how many parallel audio-samples- + // buffers shall be maximal exist and + // mixed together? + +const Uint8 DEFAULT_CHANNELS = 2; + +const Uint8 SURROUND_CHANNELS = +#ifndef DISABLE_SURROUND + 4; +#else + 2; +#endif + +const Uint8 QUALITY_LEVELS = 2; +const Uint32 DEFAULT_QUALITY_LEVEL = 0; +const Uint32 HIGH_QUALITY_LEVEL = DEFAULT_QUALITY_LEVEL+1; +extern Uint32 SAMPLE_RATES[QUALITY_LEVELS]; +const Uint32 DEFAULT_SAMPLE_RATE = 44100;//SAMPLE_RATES[DEFAULT_QUALITY_LEVEL]; + + +typedef sampleType sampleFrame[DEFAULT_CHANNELS]; +typedef sampleType surroundSampleFrame[SURROUND_CHANNELS]; + +typedef struct +{ + float vol[SURROUND_CHANNELS]; +} volumeVector; + + +const Uint32 BYTES_PER_SAMPLE = sizeof( sampleType ); +const Uint32 BYTES_PER_FRAME = sizeof( sampleFrame ); +const Uint32 BYTES_PER_SURROUND_FRAME = sizeof( surroundSampleFrame ); +const Uint32 BYTES_PER_OUTPUT_SAMPLE = sizeof( outputSampleType ); + +const float OUTPUT_SAMPLE_MULTIPLIER = 32767.0f; + + +const float BASE_FREQ = 440.0f; +const tones BASE_TONE = A; +const octaves BASE_OCTAVE = OCTAVE_4; + + + +class mixer : +#ifndef QT4 + public QObject, +#endif + public QThread +{ + Q_OBJECT +public: + static inline mixer * inst( void ) + { + if( s_instanceOfMe == NULL ) + { + s_instanceOfMe = new mixer(); + } + return( s_instanceOfMe ); + } + + + void FASTCALL addBuffer( sampleFrame * _buf, Uint32 _frames, + Uint32 _framesAhead, + volumeVector & _volumeVector ); + inline Uint32 framesPerAudioBuffer( void ) const + { + return( m_framesPerAudioBuffer ); + } + + + inline bool highQuality( void ) const + { + return( m_qualityLevel > DEFAULT_QUALITY_LEVEL ); + } + + + inline const surroundSampleFrame * currentAudioBuffer( void ) const + { + return( m_curBuf ); + } + + // audio-device-stuff + inline const QString & audioDevName( void ) const + { + return( m_audioDevName ); + } + + void FASTCALL setAudioDevice( audioDevice * _dev, bool _hq ); + void restoreAudioDevice( void ); + + + // MIDI-device-stuff + inline const QString & midiDevName( void ) const + { + return( m_midiDevName ); + } + + inline midiDevice * getMIDIDevice( void ) + { + return( m_midiDev ); + } + + + inline void addPlayHandle( playHandle * _ph ) + { + m_playHandles.push_back( _ph ); + } + + inline void removePlayHandle( playHandle * _ph ) + { + m_playHandlesToRemove.push_back( _ph ); + } + + void FASTCALL checkValidityOfPlayHandles( void ); + + + inline int sampleRate( void ) + { + return( SAMPLE_RATES[m_qualityLevel] ); + } + + + inline float masterOutput( void ) const + { + return( m_masterOutput ); + } + + inline void setMasterOutput( float _mo ) + { + m_masterOutput = _mo; + } + + + static inline sampleType clip( sampleType _s ) + { + if( _s > 1.0f ) + { + return( 1.0f ); + } + else if( _s < -1.0f ) + { + return( -1.0f ); + } + return( _s ); + } + + + inline void pause( void ) + { + m_safetySyncMutex.lock(); + } + + inline void play( void ) + { + m_safetySyncMutex.unlock(); + } + + + void clear( void ); + + + void FASTCALL clearAudioBuffer( sampleFrame * _ab, Uint32 _frames ); +#ifndef DISABLE_SURROUND + void FASTCALL clearAudioBuffer( surroundSampleFrame * _ab, + Uint32 _frames ); +#endif + + inline bool haveNoRunningNotes( void ) const + { + return( m_playHandles.size() == 0 ); + } + + +public slots: + void setHighQuality( bool _hq_on = FALSE ); + + +signals: + void sampleRateChanged( void ); + void nextAudioBuffer( const surroundSampleFrame *, Uint32 _frames ); + + +private: + struct samplePacket + { + surroundSampleFrame * m_buffer; // actual buffer for + // wave-data + Uint32 m_frames; + Uint32 m_framesDone; + Uint32 m_framesAhead; // number of frames, the buffer + // should be mixed ahead + volume m_vol; + panning m_pan; + enum samplePacketStates + { + READY, FILLING, UNUSED + } m_state; + } ; + + + static mixer * s_instanceOfMe; + + mixer(); + ~mixer(); + + void quitThread( void ); + + + // we don't allow to create mixer by using copy-ctor + mixer( const mixer & ) : +#ifndef QT4 + QObject(), +#endif + QThread(), + m_curBuf( m_buffer1 ), + m_nextBuf( m_buffer2 ) + { + } + + virtual void run( void ); + + + void FASTCALL mixSamplePacket( samplePacket * _sp ); + + + audioDevice * tryAudioDevices( void ); + midiDevice * tryMIDIDevices( void ); + + + + sampleFrame * m_silence; +#ifndef DISABLE_SURROUND + surroundSampleFrame * m_surroundSilence;// cool, silence in surround ;-) +#endif + + + samplePacket m_samplePackets[MAX_SAMPLE_PACKETS]; + + Uint32 m_framesPerAudioBuffer; + + surroundSampleFrame * m_buffer1; + surroundSampleFrame * m_buffer2; + + surroundSampleFrame * m_curBuf; + surroundSampleFrame * m_nextBuf; + + bool m_discardCurBuf; + + + playHandleVector m_playHandles; + playHandleVector m_playHandlesToRemove; + + Uint8 m_qualityLevel; + volatile float m_masterOutput; + + volatile bool m_quit; + + + + audioDevice * m_audioDev; + audioDevice * m_oldAudioDev; + QString m_audioDevName; + + + midiDevice * m_midiDev; + QString m_midiDevName; + + + QMutex m_safetySyncMutex; + QMutex m_devMutex; + + + friend class lmmsMainWin; + +} ; + + +#endif diff --git a/include/mmp.h b/include/mmp.h new file mode 100644 index 00000000000..5490a8ab5a4 --- /dev/null +++ b/include/mmp.h @@ -0,0 +1,109 @@ +/* + * mmp.h - class for reading and writing multimedia-project-files + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _MMP_H +#define _MMP_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +#include "types.h" + + +class multimediaProject : public QDomDocument +{ +public: + enum projectTypes + { + UNKNOWN, + SONG_PROJECT, + CHANNEL_SETTINGS, + EFFECT_SETTINGS, + VIDEO_PROJECT, // will come later... + BURN_PROJECT, // will come later... + PLAYLIST, // will come later... + PROJ_TYPE_COUNT + } ; + + + multimediaProject( const QString & _in_file_name ); + multimediaProject( projectTypes _project_type ); + ~multimediaProject(); + + bool FASTCALL writeFile( const QString & _fn, + bool _overwrite_check = TRUE ); + + inline QDomElement & content( void ) + { + return( m_content ); + } + inline QDomElement & head( void ) + { + return( m_head ); + } + + inline projectTypes type( void ) const + { + return( m_type ); + } + + static projectTypes FASTCALL typeOfFile( const QString & _fn ); + + +private: + static projectTypes FASTCALL type( const QString & _type_name ); + static QString FASTCALL typeName( projectTypes _project_type ); + + struct typeDescStruct + { + projectTypes m_type; + QString m_name; + } ; + static typeDescStruct s_types[PROJ_TYPE_COUNT]; + + QDomElement m_content; + QDomElement m_head; + projectTypes m_type; + +} ; + + +const Uint8 MMP_MAJOR_VERSION = 1; +const Uint8 MMP_MINOR_VERSION = 0; +const QString MMP_VERSION_STRING = QString::number( MMP_MAJOR_VERSION ) + "." + + QString::number( MMP_MINOR_VERSION ); + + +#endif + diff --git a/include/name_label.h b/include/name_label.h new file mode 100644 index 00000000000..c396e761107 --- /dev/null +++ b/include/name_label.h @@ -0,0 +1,75 @@ +/* + * name_label.h - class nameLabel, a label which is renamable by + * double-clicking it + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _NAME_LABEL_H +#define _NAME_LABEL_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + + +class nameLabel : public QLabel +{ + Q_OBJECT +public: + nameLabel( const QString & _initial_name, QWidget * _parent, + const QPixmap & _pm = QPixmap() ); + ~nameLabel(); + const QPixmap * pixmap( void ) const; + + +public slots: + void setPixmap( const QPixmap & _pm ); + void rename( void ); + + +signals: + void nameChanged( const QString & _new_name ); + void clicked( void ); + + +protected: + virtual void mousePressEvent( QMouseEvent * _me ); + virtual void mouseDoubleClickEvent( QMouseEvent * _me ); + virtual void paintEvent( QPaintEvent * _pe ); + + +private: + QPixmap m_pm; + +} ; + +#endif diff --git a/include/note.h b/include/note.h new file mode 100644 index 00000000000..f3293988e34 --- /dev/null +++ b/include/note.h @@ -0,0 +1,167 @@ +/* + * note.h - declaration of class note which contains all informations about a + * note + definitions of several constants and enums + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _NOTE_H +#define _NOTE_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + +#include "volume.h" +#include "panning.h" +#include "midi_time.h" +#include "settings.h" + +enum tones +{ + C = 0, + CIS = 1, DES = 1, + D = 2, + DIS = 3, ES = 3, + E = 4, FES = 4, + F = 5, + FIS = 6, GES = 6, + G = 7, + GIS = 8, AS = 8, + A = 9, + AIS = 10, B = 10, + H = 11 +} ; + + +enum octaves +{ + OCTAVE_0, + OCTAVE_1, + OCTAVE_2, + OCTAVE_3, + OCTAVE_4, // default + OCTAVE_5, + OCTAVE_6, + OCTAVE_7, + OCTAVE_8 +} ; + +const octaves DEFAULT_OCTAVE = OCTAVE_4; +const octaves MIN_OCTAVE = OCTAVE_0; +const octaves MAX_OCTAVE = OCTAVE_8; + +const int WHITE_KEYS_PER_OCTAVE = 7; +const int BLACK_KEYS_PER_OCTAVE = 5; +const int NOTES_PER_OCTAVE = WHITE_KEYS_PER_OCTAVE + BLACK_KEYS_PER_OCTAVE; +const int OCTAVES = 9; + + + +class note : public settings +{ +public: + note( const midiTime & _length = 0, const midiTime & _pos = 0, + tones _tone = A, octaves _octave = DEFAULT_OCTAVE, + volume _volume = DEFAULT_VOLUME, + panning _panning = DEFAULT_PANNING ) FASTCALL; + ~note(); + void FASTCALL setLength( const midiTime & _length ); + void FASTCALL setPos( const midiTime & _pos ); + void FASTCALL setTone( tones _tone = C ); + void FASTCALL setOctave( octaves _octave = DEFAULT_OCTAVE ); + void FASTCALL setKey( int _key ); + void FASTCALL setVolume( volume _volume = DEFAULT_VOLUME ); + void FASTCALL setPanning( panning _panning = DEFAULT_PANNING ); + inline midiTime endPos( void ) const + { + return( m_pos + m_length); + } + inline const midiTime & length( void ) const + { + return( m_length ); + } + inline const midiTime & pos( void ) const + { + return( m_pos ); + } + inline midiTime pos( midiTime _base_pos ) const + { + return( m_pos - _base_pos ); + } + inline tones tone( void ) const + { + return( m_tone ); + } + inline octaves octave( void ) const + { + return( m_octave ); + } + inline int key( void ) const + { + return( m_octave * NOTES_PER_OCTAVE + m_tone ); + } + inline volume getVolume( void ) const + { + return( m_volume ); + } + inline panning getPanning( void ) const + { + return( m_panning ); + } + + virtual void FASTCALL saveSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void FASTCALL loadSettings( const QDomElement & _this ); + inline virtual QString nodeName( void ) const + { + return( "note" ); + } + + +private: + tones m_tone; + octaves m_octave; + volume m_volume; + panning m_panning; + midiTime m_length; + midiTime m_pos; + +} ; + + +typedef vvector noteVector; + + +#endif + diff --git a/include/note_play_handle.h b/include/note_play_handle.h new file mode 100644 index 00000000000..3bd5e0ccbcf --- /dev/null +++ b/include/note_play_handle.h @@ -0,0 +1,180 @@ +/* + * note_play_handle.h - declaration of class notePlayHandle which is needed + * by LMMS-Play-Engine + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _NOTE_PLAY_HANDLE_H +#define _NOTE_PLAY_HANDLE_H + +#include + +#include "play_handle.h" +#include "basic_filters.h" +#include "note.h" + + +class channelTrack; +class notePlayHandle; + +typedef vvector notePlayHandleVector; + + +class notePlayHandle : public playHandle, public note +{ +public: + void * m_pluginData; + basicFilters<> * m_filter; + + notePlayHandle( channelTrack * _chnl_trk, Uint32 _frames_ahead, + Uint32 _frames, note * n, + bool _arp_note = FALSE ) FASTCALL; + ~notePlayHandle(); + + + virtual void play( void ); + + virtual inline bool done( void ) const + { + return( ( m_released && m_framesBeforeRelease == 0 && + m_releaseFramesDone >= m_releaseFramesToDo ) || + m_channelTrack == NULL ); + } + + virtual void checkValidity( void ); + + + void FASTCALL noteOff( Uint32 _s = 0 ); + + inline Uint32 framesBeforeRelease( void ) const + { + return( m_framesBeforeRelease ); + } + + inline Uint32 releaseFramesDone( void ) const + { + return( m_releaseFramesDone ); + } + + Uint32 actualReleaseFramesToDo( void ) const; + + // returns how many samples this note is aligned ahead, i.e. + // at which position it is inserted in the according buffer + inline Uint32 framesAhead( void ) const + { + return ( m_framesAhead ); + } + + // returns total numbers of frames to play + inline Uint32 frames( void ) const + { + return( m_frames ); + } + + void setFrames( Uint32 _frames ); + + // returns whether note was released + inline bool released( void ) const + { + return( m_released ); + } + + // returns total numbers of played frames + inline Uint32 totalFramesPlayed( void ) const + { + return( m_totalFramesPlayed ); + } + + // returns volume-level at frame _frame (envelope/LFO) + float FASTCALL volumeLevel( Uint32 _frame ); + + // adds note-play-handle _n as subnote + inline void addSubNote( notePlayHandle * _n ) + { + m_subNotes.push_back( _n ); + _n->m_baseNote = FALSE; + // if there was an arp-note added and this note is a base-note + // we set arp-note-flag for indicating that this note is an + // arpeggio-base-note + m_arpNote = _n->arpNote() && baseNote(); + } + + // returns channel-track this note-play-handle plays + inline channelTrack * getChannelTrack( void ) + { + return( m_channelTrack ); + } + + // returns whether note is a base-note, e.g. is not part of an arpeggio + // or a chord + inline bool baseNote( void ) const + { + return( m_baseNote ); + } + + // returns whether note is part of an arpeggio + inline bool arpNote( void ) const + { + return( m_arpNote ); + } + + // returns whether note is base-note for arpeggio + inline bool arpBaseNote( void ) const + { + return( baseNote() && arpNote() ); + } + + inline bool muted( void ) const + { + return( m_muted ); + } + + void mute( void ); + + +private: + channelTrack * m_channelTrack; // needed for calling + // channelTrack::playNote + Uint32 m_frames; // total frames to play + Uint32 m_framesAhead; // numbers of frames ahead in buffer + // to mix in + Uint32 m_totalFramesPlayed; // total frame-counter - used for + // figuring out whether a whole note + // has been played + Uint32 m_framesBeforeRelease; // number of frames after which note + // is released + Uint32 m_releaseFramesToDo; // total numbers of frames to be + // played after release + Uint32 m_releaseFramesDone; // number of frames done after + // release of note + notePlayHandleVector m_subNotes;// used for chords and arpeggios + bool m_released; // indicates whether note is released + bool m_baseNote; // indicates whether note is a + // base-note (i.e. no sub-note) + bool m_arpNote; // indicates whether note is part of + // an arpeggio (either base-note or + // sub-note) + bool m_muted; // indicates whether note is muted + +} ; + +#endif diff --git a/include/nstate_button.h b/include/nstate_button.h new file mode 100644 index 00000000000..68cd7bd3b93 --- /dev/null +++ b/include/nstate_button.h @@ -0,0 +1,91 @@ +/* + * nstate_button.h - declaration of class nStateButton + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _NSTATE_BUTTON_H +#define _NSTATE_BUTTON_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include +#include + +#else + +#include +#include +#include +#include + +#endif + + +class nStateButton : public QWidget +{ + Q_OBJECT +public: + nStateButton( QWidget * _parent ); + virtual ~nStateButton(); + void addState( const QPixmap & _pixmap, const QString & _tooltip = "" ); + + inline void setGeneralToolTip( const QString & _tooltip ) + { + m_generalToolTip = _tooltip; + } + + inline int state( void ) const + { + return( m_curState ); + } + + +public slots: + void changeState( int _n ); + + +signals: + void stateChanged( int _n ); + + +protected: + virtual void paintEvent( QPaintEvent * _pe ); + virtual void mousePressEvent( QMouseEvent * _me ); + + +private: + vvector > m_states; + QString m_generalToolTip; + + int m_curState; + +} ; + +#endif diff --git a/include/oscillator.h b/include/oscillator.h new file mode 100644 index 00000000000..a5ead6a4f82 --- /dev/null +++ b/include/oscillator.h @@ -0,0 +1,211 @@ +/* + * oscillator.h - header-file for oscillator.cpp, a powerful oscillator-class + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _OSCILLATOR_H +#define _OSCILLATOR_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#include "mixer.h" +#include "interpolation.h" + + +// fwd-decl because we need it for the typedef below... +class oscillator; + +typedef void ( oscillator:: * oscFuncPtr ) + ( sampleFrame * _ab, Uint32 _frames, Uint8 _chnl ); + + + +class oscillator +{ +public: + enum waveShapes + { + SIN_WAVE, + TRIANGLE_WAVE, + SAW_WAVE, + SQUARE_WAVE, + MOOG_SAW_WAVE, + EXP_WAVE, + WHITE_NOISE_WAVE, + USER_DEF_WAVE + } ; + + enum modulationAlgos + { + FREQ_MODULATION, AMP_MODULATION, MIX, SYNC + } ; + + oscillator( modulationAlgos _modulation_algo, float _freq, + Sint16 _phase_offset, float _volume_factor, + oscillator * _m_subOsc ); + inline virtual ~oscillator() + { + delete m_subOsc; + } + inline void setUserWave( const sampleFrame * _data, Uint32 _frames ) + { + m_userWaveData = _data; + m_userWaveFrames = _frames; + } + inline void update( sampleFrame * _ab, Uint32 _frames, Uint8 _chnl ) + { + ( this->*m_callUpdate )( _ab, _frames, _chnl ); + } + inline void setNewFreq( float _new_freq ) + { + // save current state - we need it later for restoring same + // phase (otherwise we'll get clicks in the audio-stream) + const float v = m_sample * m_oscCoeff; + m_freq = _new_freq; + recalcOscCoeff( phase( v ) ); + } + + static oscillator * FASTCALL createNewOsc( waveShapes _wave_shape, + modulationAlgos _modulation_algo, float _freq, + Sint16 _phase_offset, float _volume_factor, + oscillator * _m_subOsc = NULL ); + + inline bool syncOk( void ) + { + const float v1 = m_sample * m_oscCoeff; + const float v2 = ++m_sample * m_oscCoeff; + // check whether v2 is in next period + return( floorf( v2 ) > floorf( v1 ) ); + } + static inline float phase( float _sample ) + { + float t; + return( modff( _sample, &t ) ); + //return( _sample - floorf( _sample ) ); + } + // now follow the wave-shape-routines... + static inline sampleType sinSample( float _sample ) + { + return( sinf( _sample * static_cast( 2.0f * M_PI + ) ) ); + } + + static inline sampleType triangleSample( float _sample ) + { + const float ph = phase( _sample ); + if( ph <= 0.25f ) + { + return( ph * 4.0f ); + } + else if( ph <= 0.75f ) + { + return( 2.0f - ph * 4.0f ); + } + return( ph * 4.0f - 4.0f ); + } + + static inline sampleType sawSample( float _sample ) + { + return( -1.0f + phase( _sample ) * 2.0f ); + } + + static inline sampleType squareSample( float _sample ) + { + return( ( phase( _sample ) > 0.5f ) ? -1.0f : 1.0f ); + } + + static inline sampleType moogSawSample( float _sample ) + { + const float ph= phase( _sample ); + if( ph < 0.5f ) + { + return( -1.0f + ph * 4.0f ); + } + return( 1.0f - 2.0f * ph ); + } + + static inline sampleType expSample( float _sample ) + { + float ph = phase( _sample ); + if( ph > 0.5f ) + { + ph = 1.0f - ph; + } + return( -1.0f + 8.0f * ph * ph ); + } + + static inline sampleType noiseSample( float ) + { + return( 1.0f - 2.0f * ( ( float )rand() * ( 1.0f / + RAND_MAX ) ) ); + } + inline sampleType userWaveSample( float _sample ) + { + const float frame = phase( _sample ) * m_userWaveFrames; + const Uint32 f1 = static_cast( frame ); + const Uint32 f2 = ( f1 + 1 ) % m_userWaveFrames; + return( linearInterpolate( m_userWaveData[f1][0], + m_userWaveData[f2][0], + frame - floorf( frame ) ) ); + } + + +protected: + float m_freq; + float m_volumeFactor; + Sint16 m_phaseOffset; + oscillator * m_subOsc; + Uint32 m_sample; + float m_oscCoeff; + sampleFrame const * m_userWaveData; + Uint32 m_userWaveFrames; + oscFuncPtr m_callUpdate; + + + virtual void FASTCALL updateNoSub( sampleFrame * _ab, Uint32 _frames, + Uint8 _chnl ) = 0; + virtual void FASTCALL updateFM( sampleFrame * _ab, Uint32 _frames, + Uint8 _chnl ) = 0; + virtual void FASTCALL updateAM( sampleFrame * _ab, Uint32 _frames, + Uint8 _chnl ) = 0; + virtual void FASTCALL updateMix( sampleFrame * _ab, Uint32 _frames, + Uint8 _chnl ) = 0; + virtual void FASTCALL updateSync( sampleFrame * _ab, Uint32 _frames, + Uint8 _chnl ) = 0; + + inline void sync( void ) + { + m_sample = 0; + } + void FASTCALL recalcOscCoeff( const float _additional_phase_offset = + 0.0 ); + +} ; + + +#endif diff --git a/include/panning.h b/include/panning.h new file mode 100644 index 00000000000..6fdd7b1214e --- /dev/null +++ b/include/panning.h @@ -0,0 +1,35 @@ +/* + * panning.h - declaration of some constants and types, concerning the + * panning of a note + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _PANNING_H +#define _PANNING_H + +#include "types.h" + +const panning PANNING_LEFT = ( 0 - 100); +const panning PANNING_RIGHT = ( 0 + 100); +const panning PANNING_CENTER = 0; +const panning DEFAULT_PANNING = PANNING_CENTER; + +#endif diff --git a/include/pattern.h b/include/pattern.h new file mode 100644 index 00000000000..15851671e14 --- /dev/null +++ b/include/pattern.h @@ -0,0 +1,216 @@ +/* + * pattern.h - declaration of class pattern, which contains all informations + * about a pattern + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _PATTERN_H +#define _PATTERN_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include +#include + +#else + +#include +#include +#include +#include + +#endif + + +#include "note.h" +#include "track.h" +#include "mixer.h" + + +class channelTrack; +class sampleBuffer; +class audioSampleRecorder; +class QTimer; +class QProgressBar; +class QPushButton; +class QPixmap; +class patternFreezeStatusDialog; + + + +const int MAX_BEATS_PER_TACT = 16; +const int MAIN_BEATS_PER_TACT = 4; + + +class pattern : public trackContentObject +{ + Q_OBJECT +public: + enum patternTypes + { + BEAT_PATTERN, MELODY_PATTERN/*, EVENT_PATTERN*/ + } ; + + pattern( channelTrack * _channel_track ); + pattern( const pattern & _pat_to_copy ) FASTCALL; + virtual ~pattern(); + + virtual void FASTCALL movePosition( const midiTime & _pos ); + + + virtual midiTime length( void ) const; + note * FASTCALL addNote( const note & _new_note ); + void FASTCALL removeNote( const note * _note_to_del ); + note * FASTCALL rearrangeNote( const note * _note_to_proc ); + void clearNotes( void ); + + inline noteVector & notes( void ) + { + return( m_notes ); + } + + inline patternTypes type( void ) const + { + return( m_patternType ); + } + void FASTCALL setType( patternTypes _new_pattern_type ); + inline const QString & name( void ) const + { + return( m_name ); + } + inline void setName( const QString & _name ) + { + m_name = _name; + update(); + } + inline channelTrack * getChannelTrack( void ) + { + return( m_channelTrack ); + } + + // functions which are part of freezing-feature + inline bool frozen( void ) const + { + return( m_frozenPattern != NULL ); + } + void FASTCALL playFrozenData( sampleFrame * _ab, Uint32 _start_frame, + Uint32 _frames ); + inline bool isFreezing( void ) const + { + return( m_freezeRecorder != NULL ); + } + void finishFreeze( void ); + + + note * FASTCALL noteAt( int _note_num ); + void FASTCALL setNoteAt( int _note_num, note _new_note ); + void checkType( void ); + + virtual void FASTCALL saveSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void FASTCALL loadSettings( const QDomElement & _this ); + inline virtual QString nodeName( void ) const + { + return( "pattern" ); + } + + +protected slots: + void openInPianoRoll( bool _c ); + void openInPianoRoll( void ); + void clear( void ); + void resetName( void ); + void changeName( void ); + void freeze( void ); + void unfreeze( void ); + void updateFreezeStatusDialog( void ); + void abortFreeze( void ); + + +protected: + void paintEvent( QPaintEvent * _pe ); + void mousePressEvent( QMouseEvent * _me ); + void mouseDoubleClickEvent( QMouseEvent * _me ); + virtual void constructContextMenu( QMenu * ); + + void ensureBeatNotes( void ); + + +private: + static QPixmap * s_patternBg; + static QPixmap * s_stepBtnOn; + static QPixmap * s_stepBtnOff; + static QPixmap * s_stepBtnOffLight; + static QPixmap * s_frozen; + + static void initPixmaps( void ); + + + channelTrack * m_channelTrack; + patternTypes m_patternType; + QString m_name; + noteVector m_notes; + + QMutex m_frozenPatternMutex; + sampleBuffer * m_frozenPattern; + audioSampleRecorder * m_freezeRecorder; + patternFreezeStatusDialog * m_freezeStatusDialog; + QTimer * m_freezeStatusUpdateTimer; +} ; + + + + +class patternFreezeStatusDialog : public QDialog +{ + Q_OBJECT +public: + patternFreezeStatusDialog(); + ~patternFreezeStatusDialog(); + + void FASTCALL setProgress( int _p ); + + +protected: + void closeEvent( QCloseEvent * _ce ); + + +protected slots: + void cancelBtnClicked( void ); + + +private: + QProgressBar * m_progressBar; + QPushButton * m_cancelBtn; + + +signals: + void aborted( void ); + +} ; + + +#endif diff --git a/include/pch.h b/include/pch.h new file mode 100644 index 00000000000..f44e92218b1 --- /dev/null +++ b/include/pch.h @@ -0,0 +1,69 @@ +// Qt-headers +#include + +#if QT_VERSION >= 0x040000 + +#include +#include +#include + +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif + + + +// C++ STL / C-stdlib +#include +#include +#include +#include +#include +#include + diff --git a/include/piano_roll.h b/include/piano_roll.h new file mode 100644 index 00000000000..e2c0b70cec2 --- /dev/null +++ b/include/piano_roll.h @@ -0,0 +1,237 @@ +/* + * piano_roll.h - declaration of class pianoRoll which is a window where you + * can set and edit notes in an easy way + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _PIANO_ROLL_H +#define _PIANO_ROLL_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + +#include "types.h" +#include "note.h" + + +class QScrollBar; +class QPainter; +class QPixmap; + +class crystalButton; +class pattern; +class notePlayHandle; +class pixmapButton; +class timeLine; + + + +class pianoRoll : public QWidget +{ + Q_OBJECT +public: + static inline pianoRoll * inst( void ) + { + if( s_instanceOfMe == NULL ) + { + s_instanceOfMe = new pianoRoll(); + } + return( s_instanceOfMe ); + } + + void FASTCALL setCurrentPattern( pattern * _new_pattern ); + inline const pattern * currentPattern( void ) const + { + return( m_pattern ); + } + inline bool validPattern( void ) const + { + return( m_pattern != NULL ); + } + + +protected: + void closeEvent( QCloseEvent * _ce ); + void paintEvent( QPaintEvent * _pe ); + void resizeEvent( QResizeEvent * _re ); + void mousePressEvent( QMouseEvent * _me ); + void mouseReleaseEvent( QMouseEvent * _me ); + void mouseMoveEvent( QMouseEvent * _me ); + void keyPressEvent( QKeyEvent * _ke ); + void keyReleaseEvent( QKeyEvent * _ke ); + void wheelEvent( QWheelEvent * _we ); + + int FASTCALL getKey( int _y ); + inline void drawNoteRect( QPainter & _p, Uint16 _x, Uint16 _y, + Sint16 _width, bool _is_selected ); + void removeSelection( void ); + void selectAll( void ); + void FASTCALL getSelectedNotes( noteVector & _selected_notes ); + + +protected slots: + void play( void ); + void record( void ); + void stop( void ); + + void recordNote( const note & _n ); + + void horScrolled( int _new_pos ); + void verScrolled( int _new_pos ); + + void drawButtonToggled( bool = FALSE ); + void eraseButtonToggled( bool = FALSE ); + void selectButtonToggled( bool = FALSE ); + void moveButtonToggled( bool = FALSE ); + + void copySelectedNotes( void ); + void cutSelectedNotes( void ); + void pasteNotes( void ); + void deleteSelectedNotes( void ); + + void updatePosition( const midiTime & _t ); + + +private: + + enum editModes + { + DRAW, + ERASE, + SELECT, + MOVE + } ; + + enum actions + { + NONE, + MOVE_NOTE, + RESIZE_NOTE, + SELECT_NOTES, + MOVE_SELECTION, + CHANGE_NOTE_VOLUME, + CHANGE_NOTE_PANNING + } ; + + enum pianoRollKeyTypes + { + PR_WHITE_KEY_SMALL, + PR_WHITE_KEY_BIG, + PR_BLACK_KEY + } ; + + + static pianoRoll * s_instanceOfMe; + + static QPixmap * s_whiteKeyBigPm; + static QPixmap * s_whiteKeySmallPm; + static QPixmap * s_artwork1; + static QPixmap * s_artwork2; + static QPixmap * s_blackKeyPm; + static QPixmap * s_toolDraw; + static QPixmap * s_toolErase; + static QPixmap * s_toolSelect; + static QPixmap * s_toolMove; + + static pianoRollKeyTypes prKeyOrder[]; + + + pixmapButton * m_playButton; + pixmapButton * m_recordButton; + pixmapButton * m_stopButton; + + crystalButton * m_drawButton; + crystalButton * m_eraseButton; + crystalButton * m_selectButton; + crystalButton * m_moveButton; + + crystalButton * m_cutButton; + crystalButton * m_copyButton; + crystalButton * m_pasteButton; + + pattern * m_pattern; + QScrollBar * m_leftRightScroll; + QScrollBar * m_topBottomScroll; + + midiTime m_currentPosition; + bool m_recording; + + note * m_currentNote; + actions m_action; + + Uint32 m_selectStartTact64th; + int m_selectedTact64th; + int m_selectStartKey; + int m_selectedKeys; + + int m_moveStartKey; + int m_moveStartTact64th; + int m_moveXOffset; + + int m_notesEditHeight; + int m_ppt; + int m_totalKeysToScroll; + + midiTime m_lenOfNewNotes; + + bool m_shiftPressed; + bool m_controlPressed; + + int m_startKey; // first key when drawing + + int m_lastKey; + + noteVector m_notesToCopy; + noteVector m_selNotesForMove; + + + editModes m_editMode; + + + timeLine * m_timeLine; + bool m_scrollBack; + + + pianoRoll( void ); + pianoRoll( const pianoRoll & ); + ~pianoRoll(); + + +signals: + void positionChanged( const midiTime & ); + +} ; + + +#endif + diff --git a/include/piano_widget.h b/include/piano_widget.h new file mode 100644 index 00000000000..fd113aa3cfa --- /dev/null +++ b/include/piano_widget.h @@ -0,0 +1,104 @@ +/* + * piano_widget.h - declaration of class pianoWidget, a widget which provides + * an interactive piano/keyboard-widget + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _PIANO_WIDGET_H +#define _PIANO_WIDGET_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include +#include + +#endif + + +#include "note.h" + + +class channelTrack; +class notePlayHandle; + + +enum keyTypes +{ + WHITE_KEY, + BLACK_KEY +} ; + + +class pianoWidget : public QWidget +{ + Q_OBJECT +public: + pianoWidget( channelTrack * _channel_track ); + ~pianoWidget(); + + +protected: + void paintEvent( QPaintEvent * ); + void mousePressEvent( QMouseEvent * me ); + void mouseReleaseEvent( QMouseEvent * me ); + void mouseMoveEvent( QMouseEvent * me ); + void keyPressEvent( QKeyEvent * ke ); + void keyReleaseEvent( QKeyEvent * ke ); + void focusInEvent( QFocusEvent * _fe ); + void focusOutEvent( QFocusEvent * _fe ); + + +private: + int FASTCALL getKeyFromMouse( const QPoint & _p ); + int FASTCALL getKeyFromKeyboard( int _k ) const; + int FASTCALL getKeyX( int _key_num ); + + static QPixmap * s_whiteKeyPm; + static QPixmap * s_blackKeyPm; + static QPixmap * s_whiteKeyPressedPm; + static QPixmap * s_blackKeyPressedPm; + + QScrollBar * m_pianoScroll; + channelTrack * m_channelTrack; + tones m_startTone; // first key when drawing + octaves m_startOctave; + + int m_lastKey; + + +private slots: + void pianoScrolled( int _new_pos ); + +} ; + + +#endif + diff --git a/include/pixmap_button.h b/include/pixmap_button.h new file mode 100644 index 00000000000..6376b780c6b --- /dev/null +++ b/include/pixmap_button.h @@ -0,0 +1,78 @@ +/* + * pixmap_button.h - declaration of class pixmapButton + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _PIXMAP_BUTTON_H +#define _PIXMAP_BUTTON_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + + + +class pixmapButton : public QPushButton +{ + Q_OBJECT +public: + pixmapButton( QWidget * _parent ); + virtual ~pixmapButton(); + virtual void FASTCALL setActiveGraphic( const QPixmap & _pm ); + virtual void FASTCALL setInactiveGraphic( const QPixmap & _pm, + bool _update = TRUE ); + void FASTCALL setBgGraphic( const QPixmap & _pm ); + + +signals: + void doubleClicked( void ); + void clickedRight( void ); + + +protected: + virtual void paintEvent( QPaintEvent * _pe ); + virtual void mousePressEvent( QMouseEvent * _me ); + virtual void mouseDoubleClickEvent( QMouseEvent * _me ); + + +private: + QPixmap * m_activePixmap; + QPixmap * m_inactivePixmap; + QPixmap * m_bgPixmap; + +} ; + +#endif diff --git a/include/play_handle.h b/include/play_handle.h new file mode 100644 index 00000000000..cc96636bfa6 --- /dev/null +++ b/include/play_handle.h @@ -0,0 +1,76 @@ +/* + * play_handle.h - base-class playHandle which is needed by + * LMMS-Play-Engine + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _PLAY_HANDLE_H +#define _PLAY_HANDLE_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +class playHandle +{ +public: + inline playHandle( void ) + { + } + virtual inline ~playHandle() + { + } + virtual void play( void ) = 0; + virtual bool done( void ) const = 0; + + // play-handles can invalidate themselves if an object they depend on + // is going to be deleted or things like that - every of those objects + // has to call mixer::inst()->checkValidityOfPlayHandles() in it's dtor + // and set flag before, so LMMS doesn't crash because these play-handles + // would continue using pointers to deleted objects... + virtual void checkValidity( void ) + { + } + + +private: + +} ; + + +typedef vvector playHandleVector; + + +#endif diff --git a/include/preset_preview_play_handle.h b/include/preset_preview_play_handle.h new file mode 100644 index 00000000000..f263524216e --- /dev/null +++ b/include/preset_preview_play_handle.h @@ -0,0 +1,60 @@ +/* + * preset_preview_play_handle.h - play-handle for playing a short preview-sound + * of a preset + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _PRESET_PREVIEW_PLAY_HANDLE_H +#define _PRESET_PREVIEW_PLAY_HANDLE_H + +#include "play_handle.h" + + +class channelTrack; +class notePlayHandle; +class QMutex; + + +class presetPreviewPlayHandle : public playHandle +{ +public: + presetPreviewPlayHandle( const QString & _preset_file ); + virtual ~presetPreviewPlayHandle(); + + static void cleanUp( void ); + + + virtual void play( void ); + virtual bool done( void ) const; + + +private: + static channelTrack * s_globalChannelTrack; + static notePlayHandle * s_globalPreviewNote; + static QMutex * s_globalDataMutex; + + notePlayHandle * m_previewNote; + +} ; + + +#endif diff --git a/include/project_notes.h b/include/project_notes.h new file mode 100644 index 00000000000..5c9bdb312b7 --- /dev/null +++ b/include/project_notes.h @@ -0,0 +1,98 @@ +/* + * project_notes.h - header for project-notes-editor + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _PROJECT_NOTES_H +#define _PROJECT_NOTES_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + +#include "settings.h" + + +class QAction; +class QComboBox; +class QTextEdit; + + +class projectNotes : public QMainWindow, public settings +{ + Q_OBJECT +public: + projectNotes(); + void clear( void ); + + virtual void FASTCALL saveSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void FASTCALL loadSettings( const QDomElement & _this ); + inline virtual QString nodeName( void ) const + { + return( "projectnotes" ); + } + + +protected: + void setupActions( void ); + + +private slots: + void textBold( void ); + void textUnderline( void ); + void textItalic( void ); + void textFamily( const QString & _f ); + void textSize( const QString & _p ); + void textColor( void ); + void textAlign( QAction * _a ); + + void fontChanged( const QFont & _f ); + void colorChanged( const QColor & _c ); + void alignmentChanged( int _a ); + + +private: + QTextEdit * m_edit; + QAction * m_actionTextBold, + * m_actionTextUnderline, + * m_actionTextItalic, + * m_actionTextColor, + * m_actionAlignLeft, + * m_actionAlignCenter, + * m_actionAlignRight, + * m_actionAlignJustify; + QComboBox * m_comboFont; + QComboBox * m_comboSize; + +} ; + + +#endif diff --git a/include/qt3support.h b/include/qt3support.h new file mode 100644 index 00000000000..f0846ff0d1a --- /dev/null +++ b/include/qt3support.h @@ -0,0 +1,177 @@ +/* + * qt3support.h - layer for supporting Qt3 + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _QT3SUPPORT_H +#define _QT3SUPPORT_H + +// don't know why following line is neccessary, it's a bug in qt-headers - +// otherwise LMMS sometimes fails to compile +//#include + +#include +//#include + +#if QT_VERSION >= 0x040000 +#ifndef QT4 +#define QT4 +#endif +#endif + + +#ifdef QT4 + + +class QColorGroup; +#include + + +typedef int csize; +#define QListViewItem Q3ListViewItem +#define vvector QVector +#define vlist QList + + +#else + + +#define vvector QValueVector +#define vlist QValueList + +#define QMenu QPopupMenu +#define QAbstractButton QButton +#define QScrollArea QScrollView + +// QWidget +#define setWindowTitle setCaption +#define setWindowIcon setIcon +#define isExplicitlyHidden isHidden +#define accessibleName name +#define ensurePolished constPolish + + +// QMenu/QPopupMenu +#define addAction insertItem +//#define addSeparator insertSeparator + + +// QFile/QIODevice +#define seek at + + +// QFileDialog +#define setFileMode setMode +#define setDirectory setDir +#define selectFile setSelection + + +// QThread +#define isRunning running + + +// QScrollView/QScrollArea +#define setHorizontalScrollBarPolicy setHScrollBarMode + + +// QScrollBar +#define setMaximum setMaxValue +#define setMinimum setMinValue + + +// QAbstractButton/QButton +#define setCheckable setToggleButton + + +// QInputEvent/QKeyEvent +#define modifiers state + + +// QButtonGroup +#define addButton insert + + +// QProgressBar +#define setTextVisible setPercentageVisible + + +// QFileInfo +//#define completeSuffix extension +//#define suffix() extension( FALSE ) + + +// QComboBox +#define addItem insertItem +//#define currentIndex currentItem +//#define setCurrentIndex setCurrentItem + + +// QString +#define toLower lower + + +// QTextEdit +#define setLineWrapMode setWordWrap +#define setPlainText setText + + +// QSlider +#define setTickPosition setTickmarks + + +// QStatusBar/QSplashScreen +#define showMessage message +#define clearMessage clear + + +// QDir +#define NoFilter DefaultFilter +#define homePath homeDirPath +#define rootPath rootDirPath +//#define absolutePath absPath + + +// QToolButton +#define setMenu setPopup + + +// QPixmap +#define transformed xForm + + +#define Q3ListView QListView +#define Q3ListViewItem QListViewItem +#define Q3ScrollView QScrollView + +#define QMatrix QWMatrix +#define QIcon QIconSet + +#define ShiftModifier ShiftButton +#define ControlModifier ControlButton + +typedef unsigned int csize; + + +#endif + + +#endif diff --git a/include/rename_dialog.h b/include/rename_dialog.h new file mode 100644 index 00000000000..6e5860f8b5d --- /dev/null +++ b/include/rename_dialog.h @@ -0,0 +1,70 @@ +/* + * rename_dialog.h - declaration of class renameDialog, a simple dialog for + * changing the content of a string + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _RENAME_DIALOG_H +#define _RENAME_DIALOG_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +class QLineEdit; + + +class renameDialog : public QDialog +{ + Q_OBJECT +public: + renameDialog( QString & _string ); + ~renameDialog(); + + +protected: + void keyPressEvent( QKeyEvent * _ke ); + + +protected slots: + void textChanged( const QString & _new_string ); + + +private: + QString & m_stringToEdit; + QString m_originalString; + QLineEdit * m_stringLE; + +} ; + + +#endif + diff --git a/include/sample_buffer.h b/include/sample_buffer.h new file mode 100644 index 00000000000..f3bd38ea301 --- /dev/null +++ b/include/sample_buffer.h @@ -0,0 +1,168 @@ +/* + * sample_buffer.h - container-class sampleBuffer + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _SAMPLE_BUFFER_H +#define _SAMPLE_BUFFER_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SAMPLERATE_H +#include +#endif + + +#include "mixer.h" +#include "types.h" + + +class QPainter; + + +class sampleBuffer : public QObject +{ + Q_OBJECT +public: + enum drawMethods + { + LINE_CONNECT, + DOTS + } ; + + sampleBuffer( const QString & _audio_file = "" ); + sampleBuffer( const sampleFrame * _data, Uint32 _frames ); + + ~sampleBuffer(); + + bool FASTCALL play( sampleFrame * _ab, Uint32 _start_frame, + Uint32 _frames = + mixer::inst()->framesPerAudioBuffer(), + float _freq = BASE_FREQ, bool _looped = FALSE, + void * * _resampling_data = NULL ); + void FASTCALL drawWaves( QPainter & _p, QRect _dr, + drawMethods _dm = LINE_CONNECT ); + inline const QString & audioFile( void ) const + { + return( m_audioFile ); + } + inline Uint32 startFrame( void ) const + { + return( m_startFrame ); + } + inline Uint32 endFrame( void ) const + { + return( m_endFrame ); + } + inline Uint32 frames( void ) const + { + return( m_frames ); + } + inline float amplification( void ) const + { + return( m_amplification ); + } + inline bool reversed( void ) const + { + return( m_reversed ); + } + inline const sampleFrame * data( void ) const + { + return( m_data ); + } + + void FASTCALL deleteResamplingData( void * * _ptr ); + + QString openAudioFile( void ) const; + + + +public slots: + void setAudioFile( const QString & _audio_file ); + void setStartFrame( Uint32 _s ); + void setEndFrame( Uint32 _e ); + void setAmplification( float _a ); + void setReversed( bool _on ); + + +private: + void FASTCALL update( bool _keep_settings = FALSE ); + +#ifdef SDL_SDL_SOUND_H + Uint32 FASTCALL decodeSampleSDL( const char * _f, Sint16 * & _buf, + Uint8 & _channels ); +#endif +#ifdef HAVE_SNDFILE_H + Uint32 FASTCALL decodeSampleSF( const char * _f, Sint16 * & _buf, + Uint8 & _channels ); +#endif +#ifdef HAVE_VORBIS_VORBISFILE_H + Uint32 FASTCALL decodeSampleOGG( const char * _f, Sint16 * & _buf, + Uint8 & _channels ); +#endif + + QString m_audioFile; + sampleFrame * m_origData; + Uint32 m_origFrames; + sampleFrame * m_data; + Uint32 m_frames; + Uint32 m_startFrame; + Uint32 m_endFrame; + float m_amplification; + bool m_reversed; + QMutex m_dataMutex; + +#ifdef HAVE_SAMPLERATE_H + void initResampling( void ); + void quitResampling( void ); + SRC_STATE * createResamplingContext( void ); + void FASTCALL destroyResamplingContext( SRC_STATE * _context ); + + SRC_DATA m_srcData; + SRC_STATE * m_srcState; +#endif + + +signals: + void sampleUpdated( void ); + +} ; + + +#endif diff --git a/include/sample_play_handle.h b/include/sample_play_handle.h new file mode 100644 index 00000000000..2df0c434f72 --- /dev/null +++ b/include/sample_play_handle.h @@ -0,0 +1,66 @@ +/* + * sample_play_handle.h - play-handle for playing a sample + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _SAMPLE_PLAY_HANDLE_H +#define _SAMPLE_PLAY_HANDLE_H + +#include "play_handle.h" +#include "types.h" + + +class sampleBuffer; + + +class samplePlayHandle : public playHandle +{ +public: + samplePlayHandle( const QString & _sample_file ); + samplePlayHandle( sampleBuffer * _sample_buffer ); + virtual ~samplePlayHandle(); + + virtual void play( void ); + virtual bool done( void ) const; + + Uint32 totalFrames( void ) const; + inline Uint32 framesDone( void ) const + { + return( m_frame ); + } + void setDoneMayReturnTrue( bool _enable ) + { + m_doneMayReturnTrue = _enable; + } + + +private: + sampleBuffer * m_sampleBuffer; + const bool m_ownSampleBuffer; + bool m_doneMayReturnTrue; + + Uint32 m_frame; + +} ; + + +#endif diff --git a/include/sample_track.h b/include/sample_track.h new file mode 100644 index 00000000000..5953e4e0bde --- /dev/null +++ b/include/sample_track.h @@ -0,0 +1,151 @@ +/* + * sample_track.h - class sampleTrack, a track which provides arrangement of + * samples + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _SAMPLE_TRACK_H +#define _SAMPLE_TRACK_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +#include "track.h" +#include "sample_buffer.h" + + +class nameLabel; +class QLabel; +//class sampleTCOSettingsDialog; + + +class sampleTCO : public trackContentObject +{ + Q_OBJECT +public: + sampleTCO( track * _track ); + virtual ~sampleTCO(); + + virtual void FASTCALL changeLength( const midiTime & _length ); + void FASTCALL play( sampleFrame * _ab, Uint32 _start_frame, + Uint32 _frames ); + const QString & sampleFile( void ) const; + + virtual void FASTCALL saveSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void FASTCALL loadSettings( const QDomElement & _this ); + inline virtual QString nodeName( void ) const + { + return( "sampletco" ); + } + + +public slots: + void setSampleFile( const QString & _sf ); + void updateLength( int = 0 ); + + +protected: + void paintEvent( QPaintEvent * ); + void mouseDoubleClickEvent( QMouseEvent * ); + midiTime getSampleLength( void ) const; + + +private: + sampleBuffer m_sampleBuffer; + + + //friend class sampleTCOSettingsDialog; + +} ; + + + +/* +class sampleTCOSettingsDialog : public QDialog +{ + Q_OBJECT +public: + sampleTCOSettingsDialog( sampleTCO * _stco ); + ~sampleTCOSettingsDialog(); + + +protected slots: + void openSampleFile( void ); + void setSampleFile( const QString & _f ); + + +private: + sampleTCO * m_sampleTCO; + QLabel * m_fileLbl; + +} ; +*/ + + + +class sampleTrack : public QObject, public track +{ + Q_OBJECT +public: + sampleTrack( trackContainer * _tc ); + virtual ~sampleTrack(); + + virtual trackTypes trackType( void ) const; + virtual bool FASTCALL play( const midiTime & _start, + Uint32 _start_frame, Uint32 _frames, + Uint32 _frame_base, + Sint16 _tco_num = -1 ); + virtual trackContentObject * FASTCALL createTCO( const midiTime & + _pos ); + + + virtual void FASTCALL saveTrackSpecificSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void FASTCALL loadTrackSpecificSettings( const QDomElement & + _this ); + + +public slots: + virtual QString nodeName( void ) const + { + return( "sampletrack" ); + } + + +private: + nameLabel * m_trackLabel; + +} ; + + +#endif diff --git a/include/setup_dialog.h b/include/setup_dialog.h new file mode 100644 index 00000000000..ff9e03b0102 --- /dev/null +++ b/include/setup_dialog.h @@ -0,0 +1,113 @@ +/* + * setup_dialog.h - dialog for setting up LMMS + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _SETUP_DIALOG_H +#define _SETUP_DIALOG_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + +#include "audio_device.h" +#include "midi_device.h" + + +class QComboBox; +class QLabel; +class QSlider; + +class tabBar; + + +class setupDialog : public QDialog +{ + Q_OBJECT +public: + enum configTabs + { + GENERAL_SETTINGS, AUDIO_SETTINGS, MIDI_SETTINGS + } ; + + setupDialog( configTabs _tab_to_open = GENERAL_SETTINGS ); + ~setupDialog(); + + +protected slots: + virtual void accept( void ); + + +private slots: + // general settings widget + void setBufferSize( int _value ); + void resetBufSize( void ); + void displayBufSizeHelp( void ); + + // audio settings widget + void audioInterfaceChanged( const QString & _driver ); + void displayAudioHelp( void ); + + // MIDI settings widget + void midiInterfaceChanged( const QString & _driver ); + void displayMIDIHelp( void ); + + + void toggleToolTips( bool _disabled ); + void toggleKnobUsability( bool _classical ); + + +private: + tabBar * m_tabBar; + + QSlider * m_bufSizeSlider; + QLabel * m_bufSizeLbl; + int m_bufferSize; + + bool m_disableToolTips; + bool m_classicalKnobUsability; + + + typedef QMap aswMap; + typedef QMap mswMap; + + QComboBox * m_audioInterfaces; + aswMap m_audioIfaceSetupWidgets; + + QComboBox * m_midiInterfaces; + mswMap m_midiIfaceSetupWidgets; + + +} ; + + +#endif diff --git a/include/side_bar.h b/include/side_bar.h new file mode 100644 index 00000000000..0f0f427995a --- /dev/null +++ b/include/side_bar.h @@ -0,0 +1,106 @@ +/* + * side_bar.h - code for side-bar in LMMS + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _SIDE_BAR_H +#define _SIDE_BAR_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +#include "kmultitabbar.h" +#include "side_bar_widget.h" + + +class sideBar : public KMultiTabBar +{ + Q_OBJECT +public: + sideBar( Qt::Orientation _o, QWidget * _parent ) : + KMultiTabBar( _o, _parent ) + { + } + virtual ~sideBar() + { + } + + inline int appendTab( sideBarWidget * _sbw, int _id ) + { + int ret = KMultiTabBar::appendTab( _sbw->icon(), _id, + _sbw->title() ); + m_widgets[_id] = _sbw; + _sbw->hide(); + _sbw->setMinimumWidth( 200 ); + connect( tab( _id ), SIGNAL( clicked( int ) ), this, + SLOT( tabClicked( int ) ) ); + return( ret ); + } + + +private slots: + inline void tabClicked( int _id ) + { + // disable all other tabbar-buttons + QMap::Iterator it; + for( it = m_widgets.begin(); it != m_widgets.end(); ++it ) + { + if( it.key() != _id/* && isTabRaised(it.key()) == TRUE*/ ) + { + setTab( it.key(), FALSE ); + } + if( m_widgets[it.key()] != NULL ) + { + m_widgets[it.key()]->hide(); + } + } + if( m_widgets[_id] != NULL ) + { + if( isTabRaised( _id ) ) + { + m_widgets[_id]->show(); + } + else + { + m_widgets[_id]->hide(); + } + } + } + + +private: + QMap m_widgets; + +} ; + + +#endif diff --git a/include/side_bar_widget.h b/include/side_bar_widget.h new file mode 100644 index 00000000000..11032a954ca --- /dev/null +++ b/include/side_bar_widget.h @@ -0,0 +1,88 @@ +/* + * side_bar_widget.h - base-class for all side-bar-widgets + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _SIDE_BAR_WIDGET_H +#define _SIDE_BAR_WIDGET_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include +#include + +#endif + + +class sideBarWidget : public QWidget +{ + Q_OBJECT +public: + sideBarWidget( const QString & _title, const QPixmap & _icon, + QWidget * _parent ); + ~sideBarWidget(); + inline const QPixmap & icon( void ) const + { + return( m_icon ); + } + inline const QString & title( void ) const + { + return( m_title ); + } + + +protected: + void paintEvent( QPaintEvent * _pe ); + void resizeEvent( QResizeEvent * _re ); + inline void contextMenuEvent( QContextMenuEvent * ) + { + } + + inline QWidget * contentParent( void ) + { + return( m_contents ); + } + inline void addContentWidget( QWidget * _w ) + { + m_layout->addWidget( _w ); + } + + +private: + QWidget * m_contents; + QVBoxLayout * m_layout; + QString m_title; + QPixmap m_icon; + +} ; + + +#endif diff --git a/include/song_editor.h b/include/song_editor.h new file mode 100644 index 00000000000..c70f62a6a3c --- /dev/null +++ b/include/song_editor.h @@ -0,0 +1,342 @@ +/* + * song_editor.h - declaration of class songEditor, a window where you can + * setup your songs + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _SONG_EDITOR_H +#define _SONG_EDITOR_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +#include "lmms_main_win.h" +#include "track_container.h" +#include "types.h" + + +class QLabel; +class QPixmap; +class QPushButton; +class QScrollBar; +class QSlider; +class QToolButton; +class exportProjectDialog; +class lcdSpinBox; +class pattern; +class projectNotes; +class timeLine; +class visualizationWidget; + + + +const int MIN_BPM = 10; +const int DEFAULT_BPM = 140; +const int MAX_BPM = 1000; +const Uint16 MAX_SONG_LENGTH = 9999; + + + +class songEditor : public trackContainer +{ + Q_OBJECT +public: + enum playModes + { + PLAY_SONG, + PLAY_TRACK, + PLAY_BB, + PLAY_PATTERN, + PLAY_MODE_CNT + } ; + + + class playPos : public midiTime + { + public: + playPos( Sint32 _abs = 0 ) : + midiTime( _abs ), + m_timeLine( NULL ), + m_timeLineUpdate( TRUE ), + m_currentFrame( 0 ) + { + } + inline void setCurrentFrame( Uint32 _f ) + { + m_currentFrame = _f; + } + inline Uint32 currentFrame( void ) const + { + return( m_currentFrame ); + } + timeLine * m_timeLine; + bool m_timeLineUpdate; + + private: + Uint32 m_currentFrame; + } ; + + + + static inline songEditor * inst( void ) + { + if( s_instanceOfMe == NULL ) + { + s_instanceOfMe = new songEditor(); + } + return( s_instanceOfMe ); + } + + void processNextBuffer( void ); + + + inline bool paused( void ) const + { + return( m_paused ); + } + + inline bool playing( void ) const + { + return( m_playing && m_exporting == FALSE ); + } + + inline bool exporting( void ) const + { + return( m_exporting ); + } + + inline bool exportDone( void ) const + { + return( m_exporting == TRUE && + m_playPos[PLAY_SONG].getTact() >= lengthInTacts() + 1 ); + } + inline void setExportProjectDialog( exportProjectDialog * _epd ) + { + m_epd = _epd; + } + inline playModes playMode( void ) const + { + return( m_playMode ); + } + inline playPos & getPlayPos( playModes _pm ) + { + return( m_playPos[_pm] ); + } + + // every function that replaces current file (e.g. creates new file, + // opens another file...) has to call this before and may only process + // if this function returns true + bool mayChangeProject( void ); + + + float framesPerTact( void ) const; + + // file management + void createNewProject( void ); + void FASTCALL createNewProjectFromTemplate( const QString & _template ); + void FASTCALL loadProject( const QString & _file_name ); + bool saveProject( void ); + bool FASTCALL saveProjectAs( const QString & _file_name ); + inline const QString & projectFileName( void ) const + { + return( m_fileName ); + } + virtual void FASTCALL saveSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void FASTCALL loadSettings( const QDomElement & _this ); + inline virtual QString nodeName( void ) const + { + return( "songeditor" ); + } + + virtual inline bool fixedTCOs( void ) const + { + return( FALSE ); + } + + int masterPitch( void ) const; + + projectNotes * getProjectNotesWindow( void ) + { + return( m_projectNotes ); + } + + +public slots: + void play( void ); + void stop( void ); + void playTrack( track * _trackToPlay ); + void playBB( void ); + void playPattern( pattern * _patternToPlay, bool _loop = TRUE ); + void pause( void ); + void resumeFromPause( void ); + + void importProject( void ); + void exportProject( void ); + + void startExport( void ); + void stopExport( void ); + // set BPM (beats per minute) + void setBPM( int _new_bpm = DEFAULT_BPM ); + + inline void setModified( void ) + { + m_modified = TRUE; + } + + +protected: + void closeEvent( QCloseEvent * _ce ); + void resizeEvent( QResizeEvent * _re ); + void keyPressEvent( QKeyEvent * _ke ); + void wheelEvent( QWheelEvent * _we ); + void paintEvent( QPaintEvent * _pe ); + + +protected slots: + void insertTact( void ); + void removeTact( void ); + void addChannelTrack( void ); + void addBBTrack( void ); + void addSampleTrack( void ); + void scrolled( int _new_pos ); + void updateTimeLinePosition( void ); + + void masterVolumeChanged( int _new_val ); + void masterVolumePressed( void ); + void masterVolumeMoved( int _new_val ); + void masterVolumeReleased( void ); + void masterPitchChanged( int _new_val ); + void masterPitchPressed( void ); + void masterPitchMoved( int _new_val ); + void masterPitchReleased( void ); + void toggleHQMode( void ); + + void updatePosition( const midiTime & _t ); + + +private: + songEditor(); + songEditor( const songEditor & ); + virtual ~songEditor(); + + void clearProject( void ); + + + inline tact currentTact( void ) const + { + return( m_playPos[m_playMode].getTact() ); + } + + midiTime length( void ) const; + tact lengthInTacts( void ) const; + inline tact64th currentTact64th( void ) const + { + return( m_playPos[m_playMode].getTact64th() ); + } + void FASTCALL setPlayPos( tact _tact_num, tact64th _t_64th, playModes + _play_mode ); + + + + static songEditor * s_instanceOfMe; + + QScrollBar * m_leftRightScroll; + + QToolButton * m_playButton; + QToolButton * m_stopButton; + lcdSpinBox * m_bpmSpinBox; + + QSlider * m_masterVolumeSlider; + QSlider * m_masterPitchSlider; + + visualizationWidget * m_masterOutputGraph; + + + QToolButton * m_addChannelTrackButton; + QToolButton * m_addBBTrackButton; + QToolButton * m_addSampleTrackButton; + QToolButton * m_insertTactButton; + QToolButton * m_removeTactButton; + + + + QString m_fileName; + QString m_oldFileName; + bool m_modified; + + volatile bool m_exporting; + volatile bool m_playing; + volatile bool m_paused; + + playModes m_playMode; + playPos m_playPos[PLAY_MODE_CNT]; + + track * m_trackToPlay; + pattern * m_patternToPlay; + bool m_loopPattern; + + bool m_scrollBack; + + exportProjectDialog * m_epd; + + + projectNotes * m_projectNotes; + + + + enum ACTIONS + { + ACT_STOP_PLAY, ACT_PLAY_SONG, ACT_PLAY_TRACK, ACT_PLAY_BB, + ACT_PLAY_PATTERN, ACT_PAUSE, ACT_RESUME_FROM_PAUSE + } ; + vvector m_actions; + + void doActions( void ); + + + bool m_shiftPressed; + bool m_controlPressed; + + + + friend lmmsMainWin::~lmmsMainWin(); + + + +signals: + void bpmChanged( int _new_bpm ); + +} ; + + +#endif diff --git a/include/spc_bg_hndl_widget.h b/include/spc_bg_hndl_widget.h new file mode 100644 index 00000000000..901a3f0fba7 --- /dev/null +++ b/include/spc_bg_hndl_widget.h @@ -0,0 +1,135 @@ +/* + * spc_bg_hndl_widget.h - class specialBgHandlingWidget + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _SPC_BG_HNDL_WIDGET_H +#define _SPC_BG_HNDL_WIDGET_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include + +#endif + + +class specialBgHandlingWidget +{ +public: + specialBgHandlingWidget( const QPixmap & _pm ) : + m_backgroundPixmap( _pm ), + m_backgroundColor( QColor( 0, 0, 0 ) ) + { + } + + specialBgHandlingWidget( const QColor & _c ) : + m_backgroundPixmap(), + m_backgroundColor( _c ) + { + } + + ~specialBgHandlingWidget() + { + } + + const QPixmap & backgroundPixmap( void ) const + { + return( m_backgroundPixmap ); + } + const QColor & backgroundColor( void ) const + { + return( m_backgroundColor ); + } + + static QPixmap getBackground( const QWidget * _w ) + { + QPixmap pm( _w->size() ); + const QWidget * pw = _w->parentWidget(); + if( dynamic_cast( pw ) ) + { + const specialBgHandlingWidget * s = dynamic_cast< + const specialBgHandlingWidget *>( pw ); + if( s->backgroundPixmap().isNull() == FALSE ) + { +#ifdef QT4 + QPainter p( &pm ); + p.drawPixmap( 0, 0, s->backgroundPixmap(), + _w->x(), _w->y(), _w->width(), + _w->height() ); +#else + bitBlt( &pm, 0, 0, &s->backgroundPixmap(), + _w->x(), _w->y(), _w->width(), + _w->height() ); +#endif + } + else + { + pm.fill( s->backgroundColor() ); + } + } + else + { +#ifdef QT4 + QPainter p( &pm ); + // TODO: fix that for background-pixmaps, because + // drawing is started at the top left edge even + // if this widget isn't posated there + p.fillRect( _w->rect(), pw->palette().brush( + pw->backgroundRole() ) ); +#else + const QPixmap * pbp = pw->paletteBackgroundPixmap(); + if( pbp == NULL ) + { + pbp = pw->erasePixmap(); + } + if( pbp ) + { + bitBlt( &pm, 0, 0, pbp, _w->x(), _w->y(), + _w->width(), _w->height() ); + } + else + { + pm.fill( pw->paletteBackgroundColor() ); + } +#endif + } + return( pm ); + } + + + +private: + QPixmap m_backgroundPixmap; + QColor m_backgroundColor; + +} ; + +#endif diff --git a/include/surround_area.h b/include/surround_area.h new file mode 100644 index 00000000000..23dd9cdb31e --- /dev/null +++ b/include/surround_area.h @@ -0,0 +1,91 @@ +/* + * surround_area.h - class surroundArea which provides widget for setting + * position of a channel + calculation of volume for each + * speaker + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _SURROUND_AREA_H +#define _SURROUND_AREA_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +#include "types.h" +#include "mixer.h" +#include "templates.h" + + +class QPixmap; + +const int SURROUND_AREA_SIZE = 1024; + + +class surroundArea : public QWidget +{ + Q_OBJECT +public: + surroundArea( QWidget * _parent = NULL ); + virtual ~surroundArea(); + volumeVector getVolumeVector( float _v_scale = 0.0f ) const; + inline const QPoint & value( void ) const + { + return( m_sndSrcPos ); + } + void FASTCALL setValue( const QPoint & _p ); + + +protected: + virtual void paintEvent( QPaintEvent * _pe ); + virtual void mousePressEvent( QMouseEvent * _me ); + virtual void mouseMoveEvent( QMouseEvent * _me ); + virtual void mouseReleaseEvent( QMouseEvent * _me ); + + +signals: + void valueChanged( const QPoint & _p ); + + +private: + float FASTCALL getVolume( const QPoint & _speaker_pos, + float _v_scale ) const; + + QPoint m_sndSrcPos; + + static const QPoint s_defaultSpeakerPositions[SURROUND_CHANNELS]; + static QPixmap * s_backgroundArtwork; + +} ; + + +#endif + diff --git a/include/tab_bar.h b/include/tab_bar.h new file mode 100644 index 00000000000..e960965003b --- /dev/null +++ b/include/tab_bar.h @@ -0,0 +1,102 @@ +/* + * tab_bar.h - class tabBar + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _TAB_BAR_H +#define _TAB_BAR_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include +#include + +#endif + + + +class tabButton; + + +class tabBar : public QWidget +{ + Q_OBJECT +public: + tabBar( QWidget * _parent, + QBoxLayout::Direction _dir = QBoxLayout::LeftToRight ); + virtual ~tabBar(); + + tabButton * FASTCALL addTab( QWidget * _w, const QString & _text, + int _id, bool _add_stretch = FALSE, + bool _text_is_tooltip = FALSE ); + void FASTCALL removeTab( int _id ); + + inline void setExclusive( bool _on ) + { + m_exclusive = _on; + } + + int activeTab( void ); + + +public slots: + void setActiveTab( int _id ); + + +protected: + bool FASTCALL tabState( int _id ); + void FASTCALL setTabState( int _id, bool _checked ); + bool allHidden( void ); + + +protected slots: + void hideAll( int _exception = -1 ); + void tabClicked( int _id ); + + +private: + QMap > m_tabs; + QBoxLayout * m_layout; + bool m_exclusive; + + +signals: + void allWidgetsHidden( void ); + void widgetShown( void ); + +} ; + + +#endif diff --git a/include/tab_button.h b/include/tab_button.h new file mode 100644 index 00000000000..abda20ec96d --- /dev/null +++ b/include/tab_button.h @@ -0,0 +1,75 @@ +/* + * tab_button.h - declaration of class tabButton + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _TAB_BUTTON_H +#define _TAB_BUTTON_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + + +class tabButton : public QPushButton +{ + Q_OBJECT +public: + tabButton( const QString & _text, int _id, QWidget * _parent ) : + QPushButton( _text, _parent ), + m_id( _id ) + { + setCheckable( TRUE ); + connect( this, SIGNAL( clicked() ), this, + SLOT( slotClicked() ) ); + } + virtual ~tabButton() + { + } + + +signals: + void clicked( int ); + + +protected slots: + void slotClicked( void ) + { + emit clicked( m_id ); + } + + +private: + int m_id; + +} ; + +#endif diff --git a/include/tab_widget.h b/include/tab_widget.h new file mode 100644 index 00000000000..72f4b8153cd --- /dev/null +++ b/include/tab_widget.h @@ -0,0 +1,74 @@ +/* + * tab_widget.h - LMMS-tabwidget + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _TAB_WIDGET_H +#define _TAB_WIDGET_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + + +class tabWidget : public QWidget +{ + Q_OBJECT +public: + tabWidget( const QString & _caption, QWidget * _parent ); + ~tabWidget(); + + void addTab( QWidget * _w, const QString & _name ); + + +protected: + virtual void mousePressEvent( QMouseEvent * _me ); + virtual void paintEvent( QPaintEvent * _pe ); + virtual void resizeEvent( QResizeEvent * _re ); + + +private: + struct widgetDesc + { + QWidget * w; // ptr to widget + QString name; // name for widget + int nwidth; // width of name when painting + } ; + typedef vvector widgetStack; + + widgetStack m_widgets; + int m_curWidget; + QString m_caption; + +} ; + +#endif diff --git a/include/templates.h b/include/templates.h new file mode 100644 index 00000000000..45538867198 --- /dev/null +++ b/include/templates.h @@ -0,0 +1,102 @@ +/* + * templates.h - miscellanous templates and algorithms + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _TEMPLATES_H +#define _TEMPLATES_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include +#include + +#endif + + +template +inline T tAbs( const T & x ) +{ + return( x < static_cast( 0 ) ? -x : x ); +} + + + + +template +inline T tMin( const T & x1, const T & x2 ) +{ + if( x1 < x2 ) + { + return( x1 ); + } + return( x2 ); +} + + + + +template +inline T tMax( const T & x1, const T & x2 ) +{ + if( x1 > x2 ) + { + return( x1 ); + } + return( x2 ); +} + + + + +template +inline T tLimit( const T & x, const T & x1, const T & x2 ) +{ + return( tMin( tMax( x, tMin( x1, x2 ) ), + tMax( x1, x2 ) ) ); + +} + + +template +inline QFont pointSize( QFont _f ) +{ + const int DPI = 96; +#ifdef QT4 + _f.setPointSizeF( SIZE * DPI / QX11Info::appDpiX() ); +#else + _f.setPointSizeFloat( SIZE * DPI / QPaintDevice::x11AppDpiX() ); +#endif + return( _f ); +} + + +#endif diff --git a/include/text_float.h b/include/text_float.h new file mode 100644 index 00000000000..5263dda5f2e --- /dev/null +++ b/include/text_float.h @@ -0,0 +1,66 @@ +/* + * text_float.h - class textFloat, a floating text-label + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _TEXT_FLOAT +#define _TEXT_FLOAT + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +class textFloat : public QWidget +{ +public: + textFloat( QWidget * _parent ); + virtual ~textFloat() + { + } + + void setText( const QString & _text ); + + void reparent( QWidget * _new_parent ); + + void setVisibilityTimeOut( int _msecs ); + + +protected: + virtual void paintEvent( QPaintEvent * _me ); + + +private: + QString m_text; + +} ; + + +#endif diff --git a/include/timeline.h b/include/timeline.h new file mode 100644 index 00000000000..b9d0dd1cf29 --- /dev/null +++ b/include/timeline.h @@ -0,0 +1,160 @@ +/* + * timeline.h - class timeLine, representing a time-line with position marker + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _TIMELINE_H +#define _TIMELINE_H + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +#include "song_editor.h" + + +class QPixmap; +class nStateButton; + + +class timeLine : public QWidget +{ + Q_OBJECT +public: + timeLine( int _xoff, int _yoff, float _ppt, songEditor::playPos & _pos, + const midiTime & _begin, QWidget * _parent ); + ~timeLine(); + + inline songEditor::playPos & pos( void ) + { + return( m_pos ); + } + + enum behaviourAtStopStates + { + BACK_TO_ZERO, BACK_TO_START, KEEP_STOP_POSITION + } ; + + + behaviourAtStopStates behaviourAtStop( void ) const; + + bool loopPointsEnabled( void ) const; + inline const midiTime & loopBegin( void ) const + { + return( ( m_loopPos[0] < m_loopPos[1] ) ? + m_loopPos[0] : m_loopPos[1] ); + } + inline const midiTime & loopEnd( void ) const + { + return( ( m_loopPos[0] > m_loopPos[1] ) ? + m_loopPos[0] : m_loopPos[1] ); + } + + inline void savePos( const midiTime & _pos ) + { + m_savedPos = _pos; + } + inline const midiTime & savedPos( void ) const + { + return( m_savedPos ); + } + + inline void setPixelsPerTact( float _ppt ) + { + m_ppt = _ppt; + update(); + } + + +public slots: + void updatePosition( const midiTime & = 0 ); + void toggleLoopPoints( int _n ); + + +protected: + virtual void paintEvent( QPaintEvent * _pe ); + virtual void mousePressEvent( QMouseEvent * _me ); + virtual void mouseMoveEvent( QMouseEvent * _me ); + virtual void mouseReleaseEvent( QMouseEvent * _me ); + + +private: + inline int markerX( const midiTime & _t ) const + { + return( m_xOffset + static_cast( ( _t - m_begin ) * + m_ppt / 64.0f ) ); + } + + + static QPixmap * s_timeLinePixmap; + static QPixmap * s_posMarkerPixmap; + static QPixmap * s_loopPointPixmap; + + nStateButton * m_autoScroll; + nStateButton * m_loopPoints; + nStateButton * m_behaviourAtStop; + + int m_xOffset; + int m_posMarkerX; + float m_ppt; + songEditor::playPos & m_pos; + const midiTime & m_begin; + midiTime m_loopPos[2]; + + midiTime m_savedPos; + + + enum actions + { + NONE, MOVE_POS_MARKER, MOVE_LOOP_BEGIN, MOVE_LOOP_END + } m_action; + + int m_moveXOff; + + + enum autoScrollStates + { + AUTOSCROLL_ENABLED, AUTOSCROLL_DISABLED + } ; + + enum loopPointStates + { + LOOP_POINTS_DISABLED, LOOP_POINTS_ENABLED + } ; + + +signals: + void positionChanged( const midiTime & _t ); + +} ; + + +#endif diff --git a/include/tooltip.h b/include/tooltip.h new file mode 100644 index 00000000000..7bf2b65a1bb --- /dev/null +++ b/include/tooltip.h @@ -0,0 +1,42 @@ +/* + * tooltip.h - namespace toolTip, a tooltip-wrapper for LMMS + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _TOOLTIP_H +#define _TOOLTIP_H + +#include + +class QWidget; + + +namespace toolTip +{ + + void add( QWidget * _w, const QString & _txt ); + //void remove( QWidget * _w ); + +} ; + + +#endif diff --git a/include/track.h b/include/track.h new file mode 100644 index 00000000000..39e2605b86e --- /dev/null +++ b/include/track.h @@ -0,0 +1,358 @@ +/* + * track.h - declaration of classes concerning tracks -> neccessary for all + * track-like objects (beat/bassline, sample-track...) + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _TRACK_H +#define _TRACK_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include +#include + +#endif + +#ifdef HAVE_CONFIG_H +#include +#endif + + +#include "types.h" +#include "midi_time.h" +#include "settings.h" + + +class track; +class trackContainer; +class trackContentWidget; +class trackWidget; +class pixmapButton; +class QMenu; + +typedef QWidget trackSettingsWidget; +typedef QWidget trackOperationsWidget; + + + +const Uint16 DEFAULT_SETTINGS_WIDGET_WIDTH = 224; +const Uint16 TRACK_OP_WIDTH = 70; +const Uint16 TCO_BORDER_WIDTH = 1; + + +class trackContentObject : public QWidget, public settings +{ + Q_OBJECT +public: + trackContentObject( track * _track ); + trackContentObject( const trackContentObject & _copy ); + virtual ~trackContentObject(); + inline track * getTrack( void ) + { + return( m_track ); + } + inline const midiTime & startPosition( void ) const + { + return( m_startPosition ); + } + inline midiTime endPosition( void ) const + { + return( m_startPosition + m_length ); + } + inline const midiTime & length( void ) const + { + return( m_length ); + } + bool fixedTCOs( void ); + virtual void FASTCALL movePosition( const midiTime & _pos ); + virtual void FASTCALL changeLength( const midiTime & _length ); + + +public slots: + virtual void close( void ); + + +protected: + virtual void mousePressEvent( QMouseEvent * _me ); + virtual void mouseMoveEvent( QMouseEvent * _me ); + virtual void mouseReleaseEvent( QMouseEvent * _me ); + virtual void contextMenuEvent( QContextMenuEvent * _cme ); + virtual void constructContextMenu( QMenu * ) + { + } + void setAutoResizeEnabled( bool _e = FALSE ); + float pixelsPerTact( void ); + + +protected slots: + void cut( void ); + void copy( void ); + void paste( void ); + + +private: + track * m_track; + midiTime m_startPosition; + midiTime m_length; + bool m_moving; + bool m_resizing; + bool m_autoResize; + Sint16 m_initialMouseX; + +} ; + + + + +class trackContentWidget : public QWidget +{ + Q_OBJECT +public: + trackContentWidget( trackWidget * _parent ); + virtual ~trackContentWidget(); + + trackContentObject * FASTCALL getTCO( csize _tco_num ); + csize numOfTCOs( void ); + trackContentObject * FASTCALL addTCO( trackContentObject * _tco ); + void FASTCALL removeTCO( csize _tco_num, bool _also_delete = TRUE ); + void FASTCALL removeTCO( trackContentObject * _tco, + bool _also_delete = TRUE ); + void removeAllTCOs( void ); + void FASTCALL swapPositionOfTCOs( csize _tco_num1, csize _tco_num2 ); + + inline Uint16 pixelsPerTact( void ) const + { + return( m_pixelsPerTact ); + } + inline void setPixelsPerTact( Uint16 _ppt ) + { + m_pixelsPerTact = _ppt; + } + tact length( void ) const; + + +public slots: + void insertTact( const midiTime & _pos ); + void removeTact( const midiTime & _pos ); + void updateTCOs( void ); + + +protected: + virtual void mousePressEvent( QMouseEvent * _me ); + virtual void mouseMoveEvent( QMouseEvent * _me ); + virtual void mouseReleaseEvent( QMouseEvent * _me ); + virtual void resizeEvent( QResizeEvent * _re ); + + +private: + typedef vvector tcoVector; + + tcoVector m_trackContentObjects; + trackWidget * m_trackWidget; + Uint16 m_pixelsPerTact; + +} ; + + + + +// actual widget shown in trackContainer +class trackWidget : public QWidget +{ + Q_OBJECT +public: + trackWidget( track * _track, QWidget * _parent ); + virtual ~trackWidget(); + + inline const track * getTrack( void ) const + { + return( m_track ); + } + inline track * getTrack( void ) + { + return( m_track ); + } + inline const trackSettingsWidget & getTrackSettingsWidget( void ) const + { + return( m_trackSettingsWidget ); + } + inline const trackContentWidget & getTrackContentWidget( void ) const + { + return( m_trackContentWidget ); + } + inline trackSettingsWidget & getTrackSettingsWidget( void ) + { + return( m_trackSettingsWidget ); + } + inline trackContentWidget & getTrackContentWidget( void ) + { + return( m_trackContentWidget ); + } + bool muted( void ) const; + + +public slots: + void changePosition( const midiTime & _new_pos = -1 ); + void cloneTrack( void ); + void deleteTrack( void ); + void moveTrackUp( void ); + void moveTrackDown( void ); + void setMuted( bool _muted ); + void muteBtnRightClicked( void ); + + +protected: + virtual void resizeEvent( QResizeEvent * _re ); + virtual void paintEvent( QPaintEvent * _pe ); + midiTime FASTCALL endPosition( const midiTime & _pos_start ); + + +private: + track * m_track; + + trackOperationsWidget m_trackOperationsWidget; + trackSettingsWidget m_trackSettingsWidget; + trackContentWidget m_trackContentWidget; + + pixmapButton * m_muteBtn; + +} ; + + + + +// base-class for all tracks +class track : public settings +{ +public: + enum trackTypes + { + CHANNEL_TRACK, + BB_TRACK, + SAMPLE_TRACK, + EVENT_TRACK, + VIDEO_TRACK, + NULL_TRACK, + TOTAL_TRACK_TYPES + } ; + + track( trackContainer * _tc ); + virtual ~track(); + static track * FASTCALL createTrack( trackTypes _tt, + trackContainer * _tc ); + static track * FASTCALL createTrack( const QDomElement & _this, + trackContainer * _tc ); + static track * FASTCALL cloneTrack( track * _track ); + + tact length( void ) const; + + inline bool muted( void ) const + { + return( m_trackWidget->muted() ); + } + + // pure virtual functions + virtual trackTypes trackType( void ) const = 0; + + virtual bool FASTCALL play( const midiTime & _start, + Uint32 _start_frame, + Uint32 _frames, + Uint32 _frame_base, + Sint16 _tco_num = -1 ) = 0; + + + virtual trackContentObject * FASTCALL createTCO( + const midiTime & _pos ) = 0; + + virtual void FASTCALL saveTrackSpecificSettings( QDomDocument & _doc, + QDomElement & _parent ) = 0; + virtual void FASTCALL loadTrackSpecificSettings( + const QDomElement & _this ) = 0; + + + virtual void FASTCALL saveSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void FASTCALL loadSettings( const QDomElement & _this ); + + + trackContentObject * FASTCALL addTCO( trackContentObject * _tco ); + void FASTCALL removeTCO( csize _tco_num ); + csize numOfTCOs( void ); + trackContentObject * FASTCALL getTCO( csize _tco_num ); + csize FASTCALL getTCONum( trackContentObject * _tco ); + void FASTCALL getTCOsInRange( vlist & _tco_v, + const midiTime & _start, + const midiTime & _end ); + void FASTCALL swapPositionOfTCOs( csize _tco_num1, csize _tco_num2 ); + + inline trackWidget * getTrackWidget( void ) + { + return( m_trackWidget ); + } + inline trackContainer * getTrackContainer( void ) + { + return( m_trackContainer ); + } + inline const trackSettingsWidget * getTrackSettingsWidget( void ) const + { + return( &m_trackWidget->getTrackSettingsWidget() ); + } + inline const trackContentWidget * getTrackContentWidget( void ) const + { + return( &m_trackWidget->getTrackContentWidget() ); + } + inline trackSettingsWidget * getTrackSettingsWidget( void ) + { + return( &m_trackWidget->getTrackSettingsWidget() ); + } + inline trackContentWidget * getTrackContentWidget( void ) + { + return( &m_trackWidget->getTrackContentWidget() ); + } + + +private: + trackContainer * m_trackContainer; + trackWidget * m_trackWidget; + +} ; + + +typedef vvector trackVector; +typedef vvector constTrackVector; + + +#endif diff --git a/include/track_container.h b/include/track_container.h new file mode 100644 index 00000000000..7b221f34514 --- /dev/null +++ b/include/track_container.h @@ -0,0 +1,119 @@ +/* + * track_container.h - base-class for all track-containers like Playlist-Editor, BB-Editor... + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _TRACK_CONTAINER_H +#define _TRACK_CONTAINER_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include +#include + +#endif + + +#include "track.h" +#include "settings.h" + + + +class trackContainer : public QMainWindow, public settings +{ + Q_OBJECT +public: + trackContainer(); + ~trackContainer(); + inline QWidget * containerWidget( void ) + { + return( m_scrollArea ); + } + virtual void FASTCALL saveSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void FASTCALL loadSettings( const QDomElement & _this ); + + inline float pixelsPerTact( void ) const + { + return( m_ppt ); + } + inline const midiTime & currentPosition( void ) const + { + return( m_currentPosition ); + } + virtual bool fixedTCOs( void ) const + { + return( FALSE ); + } + unsigned int FASTCALL countTracks( track::trackTypes _tt = + track::TOTAL_TRACK_TYPES ) const; + + void FASTCALL setMutedOfAllTracks( bool _muted ); + + + virtual void updateAfterTrackAdd( void ); + void FASTCALL setPixelsPerTact( Uint16 _ppt ); + void FASTCALL cloneTrack( track * _track ); + void FASTCALL addTrack( track * _track ); + void FASTCALL removeTrack( track * _track ); + void FASTCALL moveTrackUp( track * _track ); + void FASTCALL moveTrackDown( track * _track ); + void FASTCALL realignTracks( bool _complete_update = FALSE ); + + +protected: + constTrackVector tracks( void ) const; + trackVector tracks( void ); + + virtual void resizeEvent( QResizeEvent * ); + + midiTime m_currentPosition; + + +protected slots: + void updateScrollArea( void ); + + +private: + QScrollArea * m_scrollArea; + typedef vvector trackWidgetVector; + + trackWidgetVector m_trackWidgets; + float m_ppt; + + +signals: + void positionChanged( const midiTime & _pos ); + +} ; + + +#endif diff --git a/include/types.h b/include/types.h new file mode 100644 index 00000000000..796ca2513fd --- /dev/null +++ b/include/types.h @@ -0,0 +1,48 @@ +/* + * types.h - typedefs for common types that are used in the whole app + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _TYPES_H +#define _TYPES_H + + +typedef unsigned char Uint8; +typedef signed char Sint8; +typedef unsigned short Uint16; +typedef signed short Sint16; +typedef unsigned int Uint32; +typedef signed int Sint32; + + +typedef Uint32 minute; +typedef Sint8 second; +typedef Sint32 tact; +typedef Sint8 tact64th; +typedef Uint8 volume; +typedef Sint8 panning; + + +typedef float sampleType; +typedef Sint16 outputSampleType; + + +#endif diff --git a/include/visualization_widget.h b/include/visualization_widget.h new file mode 100644 index 00000000000..4367e33c523 --- /dev/null +++ b/include/visualization_widget.h @@ -0,0 +1,81 @@ +/* + * visualization_widget.h - widget for visualization of waves + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _OUTPUT_GRAPH_H +#define _OUTPUT_GRAPH_H + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + + +#include "mixer.h" + +class QTimer; + + +class visualizationWidget : public QWidget +{ + Q_OBJECT +public: + enum visualizationTypes + { + SIMPLE // add more here + } ; + visualizationWidget( const QPixmap & _bg, QWidget * _parent, + visualizationTypes _vtype = SIMPLE ); + virtual ~visualizationWidget(); + + +protected: + void paintEvent( QPaintEvent * _pe ); + void mousePressEvent( QMouseEvent * _me ); + + +protected slots: + void setAudioBuffer( const surroundSampleFrame * _ab, Uint32 _frames ); + + +private: + QPixmap s_background; + + bool m_enabled; + surroundSampleFrame * m_buffer; + Uint32 m_frames; + + QTimer * m_updateTimer; + +} ; + +#endif diff --git a/include/volume.h b/include/volume.h new file mode 100644 index 00000000000..dc37abd4801 --- /dev/null +++ b/include/volume.h @@ -0,0 +1,33 @@ +/* + * volume.h - declaration of some constants and types, concerning the volume of a note + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _VOLUME_H +#define _VOLUME_H + +#include "types.h" + +const volume MIN_VOLUME = 0; +const volume MAX_VOLUME = 200; +const volume DEFAULT_VOLUME = 100; + +#endif diff --git a/lmms.spec.in b/lmms.spec.in new file mode 100644 index 00000000000..95b6d716458 --- /dev/null +++ b/lmms.spec.in @@ -0,0 +1,122 @@ +%define _suse %(if [ -f /etc/SuSE-release ] ; then echo 1 ; else echo 0 ; fi) + + +Name: @PACKAGE@ +Version: @VERSION@ +Release: 0 +Summary: powerful sequencer-, synthesizer- and sample-studio for Linux +Summary(de): Leistungsfaehiges Sequenzer-, Synthesizer- und Sample-Studio fuer Linux +License: GPL +URL: http://lmms.sourceforge.net/ +Group: Applications/Multimedia/Sound +Packager: Tobias Doerffel +Provides: lmms = %{version}-%{release} +%if %_suse +BuildRequires: gcc gcc-c++ libstdc++-devel autoconf automake libtool make alsa +BuildRequires: alsa-devel SDL SDL-devel SDL_sound libvorbis libvorbis-devel +BuildRequires: libsamplerate libsamplerate-devel libsndfile libsndfile-devel +BuildRequires: jack-devel +BuildRequires: qt3 qt3-devel qt3-devel-tools +Requires: qt3 alsa SDL_sound libvorbis libsamplerate libsndfile jack +%endif +Requires: lmms-data +Source: %{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot +Prefix: %{_prefix} + + +%description +LMMS aims to be a free alternative to popular (but commercial and closed- +source) programs like FruityLoops, Cubase and Logic giving you the ability of +producing music with your computer by creating/synthesizing sounds, arranging +samples, playing live with keyboard and much more... + +LMMS combines the features of a tracker-/sequencer-program (pattern-/channel-/ +sample-/song-/effect-management) and those of powerful synthesizers and +samplers in a modern, user-friendly and easy to use graphical user-interface. + +LMMS is still in heavy development, so with this version please don't expect a +complete, ready and bugfree program!! + + +%description -l de +LMMS ist eine freie Alternative zu bekannten (aber kommerziellen und +Closed-Source-) Programmen wie FruityLoops, Cubase und Logic, die Ihnen die +Moeglichkeit geben, mit Ihrem Computer Musik zu produzieren, indem Sie +Klaenge kreieren/synthetisieren, Samples anordnen, mit dem Keyboard live +spielen usw.... + +LMMS kombiniert die Funktionen eines Tracker-/Sequenzer-Programms (Pattern-/ +Kanal-/Sample-/Song-/Effekt-Management) und die von leistungsfaehigen +Synthesizern und Samplern in einer modernen, benutzerfreundlichen und einfach zu +benutzenden grafischen Oberflaeche. + +Derzeit befindet sich LMMS komplett in Entwicklung. Also erwarten Sie bitte mit +dieser Version nicht ein vollstaendiges, fertiges und fehlerfreies Programm!! + + +%package data +Summary: samples, presets, demo-projects and localization-files for LMMS +Summary(de): Samples, Presets, Demo-Projekte und Lokalisierungsdateien fuer LMMS +Group: Applications/Multimedia/Sound +Provides: lmms-data = %{version}-%{release} + +%description data +This package contains platform-independent data and resources for Linux +MultiMedia Studio (LMMS), e.g. samples, presets and demo-projects. + + +%description data -l de +Dieses Paket beinhaltet plattform-unabhaengige Daten und Resourcen fuer Linux +MultiMedia Studio (LMMS), wie z.B. Samples, Presets und Demo-Projekte. + + +%prep +%setup -n %{name}-%{version} + + +%build +CXXFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{prefix} + +make + + +%install +make DESTDIR=$RPM_BUILD_ROOT install + +%clean +[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT + + +%pre +%post +%preun +%postun + + +%files +%defattr(-,root,root) +%{_bindir}/lmms + + +%files data +%defattr(-,root,root) +%{_datadir}/lmms/ + + + +%changelog +* Tue Sep 20 2005 Tobias Doerffel +- added JACK-dependencies + +* Fri Jul 22 2005 Tobias Doerffel +- added more dependencies for builds under SuSE + +* Sat Jun 25 2005 Tobias Doerffel +- splitted package into lmms and lmms-data +- additional requirements +- updated project-homepage and email-address of packager + +* Thu May 12 2005 Tobias Doerffel +- created lmms.spec.in + diff --git a/resources/add_bb_track.png b/resources/add_bb_track.png new file mode 100644 index 00000000000..bed9f4a46ee Binary files /dev/null and b/resources/add_bb_track.png differ diff --git a/resources/add_sample_track.png b/resources/add_sample_track.png new file mode 100644 index 00000000000..9643357a2f2 Binary files /dev/null and b/resources/add_sample_track.png differ diff --git a/resources/apply.png b/resources/apply.png new file mode 100644 index 00000000000..8d8e7eafccd Binary files /dev/null and b/resources/apply.png differ diff --git a/resources/arp_down_off.png b/resources/arp_down_off.png new file mode 100644 index 00000000000..435a4db254a Binary files /dev/null and b/resources/arp_down_off.png differ diff --git a/resources/arp_down_on.png b/resources/arp_down_on.png new file mode 100644 index 00000000000..ad5c19b9d04 Binary files /dev/null and b/resources/arp_down_on.png differ diff --git a/resources/arp_random_off.png b/resources/arp_random_off.png new file mode 100644 index 00000000000..74391a256b1 Binary files /dev/null and b/resources/arp_random_off.png differ diff --git a/resources/arp_random_on.png b/resources/arp_random_on.png new file mode 100644 index 00000000000..9d8e503b127 Binary files /dev/null and b/resources/arp_random_on.png differ diff --git a/resources/arp_up_and_down_off.png b/resources/arp_up_and_down_off.png new file mode 100644 index 00000000000..1909a94aa56 Binary files /dev/null and b/resources/arp_up_and_down_off.png differ diff --git a/resources/arp_up_and_down_on.png b/resources/arp_up_and_down_on.png new file mode 100644 index 00000000000..2170b84bdad Binary files /dev/null and b/resources/arp_up_and_down_on.png differ diff --git a/resources/arp_up_off.png b/resources/arp_up_off.png new file mode 100644 index 00000000000..ae8ecd653cf Binary files /dev/null and b/resources/arp_up_off.png differ diff --git a/resources/arp_up_on.png b/resources/arp_up_on.png new file mode 100644 index 00000000000..5b4d2d77d85 Binary files /dev/null and b/resources/arp_up_on.png differ diff --git a/resources/autoscroll_off.png b/resources/autoscroll_off.png new file mode 100644 index 00000000000..3fec304904a Binary files /dev/null and b/resources/autoscroll_off.png differ diff --git a/resources/autoscroll_on.png b/resources/autoscroll_on.png new file mode 100644 index 00000000000..b1355c6867e Binary files /dev/null and b/resources/autoscroll_on.png differ diff --git a/resources/back_to_start.png b/resources/back_to_start.png new file mode 100644 index 00000000000..2dc113ee240 Binary files /dev/null and b/resources/back_to_start.png differ diff --git a/resources/back_to_zero.png b/resources/back_to_zero.png new file mode 100644 index 00000000000..162ee36b402 Binary files /dev/null and b/resources/back_to_zero.png differ diff --git a/resources/background_artwork.png b/resources/background_artwork.png new file mode 100644 index 00000000000..2aa3a7d12a4 Binary files /dev/null and b/resources/background_artwork.png differ diff --git a/resources/bb_track.png b/resources/bb_track.png new file mode 100644 index 00000000000..db6a8c913c9 Binary files /dev/null and b/resources/bb_track.png differ diff --git a/resources/black_key.png b/resources/black_key.png new file mode 100644 index 00000000000..c6350945692 Binary files /dev/null and b/resources/black_key.png differ diff --git a/resources/black_key_pressed.png b/resources/black_key_pressed.png new file mode 100644 index 00000000000..c58e28ee684 Binary files /dev/null and b/resources/black_key_pressed.png differ diff --git a/resources/cancel.png b/resources/cancel.png new file mode 100644 index 00000000000..49dd0e6abc1 Binary files /dev/null and b/resources/cancel.png differ diff --git a/resources/clock.png b/resources/clock.png new file mode 100644 index 00000000000..9060065cab8 Binary files /dev/null and b/resources/clock.png differ diff --git a/resources/colorize.png b/resources/colorize.png new file mode 100644 index 00000000000..ed2cb749a0d Binary files /dev/null and b/resources/colorize.png differ diff --git a/resources/edit_copy.png b/resources/edit_copy.png new file mode 100644 index 00000000000..5819ebc944d Binary files /dev/null and b/resources/edit_copy.png differ diff --git a/resources/edit_cut.png b/resources/edit_cut.png new file mode 100644 index 00000000000..0c45b181ad6 Binary files /dev/null and b/resources/edit_cut.png differ diff --git a/resources/edit_erase.png b/resources/edit_erase.png new file mode 100644 index 00000000000..babe8838342 Binary files /dev/null and b/resources/edit_erase.png differ diff --git a/resources/edit_paste.png b/resources/edit_paste.png new file mode 100644 index 00000000000..120793d6a27 Binary files /dev/null and b/resources/edit_paste.png differ diff --git a/resources/edit_redo.png b/resources/edit_redo.png new file mode 100644 index 00000000000..2c19335ebdb Binary files /dev/null and b/resources/edit_redo.png differ diff --git a/resources/edit_undo.png b/resources/edit_undo.png new file mode 100644 index 00000000000..f81746373b1 Binary files /dev/null and b/resources/edit_undo.png differ diff --git a/resources/effect_board.png b/resources/effect_board.png new file mode 100644 index 00000000000..01f1993ceeb Binary files /dev/null and b/resources/effect_board.png differ diff --git a/resources/empty.png b/resources/empty.png new file mode 100644 index 00000000000..859ba35d5f8 Binary files /dev/null and b/resources/empty.png differ diff --git a/resources/envelope_graph.png b/resources/envelope_graph.png new file mode 100644 index 00000000000..dfe7d6cfa73 Binary files /dev/null and b/resources/envelope_graph.png differ diff --git a/resources/exit.png b/resources/exit.png new file mode 100644 index 00000000000..7cc7d4de9b1 Binary files /dev/null and b/resources/exit.png differ diff --git a/resources/exp_wave_active.png b/resources/exp_wave_active.png new file mode 100644 index 00000000000..fa4b2099335 Binary files /dev/null and b/resources/exp_wave_active.png differ diff --git a/resources/exp_wave_inactive.png b/resources/exp_wave_inactive.png new file mode 100644 index 00000000000..d59dfd120d4 Binary files /dev/null and b/resources/exp_wave_inactive.png differ diff --git a/resources/folder.png b/resources/folder.png new file mode 100644 index 00000000000..05731b1a7a2 Binary files /dev/null and b/resources/folder.png differ diff --git a/resources/folder_locked.png b/resources/folder_locked.png new file mode 100644 index 00000000000..307684747fd Binary files /dev/null and b/resources/folder_locked.png differ diff --git a/resources/folder_opened.png b/resources/folder_opened.png new file mode 100644 index 00000000000..ab67758d747 Binary files /dev/null and b/resources/folder_opened.png differ diff --git a/resources/freeze.png b/resources/freeze.png new file mode 100644 index 00000000000..26b81741639 Binary files /dev/null and b/resources/freeze.png differ diff --git a/resources/frozen.png b/resources/frozen.png new file mode 100644 index 00000000000..ce4049472fa Binary files /dev/null and b/resources/frozen.png differ diff --git a/resources/groupbox_led_bg.png b/resources/groupbox_led_bg.png new file mode 100644 index 00000000000..6266b801102 Binary files /dev/null and b/resources/groupbox_led_bg.png differ diff --git a/resources/help.png b/resources/help.png new file mode 100644 index 00000000000..8bd601edf71 Binary files /dev/null and b/resources/help.png differ diff --git a/resources/home.png b/resources/home.png new file mode 100644 index 00000000000..896c78f1fe9 Binary files /dev/null and b/resources/home.png differ diff --git a/resources/hourglass.png b/resources/hourglass.png new file mode 100644 index 00000000000..ff50c1e47c3 Binary files /dev/null and b/resources/hourglass.png differ diff --git a/resources/keep_stop_position.png b/resources/keep_stop_position.png new file mode 100644 index 00000000000..b13e6f10b04 Binary files /dev/null and b/resources/keep_stop_position.png differ diff --git a/resources/knob01.png b/resources/knob01.png new file mode 100644 index 00000000000..d16a87f6cb7 Binary files /dev/null and b/resources/knob01.png differ diff --git a/resources/knob02.png b/resources/knob02.png new file mode 100644 index 00000000000..99f8bc71411 Binary files /dev/null and b/resources/knob02.png differ diff --git a/resources/knob03.png b/resources/knob03.png new file mode 100644 index 00000000000..5d2f068084c Binary files /dev/null and b/resources/knob03.png differ diff --git a/resources/led_green.png b/resources/led_green.png new file mode 100644 index 00000000000..ac978151ee3 Binary files /dev/null and b/resources/led_green.png differ diff --git a/resources/led_off.png b/resources/led_off.png new file mode 100644 index 00000000000..ef8b75b5d6b Binary files /dev/null and b/resources/led_off.png differ diff --git a/resources/led_yellow.png b/resources/led_yellow.png new file mode 100644 index 00000000000..5b50506d2cb Binary files /dev/null and b/resources/led_yellow.png differ diff --git a/resources/lfo_graph.png b/resources/lfo_graph.png new file mode 100644 index 00000000000..67fb82939ca Binary files /dev/null and b/resources/lfo_graph.png differ diff --git a/resources/loop_point.png b/resources/loop_point.png new file mode 100644 index 00000000000..0592ef9fb4d Binary files /dev/null and b/resources/loop_point.png differ diff --git a/resources/loop_points_off.png b/resources/loop_points_off.png new file mode 100644 index 00000000000..f0c10eb9a05 Binary files /dev/null and b/resources/loop_points_off.png differ diff --git a/resources/loop_points_on.png b/resources/loop_points_on.png new file mode 100644 index 00000000000..d9a9e341dbe Binary files /dev/null and b/resources/loop_points_on.png differ diff --git a/resources/master_pitch.png b/resources/master_pitch.png new file mode 100644 index 00000000000..9aa039a108d Binary files /dev/null and b/resources/master_pitch.png differ diff --git a/resources/master_volume.png b/resources/master_volume.png new file mode 100644 index 00000000000..774a5986bae Binary files /dev/null and b/resources/master_volume.png differ diff --git a/resources/moog_saw_wave_active.png b/resources/moog_saw_wave_active.png new file mode 100644 index 00000000000..8c57878ebe6 Binary files /dev/null and b/resources/moog_saw_wave_active.png differ diff --git a/resources/moog_saw_wave_inactive.png b/resources/moog_saw_wave_inactive.png new file mode 100644 index 00000000000..b4d1cd616a7 Binary files /dev/null and b/resources/moog_saw_wave_inactive.png differ diff --git a/resources/mute_off.png b/resources/mute_off.png new file mode 100644 index 00000000000..58d9e9a0489 Binary files /dev/null and b/resources/mute_off.png differ diff --git a/resources/mute_on.png b/resources/mute_on.png new file mode 100644 index 00000000000..499ebe33dc3 Binary files /dev/null and b/resources/mute_on.png differ diff --git a/resources/output_graph.png b/resources/output_graph.png new file mode 100644 index 00000000000..67e0efbfbbc Binary files /dev/null and b/resources/output_graph.png differ diff --git a/resources/pause.png b/resources/pause.png new file mode 100644 index 00000000000..85f06664cbd Binary files /dev/null and b/resources/pause.png differ diff --git a/resources/piano.png b/resources/piano.png new file mode 100644 index 00000000000..3f3a8203ea7 Binary files /dev/null and b/resources/piano.png differ diff --git a/resources/play.png b/resources/play.png new file mode 100644 index 00000000000..d43c2478acb Binary files /dev/null and b/resources/play.png differ diff --git a/resources/playpos_marker.png b/resources/playpos_marker.png new file mode 100644 index 00000000000..3985567e9f7 Binary files /dev/null and b/resources/playpos_marker.png differ diff --git a/resources/pr_black_key.png b/resources/pr_black_key.png new file mode 100644 index 00000000000..dcfe295898c Binary files /dev/null and b/resources/pr_black_key.png differ diff --git a/resources/pr_white_key_big.png b/resources/pr_white_key_big.png new file mode 100644 index 00000000000..424e8a8c4f4 Binary files /dev/null and b/resources/pr_white_key_big.png differ diff --git a/resources/pr_white_key_small.png b/resources/pr_white_key_small.png new file mode 100644 index 00000000000..5715d768661 Binary files /dev/null and b/resources/pr_white_key_small.png differ diff --git a/resources/preset_file.png b/resources/preset_file.png new file mode 100644 index 00000000000..ad4cdfacb08 Binary files /dev/null and b/resources/preset_file.png differ diff --git a/resources/project_export.png b/resources/project_export.png new file mode 100644 index 00000000000..e23861bf708 Binary files /dev/null and b/resources/project_export.png differ diff --git a/resources/project_file.png b/resources/project_file.png new file mode 100644 index 00000000000..9c43e578df3 Binary files /dev/null and b/resources/project_file.png differ diff --git a/resources/project_new.png b/resources/project_new.png new file mode 100644 index 00000000000..ba32d712d4a Binary files /dev/null and b/resources/project_new.png differ diff --git a/resources/project_notes.png b/resources/project_notes.png new file mode 100644 index 00000000000..32414af8e21 Binary files /dev/null and b/resources/project_notes.png differ diff --git a/resources/project_open.png b/resources/project_open.png new file mode 100644 index 00000000000..0e306f254e6 Binary files /dev/null and b/resources/project_open.png differ diff --git a/resources/project_save.png b/resources/project_save.png new file mode 100644 index 00000000000..677ce2097d1 Binary files /dev/null and b/resources/project_save.png differ diff --git a/resources/project_saveas.png b/resources/project_saveas.png new file mode 100644 index 00000000000..fa310a1455f Binary files /dev/null and b/resources/project_saveas.png differ diff --git a/resources/record.png b/resources/record.png new file mode 100644 index 00000000000..367a6dad2ad Binary files /dev/null and b/resources/record.png differ diff --git a/resources/reload.png b/resources/reload.png new file mode 100644 index 00000000000..d65b6d59be6 Binary files /dev/null and b/resources/reload.png differ diff --git a/resources/rename.png b/resources/rename.png new file mode 100644 index 00000000000..232f775dccd Binary files /dev/null and b/resources/rename.png differ diff --git a/resources/root.png b/resources/root.png new file mode 100644 index 00000000000..327167707bd Binary files /dev/null and b/resources/root.png differ diff --git a/resources/sample_track.png b/resources/sample_track.png new file mode 100644 index 00000000000..c8eeee88194 Binary files /dev/null and b/resources/sample_track.png differ diff --git a/resources/saw_wave_active.png b/resources/saw_wave_active.png new file mode 100644 index 00000000000..a48c35f6eb7 Binary files /dev/null and b/resources/saw_wave_active.png differ diff --git a/resources/saw_wave_inactive.png b/resources/saw_wave_inactive.png new file mode 100644 index 00000000000..9421664b18b Binary files /dev/null and b/resources/saw_wave_inactive.png differ diff --git a/resources/setup_audio.png b/resources/setup_audio.png new file mode 100644 index 00000000000..705c7fd5f27 Binary files /dev/null and b/resources/setup_audio.png differ diff --git a/resources/setup_general.png b/resources/setup_general.png new file mode 100644 index 00000000000..270de5614b4 Binary files /dev/null and b/resources/setup_general.png differ diff --git a/resources/setup_midi.png b/resources/setup_midi.png new file mode 100644 index 00000000000..3074404440f Binary files /dev/null and b/resources/setup_midi.png differ diff --git a/resources/sin_wave_active.png b/resources/sin_wave_active.png new file mode 100644 index 00000000000..81794ee6c2e Binary files /dev/null and b/resources/sin_wave_active.png differ diff --git a/resources/sin_wave_inactive.png b/resources/sin_wave_inactive.png new file mode 100644 index 00000000000..abccbbcfb58 Binary files /dev/null and b/resources/sin_wave_inactive.png differ diff --git a/resources/songeditor.png b/resources/songeditor.png new file mode 100644 index 00000000000..31b862ba745 Binary files /dev/null and b/resources/songeditor.png differ diff --git a/resources/sound_file.png b/resources/sound_file.png new file mode 100644 index 00000000000..01a273867b3 Binary files /dev/null and b/resources/sound_file.png differ diff --git a/resources/square_wave_active.png b/resources/square_wave_active.png new file mode 100644 index 00000000000..e30f98ec1e5 Binary files /dev/null and b/resources/square_wave_active.png differ diff --git a/resources/square_wave_inactive.png b/resources/square_wave_inactive.png new file mode 100644 index 00000000000..c429abff6c8 Binary files /dev/null and b/resources/square_wave_inactive.png differ diff --git a/resources/step_btn_off.png b/resources/step_btn_off.png new file mode 100644 index 00000000000..ef91a2c4ebe Binary files /dev/null and b/resources/step_btn_off.png differ diff --git a/resources/step_btn_off_light.png b/resources/step_btn_off_light.png new file mode 100644 index 00000000000..d360521cb78 Binary files /dev/null and b/resources/step_btn_off_light.png differ diff --git a/resources/step_btn_on.png b/resources/step_btn_on.png new file mode 100644 index 00000000000..f0101d05379 Binary files /dev/null and b/resources/step_btn_on.png differ diff --git a/resources/stop.png b/resources/stop.png new file mode 100644 index 00000000000..9b35d2278a7 Binary files /dev/null and b/resources/stop.png differ diff --git a/resources/surround_area.png b/resources/surround_area.png new file mode 100644 index 00000000000..ded56ebff0e Binary files /dev/null and b/resources/surround_area.png differ diff --git a/resources/text_block.png b/resources/text_block.png new file mode 100644 index 00000000000..9413dbe1dd4 Binary files /dev/null and b/resources/text_block.png differ diff --git a/resources/text_bold.png b/resources/text_bold.png new file mode 100644 index 00000000000..1fb59dec3d7 Binary files /dev/null and b/resources/text_bold.png differ diff --git a/resources/text_center.png b/resources/text_center.png new file mode 100644 index 00000000000..cce40807235 Binary files /dev/null and b/resources/text_center.png differ diff --git a/resources/text_italic.png b/resources/text_italic.png new file mode 100644 index 00000000000..c748276fca6 Binary files /dev/null and b/resources/text_italic.png differ diff --git a/resources/text_left.png b/resources/text_left.png new file mode 100644 index 00000000000..89788e76e82 Binary files /dev/null and b/resources/text_left.png differ diff --git a/resources/text_right.png b/resources/text_right.png new file mode 100644 index 00000000000..2f3c6752bcc Binary files /dev/null and b/resources/text_right.png differ diff --git a/resources/text_under.png b/resources/text_under.png new file mode 100644 index 00000000000..58ac92a5b8b Binary files /dev/null and b/resources/text_under.png differ diff --git a/resources/timeline.png b/resources/timeline.png new file mode 100644 index 00000000000..db4ec891cc0 Binary files /dev/null and b/resources/timeline.png differ diff --git a/resources/toolbar_bg.png b/resources/toolbar_bg.png new file mode 100644 index 00000000000..c8e8972d15a Binary files /dev/null and b/resources/toolbar_bg.png differ diff --git a/resources/triangle_wave_active.png b/resources/triangle_wave_active.png new file mode 100644 index 00000000000..d2b23e7f968 Binary files /dev/null and b/resources/triangle_wave_active.png differ diff --git a/resources/triangle_wave_inactive.png b/resources/triangle_wave_inactive.png new file mode 100644 index 00000000000..c84f8b2d6a0 Binary files /dev/null and b/resources/triangle_wave_inactive.png differ diff --git a/resources/unfreeze.png b/resources/unfreeze.png new file mode 100644 index 00000000000..2282d291c1c Binary files /dev/null and b/resources/unfreeze.png differ diff --git a/resources/unknown_file.png b/resources/unknown_file.png new file mode 100644 index 00000000000..0c159481272 Binary files /dev/null and b/resources/unknown_file.png differ diff --git a/resources/usr_wave_active.png b/resources/usr_wave_active.png new file mode 100644 index 00000000000..1c574e5f576 Binary files /dev/null and b/resources/usr_wave_active.png differ diff --git a/resources/usr_wave_inactive.png b/resources/usr_wave_inactive.png new file mode 100644 index 00000000000..20890771c7e Binary files /dev/null and b/resources/usr_wave_inactive.png differ diff --git a/resources/whatsthis.png b/resources/whatsthis.png new file mode 100644 index 00000000000..f77572efb29 Binary files /dev/null and b/resources/whatsthis.png differ diff --git a/resources/white_key.png b/resources/white_key.png new file mode 100644 index 00000000000..b2ae40a0157 Binary files /dev/null and b/resources/white_key.png differ diff --git a/resources/white_key_pressed.png b/resources/white_key_pressed.png new file mode 100644 index 00000000000..4832392f423 Binary files /dev/null and b/resources/white_key_pressed.png differ diff --git a/resources/white_noise_wave_active.png b/resources/white_noise_wave_active.png new file mode 100644 index 00000000000..253513564ee Binary files /dev/null and b/resources/white_noise_wave_active.png differ diff --git a/resources/white_noise_wave_inactive.png b/resources/white_noise_wave_inactive.png new file mode 100644 index 00000000000..ba5739c65bf Binary files /dev/null and b/resources/white_noise_wave_inactive.png differ diff --git a/resources/wizard.png b/resources/wizard.png new file mode 100644 index 00000000000..6a3becd1c19 Binary files /dev/null and b/resources/wizard.png differ diff --git a/src/audio/audio_alsa.cpp b/src/audio/audio_alsa.cpp new file mode 100644 index 00000000000..ee979f9306e --- /dev/null +++ b/src/audio/audio_alsa.cpp @@ -0,0 +1,439 @@ +/* + * audio_alsa.cpp - device-class that implements ALSA-PCM-output + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include +#include + +#endif + + +#include "audio_alsa.h" + + +#ifdef ALSA_SUPPORT + +#include "endian_handling.h" +#include "buffer_allocator.h" +#include "config_mgr.h" +#include "lcd_spinbox.h" +#include "templates.h" + + + +audioALSA::audioALSA( Uint32 _sample_rate, bool & _success_ful ) : + audioDevice( _sample_rate, tLimit( configManager::inst()->value( + "audioalsa", "channels" ).toInt(), + DEFAULT_CHANNELS, SURROUND_CHANNELS ) ), + m_handle( NULL ), + m_hwParams( NULL ), + m_swParams( NULL ), + m_littleEndian( isLittleEndian() ) +{ + _success_ful = FALSE; + + int err; + + if( ( err = snd_pcm_open( &m_handle, +#ifdef QT4 + probeDevice().toAscii().constData(), +#else + probeDevice().ascii(), +#endif + SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK ) ) < 0 ) + { + printf( "Playback open error: %s\n", snd_strerror( err ) ); + return; + } + + snd_pcm_hw_params_alloca( &m_hwParams ); + snd_pcm_sw_params_alloca( &m_swParams ); + + if( ( err = setHWParams( _sample_rate, channels(), + SND_PCM_ACCESS_RW_INTERLEAVED ) ) < 0 ) + { + printf( "Setting of hwparams failed: %s\n", + snd_strerror( err ) ); + return; + } + if( ( err = setSWParams() ) < 0 ) + { + printf( "Setting of swparams failed: %s\n", + snd_strerror( err ) ); + return; + } + + _success_ful = TRUE; +} + + + + +audioALSA::~audioALSA() +{ + if( m_handle != NULL ) + { + snd_pcm_close( m_handle ); + } + // the following code doesn't work and leads to a crash... +/* if( m_hwParams != NULL ) + { + snd_pcm_hw_params_free( m_hwParams ); + } + + if( m_swParams != NULL ) + { + snd_pcm_sw_params_free( m_swParams ); + }*/ +} + + + + +QString audioALSA::probeDevice( void ) +{ + QString dev = configManager::inst()->value( "audioalsa", "device" ); + if( dev == "" ) + { + if( getenv( "AUDIODEV" ) != NULL ) + { + return( getenv( "AUDIODEV" ) ); + } + return( "default" ); + } + return( dev ); +} + + + + +int audioALSA::handleError( int _err ) +{ + if( _err == -EPIPE ) + { + // under-run + _err = snd_pcm_prepare( m_handle ); + if( _err < 0 ) + printf( "Can't recovery from underrun, prepare " + "failed: %s\n", snd_strerror( _err ) ); + return ( 0 ); + } + else if( _err == -ESTRPIPE ) + { + while( ( _err = snd_pcm_resume( m_handle ) ) == -EAGAIN ) + { + sleep( 1 ); // wait until the suspend flag + // is released + } + + if( _err < 0 ) + { + _err = snd_pcm_prepare( m_handle ); + if( _err < 0 ) + printf( "Can't recovery from suspend, prepare " + "failed: %s\n", snd_strerror( _err ) ); + } + return ( 0 ); + } + return( _err ); +} + + + + +void audioALSA::writeBufferToDev( surroundSampleFrame * _ab, Uint32 _frames, + float _master_output ) +{ + outputSampleType * outbuf = bufferAllocator::alloc( + _frames * channels() ); + bufferAllocator::autoCleaner<> ac( outbuf ); + + convertToS16( _ab, _frames, _master_output, outbuf, + m_littleEndian != isLittleEndian() ); + + Uint32 frame = 0; + + while( frame < _frames ) + { + int err = snd_pcm_writei( m_handle, outbuf, _frames ); + + if( err == -EAGAIN ) + { + continue; + } + + if( err < 0 ) + { + if( handleError( err ) < 0 ) + { + printf( "Write error: %s\n", + snd_strerror( err ) ); + return; + } + break; // skip this buffer + } + outbuf += err * channels(); + frame += err; + } +} + + + + +int audioALSA::setHWParams( Uint32 _sample_rate, Uint32 _channels, + snd_pcm_access_t _access ) +{ + int err, dir; + + // choose all parameters + if( ( err = snd_pcm_hw_params_any( m_handle, m_hwParams ) ) < 0 ) + { + printf( "Broken configuration for playback: no configurations " + "available: %s\n", snd_strerror( err ) ); + return( err ); + } + + // set the interleaved read/write format + if( ( err = snd_pcm_hw_params_set_access( m_handle, m_hwParams, + _access ) ) < 0 ) + { + printf( "Access type not available for playback: %s\n", + snd_strerror( err ) ); + return( err ); + } + + // set the sample format + if( ( snd_pcm_hw_params_set_format( m_handle, m_hwParams, + SND_PCM_FORMAT_S16_LE ) ) < 0 ) + { + if( ( snd_pcm_hw_params_set_format( m_handle, m_hwParams, + SND_PCM_FORMAT_S16_BE ) ) < 0 ) + { + printf( "Neither little- nor big-endian available for " + "playback: %s\n", snd_strerror( err ) ); + return( err ); + } + m_littleEndian = FALSE; + } + + // set the count of channels + if( ( err = snd_pcm_hw_params_set_channels( m_handle, m_hwParams, + _channels ) ) < 0 ) + { + printf( "Channel count (%i) not available for playbacks: %s\n" + "(Does your soundcard not support surround?)\n", + _channels, snd_strerror( err ) ); + return( err ); + } + + // set the sample rate + if( ( err = snd_pcm_hw_params_set_rate( m_handle, m_hwParams, + _sample_rate, 0 ) ) < 0 ) + { + int q = 0; + if( sampleRate() == SAMPLE_RATES[1] ) + { + q = 1; + } + if( sampleRate() == 44100 || sampleRate() == 88200 ) + { + SAMPLE_RATES[0] = 48000; + SAMPLE_RATES[1] = 96000; + } + else + { + SAMPLE_RATES[0] = 44100; + SAMPLE_RATES[1] = 82000; + } + setSampleRate( SAMPLE_RATES[q] ); + if( ( err = snd_pcm_hw_params_set_rate( m_handle, m_hwParams, + SAMPLE_RATES[q], 0 ) ) < 0 ) + { + printf( "Could not set sample rate: %s\n", + snd_strerror( err ) ); + return( err ); + } + } + + m_periodSize = mixer::inst()->framesPerAudioBuffer(); + m_bufferSize = m_periodSize * 8; + dir = 0; + err = snd_pcm_hw_params_set_period_size_near( m_handle, m_hwParams, + &m_periodSize, &dir ); + if( err < 0 ) + { + printf( "Unable to set period size %lu for playback: %s\n", + m_periodSize, snd_strerror( err ) ); + return( err ); + } + dir = 0; + err = snd_pcm_hw_params_get_period_size( m_hwParams, &m_periodSize, + &dir ); + if( err < 0 ) + { + printf( "Unable to get period size for playback: %s\n", + snd_strerror( err ) ); + } + + dir = 0; + err = snd_pcm_hw_params_set_buffer_size_near( m_handle, m_hwParams, + &m_bufferSize ); + if( err < 0 ) + { + printf( "Unable to set buffer size %lu for playback: %s\n", + m_bufferSize, snd_strerror( err ) ); + return ( err ); + } + err = snd_pcm_hw_params_get_buffer_size( m_hwParams, &m_bufferSize ); + + if( 2 * m_periodSize > m_bufferSize ) + { + printf( "buffer to small, could not use\n" ); + return ( err ); + } + + + // write the parameters to device + err = snd_pcm_hw_params( m_handle, m_hwParams ); + if( err < 0 ) + { + printf( "Unable to set hw params for playback: %s\n", + snd_strerror( err ) ); + return ( err ); + } + + return ( 0 ); // all ok +} + + + + +int audioALSA::setSWParams( void ) +{ + int err; + + // get the current swparams + if( ( err = snd_pcm_sw_params_current( m_handle, m_swParams ) ) < 0 ) + { + printf( "Unable to determine current swparams for playback: %s" + "\n", snd_strerror( err ) ); + return( err ); + } + + // start the transfer when a period is full + if( ( err = snd_pcm_sw_params_set_start_threshold( m_handle, + m_swParams, m_periodSize ) ) < 0 ) + { + printf( "Unable to set start threshold mode for playback: %s\n", + snd_strerror( err ) ); + return( err ); + } + + // allow the transfer when at least m_periodSize samples can be + // processed + if( ( err = snd_pcm_sw_params_set_avail_min( m_handle, m_swParams, + m_periodSize ) ) < 0 ) + { + printf( "Unable to set avail min for playback: %s\n", + snd_strerror( err ) ); + return( err ); + } + + // align all transfers to 1 sample + if( ( err = snd_pcm_sw_params_set_xfer_align( m_handle, + m_swParams, 1 ) ) < 0 ) + { + printf( "Unable to set transfer align for playback: %s\n", + snd_strerror( err ) ); + return( err ); + } + + // write the parameters to the playback device + if( ( err = snd_pcm_sw_params( m_handle, m_swParams ) ) < 0 ) + { + printf( "Unable to set sw params for playback: %s\n", + snd_strerror( err ) ); + return( err ); + } + + return( 0 ); // all ok +} + + + + + +audioALSA::setupWidget::setupWidget( QWidget * _parent ) : + audioDevice::setupWidget( audioALSA::name(), _parent ) +{ + m_device = new QLineEdit( audioALSA::probeDevice(), this ); + m_device->setGeometry( 10, 20, 160, 20 ); + + QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + dev_lbl->setFont( pointSize<6>( dev_lbl->font() ) ); + dev_lbl->setGeometry( 10, 40, 160, 10 ); + + m_channels = new lcdSpinBox( DEFAULT_CHANNELS, SURROUND_CHANNELS, 1, + this ); + m_channels->setStep( 2 ); + m_channels->setLabel( tr( "CHANNELS" ) ); + m_channels->setValue( configManager::inst()->value( "audioalsa", + "channels" ).toInt() ); + m_channels->move( 180, 20 ); + +} + + + + +audioALSA::setupWidget::~setupWidget() +{ + +} + + + + +void audioALSA::setupWidget::saveSettings( void ) +{ + configManager::inst()->setValue( "audioalsa", "device", + m_device->text() ); + configManager::inst()->setValue( "audioalsa", "channels", + QString::number( m_channels->value() ) ); +} + + +#endif + diff --git a/src/audio/audio_device.cpp b/src/audio/audio_device.cpp new file mode 100644 index 00000000000..2a1769d3cdf --- /dev/null +++ b/src/audio/audio_device.cpp @@ -0,0 +1,290 @@ +/* + * audio_device.cpp - base-class for audio-devices used by LMMS-mixer + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + + +#include "audio_device.h" +#include "buffer_allocator.h" +#include "debug.h" + + + +audioDevice::audioDevice( Uint32 _sample_rate, Uint8 _channels ) : + m_sampleRate( _sample_rate ), + m_channels( _channels ) +{ +#ifdef HAVE_SAMPLERATE_H + int error; + if( ( m_srcState = src_new( +#ifdef HQ_SINC + SRC_SINC_BEST_QUALITY, +#else + SRC_SINC_FASTEST, +#endif + SURROUND_CHANNELS, &error ) ) == NULL ) + { + printf( "Error: src_new() failed in audio_device.cpp!\n" ); + } + m_srcData.end_of_input = 0; +#endif +} + + + + +audioDevice::~audioDevice() +{ +#ifdef HAVE_SAMPLERATE_H + src_delete( m_srcState ); +#endif + unlock(); +} + + + + +void audioDevice::writeBuffer( surroundSampleFrame * _ab, Uint32 _frames, + Uint32 _src_sample_rate, float _master_output ) +{ + // make sure, no other thread is accessing device + lock(); + // now were save to access the device + if( _src_sample_rate != m_sampleRate ) + { + surroundSampleFrame * temp = + bufferAllocator::alloc( + _frames * channels() ); + resample( _ab, _frames, temp, _src_sample_rate, m_sampleRate ); + writeBufferToDev( temp, _frames * m_sampleRate / + _src_sample_rate, _master_output ); + bufferAllocator::free( temp ); + } + else + { + writeBufferToDev( _ab, _frames, _master_output ); + } + // release lock + unlock(); +} + + +#ifndef HAVE_SAMPLERATE_H +const Uint8 LP_FILTER_TAPS = 24; +const float LP_FILTER_COEFFS[LP_FILTER_TAPS] = +{ + +0.000511851442, + -0.001446936402, + -0.005058312516, + -0.002347181570, + +0.011236146012, + +0.020351310667, + -0.000479735368, + -0.045333228189 + -0.055186434405, + +0.032962246498, + +0.202439670159, + +0.342350604673, + +0.342350604673, + +0.202439670159, + +0.032962246498, + -0.055186434405, + -0.045333228189 + -0.000479735368, + +0.020351310667, + +0.011236146012, + -0.002347181570, + -0.005058312516, + -0.001446936402, + +0.000511851442 +} ; +#endif + + +void FASTCALL audioDevice::resample( surroundSampleFrame * _src, Uint32 _frames, + surroundSampleFrame * _dst, + Uint32 _src_sr, Uint32 _dst_sr ) +{ +#ifdef HAVE_SAMPLERATE_H + if( m_srcState == NULL ) + { + return; + } + m_srcData.input_frames = _frames; + m_srcData.output_frames = _frames; + m_srcData.data_in = _src[0]; + m_srcData.data_out = _dst[0]; + m_srcData.src_ratio = (float) _dst_sr / _src_sr; + + int error; + if( ( error = src_process( m_srcState, &m_srcData ) ) ) + { + printf( "audioDevice::resample(): error while resampling: %s\n", + src_strerror( error ) ); + } +#else + if( _src_sr == 2*SAMPLE_RATES[DEFAULT_QUALITY_LEVEL] ) + { + // we use a simple N-tap FIR-Filter with + // precalculated/-designed LP-Coeffs + static surroundSampleFrame lp_hist[LP_FILTER_TAPS] = + { +#ifndef DISABLE_SURROUND + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f } +#else + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f }, + { 0.0f, 0.0f } +#endif + } ; + static Uint8 oldest = 0; + + for( Uint32 frame = 0; frame < _frames; ++frame ) + { + for( Uint8 chnl = 0; chnl < SURROUND_CHANNELS; ++chnl ) + { + lp_hist[oldest][chnl] = _src[frame][chnl]; + if( frame % 2==0 ) + { + _dst[frame/2][chnl] = 0.0f; + for( Uint8 tap = 0; + tap < LP_FILTER_TAPS; ++tap ) + { + _dst[frame / 2][chnl] += +LP_FILTER_COEFFS[tap] * lp_hist[( oldest + tap ) % LP_FILTER_TAPS][chnl]; + } + } + } + oldest = ( oldest + 1 ) % LP_FILTER_TAPS; + } + } + else if( _src_sr == SAMPLE_RATES[DEFAULT_QUALITY_LEVEL] / 2 ) + { + printf( "No resampling for given sample-rates implemented!\n" + "Consider installing libsamplerate and recompile " + "LMMS!\n" ); + } +#endif +} + + + + +int FASTCALL audioDevice::convertToS16( surroundSampleFrame * _ab, + Uint32 _frames, float _master_output, + outputSampleType * _output_buffer, + bool _convert_endian ) +{ + for( Uint32 frame = 0; frame < _frames; ++frame ) + { + for( Uint8 chnl = 0; chnl < channels(); ++chnl ) + { + ( _output_buffer + frame * channels() )[chnl] = + static_cast( + mixer::clip( _ab[frame][chnl] * + _master_output ) * + OUTPUT_SAMPLE_MULTIPLIER ); + } + } + if( _convert_endian ) + { + for( Uint32 frame = 0; frame < _frames; ++frame ) + { + for( Uint8 chnl = 0; chnl < channels(); ++chnl ) + { + Sint8 * ptr = reinterpret_cast( + _output_buffer + + frame * channels() + + chnl ); + *(outputSampleType *)ptr = + ( ( outputSampleType )*ptr << 8 + ) | + ( ( outputSampleType ) * + ( ptr+1 ) ); + } + } + } + return( _frames * channels() * BYTES_PER_OUTPUT_SAMPLE ); +} + + + + +void FASTCALL audioDevice::clearS16Buffer( outputSampleType * _outbuf, + Uint32 _frames ) +{ +#ifdef LMMS_DEBUG + assert( _outbuf != NULL ); +#endif + memset( _outbuf, 0, _frames * channels() * BYTES_PER_OUTPUT_SAMPLE ); +} + diff --git a/src/audio/audio_file_device.cpp b/src/audio/audio_file_device.cpp new file mode 100644 index 00000000000..f13f0506843 --- /dev/null +++ b/src/audio/audio_file_device.cpp @@ -0,0 +1,103 @@ +/* + * audio_file_device.cpp - base-class for audio-device-classes which write + * their output into a file + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + + +#include "audio_file_device.h" +#include "export_project_dialog.h" + + +audioFileDevice::audioFileDevice( Uint32 _sample_rate, Uint8 _channels, + const QString & _file, + bool _use_vbr, + Uint16 _nom_bitrate, + Uint16 _min_bitrate, + Uint16 _max_bitrate ) : + audioDevice( _sample_rate, _channels), + m_outputFile( _file ), + m_useVbr( _use_vbr ), + m_nomBitrate( _nom_bitrate ), + m_minBitrate( _min_bitrate ), + m_maxBitrate( _max_bitrate ) +{ +#ifdef QT4 + if( m_outputFile.open( QFile::WriteOnly | QFile::Truncate ) == FALSE ) +#else + if( m_outputFile.open( IO_WriteOnly | IO_Truncate ) == FALSE ) +#endif + { + QMessageBox::critical( NULL, + exportProjectDialog::tr( "Could not open file" ), + exportProjectDialog::tr( "Could not open file %1 " + "for writing.\nPlease make " + "sure you have write-" + "permission to the file and " + "the directory containing the " + "file and try again!" ).arg( + _file ), + QMessageBox::Ok, + QMessageBox::NoButton ); + } +} + + + + +audioFileDevice::~audioFileDevice() +{ + m_outputFile.close(); +} + + + + +int audioFileDevice::writeData( const void * _data, int _len ) +{ +#ifdef QT4 + return( m_outputFile.write( (const char *)_data, _len ) ); +#else + return( m_outputFile.writeBlock( (const char *)_data, _len ) ); +#endif +} + + + + +void audioFileDevice::seekToBegin( void ) +{ + m_outputFile.seek( 0 ); +} + diff --git a/src/audio/audio_file_ogg.cpp b/src/audio/audio_file_ogg.cpp new file mode 100644 index 00000000000..c8704309a6a --- /dev/null +++ b/src/audio/audio_file_ogg.cpp @@ -0,0 +1,267 @@ +/* + * audio_file_ogg.cpp - Audio-device which encodes wave-stream and writes it + * into an OGG-file. This is used for song-export. + * + * This file is based on encode.c from vorbis-tools-source, for more information + * see below. + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +/* OggEnc + ** + ** This program is distributed under the GNU General Public License, version 2. + ** A copy of this license is included with this source. + ** + ** Copyright 2000-2002, Michael Smith + ** + ** Portions from Vorbize, (c) Kenneth Arnold + ** and libvorbis examples, (c) Monty + **/ + + +#include + +#include "audio_file_ogg.h" + +#ifdef HAVE_VORBIS_CODEC_H + + +#include +#include + + +audioFileOgg::audioFileOgg( Uint32 _sample_rate, Uint32 _channels, + bool & _success_ful, const QString & _file, + bool _use_vbr, Uint16 _nom_bitrate, + Uint16 _min_bitrate, Uint16 _max_bitrate ) : + audioFileDevice( _sample_rate, _channels, _file, _use_vbr, + _nom_bitrate, _min_bitrate, _max_bitrate ) +{ + _success_ful = startEncoding(); +} + + + + +audioFileOgg::~audioFileOgg() +{ + finishEncoding(); +} + + + + +inline int audioFileOgg::writePage( void ) +{ + int written = writeData( m_og.header, m_og.header_len ); + written += writeData( m_og.body, m_og.body_len ); + return( written ); +} + + + + +bool audioFileOgg::startEncoding( void ) +{ + vorbis_comment vc; + char * comments = "Cool=This song was written with Linux " + "MultiMedia Studio"; + int comment_length = strlen( comments ); + + vc.user_comments = &comments; + vc.comment_lengths = &comment_length; + vc.comments = 1; + vc.vendor = NULL; + + m_channels = channels(); + // vbr enabled? + if( useVBR() == 0 ) + { + m_managed = -1; // we don't want vbr + m_minBitrate = nominalBitrate(); // min for vbr + m_maxBitrate = nominalBitrate(); // max for vbr + } + else + { + m_managed = 0; // let's use vbr + m_minBitrate = minBitrate(); // min for vbr + m_maxBitrate = maxBitrate(); // max for vbr + } + + m_bitrate = nominalBitrate(); // nominal bitrate + m_rate = sampleRate(); // default-samplerate + m_serialNo = 0; // track-num? + m_comments = &vc; // comments for ogg-file + + // Have vorbisenc choose a mode for us + vorbis_info_init( &m_vi ); + + if( vorbis_encode_setup_managed( &m_vi, m_channels, m_rate, + ( m_maxBitrate > 0 )? m_maxBitrate * 1000 : -1, + m_bitrate * 1000, + ( m_minBitrate > 0 )? m_minBitrate * 1000 : -1 ) ) + { + printf( "Mode initialization failed: invalid parameters for " + "bitrate\n" ); + vorbis_info_clear( &m_vi ); + return( FALSE ); + } + + if( m_managed && m_bitrate < 0 ) + { + vorbis_encode_ctl( &m_vi, OV_ECTL_RATEMANAGE_AVG, NULL ); + } + else if( !m_managed ) + { + // Turn off management entirely (if it was turned on). + vorbis_encode_ctl( &m_vi, OV_ECTL_RATEMANAGE_SET, NULL ); + } + + vorbis_encode_setup_init( &m_vi ); + + // Now, set up the analysis engine, stream encoder, and other + // preparation before the encoding begins. + vorbis_analysis_init( &m_vd, &m_vi ); + vorbis_block_init( &m_vd, &m_vb ); + + ogg_stream_init( &m_os, m_serialNo ); + + // Now, build the three header packets and send through to the stream + // output stage (but defer actual file output until the main encode + // loop) + + ogg_packet header_main; + ogg_packet header_comments; + ogg_packet header_codebooks; + int result; + + // Build the packets + vorbis_analysis_headerout( &m_vd, m_comments, &header_main, + &header_comments, &header_codebooks ); + + // And stream them out + ogg_stream_packetin( &m_os, &header_main ); + ogg_stream_packetin( &m_os, &header_comments ); + ogg_stream_packetin( &m_os, &header_codebooks ); + + while( ( result = ogg_stream_flush( &m_os, &m_og ) ) ) + { + if( !result ) + { + break; + } + int ret = writePage(); + if( ret != m_og.header_len + m_og.body_len ) + { + // clean up + finishEncoding(); + return( FALSE ); + } + } + + return( TRUE ); +} + + + + +void FASTCALL audioFileOgg::writeBufferToDev( surroundSampleFrame * _ab, + Uint32 _frames, + float _master_output ) +{ + int eos = 0; + + float * * buffer = vorbis_analysis_buffer( &m_vd, _frames * + BYTES_PER_SAMPLE * + channels() ); + for( Uint32 frame = 0; frame < _frames; ++frame ) + { + for( Uint8 chnl = 0; chnl < channels(); ++chnl ) + { + buffer[chnl][frame] = _ab[frame][chnl] * _master_output; + } + } + + vorbis_analysis_wrote( &m_vd, _frames ); + + // While we can get enough data from the library to analyse, + // one block at a time... + while( vorbis_analysis_blockout( &m_vd, &m_vb ) == 1 ) + { + // Do the main analysis, creating a packet + vorbis_analysis( &m_vb, NULL ); + vorbis_bitrate_addblock( &m_vb ); + + while( vorbis_bitrate_flushpacket( &m_vd, &m_op ) ) + { + // Add packet to bitstream + ogg_stream_packetin( &m_os, &m_op ); + + // If we've gone over a page boundary, we can do + // actual output, so do so (for however many pages + // are available) + while( !eos ) + { + int result = ogg_stream_pageout( &m_os, + &m_og ); + if( !result ) + { + break; + } + + int ret = writePage(); + if( ret != m_og.header_len + + m_og.body_len ) + { + printf( "failed writing to " + "outstream\n" ); + return; + } + + if( ogg_page_eos( &m_og ) ) + { + eos = 1; + } + } + } + } +} + + + + +void audioFileOgg::finishEncoding( void ) +{ + // just for flushing buffers... + writeBufferToDev( NULL, 0, 0.0f ); + + // clean up + ogg_stream_clear( &m_os ); + + vorbis_block_clear( &m_vb ); + vorbis_dsp_clear( &m_vd ); + vorbis_info_clear( &m_vi ); +} + + +#endif + diff --git a/src/audio/audio_file_wave.cpp b/src/audio/audio_file_wave.cpp new file mode 100644 index 00000000000..89bebb54619 --- /dev/null +++ b/src/audio/audio_file_wave.cpp @@ -0,0 +1,118 @@ +/* + * audio_file_wave.cpp - Audio-device which encodes wave-stream and writes it + * into a WAVE-file. This is used for song-export. + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + + +#include "audio_file_wave.h" +#include "endian_handling.h" +#include "buffer_allocator.h" + +#include + + +audioFileWave::audioFileWave( Uint32 _sample_rate, Uint32 _channels, + bool & _success_ful, const QString & _file, + bool _use_vbr, Uint16 _nom_bitrate, + Uint16 _min_bitrate, Uint16 _max_bitrate ) : + audioFileDevice( _sample_rate, _channels, _file, _use_vbr, + _nom_bitrate, _min_bitrate, _max_bitrate ) +{ + _success_ful = startEncoding(); +} + + + + +audioFileWave::~audioFileWave() +{ + finishEncoding(); +} + + + + +bool audioFileWave::startEncoding( void ) +{ + if( outputFileOpened() == FALSE ) + { + return( FALSE ); + } + + m_bytesWritten = 0; + + memcpy( m_waveFileHeader.riff_id, "RIFF", 4 ); + m_waveFileHeader.total_bytes = swap32IfBE( 0 ); + memcpy( m_waveFileHeader.wave_fmt_str, "WAVEfmt ", 8 ); + m_waveFileHeader.bitrate_1 = + m_waveFileHeader.bitrate_2 = + swap16IfBE( BYTES_PER_OUTPUT_SAMPLE * 8 ); + m_waveFileHeader.uncompressed = swap16IfBE( 1 ); + m_waveFileHeader.channels = swap16IfBE( channels() ); + m_waveFileHeader.sample_rate = swap32IfBE( sampleRate() ); + m_waveFileHeader.bytes_per_second = swap32IfBE( sampleRate() * + BYTES_PER_OUTPUT_SAMPLE * + channels() ); + m_waveFileHeader.block_alignment = swap16IfBE( BYTES_PER_OUTPUT_SAMPLE * + channels() ); + memcpy ( m_waveFileHeader.data_chunk_id, "data", 4 ); + m_waveFileHeader.data_bytes = swap32IfBE( 0 ); + + writeData( &m_waveFileHeader, sizeof( m_waveFileHeader ) ); + + return( TRUE ); +} + + + + +void FASTCALL audioFileWave::writeBufferToDev( surroundSampleFrame * _ab, + Uint32 _frames, + float _master_output ) +{ + outputSampleType * outbuf = bufferAllocator::alloc( + _frames * channels() ); + int bytes = convertToS16( _ab, _frames, _master_output, outbuf, + !isLittleEndian() ); + writeData( outbuf, bytes ); + + bufferAllocator::free( outbuf ); + + m_bytesWritten += bytes; +} + + + + +void audioFileWave::finishEncoding( void ) +{ + seekToBegin(); + + m_waveFileHeader.total_bytes = m_bytesWritten+36; + m_waveFileHeader.data_bytes = m_bytesWritten; + + // write header again, because total-bytes-field and data-bytes-field + // have to be updated... + writeData( &m_waveFileHeader, sizeof( m_waveFileHeader ) ); +} + diff --git a/src/audio/audio_jack.cpp b/src/audio/audio_jack.cpp new file mode 100644 index 00000000000..c5f3630ef14 --- /dev/null +++ b/src/audio/audio_jack.cpp @@ -0,0 +1,379 @@ +/* + * audio_jack.cpp - support for JACK-transport + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + + +#include "audio_jack.h" + +#ifdef HAVE_UNISTD_H +// for usleep +#include +#endif + + +#ifdef JACK_SUPPORT + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + + + +#include "debug.h" +#include "templates.h" +#include "buffer_allocator.h" +#include "config_mgr.h" +#include "lcd_spinbox.h" + + +audioJACK::audioJACK( Uint32 _sample_rate, bool & _success_ful ) : + audioDevice( _sample_rate, tLimit( configManager::inst()->value( + "audiojack", "channels" ).toInt(), + DEFAULT_CHANNELS, SURROUND_CHANNELS ) ), + m_framesDoneInCurBuf( 0 ), + m_frameSync( 0 ), + m_jackBufSize( 0 ), + m_bufMutex() +{ + _success_ful = FALSE; + + QString client_name = configManager::inst()->value( "audiojack", + "clientname" ); + if( client_name == "" ) + { + client_name = "lmms"; + } + +#ifndef OLD_JACK + const char * server_name = NULL; + jack_status_t status; + m_client = jack_client_open( client_name. +#ifdef QT4 + toAscii().constData(), +#else + ascii(), +#endif + JackNullOption, &status, + server_name ); + if( m_client == NULL ) + { + printf( "jack_client_open() failed with status %d\n", status ); + if( status & JackServerFailed ) + { + printf( "Could not connect to JACK server.\n" ); + } + return; + } + if( status & JackNameNotUnique ) + { + printf( "there's already a client with name '%s', so unique " + "name '%s' was assigned\n", client_name. +#ifdef QT4 + toAscii().constData(), +#else + ascii(), +#endif + jack_get_client_name( m_client ) ); + } +#else + m_client = jack_client_new( client_name. +#ifdef QT4 + toAscii().constData() +#else + ascii() +#endif + ); +#endif + + // set process-callback + jack_set_process_callback( m_client, processCallback, this ); + + // we need to know about buffer-size changes to know how long to block + // in writeToDev()-method + jack_set_buffer_size_callback( m_client, bufSizeCallback, this ); + + // set shutdown-callback + //jack_on_shutdown( m_client, shutdown, this ); + + m_jackBufSize = jack_get_buffer_size( m_client ); + + + if( jack_get_sample_rate( m_client ) != sampleRate() ) + { + SAMPLE_RATES[0] = jack_get_sample_rate( m_client ); + SAMPLE_RATES[1] = 2 * SAMPLE_RATES[0]; + setSampleRate( SAMPLE_RATES[0] ); + } + + for( Uint8 ch = 0; ch < channels(); ++ch ) + { + QString name = QString( "master_out_" ) + + ( ( ch % 2 ) ? "R" : "L" ) + + QString::number( ch / 2 + 1 ); + m_outputPorts.push_back( jack_port_register( m_client, +#ifdef QT4 + name.toAscii().constData(), +#else + name.ascii(), +#endif + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, 0 ) ); + if( m_outputPorts.back() == NULL ) + { + printf( "no more JACK-ports available!\n" ); + return; + } + } + + + if( jack_activate( m_client ) ) + { + printf( "cannot activate client\n" ); + return; + } + + const char * * ports = jack_get_ports( m_client, NULL, NULL, + JackPortIsPhysical | + JackPortIsInput ); + if( ports == NULL ) + { + printf( "no physical playback ports. you'll have to do " + "connections at your own!\n" ); + } + else + { + for( Uint8 ch = 0; ch < channels(); ++ch ) + { + if( jack_connect( m_client, jack_port_name( + m_outputPorts[ch] ), + ports[ch] ) ) + { + printf( "cannot connect output ports. you'll " + "have to do connections at your own!\n" + ); + } + } + } + + free( ports ); + + _success_ful = TRUE; +} + + + + +audioJACK::~audioJACK() +{ + jack_deactivate( m_client ); + jack_client_close( m_client ); + + while( m_bufferSets.size() ) + { + while( m_bufferSets.front().size() ) + { + bufferAllocator::free( + m_bufferSets.front().front().buf ); + m_bufferSets.front().erase( + m_bufferSets.front().begin() ); + } + m_bufferSets.erase( m_bufferSets.begin() ); + } +} + + + + +void audioJACK::writeBufferToDev( surroundSampleFrame * _ab, Uint32 _frames, + float _master_output ) +{ + m_bufMutex.lock(); + + vvector bufs; + for( Uint8 chnl = 0; chnl < channels(); ++chnl ) + { + sampleType * buf = bufferAllocator::alloc( + _frames ); + for( Uint32 frame = 0; frame < _frames; ++frame ) + { + buf[frame] = _ab[frame][chnl] * _master_output; + } + bufset b = { buf, _frames } ; + bufs.push_back( b ); + } + m_bufferSets.push_back( bufs ); + m_frameSync += _frames; + + m_bufMutex.unlock(); + + // now wait until data has been collected by processCallback() + while( m_frameSync > m_jackBufSize ) + { +#ifdef HAVE_UNISTD_H +#ifdef HAVE_USLEEP + // just wait and give cpu-time to other processes + usleep( 500 ); +#endif +#endif + } +} + + + + +int audioJACK::processCallback( jack_nframes_t _nframes, void * _udata ) +{ + audioJACK * _this = static_cast( _udata ); + +#ifdef LMMS_DEBUG + assert( _this != NULL ); +#endif + jack_transport_state_t ts = jack_transport_query( _this->m_client, + NULL ); + if( ts != JackTransportRolling ) + { + return( 0 ); + } + + vvector outbufs( _this->channels(), + NULL ); + Uint8 ch = 0; + for( vvector::iterator it = + outbufs.begin(); it != outbufs.end(); ++it, ++ch ) + { + *it = (jack_default_audio_sample_t *) jack_port_get_buffer( + _this->m_outputPorts[ch], _nframes ); + } + + _this->m_bufMutex.lock(); + + jack_nframes_t done = 0; + while( done < _nframes ) + { + if( _this->m_bufferSets.size() == 0 ) + { + break; + } + jack_nframes_t todo = tMin( _nframes - done, + _this->m_bufferSets.front()[0].frames - + _this->m_framesDoneInCurBuf ); + for( Uint8 ch = 0; ch < _this->channels(); ++ch ) + { + memcpy( outbufs[ch] + done, + _this->m_bufferSets.front()[ch].buf + + _this->m_framesDoneInCurBuf, + sizeof( jack_default_audio_sample_t ) * + todo ); + } + _this->m_framesDoneInCurBuf += todo; + if( _this->m_framesDoneInCurBuf >= + _this->m_bufferSets.front()[0].frames ) + { + for( Uint8 ch = 0; ch < _this->channels(); ++ch ) + { + bufferAllocator::free( + _this->m_bufferSets.front()[ch].buf ); + } + _this->m_bufferSets.erase( + _this->m_bufferSets.begin() ); + _this->m_framesDoneInCurBuf = 0; + } + done += todo; + _this->m_frameSync -= todo; + } + _this->m_bufMutex.unlock(); + + return( 0 ); +} + + + + +int audioJACK::bufSizeCallback( jack_nframes_t _nframes, void * _udata ) +{ + audioJACK * _this = static_cast( _udata ); + +#ifdef LMMS_DEBUG + assert( _this != NULL ); +#endif + _this->m_jackBufSize = _nframes; + + return( 0 ); +} + + + + +audioJACK::setupWidget::setupWidget( QWidget * _parent ) : + audioDevice::setupWidget( audioJACK::name(), _parent ) +{ + QString cn = configManager::inst()->value( "audiojack", "clientname" ); + if( cn == "" ) + { + cn = "lmms"; + } + m_clientName = new QLineEdit( cn, this ); + m_clientName->setGeometry( 10, 20, 160, 20 ); + + QLabel * cn_lbl = new QLabel( tr( "CLIENT-NAME" ), this ); + cn_lbl->setFont( pointSize<6>( cn_lbl->font() ) ); + cn_lbl->setGeometry( 10, 40, 160, 10 ); + + m_channels = new lcdSpinBox( DEFAULT_CHANNELS, SURROUND_CHANNELS, 1, + this ); + m_channels->setStep( 2 ); + m_channels->setLabel( tr( "CHANNELS" ) ); + m_channels->setValue( configManager::inst()->value( "audiojack", + "channels" ).toInt() ); + m_channels->move( 180, 20 ); + +} + + + + +audioJACK::setupWidget::~setupWidget() +{ +} + + + + +void audioJACK::setupWidget::saveSettings( void ) +{ + configManager::inst()->setValue( "audiojack", "clientname", + m_clientName->text() ); + configManager::inst()->setValue( "audiojack", "channels", + QString::number( m_channels->value() ) ); +} + + +#endif diff --git a/src/audio/audio_oss.cpp b/src/audio/audio_oss.cpp new file mode 100644 index 00000000000..60a100e37d4 --- /dev/null +++ b/src/audio/audio_oss.cpp @@ -0,0 +1,329 @@ +/* + * audio_oss.cpp - device-class that implements OSS-PCM-output + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include +#include + +#endif + + +#include "audio_oss.h" +#include "buffer_allocator.h" +#include "endian_handling.h" +#include "lcd_spinbox.h" +#include "templates.h" + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef OSS_USE_SOUNDCARD_H +/* This is installed on some systems */ +#include +#else +/* This is recommended by OSS */ +#include +#endif + + +#include "config_mgr.h" + + +#ifndef _PATH_DEV_DSP +#ifdef __OpenBSD__ +#define _PATH_DEV_DSP "/dev/audio" +#else +#define _PATH_DEV_DSP "/dev/dsp" +#endif +#endif + + + +audioOSS::audioOSS( Uint32 _sample_rate, bool & _success_ful ) : + audioDevice( _sample_rate, tLimit( configManager::inst()->value( + "audiooss", "channels" ).toInt(), + DEFAULT_CHANNELS, SURROUND_CHANNELS ) ), + m_convertEndian( FALSE ) +{ + _success_ful = FALSE; + + m_audioFD = open( +#ifdef QT4 + probeDevice().toAscii().constData(), +#else + probeDevice().ascii(), +#endif + O_WRONLY, 0 ); + + if( m_audioFD == -1 ) + { + printf( "audioOSS: failed opening audio-device\n" ); + return; + } + + + // Make the file descriptor use blocking writes with fcntl() + if ( fcntl( m_audioFD, F_SETFL, fcntl( m_audioFD, F_GETFL ) & + ~O_NONBLOCK ) < 0 ) + { + printf( "could not set audio blocking mode\n" ); + return; + } + + int frag_spec; + for( frag_spec = 0; static_cast( 0x01 << frag_spec ) < + mixer::inst()->framesPerAudioBuffer() * channels() * + BYTES_PER_OUTPUT_SAMPLE; + ++frag_spec ) + { + } + + frag_spec |= 0x00020000; // two fragments, for low latency + + if ( ioctl( m_audioFD, SNDCTL_DSP_SETFRAGMENT, &frag_spec ) < 0 ) + { + perror( "SNDCTL_DSP_SETFRAGMENT" ); + printf( "Warning: Couldn't set audio fragment size\n" ); + } + + unsigned int value; + // Get a list of supported hardware formats + if ( ioctl( m_audioFD, SNDCTL_DSP_GETFMTS, &value ) < 0 ) + { + perror( "SNDCTL_DSP_GETFMTS" ); + printf( "Couldn't get audio format list\n" ); + return; + } + + // Set the audio format + if( value & AFMT_S16_LE ) + { + value = AFMT_S16_LE; + } + else if( value & AFMT_S16_BE ) + { + value = AFMT_S16_BE; + } + else + { + printf(" Soundcard doesn't support signed 16-bit-data\n"); + } + if ( ioctl( m_audioFD, SNDCTL_DSP_SETFMT, &value ) < 0 ) + { + perror( "SNDCTL_DSP_SETFMT" ); + printf( "Couldn't set audio format\n" ); + return; + } + if( ( isLittleEndian() && ( value == AFMT_S16_BE ) ) || + ( !isLittleEndian() && ( value == AFMT_S16_LE ) ) ) + { + m_convertEndian = TRUE; + } + + // Set the number of channels of output + value = channels(); + if ( ioctl( m_audioFD, SNDCTL_DSP_CHANNELS, &value ) < 0 ) + { + perror( "SNDCTL_DSP_CHANNELS" ); + printf( "Cannot set the number of channels\n" ); + return; + } + if( value != channels() ) + { + printf( "Couldn't set number of channels\n" ); + return; + } + + // Set the DSP frequency + value = sampleRate(); + if ( ioctl( m_audioFD, SNDCTL_DSP_SPEED, &value ) < 0 ) + { + perror( "SNDCTL_DSP_SPEED" ); + printf( "Couldn't set audio frequency\n" ); + return; + } + if( value != sampleRate() ) + { + //printf( "Soundcard uses different sample-rate than LMMS " + // "does!\n" ); + int q = 0; + if( sampleRate() == SAMPLE_RATES[1] ) + { + q = 1; + } + if( sampleRate() == 44100 || sampleRate() == 88200 ) + { + SAMPLE_RATES[0] = 48000; + SAMPLE_RATES[1] = 96000; + } + else + { + SAMPLE_RATES[0] = 44100; + SAMPLE_RATES[1] = 82000; + } + setSampleRate( SAMPLE_RATES[q] ); + value = sampleRate(); + if ( ioctl( m_audioFD, SNDCTL_DSP_SPEED, &value ) < 0 ) + { + perror( "SNDCTL_DSP_SPEED" ); + printf( "Couldn't set audio frequency\n" ); + return; + } + } + + _success_ful = TRUE; +} + + + + +audioOSS::~audioOSS() +{ + close( m_audioFD ); +} + + + + +QString audioOSS::probeDevice( void ) +{ + QString dev = configManager::inst()->value( "audiooss", "device" ); + if( dev == "" ) + { + char * adev = getenv( "AUDIODEV" ); // Is there a standard + // variable name? + if( adev != NULL ) + { + dev = adev; + } + else + { + dev = _PATH_DEV_DSP; // default device + } + } + + // if the first open fails, look for other devices + if ( QFileInfo( dev ).isWritable() == FALSE ) + { + int instance = -1; + while( 1 ) + { + dev = _PATH_DEV_DSP + QString::number( ++instance ); + if( !QFileInfo( dev ).exists() ) + { + dev = _PATH_DEV_DSP; + break; + } + if( QFileInfo( dev ).isWritable() ) + { + break; + } + } + } + return( dev ); +} + + + + +void audioOSS::writeBufferToDev( surroundSampleFrame * _ab, Uint32 _frames, + float _master_output ) +{ + outputSampleType * outbuf = bufferAllocator::alloc( + _frames * channels() ); + int bytes = convertToS16( _ab, _frames, _master_output, outbuf, + m_convertEndian ); + write( m_audioFD, outbuf, bytes ); + + bufferAllocator::free( outbuf ); +} + + + + +audioOSS::setupWidget::setupWidget( QWidget * _parent ) : + audioDevice::setupWidget( audioOSS::name(), _parent ) +{ + m_device = new QLineEdit( probeDevice(), this ); + m_device->setGeometry( 10, 20, 160, 20 ); + + QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + dev_lbl->setFont( pointSize<6>( dev_lbl->font() ) ); + dev_lbl->setGeometry( 10, 40, 160, 10 ); + + m_channels = new lcdSpinBox( DEFAULT_CHANNELS, SURROUND_CHANNELS, 1, + this ); + m_channels->setStep( 2 ); + m_channels->setLabel( tr( "CHANNELS" ) ); + m_channels->setValue( configManager::inst()->value( "audiooss", + "channels" ).toInt() ); + m_channels->move( 180, 20 ); + +} + + + + +audioOSS::setupWidget::~setupWidget() +{ + +} + + + + +void audioOSS::setupWidget::saveSettings( void ) +{ + configManager::inst()->setValue( "audiooss", "device", + m_device->text() ); + configManager::inst()->setValue( "audiooss", "channels", + QString::number( m_channels->value() ) ); +} + + diff --git a/src/audio/audio_sample_recorder.cpp b/src/audio/audio_sample_recorder.cpp new file mode 100644 index 00000000000..ee4bd9614bc --- /dev/null +++ b/src/audio/audio_sample_recorder.cpp @@ -0,0 +1,112 @@ +/* + * audio_sample_recorder.cpp - device-class that implements recording + * surround-audio-buffers into RAM, maybe later + * also harddisk + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + + +#include "audio_sample_recorder.h" +#include "sample_buffer.h" +#include "buffer_allocator.h" +#include "debug.h" + + + +audioSampleRecorder::audioSampleRecorder( Uint32 _sample_rate, Uint32 _channels, + bool & _success_ful ) : + audioDevice( _sample_rate, _channels ), + m_buffers() +{ + _success_ful = TRUE; +} + + + + +audioSampleRecorder::~audioSampleRecorder() +{ + while( !m_buffers.isEmpty() ) + { + bufferAllocator::free( m_buffers.front().first ); + m_buffers.erase( m_buffers.begin() ); + } +} + + + + +Uint32 audioSampleRecorder::framesRecorded( void ) const +{ + Uint32 frames = 0; + for( bufferVector::const_iterator it = m_buffers.begin(); + it != m_buffers.end(); ++it ) + { + frames += it->second; + } + return( frames ); +} + + + + +void audioSampleRecorder::createSampleBuffer( sampleBuffer * * _sample_buf ) + const +{ + Uint32 frames = framesRecorded(); + // create buffer to store all recorded buffers in + sampleFrame * data = bufferAllocator::alloc( frames ); + // make sure buffer is cleaned up properly at the end... + bufferAllocator::autoCleaner ac( data ); + +#ifdef LMMS_DEBUG + assert( data != NULL ); +#endif + // now copy all buffers into big buffer + for( bufferVector::const_iterator it = m_buffers.begin(); + it != m_buffers.end(); ++it ) + { + memcpy( data, it->first, it->second * sizeof( sampleFrame ) ); + data += it->second; + } + // create according sample-buffer out of big buffer + *_sample_buf = new sampleBuffer( ac.ptr(), frames ); +} + + + + +void audioSampleRecorder::writeBufferToDev( surroundSampleFrame * _ab, + Uint32 _frames, float ) +{ + sampleFrame * buf = bufferAllocator::alloc( _frames ); + for( Uint32 frame = 0; frame < _frames; ++frame ) + { + for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl ) + { + buf[frame][chnl] = _ab[frame][chnl]; + } + } + m_buffers.push_back( qMakePair( buf, _frames ) ); +} + + diff --git a/src/audio/audio_sdl.cpp b/src/audio/audio_sdl.cpp new file mode 100644 index 00000000000..3e186ddb004 --- /dev/null +++ b/src/audio/audio_sdl.cpp @@ -0,0 +1,203 @@ +/* + * audio_sdl.cpp - device-class that performs PCM-output via SDL + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + + +#include "audio_sdl.h" + +#ifdef SDL_AUDIO_SUPPORT + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + + +#include "buffer_allocator.h" +#include "debug.h" +#include "config_mgr.h" +#include "templates.h" + + + +audioSDL::audioSDL( Uint32 _sample_rate, bool & _success_ful ) : + audioDevice( _sample_rate, DEFAULT_CHANNELS ), + m_buffer( bufferAllocator::alloc( + mixer::inst()->framesPerAudioBuffer() * + channels() ) ), + m_bufMutex(), + m_callbackMutex(), + m_convertEndian( FALSE ) +{ + _success_ful = FALSE; + + // if device is set, we set AUDIODEV-environment-variable, so that + // SDL can evaluate and use it + QString dev = configManager::inst()->value( "audiosdl", "device" ); + if( dev != "" ) + { + putenv( const_cast( ( "AUDIODEV=" + dev ). +#ifdef QT4 + toAscii().constData() ) ); +#else + ascii() ) ); +#endif + } + + + if( SDL_Init( SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE ) < 0 ) + { + printf( "Couldn't initialize SDL: %s\n", SDL_GetError() ); + return; + } + + m_audioHandle.freq = _sample_rate; + m_audioHandle.format = AUDIO_S16SYS; // we want it in byte-order + // of system, so we don't have + // to convert the buffers + m_audioHandle.channels = channels(); + m_audioHandle.samples = mixer::inst()->framesPerAudioBuffer(); + + m_audioHandle.callback = sdlAudioCallback; + m_audioHandle.userdata = this; + + SDL_AudioSpec actual; + + // open the audio device, forcing the desired format + if( SDL_OpenAudio( &m_audioHandle, &actual ) < 0 ) + { + printf( "Couldn't open SDL-audio: %s\n", SDL_GetError() ); + return; + } + m_convertEndian = ( m_audioHandle.format != actual.format ); + + clearS16Buffer( m_buffer, m_audioHandle.samples ); + + // start playing + SDL_PauseAudio( 0 ); + + _success_ful = TRUE; +} + + + + +audioSDL::~audioSDL() +{ + SDL_PauseAudio( 1 ); + SDL_CloseAudio(); + SDL_Quit(); + + m_bufMutex.lock(); + bufferAllocator::free( m_buffer ); + m_bufMutex.unlock(); +} + + + + + +void audioSDL::writeBufferToDev( surroundSampleFrame * _ab, Uint32 _frames, + float _master_output ) +{ + m_bufMutex.lock(); + convertToS16( _ab, _frames, _master_output, m_buffer, + m_convertEndian ); + m_bufMutex.unlock(); + // before returning make sure, callback was called, so we're synced + // with it (otherwise it could be that (if there's not much to render) + // this function is called several times although we had to wait until + // we can proceed with next audio-output) + m_callbackMutex.lock(); +} + + + + +void audioSDL::sdlAudioCallback( void * _udata, Uint8 * _buf, int _len ) +{ + audioSDL * _this = static_cast( _udata ); + +#ifdef LMMS_DEBUG + assert( _this != NULL ); +#endif + + _this->m_bufMutex.lock(); + + // writeBufferToDev() prepared everything for us, so we just have + // to do a memcpy() :-) + memcpy( _buf, _this->m_buffer, _len ); + + // clear our output buffer, so that we don't output the same noise + // when being called again without that writeBufferToDev() was called + // (e.g. if there's too much to render) + _this->clearS16Buffer( _this->m_buffer, _this->m_audioHandle.samples ); + + _this->m_bufMutex.unlock(); + + // we got our last buffer, so we let writeBufferToDev() return + _this->m_callbackMutex.unlock(); +} + + + + +audioSDL::setupWidget::setupWidget( QWidget * _parent ) : + audioDevice::setupWidget( audioSDL::name(), _parent ) +{ + QString dev = configManager::inst()->value( "audiosdl", "device" ); + m_device = new QLineEdit( dev, this ); + m_device->setGeometry( 10, 20, 160, 20 ); + + QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + dev_lbl->setFont( pointSize<6>( dev_lbl->font() ) ); + dev_lbl->setGeometry( 10, 40, 160, 10 ); + +} + + + + +audioSDL::setupWidget::~setupWidget() +{ + +} + + + + +void audioSDL::setupWidget::saveSettings( void ) +{ + configManager::inst()->setValue( "audiosdl", "device", + m_device->text() ); +} + + +#endif diff --git a/src/lib/buffer_allocator.cpp b/src/lib/buffer_allocator.cpp new file mode 100644 index 00000000000..97b262bd819 --- /dev/null +++ b/src/lib/buffer_allocator.cpp @@ -0,0 +1,197 @@ +/* + * buffer_allocator.cpp - namespace bufferAllocator providing routines for own + * optimized memory-management for audio-buffers + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include +#include + +#define qSort qHeapSort + +#endif + +#include +#include + +#include "buffer_allocator.h" +#include "templates.h" +#include "mixer.h" +#include "debug.h" + + +struct bufDesc +{ + bool free; + char * origPtr; + void * buf; + Uint32 bytes; + Uint32 timesUsed; + +} ; + + +inline bool operator<( const bufDesc & _bd1, const bufDesc & _bd2 ) +{ + return( _bd1.timesUsed < _bd2.timesUsed ); +} + +#ifdef QT4 + +inline bool operator==( const bufDesc & _bd1, const bufDesc & _bd2 ) +{ + return( memcmp( &_bd1, &_bd2, sizeof( bufDesc ) ) == 0 ); +} + +#else + +inline bool operator!=( const bufDesc & _bd1, const bufDesc & _bd2 ) +{ + return( memcmp( &_bd1, &_bd2, sizeof( bufDesc ) ) != 0 ); +} + +#endif + + +static vlist s_buffers; +typedef vlist::iterator bufIt; + +QMutex s_buffersMutex; + + +const int BUFFER_ALIGN = 16; +const int BUFFER_ALIGN_MASK = BUFFER_ALIGN - 1; + + + +void bufferAllocator::cleanUp( Uint16 _level ) +{ + // first insert all unused bufs into an array + vvector bufsToRemove; + for( bufIt it = s_buffers.begin(); it != s_buffers.end(); ++it ) + { + if( ( *it ).free ) + { + bufsToRemove.push_back( *it ); + } + } + + // sort array by usage of each buffer + // ( operator<(...) compares bufDesc::timesUsed ) + qSort( bufsToRemove ); + + const Uint16 todo = tMin( s_buffers.size() - _level, + bufsToRemove.size() ); + + // now cleanup the first n elements of sorted array + for( Uint16 i = 0; i < todo ; ++i ) + { + delete[] bufsToRemove[i].origPtr; + s_buffers.erase( qFind( s_buffers.begin(), s_buffers.end(), + bufsToRemove[i] ) ); + } +#ifdef LMMS_DEBUG + //printf( "cleaned up %d buffers\n", todo ); +#endif +} + + + + +void bufferAllocator::free( void * _buf ) +{ + s_buffersMutex.lock(); + + // look for buffer + for( bufIt it = s_buffers.begin(); it != s_buffers.end(); ++it ) + { + if( !( *it ).free && ( *it ).buf == _buf ) + { + ++( *it ).timesUsed; + ( *it ).free = TRUE; + break; + } + } + + // do clean-up if neccessary + static Uint16 CLEANUP_LEVEL = static_cast( 512 / ( logf( + mixer::inst()->framesPerAudioBuffer() ) / + logf( 2 ) ) ); + if( s_buffers.size() > CLEANUP_LEVEL ) + { + cleanUp( CLEANUP_LEVEL ); + } + + s_buffersMutex.unlock(); +} + + + + +void * bufferAllocator::allocBytes( Uint32 _bytes ) +{ + QMutexLocker ml( &s_buffersMutex ); + + bufIt free_buf = s_buffers.end(); + + // look whether there's a buffer matching to the one wanted and + // find out the most used one (higher chances for being in CPU-cache) + for( bufIt it = s_buffers.begin(); it != s_buffers.end(); ++it ) + { + if( ( *it ).free && ( *it ).bytes == _bytes ) + { + if( free_buf == s_buffers.end() || + ( *it ).timesUsed > ( *free_buf ).timesUsed ) + { + free_buf = it; + } + } + } + + if( free_buf != s_buffers.end() ) + { + ( *free_buf ).free = FALSE; + return( ( *free_buf ).buf ); + } + + + // nothing so far, so we'll alloc a new (aligned) buf + bufDesc d = { FALSE, new char[_bytes + BUFFER_ALIGN], NULL, _bytes, 0 }; + d.buf = (void *)( (size_t) d.origPtr + ( BUFFER_ALIGN - + ( (size_t) d.origPtr & + BUFFER_ALIGN_MASK ) ) ); + s_buffers.push_back( d ); + return( d.buf ); +} + + + diff --git a/src/lib/clipboard.cpp b/src/lib/clipboard.cpp new file mode 100644 index 00000000000..91e876cee07 --- /dev/null +++ b/src/lib/clipboard.cpp @@ -0,0 +1,58 @@ +/* + * clipboard.cpp - the clipboard for patterns, notes etc. + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "clipboard.h" +#include "settings.h" + + +namespace clipboard +{ + + map content; + + + void copy( settings * _settings_object ) + { + QDomDocument doc; + QDomElement parent = doc.createElement( "clipboard" ); + _settings_object->saveSettings( doc, parent ); + content[_settings_object->nodeName()] = + parent.firstChild().toElement(); + } + + + + + const QDomElement * getContent( const QString & _node_name ) + { + if( content.find( _node_name ) != content.end() ) + { + return( &content[_node_name] ); + } + return( NULL ); + } + +} ; + + diff --git a/src/lib/embed.cpp b/src/lib/embed.cpp new file mode 100644 index 00000000000..eabc07d5082 --- /dev/null +++ b/src/lib/embed.cpp @@ -0,0 +1,123 @@ +/* + * embed.cpp - misc stuff for using embedded resources (linked into binary) + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include +#include + +#endif + + +#include "embed.h" +#include "config_mgr.h" + + +namespace embed +{ + +#include "embedded_resources.h" + + +QPixmap getIconPixmap( const char * _name, int _w, int _h ) +{ + if( _w == -1 || _h == -1 ) + { + QString name = QString( _name ) + ".png"; +#ifdef QT4 + const embedDesc & e = findEmbeddedData( + name.toAscii().constData() ); +#else + const embedDesc & e = findEmbeddedData( name.ascii() ); +#endif + // not found? + if( QString( e.name ) != name ) + { + // then look whether icon is in data-dir + QPixmap p( configManager::inst()->artworkDir() + name ); + if( p.isNull() ) + { + p = QPixmap( 1, 1 ); + } + return( p ); + } + QPixmap p; + p.loadFromData( e.data, e.size ); + return( p ); + } +#ifdef QT4 + return( getIconPixmap( _name ).scaled( _w, _h, Qt::IgnoreAspectRatio, + Qt::SmoothTransformation ) ); +#else + return( getIconPixmap( _name ).convertToImage().smoothScale( _w, _h ) ); +#endif +} + + + + +QString getText( const char * _name ) +{ + const embedDesc & e = findEmbeddedData( _name ); + return( QString::fromLatin1( (const char *) e.data, e.size ) ); +} + + + + +void loadTranslation( const QString & _tname ) +{ +#if QT_VERSION >= 0x030100 + QString name = _tname + ".qm"; +#ifdef QT4 + const embedDesc & e = findEmbeddedData( name.toAscii().constData() ); +#else + const embedDesc & e = findEmbeddedData( name.ascii() ); +#endif + QTranslator * t = new QTranslator( 0 ); + // not found? + if( QString( e.name ) != name ) + { + // then look whether translation is in data-dir + t->load( name, configManager::inst()->localeDir() ); + } + else + { + t->load( e.data, (int) e.size ); + } + qApp->installTranslator( t ); +#endif +} + + +} diff --git a/src/lib/mmp.cpp b/src/lib/mmp.cpp new file mode 100644 index 00000000000..64a49b20041 --- /dev/null +++ b/src/lib/mmp.cpp @@ -0,0 +1,273 @@ +/* + * mmp.cpp - implementation of class multimediaProject + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + +#ifdef HAVE_CONFIG_H +#include +#endif + + +#include "mmp.h" +#include "song_editor.h" + + + +multimediaProject::typeDescStruct multimediaProject::s_types[multimediaProject::PROJ_TYPE_COUNT] = +{ + { multimediaProject::UNKNOWN, "unknown" }, + { multimediaProject::SONG_PROJECT, "song" }, + { multimediaProject::CHANNEL_SETTINGS, "channelsettings" }, + { multimediaProject::EFFECT_SETTINGS, "effectsettings" }, + { multimediaProject::VIDEO_PROJECT, "video" }, + { multimediaProject::BURN_PROJECT, "burn" }, + { multimediaProject::PLAYLIST, "playlist" } +} ; + + + +multimediaProject::multimediaProject( projectTypes _project_type ) : + QDomDocument( "multimedia-project" ), + m_content(), + m_head(), + m_type( _project_type ) +{ + QDomElement root = createElement( "multimediaproject" ); + root.setAttribute( "version", MMP_VERSION_STRING ); + root.setAttribute( "type", typeName( _project_type ) ); + root.setAttribute( "creator", "Linux MultiMedia Studio (LMMS)" ); + root.setAttribute( "creatorversion", VERSION ); + appendChild( root ); + + m_head = createElement( "head" ); + root.appendChild( m_head ); + + m_content = createElement( typeName( _project_type ) ); + root.appendChild( m_content ); + +} + + + + +multimediaProject::multimediaProject( const QString & _in_file_name ) : + QDomDocument(), + m_content(), + m_head() +{ + QFile in_file( _in_file_name ); +#ifdef QT4 + if( !in_file.open( QIODevice::ReadOnly ) ) +#else + if( !in_file.open( IO_ReadOnly ) ) +#endif + { + QMessageBox::critical( NULL, + songEditor::tr( "Could not open file" ), + songEditor::tr( "Could not open " + "file %1. You probably " + "have no rights to " + "read this file.\n" + "Please make sure you " + "have at least read-" + "access to the file " + "and try again." + ).arg( _in_file_name ) ); + return; + } + + QString error_msg; + int line; + int col; + if( !setContent( &in_file, &error_msg, &line, &col ) ) + { + QMessageBox::critical( NULL, songEditor::tr( "Error in " + "multimedia-project" ), + songEditor::tr( "The multimedia-" + "project %1 seems to " + "contain errors. LMMS " + "will try its best " + "to recover as much as " + "possible data from " + "this file." + ).arg( _in_file_name ) ); + return; + } + in_file.close(); + + + QDomElement root = documentElement(); + m_type = type( root.attribute( "type" ) ); + + QDomNode node = root.firstChild(); + while( !node.isNull() ) + { + if( node.isElement() ) + { + if( node.nodeName() == "head" ) + { + m_head = node.toElement(); + } + else if( node.nodeName() == typeName( m_type ) ) + { + m_content = node.toElement(); + } + } + node = node.nextSibling(); + } +} + + + + +multimediaProject::~multimediaProject() +{ +} + + + + +bool multimediaProject::writeFile( const QString & _fn, bool _overwrite_check ) +{ + QString xml = "\n" + toString( +#if QT_VERSION >= 0x030100 + 2 +#endif + ); + QString fn = _fn; + if( type() == CHANNEL_SETTINGS ) + { + if( fn.section( '.', -2, -1 ) != "cs.xml" ) + { + fn += ".cs.xml"; + } + } + else if( fn.section( '.',-1 ) != "xml" ) + { + fn += ".xml"; + } + + + QFile outfile( fn ); + if( _overwrite_check == TRUE && + outfile.exists() == TRUE && + QMessageBox:: +#if QT_VERSION >= 0x030200 + question +#else + information +#endif + ( NULL, + songEditor::tr( "File already exists" ), + songEditor::tr( "The file %1 already " + "exists.\nDo you want " + "to overwrite it?" + ).arg( fn ), + QMessageBox::Yes, QMessageBox::No ) + == QMessageBox::No ) + { + return( FALSE ); + } + + +#ifdef QT4 + if( !outfile.open( QIODevice::WriteOnly | QIODevice::Truncate ) ) +#else + if( !outfile.open( IO_WriteOnly | IO_Truncate ) ) +#endif + { + QMessageBox::critical( NULL, songEditor::tr( "Could not write " + "file" ), + songEditor::tr( "Could not write file " + "%1. You probably are " + "not permitted to " + "write to this file. " + "Please make sure you " + "have write-access to " + "the file and try " + "again." + ).arg( fn ) ); + return( FALSE ); + } +#ifdef QT4 + outfile.write( xml.toAscii().constData(), xml.length() ); +#else + outfile.writeBlock( xml.ascii(), xml.length() ); +#endif + outfile.close(); + + return( TRUE ); +} + + + + +multimediaProject::projectTypes multimediaProject::typeOfFile( + const QString & _fn ) +{ + multimediaProject m( _fn ); + return( m.type() ); +} + + + + +multimediaProject::projectTypes multimediaProject::type( + const QString & _type_name ) +{ + for( int i = 0; i < PROJ_TYPE_COUNT; ++i ) + { + if( s_types[i].m_name == _type_name ) + { + return( static_cast( + i ) ); + } + } + return( UNKNOWN ); +} + + + + +QString multimediaProject::typeName( projectTypes _project_type ) +{ + if( _project_type >= UNKNOWN && _project_type < PROJ_TYPE_COUNT ) + { + return( s_types[_project_type].m_name ); + } + return( s_types[UNKNOWN].m_name ); +} + diff --git a/src/lib/oscillator.cpp b/src/lib/oscillator.cpp new file mode 100644 index 00000000000..f39c2450c96 --- /dev/null +++ b/src/lib/oscillator.cpp @@ -0,0 +1,259 @@ +/* + * oscillator.cpp - implementation of powerful oscillator-class + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "oscillator.h" + + +const sampleFrame zero_frame = { 0.0f, 0.0f }; + + +oscillator::oscillator( modulationAlgos _modulation_algo, float _freq, + Sint16 _phase_offset, float _volume_factor, + oscillator * _sub_osc ) : + m_freq(_freq), + m_volumeFactor(_volume_factor), + m_phaseOffset(_phase_offset), + m_subOsc(_sub_osc), + m_userWaveData( &zero_frame ), + m_userWaveFrames( 1 ) +{ + + if( m_subOsc != NULL ) + { + switch( _modulation_algo ) + { + case FREQ_MODULATION: + m_callUpdate = &oscillator::updateFM; + break; + + case AMP_MODULATION: + m_callUpdate = &oscillator::updateAM; + break; + + case MIX: + m_callUpdate = &oscillator::updateMix; + break; + case SYNC: + m_callUpdate = &oscillator::updateSync; + break; + } + } + else + { + m_callUpdate = &oscillator::updateNoSub; + } + + recalcOscCoeff(); +} + + + +// if we have no sub-osc, we can't do any modulation... just get our samples +#define defineNoSubUpdateFor(x,getSampleFunction) \ +void x::updateNoSub( sampleFrame * _ab, Uint32 _frames, Uint8 _chnl ) \ +{ \ + for( Uint16 frame = 0; frame < _frames; ++frame ) \ + { \ + _ab[frame][_chnl] = getSampleFunction( ++m_sample * \ + m_oscCoeff ) * m_volumeFactor; \ + } \ +} + + +// do fm by using sub-osc as modulator +#define defineFMUpdateFor(x,getSampleFunction) \ +void x::updateFM( sampleFrame * _ab, Uint32 _frames, Uint8 _chnl ) \ +{ \ + m_subOsc->update( _ab, _frames, _chnl ); \ + for( Uint16 frame = 0; frame < _frames; ++frame ) \ + { \ + _ab[frame][_chnl] = getSampleFunction( ++m_sample * \ + m_oscCoeff + \ + _ab[frame][_chnl] ) * \ + m_volumeFactor; \ + /* following line is REAL FM */ \ +/* float new_freq = powf( 2.0, _ab[frame][_chnl] ); \ + _ab[frame][_chnl] = getSampleFunction( ++m_sample*((m_freq * \ + new_freq )/mixer::inst()->sampleRate() )) * m_volumeFactor; \ + _ab[frame][_chnl] = getSampleFunction( ++m_sample*(m_oscCoeff *\ + _ab[frame][_chnl] )) * m_volumeFactor;*/ \ + } \ +} + + +// do am by using sub-osc as modulator +#define defineAMUpdateFor(x,getSampleFunction) \ +void x::updateAM( sampleFrame * _ab, Uint32 _frames, Uint8 _chnl ) \ +{ \ + m_subOsc->update( _ab, _frames, _chnl ); \ + for( Uint16 frame = 0; frame < _frames; ++frame ) \ + { \ + _ab[frame][_chnl] *= getSampleFunction( ++m_sample * \ + m_oscCoeff ) * m_volumeFactor; \ + } \ +} + + +// do mix by using sub-osc as mix-sample +#define defineMixUpdateFor(x,getSampleFunction) \ +void x::updateMix( sampleFrame * _ab, Uint32 _frames, Uint8 _chnl ) \ +{ \ + m_subOsc->update( _ab, _frames, _chnl ); \ + for( Uint16 frame = 0; frame < _frames; ++frame ) \ + { \ + _ab[frame][_chnl] += getSampleFunction( ++m_sample * \ + m_oscCoeff ) * m_volumeFactor; \ + } \ +} + + +// sync with sub-osc (every time sub-osc starts new period, we also start new +// period) +#define defineSyncUpdateFor(x,getSampleFunction) \ +void x::updateSync( sampleFrame * _ab, Uint32 _frames, Uint8 _chnl ) \ +{ \ + for( Uint16 frame = 0; frame < _frames ; ++frame ) \ + { \ + if( m_subOsc->syncOk() ) \ + { \ + sync(); \ + } \ + _ab[frame][_chnl] = getSampleFunction( ++m_sample * \ + m_oscCoeff ) * m_volumeFactor; \ + } \ +} + + + +#define generateOscillatorCodeFor(x,getSampleFunction); \ +class x : public oscillator \ +{ \ +public: \ + x( modulationAlgos modulation_algo, float _freq, Sint16 _phase_offset, \ + float _volume_factor, oscillator * _sub_osc) : \ + oscillator (modulation_algo, _freq, _phase_offset, _volume_factor, \ + _sub_osc ) \ + { \ + } \ + \ +protected: \ + void updateNoSub( sampleFrame * _ab, Uint32 _frames, \ + Uint8 _chnl ); \ + void updateFM( sampleFrame * _ab, Uint32 _frames, \ + Uint8 _chnl ); \ + void updateAM( sampleFrame * _ab, Uint32 _frames, \ + Uint8 _chnl ); \ + void updateMix( sampleFrame * _ab, Uint32 _frames, \ + Uint8 _chnl ); \ + void updateSync( sampleFrame * _ab, Uint32 _frames, \ + Uint8 _chnl ); \ + \ +} ; \ + \ +defineNoSubUpdateFor( x, getSampleFunction ) \ +defineFMUpdateFor( x, getSampleFunction ) \ +defineAMUpdateFor( x, getSampleFunction ) \ +defineMixUpdateFor( x, getSampleFunction ) \ +defineSyncUpdateFor( x, getSampleFunction ) + + +generateOscillatorCodeFor( sinWaveOsc, sinSample ); +generateOscillatorCodeFor( triangleWaveOsc, triangleSample ); +generateOscillatorCodeFor( sawWaveOsc, sawSample ); +generateOscillatorCodeFor( squareWaveOsc, squareSample ); +generateOscillatorCodeFor( moogSawWaveOsc, moogSawSample ); +generateOscillatorCodeFor( expWaveOsc, expSample ); +generateOscillatorCodeFor( noiseWaveOsc, noiseSample ); +generateOscillatorCodeFor( userWaveOsc, userWaveSample ); + + + +oscillator * FASTCALL oscillator::createNewOsc( waveShapes _wave_shape, + modulationAlgos _modulation_algo, + float _freq, Sint16 _phase_offset, + float _volume_factor, + oscillator * _sub_osc ) +{ + switch( _wave_shape ) + { + case SIN_WAVE: + return( new sinWaveOsc( _modulation_algo, _freq, + _phase_offset, _volume_factor, + _sub_osc ) ); + case TRIANGLE_WAVE: + return( new triangleWaveOsc( _modulation_algo, _freq, + _phase_offset, _volume_factor, + _sub_osc ) ); + case SAW_WAVE: + return( new sawWaveOsc( _modulation_algo, _freq, + _phase_offset, _volume_factor, + _sub_osc ) ); + case SQUARE_WAVE: + return( new squareWaveOsc( _modulation_algo, _freq, + _phase_offset, _volume_factor, + _sub_osc ) ); + case MOOG_SAW_WAVE: + return( new moogSawWaveOsc( _modulation_algo, _freq, + _phase_offset, _volume_factor, + _sub_osc ) ); + case EXP_WAVE: + return( new expWaveOsc( _modulation_algo, _freq, + _phase_offset, _volume_factor, + _sub_osc ) ); + case WHITE_NOISE_WAVE: + return( new noiseWaveOsc( _modulation_algo, _freq, + _phase_offset, _volume_factor, + _sub_osc ) ); + case USER_DEF_WAVE: + return( new userWaveOsc( _modulation_algo, _freq, + _phase_offset, _volume_factor, + _sub_osc ) ); + default: + return( new sinWaveOsc( _modulation_algo, _freq, + _phase_offset, _volume_factor, + _sub_osc ) ); + } + +} + + + + +// should be called every time phase-offset or frequency is changed... +void oscillator::recalcOscCoeff( const float additional_phase_offset ) +{ + m_oscCoeff = m_freq / static_cast( mixer::inst()->sampleRate() ); + + m_sample = static_cast( ( m_phaseOffset * ( 1.0f / 360.0f ) + + additional_phase_offset ) * + ( mixer::inst()->sampleRate() / + m_freq ) ); + // because we pre-increment m_sample in update-function, we should + // decrement it here... (not possible when 0 because it is + // unsigned - overflow!!!) + if( m_sample > 0 ) + { + --m_sample; + } +} diff --git a/src/lib/sample_buffer.cpp b/src/lib/sample_buffer.cpp new file mode 100644 index 00000000000..a9ed579ef0d --- /dev/null +++ b/src/lib/sample_buffer.cpp @@ -0,0 +1,1014 @@ +/* + * sample_buffer.cpp - container-class sampleBuffer + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include +#include +#include +#include + +#else + +#include +#include +#include +#include +#include +#include + +#if QT_VERSION < 0x030100 +#include +#endif + +#endif + + +#include + +#ifdef SDL_SDL_SOUND_H +#include SDL_SDL_SOUND_H +#endif + +#ifdef HAVE_SNDFILE_H +#include +#endif + +#ifdef HAVE_VORBIS_VORBISFILE_H +#include +#endif + + +#include "sample_buffer.h" +#include "interpolation.h" +#include "paths.h" +#include "templates.h" +#include "config_mgr.h" +#include "endian_handling.h" +#include "debug.h" + + + +sampleBuffer::sampleBuffer( const QString & _audio_file ) : + QObject(), + m_audioFile( _audio_file ), + m_origData( NULL ), + m_origFrames( 0 ), + m_data( NULL ), + m_frames( 0 ), + m_startFrame( 0 ), + m_endFrame( 0 ), + m_amplification( 1.0f ), + m_reversed( FALSE ), + m_dataMutex() +{ +#ifdef SDL_SDL_SOUND_H + // init sound-file-system of SDL + Sound_Init(); +#endif +#ifdef HAVE_SAMPLERATE_H + initResampling(); +#endif + update(); +} + + + + +sampleBuffer::sampleBuffer( const sampleFrame * _data, Uint32 _frames ) : + QObject(), + m_audioFile( "" ), + m_origData( NULL ), + m_origFrames( 0 ), + m_data( NULL ), + m_frames( 0 ), + m_startFrame( 0 ), + m_endFrame( 0 ), + m_amplification( 1.0f ), + m_reversed( FALSE ), + m_dataMutex() +{ + m_origData = new sampleFrame[_frames]; + memcpy( m_origData, _data, _frames*BYTES_PER_FRAME ); + m_origFrames = _frames; +#ifdef SDL_SDL_SOUND_H + // init sound-file-system of SDL + Sound_Init(); +#endif +#ifdef HAVE_SAMPLERATE_H + initResampling(); +#endif + update(); +} + + + + +sampleBuffer::~sampleBuffer() +{ + m_dataMutex.lock(); + delete[] m_origData; + m_origData = NULL; + delete[] m_data; + m_data = NULL; + m_dataMutex.unlock(); + +#ifdef HAVE_SAMPLERATE_H + quitResampling(); +#endif +} + + + + + + +void sampleBuffer::update( bool _keep_settings ) +{ + m_dataMutex.lock(); + + delete[] m_data; + m_data = NULL; + m_frames = 0; + + if( m_audioFile == "" && m_origData != NULL && m_origFrames > 0 ) + { + // TODO: reverse- and amplification-property is not covered + // by following code... + m_data = new sampleFrame[m_origFrames]; + memcpy( m_data, m_origData, m_origFrames * BYTES_PER_FRAME ); + if( _keep_settings == FALSE ) + { + m_frames = m_origFrames; + m_startFrame = 0; + m_endFrame = m_frames-1; + } + } + else if( m_audioFile != "" ) + { + QString file = m_audioFile; + // if there's not an absolute filename, we assume that we made + // it relative before and so we have to add sample-dir to file- + // name + if( file[0] != '/' ) + { + file = configManager::inst()->samplesDir() + file; + } + const char * f = +#ifdef QT4 + file.toAscii().constData(); +#else + file.ascii(); +#endif + Sint16 * buf = NULL; + Uint8 channels; + +#ifdef SDL_SDL_SOUND_H + if( m_frames == 0 ) + { + m_frames = decodeSampleSDL( f, buf, channels ); + } +#endif +#ifdef HAVE_SNDFILE_H + if( m_frames == 0 ) + { + m_frames = decodeSampleSF( f, buf, channels ); + } +#endif +#ifdef HAVE_VORBIS_VORBISFILE_H + if( m_frames == 0 ) + { + m_frames = decodeSampleOGG( f, buf, channels ); + } +#endif + if( m_frames > 0 && buf != NULL ) + { + if( _keep_settings == FALSE ) + { + // update frame-variables + m_startFrame = 0; + m_endFrame = m_frames - 1; + } + + // following code transforms int-samples into + // float-samples and does amplifying & reversing + float fac = m_amplification / 32767.0f; + m_data = new sampleFrame[m_frames]; + + // if reversing is on, we also reverse when + // scaling + if( m_reversed ) + { + for( Uint32 frame = 0; frame < m_frames; + ++frame ) + { + for( Uint8 chnl = 0; + chnl < DEFAULT_CHANNELS; + ++chnl ) + { +const Uint32 idx = ( m_frames - frame ) * channels + ( chnl % channels ); +m_data[frame][chnl] = buf[idx] * fac; + } + } + } + else + { + for( Uint32 frame = 0; frame < m_frames; + ++frame ) + { + for( Uint8 chnl = 0; + chnl < DEFAULT_CHANNELS; + ++chnl ) + { + const Uint32 idx = frame * channels + ( chnl % channels ); + m_data[frame][chnl] = buf[idx] * fac; + } + } + } + + delete[] buf; + + } + else + { + m_data = new sampleFrame[1]; + for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl ) + { + m_data[0][chnl] = 0.0f; + } + m_frames = 1; + } + } + else + { + m_data = new sampleFrame[1]; + for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl ) + { + m_data[0][chnl] = 0.0f; + } + m_frames = 1; + } + + m_dataMutex.unlock(); + + emit sampleUpdated(); +} + + + + +#ifdef SDL_SDL_SOUND_H +Uint32 sampleBuffer::decodeSampleSDL( const char * _f, Sint16 * & _buf, + Uint8 & _channels ) +{ + Sound_AudioInfo STD_AUDIO_INFO = + { + AUDIO_S16SYS, + DEFAULT_CHANNELS, + SAMPLE_RATES[DEFAULT_QUALITY_LEVEL] + } ; + Uint32 frames = 0; + + Sound_Sample * snd_sample = Sound_NewSampleFromFile( _f, + &STD_AUDIO_INFO, 16384 ); + // file not found? + if( snd_sample != NULL ) + { + // let SDL_sound decode our file to requested format + ( void )Sound_DecodeAll( snd_sample ); + _channels = STD_AUDIO_INFO.channels; + frames = snd_sample->buffer_size / ( BYTES_PER_OUTPUT_SAMPLE * + _channels ); + _buf = new Sint16[frames * _channels]; + memcpy( _buf, snd_sample->buffer, snd_sample->buffer_size ); + + Sound_FreeSample( snd_sample ); + } + return( frames ); +} +#endif + + + + +#ifdef HAVE_SNDFILE_H +Uint32 sampleBuffer::decodeSampleSF( const char * _f, Sint16 * & _buf, + Uint8 & _channels ) +{ + SNDFILE * snd_file; + SF_INFO sf_info; + Uint32 frames = 0; +#ifdef OLD_SNDFILE + if( ( snd_file = sf_open_read( _f, &sf_info ) ) != NULL ) + { + frames = sf_info.samples; +#else + if( ( snd_file = sf_open( _f, SFM_READ, &sf_info ) ) != NULL ) + { + frames = sf_info.frames; +#endif + _buf = new Sint16[sf_info.channels * frames]; + frames = sf_read_short( snd_file, _buf, frames ); + _channels = sf_info.channels; + + sf_close( snd_file ); + } + else + { +#ifdef DEBUG_LMMS + printf( "sampleBuffer::decodeSampleSF(): could not load " + "sample %s: %s\n", _f, sf_strerror( NULL ) ); +#endif + } + return( frames ); +} +#endif + + + + +#ifdef HAVE_VORBIS_VORBISFILE_H + +// callback-functions for reading ogg-file + +#ifndef QT4 +#define read readBlock +#define seek at +#define pos at +#endif + +size_t qfileReadCallback( void * _ptr, size_t _size, size_t _n, void * _udata ) +{ + return( static_cast( _udata )->read( (char*)_ptr, + _size * _n ) ); +} + + + + +int qfileSeekCallback( void * _udata, ogg_int64_t _offset, int _whence ) +{ + QFile * f = static_cast( _udata ); + + if( _whence == SEEK_CUR ) + { + f->seek( f->pos() + _offset ); + } + else if( _whence == SEEK_END ) + { + f->seek( f->size() + _offset ); + } + else + { + f->seek( _offset ); + } + return( 0 ); +} + + + + +int qfileCloseCallback( void * _udata ) +{ + delete static_cast( _udata ); + return( 0 ); +} + + + + +long qfileTellCallback( void * _udata ) +{ + return( static_cast( _udata )->pos() ); +} + +#undef read +#undef seek +#undef pos + + + +Uint32 sampleBuffer::decodeSampleOGG( const char * _f, Sint16 * & _buf, + Uint8 & _channels ) +{ + static ov_callbacks callbacks = + { + qfileReadCallback, + qfileSeekCallback, + qfileCloseCallback, + qfileTellCallback + } ; + + OggVorbis_File vf; + + Uint32 frames = 0; + + QFile * f = new QFile( _f ); +#ifdef QT4 + if( f->open( QFile::ReadOnly | QFile::Truncate ) == FALSE ) +#else + if( f->open( IO_ReadOnly | IO_Truncate ) == FALSE ) +#endif + { + delete f; + return( 0 ); + } + + int err = ov_open_callbacks( f, &vf, NULL, 0, callbacks ); + + if( err < 0 ) + { + switch( err ) + { + case OV_EREAD: + printf( "sampleBuffer::decodeSampleOgg(): " + "media read error\n" ); + break; + case OV_ENOTVORBIS: + printf( "sampleBuffer::decodeSampleOgg(): " + "not an Ogg Vorbis file\n" ); + break; + case OV_EVERSION: + printf( "sampleBuffer::decodeSampleOgg(): " + "vorbis version mismatch\n" ); + break; + case OV_EBADHEADER: + printf( "sampleBuffer::decodeSampleOgg(): " + "invalid Vorbis bitstream header\n" ); + break; + case OV_EFAULT: + printf( "sampleBuffer::decodeSampleOgg(): " + "internal logic fault\n" ); + break; + } + delete f; + return( 0 ); + } + + ov_pcm_seek( &vf, 0 ); + + _channels = ov_info( &vf, -1 )->channels; + ogg_int64_t total = ov_pcm_total( &vf, -1 ); + + _buf = new Sint16[total * _channels]; + int bitstream = 0; + long bytes_read = 0; + + do + { + bytes_read = ov_read( &vf, (char *)&_buf[frames * _channels], + ( total - frames ) * _channels * + sizeof( Sint16 ), + isLittleEndian()? 0 : 1, + sizeof( Sint16 ), 1, &bitstream ); + if( bytes_read < 0 ) + { + break; + } + frames += bytes_read / ( _channels * sizeof( Sint16 ) ); + } + while( bytes_read != 0 && bitstream == 0 ); + + ov_clear( &vf ); + + return( frames ); +} +#endif + + + + +#ifdef HAVE_SAMPLERATE_H +void sampleBuffer::initResampling( void ) +{ + m_srcState = createResamplingContext(); + m_srcData.end_of_input = 0; +} + + + + +void sampleBuffer::quitResampling( void ) +{ + destroyResamplingContext( m_srcState ); +} + + + + +SRC_STATE * sampleBuffer::createResamplingContext( void ) +{ + int error; + SRC_STATE * state; + if( ( state = src_new( +#ifdef HQ_SINC + SRC_SINC_MEDIUM_QUALITY, +#else + SRC_ZERO_ORDER_HOLD, +#endif + DEFAULT_CHANNELS, &error ) ) == NULL ) + { + printf( "Error: src_new() failed in sample_buffer.cpp!\n" ); + } + return( state ); +} + + + + +void sampleBuffer::destroyResamplingContext( SRC_STATE * _context ) +{ + src_delete( _context ); +} +#endif + + + + +bool FASTCALL sampleBuffer::play( sampleFrame * _ab, Uint32 _start_frame, + Uint32 _frames, float _freq, + bool _looped, + void * * _resampling_data ) +{ + mixer::inst()->clearAudioBuffer( _ab, _frames ); + + if( m_data == NULL || m_frames == 0 || m_endFrame == 0 || _frames == 0 ) + { + return( FALSE ); + } + + const float freq_factor = 1.0f / (BASE_FREQ / _freq); + const Sint16 freq_diff = static_cast( BASE_FREQ - _freq ); + + Uint32 frames_to_process = _frames; + + // calculate how many frames we have in requested pitch + const Uint32 total_frames_for_current_pitch = static_cast( ( + m_endFrame - m_startFrame ) / + freq_factor ); + if( total_frames_for_current_pitch == 0 ) + { + return( FALSE ); + } + // this holds the number of the first frame to play + const Uint32 play_frame = m_startFrame + ( _start_frame % + total_frames_for_current_pitch ); + + // this holds the number of remaining frames in current loop + Uint32 frames_for_loop = total_frames_for_current_pitch - + ( play_frame - m_startFrame ); + + // do we have frames left?? this is only important when not in + // looping-mode because in looping-mode we loop to start-frame... + if( _start_frame >= total_frames_for_current_pitch && _looped == FALSE ) + { + return( FALSE ); + } + + // make sure, data isn't accessed in any other way (e.g. deleting + // of this buffer...) + m_dataMutex.lock(); + + if( _looped == FALSE && frames_for_loop < frames_to_process ) + { + frames_to_process = frames_for_loop; + } + + // calc pointer of first frame + sampleFrame * start_frame = (sampleFrame *) m_data + + static_cast( play_frame * + freq_factor ); + sampleFrame * loop_start = start_frame; + + // check whether we have to change pitch... + if( freq_diff != 0 ) + { +#ifdef HAVE_SAMPLERATE_H + SRC_STATE * state = m_srcState; + if( _resampling_data != NULL ) + { + if( _start_frame == 0 ) + { + *_resampling_data = createResamplingContext(); + } + state = static_cast( *_resampling_data ); + } + m_srcData.data_in = start_frame[0]; + m_srcData.data_out = _ab[0]; + m_srcData.input_frames = static_cast( frames_for_loop * + freq_factor ); + m_srcData.output_frames = frames_to_process; + m_srcData.src_ratio = 1.0 / freq_factor; + int error; + if( ( error = src_process( state, &m_srcData ) ) ) + { + printf( "sampleBuffer: error while resampling: %s\n", + src_strerror( error ) ); + } +#else + Uint32 src_frame_base = 0; + // check whether we're in high-quality-mode + if( mixer::inst()->highQuality() ) + { + // we are, so let's use cubic interpolation... + for( Uint32 frame = 0; frame < frames_to_process; + ++frame ) + { + // current loop done? + if( _looped && ( frame-src_frame_base ) > + frames_for_loop ) + { + start_frame = loop_start; + src_frame_base = frame; + frames_for_loop = frames_to_process % + total_frames_for_current_pitch; + } + + const float src_frame_idx = frame*freq_factor; + Uint32 frame_num = static_cast( + src_frame_idx) - src_frame_base; + const float frac_pos = src_frame_idx - + static_cast( src_frame_idx ); + + // because of cubic interpolation we have to + // access start_frame[frame_num-1], so make + // sure we don't access data out of + // buffer-array-boundaries + if( frame_num == 0 && play_frame == 0 ) + { + frame_num = 1; + } + for ( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; + ++chnl ) + { + _ab[frame][chnl] = cubicInterpolate( + start_frame[frame_num-1][chnl], + start_frame[frame_num+0][chnl], + start_frame[frame_num+1][chnl], + start_frame[frame_num+2][chnl], + frac_pos ); + } + } + } + else + { + // just normal mode, so we can use linear + // interpolation... + for( Uint32 frame = 0; frame < frames_to_process; + ++frame ) + { + if( _looped && ( frame-src_frame_base ) > + frames_for_loop ) + { + start_frame = loop_start; + src_frame_base = frame; + frames_for_loop = frames_to_process % + total_frames_for_current_pitch; + } + const float src_frame_idx = frame * freq_factor; + const Uint32 frame_num = (Uint32)src_frame_idx - + src_frame_base + 0; + const float frac_pos = src_frame_idx - + (Uint32) src_frame_idx; + for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; + ++chnl ) + { + _ab[frame][chnl] = linearInterpolate( + start_frame[frame_num][chnl], + start_frame[frame_num+1][chnl], + frac_pos ); + } + } + } +#endif + } + else + { + // we don't have to pitch, so we just copy the sample-data + // as is into pitched-copy-buffer + if( _looped && frames_for_loop < frames_to_process ) + { + Uint32 total_frames_copied = 0; + while( total_frames_copied < frames_to_process ) + { + memcpy( _ab[total_frames_copied], start_frame, + frames_for_loop * BYTES_PER_FRAME ); + total_frames_copied += frames_for_loop; + + // reset start_frame to start + start_frame = loop_start; + // and calculate frames for next loop + frames_for_loop = frames_to_process % + total_frames_for_current_pitch; + if( frames_for_loop > + frames_to_process-total_frames_copied ) + { + frames_for_loop = frames_to_process - + total_frames_copied; + } + } + } + else + { + memcpy( _ab, start_frame, + frames_to_process * BYTES_PER_FRAME ); + } + } + + m_dataMutex.unlock(); + + return( TRUE ); + +} + + + + +void sampleBuffer::drawWaves( QPainter & _p, QRect _dr, drawMethods _dm ) +{ + _p.setClipRect( _dr ); + _p.setPen (QColor(0x22, 0xFF, 0x44)); +#ifdef QT4 + // TODO: save and restore aa-settings + _p.setRenderHint( QPainter::Antialiasing ); +#endif + const int w = _dr.width(); + const int h = _dr.height(); + + const Uint16 y_base = h/2+_dr.y(); + const float y_space = h/2; + + if( m_data == NULL || m_frames == 0 ) + { + _p.drawLine( _dr.x(), y_base, _dr.x()+w, y_base ); + return; + } + else if( _dm == LINE_CONNECT ) + { +#ifdef QT4 + float old_x = _dr.x(); + float old_y[DEFAULT_CHANNELS] = { y_base, y_base }; + + float fpp = tMax( tMin( m_frames / (float)w, + 20.0f ), 1.0f ); + + for( float frame = 0; frame < m_frames; frame += fpp ) + { + const float x = frame*w / m_frames + _dr.x(); + for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl ) + { + const float y = y_base + + m_data[static_cast( frame )][chnl] * y_space; + _p.drawLine( + QLineF( old_x, old_y[chnl], x, y ) ); + old_y[chnl] = y; + } + old_x = x; + } +#else + int old_x = _dr.x(); + int old_y[DEFAULT_CHANNELS] = { y_base, y_base }; + + Uint32 fpp = tMax( tMin( m_frames / w, 20 ), + 1 ); + + for( Uint32 frame = 0; frame < m_frames; frame += fpp ) + { + const int x = static_cast( frame / + (float) m_frames * w ) + + _dr.x(); + for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl ) + { + const Uint16 y = y_base + + static_cast( m_data[frame][chnl]*y_space ); + _p.drawLine( old_x, old_y[chnl], x, y ); + old_y[chnl] = y; + } + old_x = x; + } +#endif + + } + else if( _dm == DOTS ) + { + for( Uint32 frame = 0; frame < m_frames; ++frame ) + { + const int x = frame*w / m_frames + _dr.x(); + for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl ) + { + _p.drawPoint( x, y_base + + static_cast( + m_data[frame][chnl]*y_space ) ); + } + } + } + _p.setClipping( FALSE ); +} + + + + +QString sampleBuffer::openAudioFile( void ) const +{ +#ifdef QT4 + QFileDialog ofd( NULL, tr( "Open audio file" ) ); +#else + QFileDialog ofd( QString::null, QString::null, NULL, "", TRUE ); + ofd.setWindowTitle( tr( "Open audio file" ) ); +#endif + + QString dir; + if( m_audioFile != "" ) + { + QString f = m_audioFile; + if( QFileInfo( f ).isRelative() ) + { + f = configManager::inst()->samplesDir() + f; + } +#ifdef QT4 + dir = QFileInfo( f ).absolutePath(); +#else + dir = QFileInfo( f ).dirPath( TRUE ); +#endif + } + else + { + dir = configManager::inst()->samplesDir(); + } + // change dir to position of previously opened file + ofd.setDirectory( dir ); + ofd.setFileMode( QFileDialog::ExistingFiles ); + + // set filters +#ifdef QT4 + QStringList types; + types << tr( "All Audio-Files (*.wav *.ogg *.voc *.aif *.aiff *.au " + "*.raw)" ) + << tr( "Wave-Files (*.wav)" ) + << tr( "OGG-Files (*.ogg)" ) + //<< tr( "MP3-Files (*.mp3)" ) + //<< tr( "MIDI-Files (*.mid)" ) + << tr( "VOC-Files (*.voc)" ) + << tr( "AIFF-Files (*.aif *.aiff)" ) + << tr( "AU-Files (*.au)" ) + << tr( "RAW-Files (*.raw)" ) + //<< tr( "FLAC-Files (*.flac)" ) + //<< tr( "MOD-Files (*.mod)" ) + ; + ofd.setFilters( types ); +#else + ofd.addFilter( tr( "All Audio-Files (*.wav *.ogg *.voc *.aif *.aiff " + "*.au *.raw)" ) ); + ofd.addFilter( tr( "Wave-Files (*.wav)" ) ); + ofd.addFilter( tr( "OGG-Files (*.ogg)" ) ); + //ofd.addFilter (tr("MP3-Files (*.mp3)")); + //ofd.addFilter (tr("MIDI-Files (*.mid)")); + ofd.addFilter( tr( "VOC-Files (*.voc)" ) ); + ofd.addFilter( tr( "AIFF-Files (*.aif *.aiff)" ) ); + ofd.addFilter( tr( "AU-Files (*.au)" ) ); + ofd.addFilter( tr( "RAW-Files (*.raw)" ) ); + //ofd.addFilter (tr("FLAC-Files (*.flac)")); + //ofd.addFilter (tr("MOD-Files (*.mod)")); + ofd.setSelectedFilter( tr( "All Audio-Files (*.wav *.ogg *.voc *.aif " + "*.aiff *.au *.raw)" ) ); +#endif + if( m_audioFile != "" ) + { + // select previously opened file + ofd.selectFile( QFileInfo( m_audioFile ).fileName() ); + } + + if ( ofd.exec () == QDialog::Accepted ) + { + if( ofd.selectedFiles().isEmpty() ) + { + return( "" ); + } + QString sf = ofd.selectedFiles()[0]; + if( !QFileInfo( sf ).isRelative() ) + { +#if QT_VERSION >= 0x030100 + sf = sf.replace( configManager::inst()->samplesDir(), + "" ); +#else + sf = sf.replace( QRegExp( + configManager::inst()->samplesDir() ), + "" ); +#endif + } + return( sf ); + } + + return( "" ); +} + + + + +void sampleBuffer::setAudioFile( const QString & _audio_file ) +{ + m_audioFile = _audio_file; + // try to make path of audio-file relative if it's posated + // within LMMS-working-dir + if( !QFileInfo( m_audioFile ).isRelative() ) + { +#if QT_VERSION >= 0x030100 + m_audioFile = m_audioFile.replace( + configManager::inst()->samplesDir(), "" ); +#else + m_audioFile = m_audioFile.replace( + QRegExp( configManager::inst()->samplesDir() ), + "" ); +#endif + } + update(); +} + + + + +void sampleBuffer::setStartFrame( Uint32 _s ) +{ + // don't set this parameter while playing + m_dataMutex.lock(); + m_startFrame = _s; + m_dataMutex.unlock(); +} + + + + +void sampleBuffer::setEndFrame( Uint32 _e ) +{ + // don't set this parameter while playing + m_dataMutex.lock(); + m_endFrame = _e; + m_dataMutex.unlock(); +} + + + + +void sampleBuffer::setAmplification( float _a ) +{ + m_amplification = _a; + update( TRUE ); +} + + + + +void sampleBuffer::setReversed( bool _on ) +{ + m_reversed = _on; + update( TRUE ); +} + + + + +void sampleBuffer::deleteResamplingData( void * * _ptr ) +{ +#ifdef HAVE_SAMPLERATE_H +#ifdef LMMS_DEBUG + assert( _ptr != NULL ); + assert( *_ptr != NULL ); +#endif + destroyResamplingContext( static_cast( *_ptr ) ); +#endif + *_ptr = NULL; +} + + + +#include "sample_buffer.moc" + diff --git a/src/midi/midi_alsa_raw.cpp b/src/midi/midi_alsa_raw.cpp new file mode 100644 index 00000000000..a9062c59100 --- /dev/null +++ b/src/midi/midi_alsa_raw.cpp @@ -0,0 +1,233 @@ +/* + * midi_alsa_raw.cpp - midi-device-driver for RawMIDI via ALSA + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include +#include + +#endif + + +#include "midi_alsa_raw.h" +#include "config_mgr.h" +#include "templates.h" + + +#ifdef ALSA_SUPPORT + + +midiALSARaw::midiALSARaw( channelTrack * _ct ) : + midiDevice( _ct ), + QThread(), + m_inputp( &m_input ), + m_outputp( &m_output ), + m_quit( FALSE ) +{ + int err; + if( ( err = snd_rawmidi_open( m_inputp, m_outputp, +#ifdef QT4 + probeDevice().toAscii().constData(), +#else + probeDevice().ascii(), +#endif + 0 ) ) < 0 ) + { + printf( "cannot open MIDI-device: %s\n", snd_strerror( err ) ); + return; + } + + snd_rawmidi_read( m_input, NULL, 0 ); + + snd_rawmidi_nonblock( m_input, 1 ); + m_npfds = snd_rawmidi_poll_descriptors_count( m_input ); + m_pfds = new pollfd[m_npfds]; + snd_rawmidi_poll_descriptors( m_input, m_pfds, m_npfds ); + + start( +#if QT_VERSION >= 0x030200 + QThread::LowPriority +#endif + ); +} + + + + +midiALSARaw::~midiALSARaw() +{ + if( running() ) + { + m_quit = TRUE; + wait( 500 ); + terminate(); + + snd_rawmidi_close( m_input ); + snd_rawmidi_close( m_output ); + delete[] m_pfds; + } +} + + + + +QString midiALSARaw::probeDevice( void ) +{ + QString dev = configManager::inst()->value( "midialsa", "device" ); + if( dev == "" ) + { + if( getenv( "MIDIDEV" ) != NULL ) + { + return( getenv( "MIDIDEV" ) ); + } + return( "default" ); + } + return( dev ); +} + + + + +void midiALSARaw::sendByte( Uint8 _c ) +{ + snd_rawmidi_write( m_output, &_c, sizeof( _c ) ); +} + + + + +void midiALSARaw::run( void ) +{ + Uint8 buf[128]; + //int cnt = 0; + while( m_quit == FALSE ) + { + msleep( 5 ); // must do that, otherwise this thread takes + // too much CPU-time, even with LowPriority... + int err = poll( m_pfds, m_npfds, 10000 ); + if( err < 0 && errno == EINTR ) + { + printf( "midiALSARaw::run(): Got EINTR while " + "polling. Will stop polling MIDI-events from " + "MIDI-port.\n" ); + break; + } + if( err < 0 ) + { + printf( "poll failed: %s\nWill stop polling " + "MIDI-events from MIDI-port.\n", + strerror( errno ) ); + break; + } + if( err == 0 ) + { + //printf( "there seems to be no active MIDI-device %d\n", ++cnt ); + continue; + } + unsigned short revents; + if( ( err = snd_rawmidi_poll_descriptors_revents( + m_input, m_pfds, m_npfds, &revents ) ) < 0 ) + { + printf( "cannot get poll events: %s\nWill stop polling " + "MIDI-events from MIDI-port.\n", + snd_strerror( errno ) ); + break; + } + if( revents & ( POLLERR | POLLHUP ) ) + { + printf( "POLLERR or POLLHUP\n" ); + break; + } + if( !( revents & POLLIN ) ) + { + continue; + } + err = snd_rawmidi_read( m_input, buf, sizeof( buf ) ); + if( err == -EAGAIN ) + { + continue; + } + if( err < 0 ) + { + printf( "cannot read from port \"%s\": %s\nWill stop " + "polling MIDI-events from MIDI-port.\n", + /*port_name*/"default", snd_strerror( err ) ); + break; + } + if( err == 0 ) + continue; + for( int i = 0; i < err; ++i ) + { + const midiEvent * midi_event = parseData( buf[i] ); + if( midi_event != NULL ) + { + processInEvent( *midi_event ); + } + } + } + +} + + + + +midiALSARaw::setupWidget::setupWidget( QWidget * _parent ) : + midiDevice::setupWidget( midiALSARaw::name(), _parent ) +{ + m_device = new QLineEdit( midiALSARaw::probeDevice(), this ); + m_device->setGeometry( 10, 20, 160, 20 ); + + QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + dev_lbl->setFont( pointSize<6>( dev_lbl->font() ) ); + dev_lbl->setGeometry( 10, 40, 160, 10 ); +} + + + + +midiALSARaw::setupWidget::~setupWidget() +{ +} + + + + +void midiALSARaw::setupWidget::saveSettings( void ) +{ + configManager::inst()->setValue( "midialsa", "device", + m_device->text() ); +} + + + +#endif + diff --git a/src/midi/midi_mapper.cpp b/src/midi/midi_mapper.cpp new file mode 100644 index 00000000000..46d82466e5a --- /dev/null +++ b/src/midi/midi_mapper.cpp @@ -0,0 +1,222 @@ +/* + * midi_mapper.cpp - MIDI-mapper for any midiDevice + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + + +#include "midi_mapper.h" + +#ifdef QT4 + +#include + +#else + +#include + +#define indexOf find + +#endif + + +midiMapper::midiMapper( const QString & _map ) : + m_drumsetChannel( 0 ), + m_drumsetPatch( 0 ) +{ + // default mappings + for( Uint8 i = 0; i < MIDI_PROGRAMS; ++i ) + { + m_patchMap[i].first = i; + } + for( Uint8 i = 0; i < MIDI_KEYS; ++i ) + { + m_drumsetKeyMap[i].first = i; + } + for( Uint8 i = 0; i < MIDI_CHANNELS; ++i ) + { + m_channelMap[i] = i; + } + QFile map( _map ); +#ifdef QT4 + if( !map.open( QIODevice::ReadOnly ) ) +#else + if( !map.open( IO_ReadOnly ) ) +#endif + { + return; + } + while( !map.atEnd() ) + { + char buf[1024]; + int len = map.readLine( buf, sizeof( buf ) ); + if( len <= 0 ) + { + continue; + } + QString line( buf ); + line.replace( '\n', "" ); + if( line.left( 6 ) == "DEFINE" ) + { + if( line.section( ' ', 1, 1 ) == "PATCHMAP" ) + { + readPatchMap( map ); + } + else if( line.section( ' ', 1, 1 ) == "KEYMAP" && + line.section( ' ', 2, 2 ) == + "\"Drumset\"" ) + { + readDrumsetKeyMap( map ); + } + else if( line.section( ' ', 1, 1 ) == "CHANNELMAP" ) + { + readChannelMap( map ); + } + } + } +} + + + + +midiMapper::~midiMapper() +{ +} + + + + +void midiMapper::readPatchMap( QFile & _f ) +{ + Uint8 prog_idx = 0; + + while( !_f.atEnd() && prog_idx < MIDI_PROGRAMS ) + { + char buf[1024]; + int len = _f.readLine( buf, sizeof( buf ) ); + if( len <= 0 ) + { + continue; + } + QString line( buf ); + line.replace( '\n', "" ); + if( line.left( 3 ) == "END" ) + { + return; + } + if( QString( line ).replace( ' ', "" )[0] == '#' ) + { + continue; + } + m_patchMap[prog_idx].first = line.section( '=', 1, 1 ).toInt(); + m_patchMap[prog_idx].second = line.section( '=', 0, 0 ). + replace( ' ', "" ); + ++prog_idx; + } +} + + + + +void midiMapper::readDrumsetKeyMap( QFile & _f ) +{ + Uint8 key = 0; + while( !_f.atEnd() ) + { + char buf[1024]; + int len = _f.readLine( buf, sizeof( buf ) ); + if( len <= 0 ) + { + continue; + } + QString line( buf ); + line.replace( '\n', "" ); + if( line.left( 3 ) == "END" ) + { + return; + } + if( QString( line ).replace( ' ', "" )[0] == '#' ) + { + continue; + } + if( line[4] != '=' ) + { + m_drumsetKeyMap[key].first = line.section( '=', 1, 1 ). + toInt(); + + m_drumsetKeyMap[key].second = line.mid( 4 ). + section( '=', 0, 0 ). + section( ' ', 1, 1 ). + replace( ' ', "" ); + } + ++key; + } +} + + + + +void midiMapper::readChannelMap( QFile & _f ) +{ + while( !_f.atEnd() ) + { + char buf[1024]; + int len = _f.readLine( buf, sizeof( buf ) ); + if( len <= 0 ) + { + continue; + } + QString line( buf ); + line.replace( '\n', "" ); + if( line.left( 3 ) == "END" ) + { + return; + } + if( QString( line ).replace( ' ', "" )[0] == '#' ) + { + continue; + } + Uint8 ch = line.section( ' ', 0, 0 ).toInt(); + Uint8 mch = line.section( '=', 1, 1 ).mid( 1 ). + section( ' ', 0, 0 ). + toInt(); + if( ch < MIDI_CHANNELS && mch < MIDI_CHANNELS ) + { + m_channelMap[ch] = mch; + if( line.contains( QRegExp( "Keymap *\"Drumset\"" ) ) ) + { + m_drumsetChannel = mch; + int fp = line.indexOf( "ForcePatch" ); + if( fp != -1 ) + { + m_drumsetPatch = line.mid( fp ). + section( ' ', 1, 1 ). + toInt(); + } + } + } + } +} + + + +#undef indexOf + diff --git a/src/midi/midi_oss.cpp b/src/midi/midi_oss.cpp new file mode 100644 index 00000000000..3efb32835d9 --- /dev/null +++ b/src/midi/midi_oss.cpp @@ -0,0 +1,164 @@ +/* + * midi_oss.cpp - simple midi-device-driver for OSS + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include +#include + +#endif + + +#include "midi_oss.h" +#include "config_mgr.h" +#include "templates.h" + + + +midiOSS::midiOSS( channelTrack * _ct ) : + midiDevice( _ct ), + QThread(), + m_midiDev( probeDevice() ), + m_quit( FALSE ) +{ + // only start thread, if opening of MIDI-device is successful, + // otherwise isRunning()==FALSE indicates error +#ifdef QT4 + if( m_midiDev.open( QIODevice::ReadWrite ) || + m_midiDev.open( QIODevice::ReadOnly ) ) +#else + if( m_midiDev.open( IO_ReadWrite ) || m_midiDev.open( IO_ReadOnly ) ) +#endif + { + start( +#if QT_VERSION >= 0x030200 + QThread::LowPriority +#endif + ); + } +} + + + + +midiOSS::~midiOSS() +{ + m_quit = TRUE; + wait( 500 ); + terminate(); +} + + + + +QString midiOSS::probeDevice( void ) +{ + QString dev = configManager::inst()->value( "midioss", "device" ); + if( dev == "" ) + { + if( getenv( "MIDIDEV" ) != NULL ) + { + return( getenv( "MIDIDEV" ) ); + } + return( "/dev/midi" ); + } + return( dev ); +} + + + + +void midiOSS::sendByte( Uint8 _c ) +{ +#ifdef QT4 + m_midiDev.putChar( _c ); +#else + m_midiDev.putch( _c ); +#endif +} + + + + +void midiOSS::run( void ) +{ + while( m_quit == FALSE ) + { +#ifdef QT4 + char c; + if( !m_midiDev.getChar( &c ) ) + { + continue; + } + const midiEvent * midi_event = parseData( c ); +#else + const midiEvent * midi_event = parseData( m_midiDev.getch() ); +#endif + if( midi_event != NULL ) + { + processInEvent( *midi_event ); + } + } +} + + + + + +midiOSS::setupWidget::setupWidget( QWidget * _parent ) : + midiDevice::setupWidget( midiOSS::name(), _parent ) +{ + m_device = new QLineEdit( midiOSS::probeDevice(), this ); + m_device->setGeometry( 10, 20, 160, 20 ); + + QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this ); + dev_lbl->setFont( pointSize<6>( dev_lbl->font() ) ); + dev_lbl->setGeometry( 10, 40, 160, 10 ); +} + + + + +midiOSS::setupWidget::~setupWidget() +{ +} + + + + +void midiOSS::setupWidget::saveSettings( void ) +{ + configManager::inst()->setValue( "midioss", "device", + m_device->text() ); +} + + diff --git a/src/tracks/bb_track.cpp b/src/tracks/bb_track.cpp new file mode 100644 index 00000000000..ebfab85ddc5 --- /dev/null +++ b/src/tracks/bb_track.cpp @@ -0,0 +1,509 @@ +/* + * bb_track.cpp - implementation of class bbTrack + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include +#include + +#else + +#include +#include +#include +#include + +#endif + + +#include "bb_track.h" +#include "song_editor.h" +#include "bb_editor.h" +#include "templates.h" +#include "name_label.h" +#include "embed.h" +#include "rename_dialog.h" + +#include "bb_track.moc" + + +QMap bbTrack::s_bbNums; + + +bbTCO::bbTCO( track * _track, const QColor & _c ) : + trackContentObject( _track ), + m_name( ( dynamic_cast( _track ) != NULL ) ? + dynamic_cast( _track )->trackLabel()->text() : + QString( "" ) ), + m_color( _c.isValid() ? _c : QColor( 64, 128, 255 ) ) +{ + //setPaletteBackgroundColor( QColor( 64, 128, 255 ) ); +#ifndef QT4 + setBackgroundMode( Qt::NoBackground ); +#endif + tact t = bbEditor::inst()->lengthOfBB( + bbTrack::numOfBBTrack( getTrack() ) ); + if( t > 0 ) + { + changeLength( midiTime( t, 0 ) ); + } +} + + + + +bbTCO::~bbTCO() +{ +} + + + + +void bbTCO::movePosition( const midiTime & _pos ) +{ + // bb-playlist-entries are always aligned on tact-boundaries + trackContentObject::movePosition( midiTime( _pos.getTact(), 0 ) ); +} + + + + +void bbTCO::changeLength( const midiTime & _length ) +{ + // the length of bb-playlist-entries is always a multiple of one tact + trackContentObject::changeLength( midiTime( _length.getTact(), 0 ) ); +} + + + + +void bbTCO::constructContextMenu( QMenu * _cm ) +{ +#ifdef QT4 + QAction * a = new QAction( embed::getIconPixmap( "bb_track" ), + tr( "Open in Beat+Bassline-Editor" ), + _cm ); + _cm->insertAction( _cm->actions()[0], a ); + connect( a, SIGNAL( triggered( bool ) ), this, + SLOT( openInBBEditor( bool ) ) ); +#else + _cm->insertItem( embed::getIconPixmap( "bb_track" ), + tr( "Open in Beat+Bassline-Editor" ), + this, SLOT( openInBBEditor() ), + 0, -1, 0 ); +#endif +#ifdef QT4 + _cm->insertSeparator( _cm->actions()[1] ); +#else + _cm->insertSeparator( 1 ); +#endif +#ifdef QT4 + _cm->addSeparator(); +#else + _cm->insertSeparator(); +#endif + _cm->addAction( embed::getIconPixmap( "reload" ), tr( "Reset name" ), + this, SLOT( resetName() ) ); + _cm->addAction( embed::getIconPixmap( "rename" ), tr( "Change name" ), + this, SLOT( changeName() ) ); + _cm->addAction( embed::getIconPixmap( "colorize" ), + tr( "Change color" ), this, SLOT( changeColor() ) ); +} + + + + +void bbTCO::mouseDoubleClickEvent( QMouseEvent * ) +{ + openInBBEditor(); +} + + + + +void bbTCO::paintEvent( QPaintEvent * ) +{ + QColor col = m_color; + if( getTrack()->muted() ) + { + col = QColor( 160, 160, 160 ); + } +#ifdef QT4 + QPainter p( this ); + // TODO: set according brush/pen for gradient! + p.fillRect( rect(), col ); +#else + // create pixmap for whole widget + QPixmap pm( rect().size() ); + // and a painter for it + QPainter p( &pm ); + + // COOL gradient ;-) + for( int y = 0; y < height(); ++y ) + { + p.setPen( col.light( 130 - y * 60 / height() ) ); + p.drawLine( 0, y, width(), y ); + } + //pm.fill( col ); +#endif + + tact t = bbEditor::inst()->lengthOfBB( bbTrack::numOfBBTrack( + getTrack() ) ); + if( length().getTact() > 1 && t > 0 ) + { + for( int x = TCO_BORDER_WIDTH + static_cast( t * + pixelsPerTact() ); x < width(); + x += static_cast( t * pixelsPerTact() ) ) + { + p.setPen( col.light( 80 ) ); + p.drawLine( x, 1, x, 5 ); + p.setPen( col.light( 120 ) ); + p.drawLine( x, height() - 6, x, height() - 2 ); + } + } + + p.setPen( col.dark() ); + p.drawRect( 0, 0, width(), height() ); + + p.setFont( pointSize<7>( p.font() ) ); + p.setPen( QColor( 0, 0, 0 ) ); + p.drawText( 2, QFontMetrics( p.font() ).height() - 1, m_name ); + +#ifndef QT4 + bitBlt( this, rect().topLeft(), &pm ); +#endif +} + + + + +void bbTCO::saveSettings( QDomDocument & _doc, QDomElement & _parent ) +{ + QDomElement bbtco_de = _doc.createElement( nodeName() ); + bbtco_de.setAttribute( "name", m_name ); + if( _parent.nodeName() == "clipboard" ) + { + bbtco_de.setAttribute( "pos", QString::number( -1 ) ); + } + else + { + bbtco_de.setAttribute( "pos", + QString::number( startPosition() ) ); + } + bbtco_de.setAttribute( "len", QString::number( length() ) ); + bbtco_de.setAttribute( "color", QString::number( m_color.rgb() ) ); + _parent.appendChild( bbtco_de ); +} + + + + +void bbTCO::loadSettings( const QDomElement & _this ) +{ + m_name = _this.attribute( "name" ); + if( _this.attribute( "pos" ).toInt() >= 0 ) + { + movePosition( _this.attribute( "pos" ).toInt() ); + } + changeLength( _this.attribute( "len" ).toInt() ); + if( _this.attribute( "color" ).toUInt() != 0 ) + { + m_color.setRgb( _this.attribute( "color" ).toUInt() ); + } +} + + + + +void bbTCO::openInBBEditor( bool ) +{ + bbEditor::inst()->setCurrentBB( bbTrack::numOfBBTrack( getTrack() ) ); + bbEditor::inst()->show(); + bbEditor::inst()->setFocus(); +} + + + + +void bbTCO::openInBBEditor( void ) +{ + openInBBEditor( FALSE ); +} + + + + +void bbTCO::resetName( void ) +{ + if( dynamic_cast( getTrack() ) != NULL ) + { + m_name = dynamic_cast( getTrack() )-> + trackLabel()->text(); + } +} + + + + +void bbTCO::changeName( void ) +{ + renameDialog rename_dlg( m_name ); + rename_dlg.exec(); +} + + + + +void bbTCO::changeColor( void ) +{ + QColor _new_color = QColorDialog::getColor( m_color ); + if( _new_color.isValid() && _new_color != m_color ) + { + m_color = _new_color; + songEditor::inst()->setModified(); + update(); + } +} + + + + + +bbTrack::bbTrack( trackContainer * _tc ) + : track( _tc ) +{ + getTrackWidget()->setFixedHeight( 32 ); + + csize bbNum = s_bbNums.size(); + bbInfoStruct bis = { bbNum, "" }; + s_bbNums[this] = bis; + m_trackLabel = new nameLabel( tr( "Beat/Bassline %1" ).arg( bbNum ), + getTrackSettingsWidget(), + embed::getIconPixmap( "bb_track" ) ); + m_trackLabel->setGeometry( 1, 1, DEFAULT_SETTINGS_WIDGET_WIDTH-2, 29 ); + m_trackLabel->show(); + connect( m_trackLabel, SIGNAL( clicked() ), this, + SLOT( clickedTrackLabel() ) ); + bbEditor::inst()->setCurrentBB( bbNum ); + + _tc->updateAfterTrackAdd(); +} + + + + +bbTrack::~bbTrack() +{ + csize bb = s_bbNums[this].num; + bbEditor::inst()->removeBB( bb ); + for( QMap::iterator it = + s_bbNums.begin(); it != s_bbNums.end(); ++it ) + { +#ifdef QT4 + if( it.value().num > bb ) + { + --it.value().num; + } +#else + if( it.data().num > bb ) + { + --it.data().num; + } +#endif + } + s_bbNums.remove( this ); +} + + + + +track::trackTypes bbTrack::trackType( void ) const +{ + return( BB_TRACK ); +} + + + +// play _frames frames of given TCO within starting with _start/_start_frame +bool FASTCALL bbTrack::play( const midiTime & _start, Uint32 _start_frame, + Uint32 _frames, Uint32 _frame_base, + Sint16 _tco_num ) +{ + if( _tco_num >= 0 ) + { + return( bbEditor::inst()->play( _start, _start_frame, _frames, + _frame_base, + s_bbNums[this].num ) ); + } + + vlist tcos; + getTCOsInRange( tcos, _start, _start +static_cast( _frames * + 64 / songEditor::inst()->framesPerTact() ) ); + + if ( tcos.size() == 0 ) + { + return( FALSE ); + } + + midiTime lastPosition; + midiTime lastLen; + for( vlist::iterator it = tcos.begin(); + it != tcos.end(); ++it ) + { + if( ( *it )->startPosition() >= lastPosition ) + { + lastPosition = ( *it )->startPosition(); + lastLen = ( *it )->length(); + } + } + if( _start - lastPosition < lastLen ) + { + return( bbEditor::inst()->play( _start - lastPosition, + _start_frame, _frames, + _frame_base, + s_bbNums[this].num ) ); + } + return( FALSE ); +} + + + + +trackContentObject * bbTrack::createTCO( const midiTime & _pos ) +{ + // if we're creating a new bbTCO, we colorize it according to the + // previous bbTCO, so we have to get all TCOs from 0 to _pos and + // pickup the last and take the color if it + vlist tcos; + getTCOsInRange( tcos, 0, _pos ); + if( tcos.size() > 0 && dynamic_cast( tcos.back() ) != NULL ) + { + return( new bbTCO( this, + dynamic_cast( tcos.back() )->color() ) ); + + } + return( new bbTCO( this ) ); +} + + + + + + +void bbTrack::saveTrackSpecificSettings( QDomDocument & _doc, + QDomElement & _parent ) +{ + QDomElement bbt_de = _doc.createElement( nodeName() ); + bbt_de.setAttribute( "name", m_trackLabel->text() ); +/* bbt_de.setAttribute( "current", s_bbNums[this].num == + bbEditor::inst()->currentBB() );*/ + _parent.appendChild( bbt_de ); + if( s_bbNums[this].num == 0 && + _parent.parentNode().nodeName() != "clone" ) + { + bbEditor::inst()->saveSettings( _doc, bbt_de ); + } +} + + + + +void bbTrack::loadTrackSpecificSettings( const QDomElement & _this ) +{ + m_trackLabel->setText( _this.attribute( "name" ) ); + if( _this.firstChild().isElement() ) + { + bbEditor::inst()->loadSettings( + _this.firstChild().toElement() ); + } +/* doesn't work yet because bbTrack-ctor also sets current bb so if + bb-tracks are created after this function is called, this doesn't + help at all.... + if( _this.attribute( "current" ).toInt() ) + { + bbEditor::inst()->setCurrentBB( s_bbNums[this].num ); + }*/ +} + + + + +// return pointer to bbTrack specified by _bb_num +bbTrack * bbTrack::findBBTrack( csize _bb_num ) +{ + for( QMap::iterator it = + s_bbNums.begin(); + it != s_bbNums.end(); ++it ) + { +#ifdef QT4 + if( it.value().num == _bb_num ) +#else + if( it.data().num == _bb_num ) +#endif + { + return( it.key() ); + } + } + return( NULL ); +} + + + + +csize bbTrack::numOfBBTrack( track * _track ) +{ + if( dynamic_cast( _track ) != NULL ) + { + return( s_bbNums[dynamic_cast( _track )].num ); + } + return( 0 ); +} + + + + +void bbTrack::swapBBTracks( track * _track1, track * _track2 ) +{ + bbTrack * t1 = dynamic_cast( _track1 ); + bbTrack * t2 = dynamic_cast( _track2 ); + if( t1 != NULL && t2 != NULL ) + { + qSwap( s_bbNums[t1].num, s_bbNums[t2].num ); + bbEditor::inst()->swapBB( s_bbNums[t1].num, s_bbNums[t2].num ); + bbEditor::inst()->setCurrentBB( s_bbNums[t2].num ); + } +} + + + + +void bbTrack::clickedTrackLabel( void ) +{ + bbEditor::inst()->setCurrentBB( s_bbNums[this].num ); + bbEditor::inst()->show(); +} diff --git a/src/tracks/pattern.cpp b/src/tracks/pattern.cpp new file mode 100644 index 00000000000..c228da75803 --- /dev/null +++ b/src/tracks/pattern.cpp @@ -0,0 +1,1027 @@ +/* + * pattern.cpp - implementation of class pattern which holds notes + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include +#include +#include +#include +#include +#include + +#else + +#include +#include +#include +#include +#include +#include +#include + +#endif + + +#include "pattern.h" +#include "channel_track.h" +#include "templates.h" +#include "embed.h" +#include "piano_roll.h" +#include "track_container.h" +#include "rename_dialog.h" +#include "sample_buffer.h" +#include "audio_sample_recorder.h" +#include "song_editor.h" +#include "tooltip.h" + + +QPixmap * pattern::s_patternBg = NULL; +QPixmap * pattern::s_stepBtnOn = NULL; +QPixmap * pattern::s_stepBtnOff = NULL; +QPixmap * pattern::s_stepBtnOffLight = NULL; +QPixmap * pattern::s_frozen = NULL; + + + + +pattern::pattern ( channelTrack * _channel_track ) : + trackContentObject( _channel_track ), + m_channelTrack( _channel_track ), + m_patternType( BEAT_PATTERN ), + m_name( _channel_track->name() ), + m_frozenPatternMutex(), + m_frozenPattern( NULL ), + m_freezeRecorder( NULL ), + m_freezeStatusDialog( NULL ), + m_freezeStatusUpdateTimer( NULL ) +{ + initPixmaps(); + + setFixedHeight( s_patternBg->height() + 4 ); + +#ifndef QT4 + // set background-mode for flicker-free redraw + setBackgroundMode( Qt::NoBackground ); +#endif + + if( m_patternType == BEAT_PATTERN ) + { + for( int i = 0; i < MAX_BEATS_PER_TACT; ++i ) + { + m_notes.push_back( new note( midiTime( 0 ), + midiTime( i*4 ) ) ); + } + } + + changeLength( length() ); + + setAutoResizeEnabled( FALSE ); + + toolTip::add( this, + tr( "double-click to open this pattern in piano-roll" ) ); +} + + + + +pattern::pattern( const pattern & _pat_to_copy ) : + trackContentObject( _pat_to_copy.m_channelTrack ), + m_channelTrack( _pat_to_copy.m_channelTrack ), + m_patternType( _pat_to_copy.m_patternType ), + m_name( "" ), + m_frozenPatternMutex(), + m_frozenPattern( NULL ) +{ + initPixmaps(); + + for( noteVector::const_iterator it = _pat_to_copy.m_notes.begin(); + it != _pat_to_copy.m_notes.end(); ++it ) + { + m_notes.push_back( new note( **it ) ); + } + + setFixedHeight( s_patternBg->height() + 4 ); + +#ifndef QT4 + // set background-mode for flicker-free redraw + setBackgroundMode( Qt::NoBackground ); +#endif + + changeLength( length() ); + setAutoResizeEnabled( FALSE ); +} + + + + +pattern::~pattern() +{ + if( pianoRoll::inst()->currentPattern() == this ) + { + pianoRoll::inst()->setCurrentPattern( NULL ); + } + for( noteVector::iterator it = m_notes.begin(); + it != m_notes.end(); ++it ) + { + delete *it; + } + + m_notes.clear(); + + m_frozenPatternMutex.lock(); + delete m_frozenPattern; + m_frozenPatternMutex.unlock(); +} + + + + +void pattern::initPixmaps( void ) +{ + if( s_patternBg == NULL ) + { + s_patternBg = new QPixmap( embed::getIconPixmap( + "pattern_bg" ) ); + } + if( s_stepBtnOn == NULL ) + { + s_stepBtnOn = new QPixmap( embed::getIconPixmap( + "step_btn_on" ) ); + } + if( s_stepBtnOff == NULL ) + { + s_stepBtnOff = new QPixmap( embed::getIconPixmap( + "step_btn_off" ) ); + } + if( s_stepBtnOffLight == NULL ) + { + s_stepBtnOffLight = new QPixmap( embed::getIconPixmap( + "step_btn_off_light" ) ); + } + if( s_frozen == NULL ) + { + s_frozen = new QPixmap( embed::getIconPixmap( "frozen" ) ); + } +} + + + + +void pattern::movePosition( const midiTime & _pos ) +{ + // patterns are always aligned on tact-boundaries + trackContentObject::movePosition( midiTime( _pos.getTact(), 0 ) ); +} + + + + +void pattern::constructContextMenu( QMenu * _cm ) +{ +#ifdef QT4 + QAction * a = new QAction( embed::getIconPixmap( "piano" ), + tr( "Open in piano-roll" ), _cm ); + _cm->insertAction( _cm->actions()[0], a ); + connect( a, SIGNAL( triggered( bool ) ), this, + SLOT( openInPianoRoll( bool ) ) ); +#else + _cm->insertItem( embed::getIconPixmap( "piano" ), + tr( "Open in piano-roll" ), + this, SLOT( openInPianoRoll() ), + 0, -1, 0 ); +#endif +#ifdef QT4 + _cm->insertSeparator( _cm->actions()[1] ); +#else + _cm->insertSeparator( 1 ); +#endif + +#ifdef QT4 + _cm->addSeparator(); +#else + _cm->insertSeparator(); +#endif + _cm->addAction( embed::getIconPixmap( "edit_erase" ), + tr( "Clear all notes" ), this, SLOT( clear() ) ); +#ifdef QT4 + _cm->addSeparator(); +#else + _cm->insertSeparator(); +#endif + _cm->addAction( embed::getIconPixmap( "reload" ), tr( "Reset name" ), + this, SLOT( resetName() ) ); + _cm->addAction( embed::getIconPixmap( "rename" ), tr( "Change name" ), + this, SLOT( changeName() ) ); +#ifdef QT4 + _cm->addSeparator(); +#else + _cm->insertSeparator(); +#endif + _cm->addAction( embed::getIconPixmap( "freeze" ), + ( m_frozenPattern != NULL )? tr( "Refreeze" ) : tr( "Freeze" ), + this, SLOT( freeze() ) ); + _cm->addAction( embed::getIconPixmap( "unfreeze" ), tr( "Unfreeze" ), + this, SLOT( unfreeze() ) ); +} + + + + +void pattern::ensureBeatNotes( void ) +{ + // make sure, that all step-note exist + for( int i = 0; i < MAX_BEATS_PER_TACT; ++i ) + { + bool found = FALSE; + for( noteVector::iterator it = m_notes.begin(); + it != m_notes.end(); ++it ) + { + if( ( *it )->pos() == i * 4 && ( *it )->length() <= 0 ) + { + found = TRUE; + break; + } + } + if( found == FALSE ) + { + addNote( note( midiTime( 0 ), midiTime( i * 4 ) ) ); + } + } +} + + + + +void pattern::paintEvent( QPaintEvent * ) +{ + changeLength( length() ); + +#ifdef QT4 + QPainter p( this ); +#else + // create pixmap for whole widget + QPixmap pm( rect().size() ); + + // and a painter for it + QPainter p( &pm ); +#endif + + for( Sint16 x = 2; x < width() - 1; x += 2 ) + { + p.drawPixmap( x, 2, *s_patternBg ); + } + p.setPen( QColor( 57, 69, 74 ) ); + p.drawLine( 0, 0, width(), 0 ); + p.drawLine( 0, 0, 0, height() ); + p.setPen( QColor( 120, 130, 140 ) ); + p.drawLine( 0, height() - 1, width() - 1, height() - 1 ); + p.drawLine( width() - 1, 0, width() - 1, height() - 1 ); + + p.setPen( QColor( 0, 0, 0 ) ); + p.drawRect( 1, 1, width() - 2, height() - 2 ); + + float ppt = pixelsPerTact(); + + if( m_patternType == pattern::MELODY_PATTERN ) + { + Sint16 central_key = 0; + if( m_notes.size() > 0 ) + { + // first determine the central tone so that we can + // display the area where most of the m_notes are + Sint16 total_notes = 0; + for( noteVector::iterator it = m_notes.begin(); + it != m_notes.end(); ++it ) + { + if( ( *it )->length() > 0 ) + { + central_key += ( *it )->key(); + ++total_notes; + } + } + + if( total_notes > 0 ) + { + central_key = central_key / total_notes; + + Sint16 central_y = s_patternBg->height() / 2; + Sint16 y_base = central_y+TCO_BORDER_WIDTH-1; + + const Sint16 x_base = TCO_BORDER_WIDTH; + + p.setPen( QColor( 0, 0, 0 ) ); + for( tact tact_num = 1; tact_num < + length().getTact(); ++tact_num ) + { + p.drawLine( x_base + static_cast( + ppt*tact_num ), + TCO_BORDER_WIDTH, + x_base + + static_cast( ppt * tact_num ), + height() - 2 * + TCO_BORDER_WIDTH ); + } + if( getTrack()->muted() ) + { + p.setPen( QColor( 160, 160, 160 ) ); + } + else if( m_frozenPattern != NULL ) + { + p.setPen( QColor( 0x00, 0xE0, 0xFF ) ); + } + else + { + p.setPen( QColor( 0xFF, 0xB0, 0x00 ) ); + } + + for( noteVector::iterator it = m_notes.begin(); + it != m_notes.end(); ++it ) + { + Sint16 y_pos = central_key - + ( *it )->key(); + + if( ( *it )->length() > 0 && + y_pos > -central_y && + y_pos < central_y ) + { + Sint16 x1 = 2 * x_base + + static_cast( ( *it )->pos() * ppt / 64 ); + Sint16 x2 = x1 + + static_cast( ( *it )->length() * ppt / 64 ); + p.drawLine( x1, y_base+y_pos, + x2, + y_base+y_pos ); + + } + } + } + } + } + else if( m_patternType == pattern::BEAT_PATTERN && ppt >= 192 ) + { + QPixmap stepon; + QPixmap stepoff; + QPixmap stepoffl; +#ifdef QT4 + stepon = s_stepBtnOn->scaled( width() / 16, + s_stepBtnOn->height(), + Qt::IgnoreAspectRatio, + Qt::SmoothTransformation ); + stepoff = s_stepBtnOff->scaled( width() / 16, + s_stepBtnOff->height(), + Qt::IgnoreAspectRatio, + Qt::SmoothTransformation ); + stepoffl = s_stepBtnOffLight->scaled( width() / 16, + s_stepBtnOffLight->height(), + Qt::IgnoreAspectRatio, + Qt::SmoothTransformation ); +#else + stepon.convertFromImage( s_stepBtnOn->convertToImage().scale( + width() / 16, s_stepBtnOn->height() ) ); + stepoff.convertFromImage( s_stepBtnOff->convertToImage().scale( + width() / 16, s_stepBtnOff->height() ) ); + stepoffl.convertFromImage( s_stepBtnOffLight->convertToImage(). + scale( width() / 16, s_stepBtnOffLight->height() ) ); +#endif + for( noteVector::iterator it = m_notes.begin(); + it != m_notes.end(); ++it ) + { + Sint16 no = it - m_notes.begin(); + Sint16 x = TCO_BORDER_WIDTH + static_cast( no * + ppt / + m_notes.size() ); + Sint16 y = height() - s_stepBtnOn->height() - 1; + if( ( *it )->length() < 0 ) + { + p.drawPixmap( x, y, stepon ); + } + else if( ( no / 4 ) % 2 ) + { + p.drawPixmap( x, y, stepoff ); + } + else + { + p.drawPixmap( x, y, stepoffl ); + } + } + } + + p.setFont( pointSize<7>( p.font() ) ); + p.setPen( QColor( 32, 240, 32 ) ); + p.drawText( 2, 9, m_name ); + if( m_frozenPattern != NULL ) + { + p.setPen( QColor( 0, 224, 255 ) ); + p.drawRect( 0, 0, width(), height() - 1 ); + p.drawPixmap( 3, height() - s_frozen->height() - 4, *s_frozen ); + } + +#ifndef QT4 + // blit drawn pixmap to actual widget + bitBlt( this, rect().topLeft(), &pm ); +#endif +} + + + + +void pattern::mousePressEvent( QMouseEvent * _me ) +{ + if( _me->button() != Qt::LeftButton ) + { + _me->ignore(); + return; + } + + if( m_patternType == pattern::BEAT_PATTERN && pixelsPerTact() >= 192 && + _me->y() > height() - s_stepBtnOn->height() ) + { + note * n = m_notes[( _me->x() - TCO_BORDER_WIDTH ) * 16 / + width() ]; + if( n->length() < 0 ) + { + n->setLength( 0 ); + } + else + { + n->setLength( -64 ); + } + songEditor::inst()->setModified(); + update(); + return; + } + trackContentObject::mousePressEvent( _me ); +} + + + + +void pattern::mouseDoubleClickEvent( QMouseEvent * _me ) +{ + if( _me->button() != Qt::LeftButton ) + { + _me->ignore(); + return; + } + if( m_patternType == pattern::MELODY_PATTERN || + !( m_patternType == pattern::BEAT_PATTERN && + pixelsPerTact() >= 192 && + _me->y() > height() - s_stepBtnOn->height() ) ) + { + openInPianoRoll(); + } +} + + + + +void pattern::openInPianoRoll( void ) +{ + openInPianoRoll( FALSE ); +} + + + + +void pattern::openInPianoRoll( bool ) +{ + pianoRoll::inst()->setCurrentPattern( this ); + pianoRoll::inst()->show(); + pianoRoll::inst()->setFocus(); + return; +} + + + + +void pattern::clear( void ) +{ + clearNotes(); + ensureBeatNotes(); +} + + + + +void pattern::resetName( void ) +{ + m_name = m_channelTrack->name(); +} + + + + +void pattern::changeName( void ) +{ + renameDialog rename_dlg( m_name ); + rename_dlg.exec(); +} + + + + +void pattern::freeze( void ) +{ + if( songEditor::inst()->playing() ) + { + QMessageBox::information( 0, tr( "Cannot freeze pattern" ), + tr( "The pattern currently " + "cannot be freezed " + "because you're in " + "play-mode. Please " + "stop and try again!" ), + QMessageBox::Ok ); + return; + } + if( m_channelTrack->muted() ) + { + if( QMessageBox:: +#if QT_VERSION >= 0x030200 + question +#else + information +#endif + + ( 0, tr( "Channel muted" ), + tr( "The channel this pattern " + "belongs to is " + "currently muted, so " + "freezing makes no " + "sense! Do you still " + "want to continue?" ), + QMessageBox::Yes, + QMessageBox::No | + QMessageBox::Default | + QMessageBox::Escape ) == + QMessageBox::No ) + { + return; + } + } + + // already frozen? + if( m_frozenPattern != NULL ) + { + // then unfreeze, before freezing it again + unfreeze(); + } + + mixer::inst()->pause(); + + bool b; + m_freezeRecorder = new audioSampleRecorder( + mixer::inst()->sampleRate(), + DEFAULT_CHANNELS, b ); + mixer::inst()->setAudioDevice( m_freezeRecorder, + mixer::inst()->highQuality() ); + + songEditor::inst()->playPattern( this, FALSE ); + songEditor::playPos & ppp = songEditor::inst()->getPlayPos( + songEditor::PLAY_PATTERN ); + ppp.setTact( 0 ); + ppp.setTact64th( 0 ); + ppp.setCurrentFrame( 0 ); + ppp.m_timeLineUpdate = FALSE; + m_freezeStatusDialog = new patternFreezeStatusDialog; + connect( m_freezeStatusDialog, SIGNAL( aborted() ), this, + SLOT( abortFreeze() ) ); + + m_freezeStatusUpdateTimer = new QTimer( this ); + connect( m_freezeStatusUpdateTimer, SIGNAL( timeout() ), this, + SLOT( updateFreezeStatusDialog() ) ); + + m_freezeStatusUpdateTimer->start( 50 ); + + m_freezeStatusDialog->show(); + + mixer::inst()->play(); +} + + + + +void pattern::unfreeze( void ) +{ + if( m_frozenPattern != NULL ) + { + m_frozenPatternMutex.lock(); + delete m_frozenPattern; + m_frozenPattern = NULL; + m_frozenPatternMutex.unlock(); + } +} + + + + +void pattern::updateFreezeStatusDialog( void ) +{ + m_freezeStatusDialog->setProgress( songEditor::inst()->getPlayPos( + songEditor::PLAY_PATTERN ) * + 100 / length() ); + m_frozenPatternMutex.lock(); + + // finishFreeze called? + if( m_freezeRecorder == NULL ) + { + // then we're done and destroy the timer and the dialog + delete m_freezeStatusUpdateTimer; + delete m_freezeStatusDialog; + m_freezeStatusUpdateTimer = NULL; + m_freezeStatusDialog = NULL; + } + + m_frozenPatternMutex.unlock(); +} + + + + +void pattern::finishFreeze( void ) +{ + songEditor::inst()->stop(); + + m_frozenPatternMutex.lock(); + + m_freezeRecorder->createSampleBuffer( &m_frozenPattern ); + + mixer::inst()->restoreAudioDevice(); + m_freezeRecorder = NULL; + + songEditor::inst()->getPlayPos( songEditor::PLAY_PATTERN + ).m_timeLineUpdate = TRUE; + + m_frozenPatternMutex.unlock(); +} + + + + +void pattern::abortFreeze( void ) +{ + songEditor::inst()->stop(); + + m_frozenPatternMutex.lock(); + + mixer::inst()->restoreAudioDevice(); + m_freezeRecorder = NULL; + + songEditor::inst()->getPlayPos( songEditor::PLAY_PATTERN + ).m_timeLineUpdate = TRUE; + + m_frozenPatternMutex.unlock(); +} + + + + +void pattern::playFrozenData( sampleFrame * _ab, Uint32 _start_frame, + Uint32 _frames ) +{ + m_frozenPatternMutex.lock(); + if( m_frozenPattern != NULL ) + { + m_frozenPattern->play( _ab, _start_frame, _frames ); + } + m_frozenPatternMutex.unlock(); +} + + + + + +midiTime pattern::length( void ) const +{ + if( m_patternType == BEAT_PATTERN ) + { + // TODO: remove this limitation later by adding + // "Add step to pattern"-option + return( 64 ); + } + + Sint32 max_length = 0; + + for( noteVector::const_iterator it = m_notes.begin(); + it != m_notes.end(); + ++it ) + { + max_length = tMax( max_length, ( *it )->endPos() ); + } + if( max_length % 64 == 0 ) + { + return( midiTime( tMax( max_length, 64 ) ) ); + } + return( midiTime( tMax( midiTime( max_length ).getTact() + 1, 1 ), + 0 ) ); +} + + + + +note * pattern::addNote( const note & _new_note ) +{ + note * new_note = new note( _new_note ); + + if( m_notes.size() == 0 || m_notes.last()->pos() <= new_note->pos() ) + { + m_notes.push_back( new_note ); + } + else + { + // simple algorithm for inserting the note between two + // notes with smaller and greater position + // maybe it could be optimized by starting in the middle and + // going forward or backward but note-inserting isn't that + // time-critical since it is usually not done while playing... + long new_note_abs_time = new_note->pos(); + noteVector::iterator it = m_notes.begin(); + + while( it != m_notes.end() && + ( *it )->pos() < new_note_abs_time ) + { + ++it; + } + + m_notes.insert( it, new_note ); + } + + checkType(); + update(); + changeLength( length() ); + + return( new_note ); +} + + + + +void pattern::removeNote( const note * _note_to_del ) +{ + noteVector::iterator it = m_notes.begin(); + while( it != m_notes.end() ) + { + if( ( *it ) == _note_to_del ) + { + delete *it; + m_notes.erase( it ); + break; + } + ++it; + } + + checkType(); + update(); + changeLength( length() ); +} + + + + +note * pattern::rearrangeNote( const note * _note_to_proc ) +{ + // just rearrange the position of the note by removing it and adding + // a copy of it -> addNote inserts it at the correct position + note copy_of_note( *_note_to_proc ); + removeNote( _note_to_proc ); + + return( addNote( copy_of_note ) ); +} + + + + +void pattern::clearNotes( void ) +{ + for( noteVector::iterator it = m_notes.begin(); it != m_notes.end(); + ++it ) + { + delete *it; + } + + m_notes.clear(); + checkType(); + update(); +} + + + + +void pattern::setType( patternTypes _new_pattern_type ) +{ + if( _new_pattern_type == BEAT_PATTERN || + _new_pattern_type == MELODY_PATTERN ) + { + m_patternType = _new_pattern_type; + } +} + + + + +note * pattern::noteAt( int _note_num ) +{ + if( (csize) _note_num < m_notes.size() ) + { + return( m_notes[_note_num] ); + } + return( NULL ); +} + + + + +void pattern::setNoteAt( int _note_num, note _new_note ) +{ + if( static_cast( _note_num ) < m_notes.size() ) + { + delete m_notes[_note_num]; + m_notes[_note_num] = new note( _new_note ); + checkType(); + update(); + } +} + + + + +void pattern::checkType( void ) +{ + noteVector::iterator it = m_notes.begin(); + while( it != m_notes.end() ) + { + if( ( *it )->length() > 0 ) + { + setType( pattern::MELODY_PATTERN ); + return; + } + ++it; + } + setType( pattern::BEAT_PATTERN ); +} + + + + + +void pattern::saveSettings( QDomDocument & _doc, QDomElement & _parent ) +{ + QDomElement pattern_de = _doc.createElement( nodeName() ); + pattern_de.setAttribute( "type", QString::number( m_patternType ) ); + pattern_de.setAttribute( "name", m_name ); + if( _parent.nodeName() == "clipboard" ) + { + pattern_de.setAttribute( "pos", QString::number( -1 ) ); + } + else + { + pattern_de.setAttribute( "pos", QString::number( + startPosition() ) ); + } + pattern_de.setAttribute( "len", QString::number( length() ) ); + pattern_de.setAttribute( "frozen", QString::number( + m_frozenPattern != NULL ) ); + _parent.appendChild( pattern_de ); + + // now save settings of all notes + for( noteVector::iterator it = m_notes.begin(); + it != m_notes.end(); ++it ) + { + if( ( *it )->length() ) + { + ( *it )->saveSettings( _doc, pattern_de ); + } + } +} + + + + +void pattern::loadSettings( const QDomElement & _this ) +{ + unfreeze(); + + m_patternType = static_cast( _this.attribute( "type" + ).toInt() ); + m_name = _this.attribute( "name" ); + if( _this.attribute( "pos" ).toInt() >= 0 ) + { + movePosition( _this.attribute( "pos" ).toInt() ); + } + changeLength( midiTime( _this.attribute( "len" ).toInt() ) ); + + clearNotes(); + + QDomNode node = _this.firstChild(); + while( !node.isNull() ) + { + if( node.isElement() ) + { + note * n = new note(); + n->loadSettings( node.toElement() ); + m_notes.push_back( n ); + } + node = node.nextSibling(); + } + ensureBeatNotes(); +/* if( _this.attribute( "frozen" ).toInt() ) + { + freeze(); + }*/ + update(); +} + + + + +patternFreezeStatusDialog::patternFreezeStatusDialog( void ) +{ + setWindowTitle( tr( "Freezing pattern..." ) ); +#if QT_VERSION >= 0x030200 + setModal( TRUE ); +#endif + + m_progressBar = new QProgressBar( this ); + m_progressBar->setGeometry( 10, 10, 200, 24 ); +#ifdef QT4 + m_progressBar->setMaximum( 100 ); +#else + m_progressBar->setTotalSteps( 100 ); +#endif + m_progressBar->setTextVisible( FALSE ); + m_progressBar->show(); + m_cancelBtn = new QPushButton( embed::getIconPixmap( "cancel" ), + tr( "Cancel" ), this ); + m_cancelBtn->setGeometry( 50, 38, 120, 28 ); + connect( m_cancelBtn, SIGNAL( clicked() ), this, + SLOT( cancelBtnClicked() ) ); +} + + + + +patternFreezeStatusDialog::~patternFreezeStatusDialog() +{ +} + + + + + +void patternFreezeStatusDialog::setProgress( int _p ) +{ +#ifdef QT4 + m_progressBar->setValue( _p ); +#else + m_progressBar->setProgress( _p ); +#endif +} + + + + +void patternFreezeStatusDialog::closeEvent( QCloseEvent * _ce ) +{ + _ce->ignore(); + cancelBtnClicked(); +} + + + + +void patternFreezeStatusDialog::cancelBtnClicked( void ) +{ + emit( aborted() ); +} + + + + + +#include "pattern.moc" + diff --git a/src/tracks/sample_track.cpp b/src/tracks/sample_track.cpp new file mode 100644 index 00000000000..54eaa686240 --- /dev/null +++ b/src/tracks/sample_track.cpp @@ -0,0 +1,395 @@ +/* + * sample_track.cpp - implementation of class sampleTrack, a track which + * provides arrangement of samples + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include +#include + +#endif + + +#include "sample_track.h" +#include "song_editor.h" +#include "name_label.h" +#include "embed.h" +#include "templates.h" +#include "buffer_allocator.h" +#include "tooltip.h" + + + +sampleTCO::sampleTCO( track * _track ) : + trackContentObject( _track ), + m_sampleBuffer() +{ +#ifndef QT4 + setBackgroundMode( Qt::NoBackground ); +#endif + + setSampleFile( "" ); + + // we need to receive bpm-change-events, because then we have to + // change length of this TCO + connect( songEditor::inst(), SIGNAL( bpmChanged( int ) ), this, + SLOT( updateLength( int ) ) ); +} + + + + +sampleTCO::~sampleTCO() +{ +} + + + + +void sampleTCO::changeLength( const midiTime & _length ) +{ + trackContentObject::changeLength( tMax( static_cast( _length ), + 64 ) ); +} + + + + +void FASTCALL sampleTCO::play( sampleFrame * _ab, Uint32 _start_frame, + Uint32 _frames ) +{ + _start_frame = static_cast( tMax( 0.0f, _start_frame - + startPosition() * + songEditor::inst()->framesPerTact() / 64 ) ); + m_sampleBuffer.play( _ab, _start_frame, _frames ); +} + + + + +const QString & sampleTCO::sampleFile( void ) const +{ + return( m_sampleBuffer.audioFile() ); +} + + + + +void sampleTCO::setSampleFile( const QString & _sf ) +{ + m_sampleBuffer.setAudioFile( _sf ); + updateLength(); + update(); + // set tooltip to filename so that user can see what sample this + // sample-tco contains + toolTip::add( this, ( m_sampleBuffer.audioFile() != "" ) ? + m_sampleBuffer.audioFile() : + tr( "double-click to select sample" ) ); +} + + + + +void sampleTCO::updateLength( int ) +{ + changeLength( getSampleLength() ); +} + + + + +void sampleTCO::paintEvent( QPaintEvent * ) +{ +#ifdef QT4 + QPainter p( this ); + p.fillRect( rect(), QColor( 0, 64, 255 ) ); +#else + // create pixmap for whole widget + QPixmap pm( rect().size() ); + pm.fill( QColor( 0, 64, 255 ) ); + // and a painter for it + QPainter p( &pm ); +#endif + + if( getTrack()->muted() ) + { + p.setPen( QColor( 160, 160, 160 ) ); + } + else + { + p.setPen( QColor( 0, 0, 128 ) ); + } + p.drawRect( 0, 0, width(), height() ); + m_sampleBuffer.drawWaves( p, QRect( 1, 1, tMax( tMin( width() - 3, + static_cast( getSampleLength() * + pixelsPerTact() / 64 ) ), 1 ), + height() - 4 ) ); +#ifndef QT4 + bitBlt( this, rect().topLeft(), &pm ); +#endif +} + + + + +void sampleTCO::mouseDoubleClickEvent( QMouseEvent * ) +{ + QString af = m_sampleBuffer.openAudioFile(); + if( af != "" && af != m_sampleBuffer.audioFile() ) + { + setSampleFile( af ); + songEditor::inst()->setModified(); + } +} + + + + +midiTime sampleTCO::getSampleLength( void ) const +{ + return( static_cast( m_sampleBuffer.frames() / + songEditor::inst()->framesPerTact() * + 64 ) ); +} + + + + +void FASTCALL sampleTCO::saveSettings( QDomDocument & _doc, QDomElement & _parent ) +{ + QDomElement sampletco_de = _doc.createElement( nodeName() ); + if( _parent.nodeName() == "clipboard" ) + { + sampletco_de.setAttribute( "pos", QString::number( -1 ) ); + } + else + { + sampletco_de.setAttribute( "pos", QString::number( + startPosition() ) ); + } + sampletco_de.setAttribute( "len", QString::number( length() ) ); + sampletco_de.setAttribute( "src", sampleFile() ); + // TODO: start- and end-frame + _parent.appendChild( sampletco_de ); +} + + + + +void FASTCALL sampleTCO::loadSettings( const QDomElement & _this ) +{ + if( _this.attribute( "pos" ).toInt() >= 0 ) + { + movePosition( _this.attribute( "pos" ).toInt() ); + } + changeLength( _this.attribute( "len" ).toInt() ); + setSampleFile( _this.attribute( "src" ) ); +} + + + + + +/* + +sampleTCOSettingsDialog::sampleTCOSettingsDialog( sampleTCO * _stco ) : + QDialog(), + m_sampleTCO( _stco ) +{ + resize( 400, 300 ); + + QVBoxWidget * vb0 = new QVBoxWidget( this ); + vb0->resize( 400, 300 ); + QHBoxWidget * hb00 = new QHBoxWidget( vb0 ); + m_fileLbl = new QLabel( _stco->sampleFile(), hb00 ); + QPushButton * open_file_btn = new QPushButton( + embed::getIconPixmap( "fileopen" ), "", hb00 ); + connect( open_file_btn, SIGNAL( clicked() ), this, + SLOT( openSampleFile() ) ); + + QHBoxWidget * hb01 = new QHBoxWidget( vb0 ); + + QPushButton * ok_btn = new QPushButton( tr( "OK" ), hb01 ); + ok_btn->setGeometry( 10, 0, 100, 32 ); + connect( ok_btn, SIGNAL( clicked() ), this, SLOT( accept() ) ); + + QPushButton * cancel_btn = new QPushButton( tr( "Cancel" ), hb01 ); + cancel_btn->setGeometry( 120, 0, 100, 32 ); + connect( ok_btn, SIGNAL( clicked() ), this, SLOT( reject() ) ); + +} + + + + +sampleTCOSettingsDialog::~sampleTCOSettingsDialog() +{ +} + + + + +void sampleTCOSettingsDialog::openSampleFile( void ) +{ + QString af = m_sampleTCO->m_sampleBuffer.openAudioFile(); + if( af != "" ) + { + setSampleFile( af ); + } +} + + + + +void sampleTCOSettingsDialog::setSampleFile( const QString & _f ) +{ + m_fileLbl->setText( _f ); + m_sampleTCO->setSampleFile( _f ); + songEditor::inst()->setModified(); +} +*/ + + + + + +sampleTrack::sampleTrack( trackContainer * _tc ) + : track( _tc ) +{ + getTrackWidget()->setFixedHeight( 32 ); + + m_trackLabel = new nameLabel( tr( "Sample track" ), + getTrackSettingsWidget(), + embed::getIconPixmap( + "sample_track" ) ); + m_trackLabel->setGeometry( 1, 1, DEFAULT_SETTINGS_WIDGET_WIDTH-2, 29 ); + m_trackLabel->show(); + + _tc->updateAfterTrackAdd(); +} + + + + +sampleTrack::~sampleTrack() +{ +} + + + + +track::trackTypes sampleTrack::trackType( void ) const +{ + return( SAMPLE_TRACK ); +} + + + + +bool FASTCALL sampleTrack::play( const midiTime & _start, Uint32 _start_frame, + Uint32 _frames, Uint32 _frame_base, + Sint16 /*_tco_num*/ ) +{ + vlist tcos; + getTCOsInRange( tcos, _start, _start+static_cast( _frames * 64 / + songEditor::inst()->framesPerTact() ) ); + + if ( tcos.size() == 0 ) + { + return( FALSE ); + } + + sampleFrame * buf = bufferAllocator::alloc( _frames ); + + volumeVector v = { 1.0f, 1.0f +#ifndef DISABLE_SURROUND + , 1.0f, 1.0f +#endif + } ; + float fpt = songEditor::inst()->framesPerTact(); + + for( vlist::iterator it = tcos.begin(); + it != tcos.end(); ++it ) + { + sampleTCO * st = dynamic_cast( *it ); + if( st != NULL ) + { + st->play( buf, _start_frame + + static_cast( _start.getTact() * + fpt ), + _frames ); + mixer::inst()->addBuffer( buf, _frames, _frame_base + + static_cast( + st->startPosition().getTact64th() * + fpt / 64.0f ), v ); + } + } + + bufferAllocator::free( buf ); + + return( TRUE ); +} + + + + +trackContentObject * sampleTrack::createTCO( const midiTime & ) +{ + return( new sampleTCO( this ) ); +} + + + + + +void sampleTrack::saveTrackSpecificSettings( QDomDocument & _doc, + QDomElement & _parent ) +{ + QDomElement st_de = _doc.createElement( nodeName() ); + st_de.setAttribute( "name", m_trackLabel->text() ); + _parent.appendChild( st_de ); +} + + + + +void sampleTrack::loadTrackSpecificSettings( const QDomElement & _this ) +{ + m_trackLabel->setText( _this.attribute( "name" ) ); +} + + + + +#include "sample_track.moc" + diff --git a/src/widgets/group_box.cpp b/src/widgets/group_box.cpp new file mode 100644 index 00000000000..5da124577b3 --- /dev/null +++ b/src/widgets/group_box.cpp @@ -0,0 +1,234 @@ +/* + * group_box.cpp - groupbox for LMMS + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include +#include + +#define setChecked setOn + +#endif + +#include + + +#include "group_box.h" +#include "embed.h" +#include "spc_bg_hndl_widget.h" +#include "templates.h" + + +QPixmap * groupBox::s_ledBg = NULL; + + +groupBox::groupBox( const QString & _caption, QWidget * _parent ) : + QWidget( _parent ), + m_caption( _caption ), + m_origHeight( height() ), + m_animating( FALSE ) +{ + if( s_ledBg == NULL ) + { + s_ledBg = new QPixmap( embed::getIconPixmap( + "groupbox_led_bg" ) ); + } + updatePixmap(); + + m_led = new pixmapButton( this ); + m_led->move( 2, 3 ); + m_led->setActiveGraphic( embed::getIconPixmap( "led_green" ) ); + m_led->setInactiveGraphic( embed::getIconPixmap( "led_off" ) ); + m_led->setBgGraphic( specialBgHandlingWidget::getBackground( m_led ) ); + connect( m_led, SIGNAL( toggled( bool ) ), + this, SLOT( setState( bool ) ) ); +} + + + + +groupBox::~groupBox() +{ +} + + + + +void groupBox::resizeEvent( QResizeEvent * ) +{ + updatePixmap(); + if( m_animating == FALSE ) + { + m_origHeight = height(); + } +} + + + + +void groupBox::mousePressEvent( QMouseEvent * _me ) +{ + if( _me->y() > 1 && _me->y() < 13 ) + { + setState( !isActive(), TRUE ); + } +} + + + + +void groupBox::setState( bool _on, bool _anim ) +{ + m_led->setChecked( _on ); + if( ( _anim == TRUE || ( _on == TRUE && height() < m_origHeight ) ) && + m_animating == FALSE ) + { + m_animating = TRUE; + animate(); + } +} + + + + +void groupBox::animate( void ) +{ + float state = (float)( m_origHeight - height() ) / + (float)( m_origHeight - 19 ); + int dy = static_cast( 3 - 2 * cosf( state * 2 * M_PI ) ); + if( isActive() && height() < m_origHeight ) + { + } + else if( !isActive() && height() > 19 ) + { + dy = -dy; + } + else + { + m_animating = FALSE; + return; + } + resize( width(), height() + dy ); + QTimer::singleShot( 10, this, SLOT( animate() ) ); +#ifdef QT4 + QObjectList ch = parent()->children(); +#else + QObjectList ch = *( parent()->children() ); +#endif + for( csize i = 0; i < ch.count(); ++i ) + { + QWidget * w = dynamic_cast( ch.at( i ) ); + if( w == NULL || w->y() < y() + height() ) + { + continue; + } + w->move( w->x(), w->y() + dy ); + } +#ifdef QT4 + ch = children(); +#else + ch = *children(); +#endif + for( csize i = 0; i < ch.count(); ++i ) + { + QWidget * w = dynamic_cast( ch.at( i ) ); + if( w == NULL || w == m_led ) + { + continue; + } + w->move( w->x(), w->y() + dy ); + if( w->y() < 14) + { + w->hide(); + } + else if( w->isHidden() == TRUE ) + { + w->show(); + } + } +} + + + + +void groupBox::updatePixmap( void ) +{ + QPixmap pm( size() ); + pm.fill( QColor( 96, 96, 96 ) ); + + QPainter p( &pm ); + + // outer rect + p.setPen( QColor( 64, 64, 64 ) ); + p.drawRect( 0, 0, width(), height() ); + + // brighter line at bottom/right + p.setPen( QColor( 160, 160, 160 ) ); + p.drawLine( width() - 1, 0, width() - 1, height() - 1 ); + p.drawLine( 0, height() - 1, width() - 1, height() - 1 ); + + // draw our led-pixmap + p.drawPixmap( 2, 2, *s_ledBg ); + + // draw groupbox-titlebar + p.fillRect( 2, 2, width() - 4, 9, QColor( 30, 45, 60 ) ); + + // draw line below titlebar + p.setPen( QColor( 0, 0, 0 ) ); + p.drawLine( 2 + s_ledBg->width(), 11, width() - 3, 11 ); + + // black inner rect + p.drawRect( 1, 1, width() - 2, height() - 2 ); + + + p.setPen( QColor( 255, 255, 255 ) ); + p.setFont( pointSize<7>( font() ) ); + p.drawText( 22, 10, m_caption ); + +#ifdef QT4 + QPalette pal = palette(); + pal.setBrush( backgroundRole(), QBrush( pm ) ); + pal.setColor( QPalette::Background, QColor( 96, 96, 96 ) ); + setPalette( pal ); +#else + setPaletteBackgroundColor( QColor( 96, 96, 96 ) ); + setErasePixmap( pm ); +#endif +} + + + +#undef setChecked + +#include "group_box.moc" + diff --git a/src/widgets/kmultitabbar.cpp b/src/widgets/kmultitabbar.cpp new file mode 100644 index 00000000000..4b3adba04d0 --- /dev/null +++ b/src/widgets/kmultitabbar.cpp @@ -0,0 +1,1148 @@ +/*************************************************************************** + kmultitabbar.cpp - description + ------------------- + begin : 2001 + copyright : (C) 2001,2002,2003 by Joseph Wenninger + ***************************************************************************/ + +/*************************************************************************** + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + ***************************************************************************/ + +#include "kmultitabbar.h" + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#else + +//#include "kmultitabbar.moc" +//#include "kmultitabbar_p.h" +//#include "kmultitabbar_p.moc" +#include +#include +#include +#include +#include +#include +#include + +//#define palette colorGroup + +/*#define #palette().shadow().color() #colorGroup().shadow() +#define #palette().background().color() #colorGroup().background() +#define #palette().light().color() #colorGroup().light() +#define #palette().text().color() #colorGroup().text()*/ + +#define isChecked isOn +#define TextShowMnemonic ShowPrefix +#define State SFlags +#define State_None Style_Default +#define State_Enabled Style_Enabled +#define State_On Style_On + +#endif + +#include "templates.h" +#include "tooltip.h" + +#include "kmultitabbar.moc" + +//#include +//#include + + +class KMultiTabBarTabPrivate { +public: + QPixmap pix; +}; + + +KMultiTabBarInternal::KMultiTabBarInternal(QWidget *parent, Qt::Orientation o):Q3ScrollView(parent) +{ + m_expandedTabSize=-1; + m_showActiveTabTexts=false; +#ifndef QT4 + m_tabs.setAutoDelete(true); +#endif + setHScrollBarMode(AlwaysOff); + setVScrollBarMode(AlwaysOff); + if (o==Qt::Vertical) + { + box=new QWidget(viewport()); + mainLayout=new QVBoxLayout(box); +#ifndef QT4 + mainLayout->setAutoAdd(true); +#endif + box->setFixedWidth(24); + setFixedWidth(24); + } + else + { + box=new QWidget(viewport()); + mainLayout=new QHBoxLayout(box); +#ifndef QT4 + mainLayout->setAutoAdd(true); +#endif + box->setFixedHeight(24); + setFixedHeight(24); + } + addChild(box); + setFrameStyle(NoFrame); +#ifndef QT4 + viewport()->setBackgroundMode(Qt::PaletteBackground); +#endif +} + +void KMultiTabBarInternal::setStyle(enum KMultiTabBar::KMultiTabBarStyle style) +{ + m_style=style; + for (csize i=0;isetStyle(m_style); + + if ( (m_style==KMultiTabBar::KDEV3) || + (m_style==KMultiTabBar::KDEV3ICON ) ) { + resizeEvent(0); + } + viewport()->repaint(); +} + +void KMultiTabBarInternal::drawContents ( QPainter * paint, int clipx, int clipy, int clipw, int cliph ) +{ + Q3ScrollView::drawContents (paint , clipx, clipy, clipw, cliph ); + + if (m_position==KMultiTabBar::DockRight) + { + + paint->setPen(palette().shadow() +#ifdef QT4 + .color() +#endif + ); + paint->drawLine(0,0,0,viewport()->height()); + paint->setPen(palette().background() +#ifdef QT4 + .color() +#endif + .dark(120)); + paint->drawLine(1,0,1,viewport()->height()); + + + } + else + if (m_position==KMultiTabBar::DockLeft) + { + paint->setPen(palette().light() +#ifdef QT4 + .color() +#endif + ); + paint->drawLine(23,0,23,viewport()->height()); + paint->drawLine(22,0,22,viewport()->height()); + + paint->setPen(palette().shadow() +#ifdef QT4 + .color() +#endif + ); + paint->drawLine(0,0,0,viewport()->height()); + } + else + if (m_position==KMultiTabBar::DockBottom) + { + paint->setPen(palette().shadow() +#ifdef QT4 + .color() +#endif + ); + paint->drawLine(0,0,viewport()->width(),0); + paint->setPen(palette().background() +#ifdef QT4 + .color() +#endif + .dark(120)); + paint->drawLine(0,1,viewport()->width(),1); + } + else + { + paint->setPen(palette().light() +#ifdef QT4 + .color() +#endif + ); + paint->drawLine(0,23,viewport()->width(),23); + paint->drawLine(0,22,viewport()->width(),22); + +/* paint->setPen(palette().shadow().color()); + paint->drawLine(0,0,0,viewport()->height());*/ + + } + + +} + +void KMultiTabBarInternal::contentsMousePressEvent(QMouseEvent *ev) +{ + ev->ignore(); +} + +void KMultiTabBarInternal::mousePressEvent(QMouseEvent *ev) +{ + ev->ignore(); +} + +void KMultiTabBarInternal::resizeEvent(QResizeEvent *ev) { + //kdDebug()<<"KMultiTabBarInternal::resizeEvent"<setGeometry(0,0,width(),height()); + printf("resizevent\n"); + int lines=1; + int space; + int tmp=0; + if ((m_position==KMultiTabBar::DockBottom) || (m_position==KMultiTabBar::DockTop)) + space=width(); + else + space=height(); + + int cnt=0; +//CALCULATE LINES + for (csize i=0;ineededSize(); + if (tmp>space) { + if (cnt>1)i--; + cnt=0; + tmp=0; + lines++; + } + } +//SET SIZE & PLACE + if ((m_position==KMultiTabBar::DockBottom) || (m_position==KMultiTabBar::DockTop)) { + setFixedHeight(lines*24); + box->setFixedHeight(lines*24); + tmp=0; + cnt=0; + m_lines=lines; + lines=0; + for (csize i=0;ineededSize(); + if (tmp>space) { + if (cnt>1) i--; + else + m_tabs.at(i)->move(tmp-m_tabs.at(i)->neededSize(),lines*24); + cnt=0; + tmp=0; + lines++; + } else m_tabs.at(i)->move(tmp-m_tabs.at(i)->neededSize(),lines*24); + } + } + else { + setFixedWidth(lines*24); + box->setFixedWidth(lines*24); + tmp=0; + cnt=0; + m_lines=lines; + lines=0; + for (csize i=0;ineededSize(); + if (tmp>space) { + if (cnt>1) i--; + else + m_tabs.at(i)->move(lines*24,tmp-m_tabs.at(i)->neededSize()); + cnt=0; + tmp=0; + lines++; + } else m_tabs.at(i)->move(lines*24,tmp-m_tabs.at(i)->neededSize()); + } + } + + + //kdDebug()<<"needed lines:"< it(m_tabs);it.hasNext();it.next()){ + if (it.peekNext()->id()==id) return it.peekNext(); + } +#else + for (QPtrListIterator it(m_tabs);it.current();++it){ + if (it.current()->id()==id) return it.current(); + } +#endif + return 0; +} + + +int KMultiTabBarInternal::appendTab(const QPixmap &pic ,int id,const QString& text) +{ + KMultiTabBarTab *tab; + m_tabs.append(tab= new KMultiTabBarTab(pic,text,id,box,m_position,m_style)); + tab->showActiveTabText(m_showActiveTabTexts); + if (m_style==KMultiTabBar::KONQSBC) + { + if (m_expandedTabSizeneededSize()) { + m_expandedTabSize=tab->neededSize(); + for (csize i=0;isetSize(m_expandedTabSize); + + } else tab->setSize(m_expandedTabSize); + } else tab->updateState(); + tab->show(); + return 0; +} + +void KMultiTabBarInternal::removeTab(int id) +{ + for (csize pos=0;posid()==id) + { + delete m_tabs.at(pos); +#ifdef QT4 + m_tabs.removeAt(pos); +#else + m_tabs.remove(pos); +#endif + resizeEvent(0); + break; + } + } +} + +void KMultiTabBarInternal::setPosition(enum KMultiTabBar::KMultiTabBarPosition pos) +{ + m_position=pos; + for (csize i=0;isetTabsPosition(m_position); + viewport()->repaint(); +} + + +KMultiTabBarButton::KMultiTabBarButton(const QPixmap& pic,const QString& text, QMenu *popup, + int id,QWidget *parent,KMultiTabBar::KMultiTabBarPosition pos,KMultiTabBar::KMultiTabBarStyle style) + :QPushButton(QIcon(),text,parent),m_style(style) +{ + setIcon(pic); + setText(text); + m_position=pos; + if (popup) setMenu(popup); + setFlat(true); + setFixedHeight(24); + setFixedWidth(24); + m_id=id; + toolTip::add( this, text ); + connect(this,SIGNAL(clicked()),this,SLOT(slotClicked())); +} + +KMultiTabBarButton::KMultiTabBarButton(const QString& text, QMenu *popup, + int id,QWidget *parent,KMultiTabBar::KMultiTabBarPosition pos,KMultiTabBar::KMultiTabBarStyle style) + :QPushButton(QIcon(),text,parent),m_style(style) +{ + setText(text); + m_position=pos; + if (popup) setMenu(popup); + setFlat(true); + setFixedHeight(24); + setFixedWidth(24); + m_id=id; + toolTip::add(this,text); + connect(this,SIGNAL(clicked()),this,SLOT(slotClicked())); +} + +KMultiTabBarButton::~KMultiTabBarButton() { +} + +int KMultiTabBarButton::id() const{ + return m_id; +} + +void KMultiTabBarButton::setText(const QString& text) +{ + QPushButton::setText(text); + m_text=text; + toolTip::add(this,text); +} + +void KMultiTabBarButton::slotClicked() +{ + emit clicked(m_id); +} + +void KMultiTabBarButton::setPosition(KMultiTabBar::KMultiTabBarPosition pos) +{ + m_position=pos; + repaint(); +} + +void KMultiTabBarButton::setStyle(KMultiTabBar::KMultiTabBarStyle style) +{ + m_style=style; + repaint(); +} + +void KMultiTabBarButton::hideEvent( QHideEvent* he) { + QPushButton::hideEvent(he); + KMultiTabBar *tb=dynamic_cast(parentWidget()); + if (tb) tb->updateSeparator(); +} + +void KMultiTabBarButton::showEvent( QShowEvent* he) { + QPushButton::showEvent(he); + KMultiTabBar *tb=dynamic_cast(parentWidget()); + if (tb) tb->updateSeparator(); +} + + +QSize KMultiTabBarButton::sizeHint() const +{ + ensurePolished(); + + int w = 0, h = 0; + + // calculate contents size... +#ifndef QT_NO_ICONSET +#ifndef QT4 + if ( iconSet() && !iconSet()->isNull() ) { + int iw = iconSet()->pixmap( QIcon::Small, QIcon::Normal ).width() + 4; + int ih = iconSet()->pixmap( QIcon::Small, QIcon::Normal ).height(); + w += iw; + h = tMax( h, ih ); + } +#endif +#endif +#ifdef QT4 + QStyleOptionButton sob; + if ( menu() != 0 ) + w += style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &sob, this); +#else + if( isMenuButton() ) + w += style().pixelMetric(QStyle::PM_MenuButtonIndicator, this); +#endif + +#ifdef QT4 + if ( !icon().isNull() ) { + const QPixmap & pm = icon().pixmap( QSize( 16, 16 ) ); + w += pm.width(); + h += pm.height(); +#else + if ( pixmap() ) { + QPixmap *pm = (QPixmap *)pixmap(); + w += pm->width(); + h += pm->height(); +#endif + } else { + QString s( text() ); + bool empty = s.isEmpty(); + if ( empty ) + s = QString::fromLatin1("XXXX"); + QFontMetrics fm = fontMetrics(); + QSize sz = fm.size( Qt::TextShowMnemonic, s ); + if(!empty || !w) + w += sz.width(); + if(!empty || !h) + h = tMax(h, sz.height()); + } +#ifdef QT4 + return (style()->sizeFromContents(QStyle::CT_ToolButton, &sob, QSize(w, h), this). + expandedTo(QApplication::globalStrut())); +#else + return (style().sizeFromContents(QStyle::CT_ToolButton, this, QSize(w, h)). + expandedTo(QApplication::globalStrut())); +#endif +} + + +KMultiTabBarTab::KMultiTabBarTab(const QPixmap& pic, const QString& text, + int id,QWidget *parent,KMultiTabBar::KMultiTabBarPosition pos, + KMultiTabBar::KMultiTabBarStyle style) + :KMultiTabBarButton(text,0,id,parent,pos,style), + m_showActiveTabText(false) +{ + d=new KMultiTabBarTabPrivate(); + setIcon(pic); + m_expandedSize=24; + setCheckable(true); +} + +KMultiTabBarTab::~KMultiTabBarTab() { + delete d; +} + + +void KMultiTabBarTab::setTabsPosition(KMultiTabBar::KMultiTabBarPosition pos) +{ + if ((pos!=m_position) && ((pos==KMultiTabBar::DockLeft) || (pos==KMultiTabBar::DockRight))) { + if (!d->pix.isNull()) { + QMatrix temp;// (1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F); + temp.rotate(180); + d->pix=d->pix.transformed(temp); + setIcon(d->pix); + } + } + + setPosition(pos); +// repaint(); +} + +void KMultiTabBarTab::setIcon(const QString& icon) +{ + //QPixmap pic=SmallIcon(icon); + QPixmap pic (icon); + setIcon(pic); +} + +void KMultiTabBarTab::setIcon(const QPixmap& icon) +{ + + if (m_style!=KMultiTabBar::KDEV3) { + if ((m_position==KMultiTabBar::DockLeft) || (m_position==KMultiTabBar::DockRight)) { + QMatrix rotateMatrix; + if (m_position==KMultiTabBar::DockLeft) + rotateMatrix.rotate(90); + else + rotateMatrix.rotate(-90); + QPixmap pic=icon.transformed(rotateMatrix); + d->pix=pic; +#ifdef QT4 + QPushButton::setIcon(pic); +#else + setIconSet(pic); +#endif + } else +#ifdef QT4 + QPushButton::setIcon(icon); +#else + setIconSet(icon); +#endif + } +} + +void KMultiTabBarTab::slotClicked() +{ + updateState(); + KMultiTabBarButton::slotClicked(); +} + +void KMultiTabBarTab::setState(bool b) +{ +#ifdef QT4 + setChecked(b); +#else + setOn(b); +#endif + updateState(); +} + +void KMultiTabBarTab::updateState() +{ + + if (m_style!=KMultiTabBar::KONQSBC) { + if ((m_style==KMultiTabBar::KDEV3) || (m_style==KMultiTabBar::KDEV3ICON) || (isChecked())) { + QPushButton::setText(m_text); + } else { + //kdDebug()<<"KMultiTabBarTab::updateState(): setting text to an empty QString***************"<rotate(-90); + paint->drawPixmap(1-pixmap.width(),0,pixmap); + break; + case KMultiTabBar::DockRight: + paint->rotate(90); + paint->drawPixmap(0,1-pixmap.height(),pixmap); + break; + + default: + paint->drawPixmap(0,0,pixmap); + break; + } +// style().drawControl(QStyle::CE_PushButtonLabel,painter,this, QRect(0,0,pixmap.width(),pixmap.height()), +// colorGroup(),QStyle::Style_Enabled); + + +} + +void KMultiTabBarTab::drawButtonClassic(QPainter *paint) +{ + QPixmap pixmap; + //if ( iconSet()) + // pixmap = iconSet()->pixmap( QIcon::Small, QIcon::Normal ); +#ifdef QT4 + if( !icon().isNull() ) + { + pixmap = icon().pixmap( 16, 16 ); + } +#else + if( iconSet() ) + pixmap = iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ); +#endif + + paint->fillRect(0, 0, 24, 24, palette().background() +#ifdef QT4 + .color() +#endif + ); + + if (!isChecked()) + { + + if (m_position==KMultiTabBar::DockRight) + { + paint->fillRect(0,0,21,21,QBrush(palette().background() +#ifdef QT4 + .color() +#endif + )); + + paint->setPen(palette().background() +#ifdef QT4 + .color() +#endif + .dark(150)); + paint->drawLine(0,22,23,22); + + paint->drawPixmap(12-pixmap.width()/2,12-pixmap.height()/2,pixmap); + + paint->setPen(palette().shadow() +#ifdef QT4 + .color() +#endif + ); + paint->drawLine(0,0,0,23); + paint->setPen(palette().background() +#ifdef QT4 + .color() +#endif + .dark(120)); + paint->drawLine(1,0,1,23); + + } + else + if ((m_position==KMultiTabBar::DockBottom) || (m_position==KMultiTabBar::DockTop)) + { + paint->fillRect(0,1,23,22,QBrush(palette().background() +#ifdef QT4 + .color() +#endif + )); + + paint->drawPixmap(12-pixmap.width()/2,12-pixmap.height()/2,pixmap); + + paint->setPen(palette().background() +#ifdef QT4 + .color() +#endif + .dark(120)); + paint->drawLine(23,0,23,23); + + + paint->setPen(palette().light() +#ifdef QT4 + .color() +#endif + ); + paint->drawLine(0,22,23,22); + paint->drawLine(0,23,23,23); + paint->setPen(palette().shadow() +#ifdef QT4 + .color() +#endif + ); + paint->drawLine(0,0,23,0); + paint->setPen(palette().background() +#ifdef QT4 + .color() +#endif + .dark(120)); + paint->drawLine(0,1,23,1); + + } + else + { + paint->setPen(palette().background() +#ifdef QT4 + .color() +#endif + .dark(120)); + paint->drawLine(0,23,23,23); + paint->fillRect(0,0,23,21,QBrush(palette().background() +#ifdef QT4 + .color() +#endif + )); + paint->drawPixmap(12-pixmap.width()/2,12-pixmap.height()/2,pixmap); + + paint->setPen(palette().light() +#ifdef QT4 + .color() +#endif + ); + paint->drawLine(23,0,23,23); + paint->drawLine(22,0,22,23); + + paint->setPen(palette().shadow() +#ifdef QT4 +.color() +#endif + ); + paint->drawLine(0,0,0,23); + + } + + + } + else + { + if (m_position==KMultiTabBar::DockRight) + { + paint->setPen(palette().shadow() +#ifdef QT4 + .color() +#endif + ); + paint->drawLine(0,height()-1,23,height()-1); + paint->drawLine(0,height()-2,23,height()-2); + paint->drawLine(23,0,23,height()-1); + paint->drawLine(22,0,22,height()-1); + paint->fillRect(0,0,21,height()-3,QBrush(palette().light() +#ifdef QT4 + .color() +#endif + )); + paint->drawPixmap(10-pixmap.width()/2,10-pixmap.height()/2,pixmap); + + if (m_showActiveTabText) + { + if (height()<25+4) return; + + QPixmap tpixmap(height()-25-3, width()-2); + QPainter painter(&tpixmap); + + painter.fillRect(0,0,tpixmap.width(),tpixmap.height(),QBrush(palette().light() +#ifdef QT4 + .color() +#endif + )); + + painter.setPen(palette().text() +#ifdef QT4 + .color() +#endif + ); + painter.drawText(0,+width()/2+QFontMetrics(QFont()).height()/2,m_text); + + paint->rotate(90); + //kdDebug()<<"tpixmap.width:"<drawPixmap(25,-tpixmap.height()+1,tpixmap); + } + + } + else + if (m_position==KMultiTabBar::DockTop) + { + paint->fillRect(0,0,width()-1,23,QBrush(palette().light() +#ifdef QT4 + .color() +#endif + )); + paint->drawPixmap(10-pixmap.width()/2,10-pixmap.height()/2,pixmap); + if (m_showActiveTabText) + { + paint->setPen(palette().text() +#ifdef QT4 + .color() +#endif + ); + paint->drawText(25,height()/2+QFontMetrics(QFont()).height()/2,m_text); + } + } + else + if (m_position==KMultiTabBar::DockBottom) + { + paint->setPen(palette().shadow() +#ifdef QT4 + .color() +#endif + ); + paint->drawLine(0,23,width()-1,23); + paint->drawLine(0,22,width()-1,22); + paint->fillRect(0,0,width()-1,21,QBrush(palette().light() +#ifdef QT4 + .color() +#endif + )); + paint->drawPixmap(10-pixmap.width()/2,10-pixmap.height()/2,pixmap); + if (m_showActiveTabText) + { + paint->setPen(palette().text() +#ifdef QT4 + .color() +#endif + ); + paint->drawText(25,height()/2+QFontMetrics(QFont()).height()/2,m_text); + } + + } + else + { + + + paint->setPen(palette().shadow() +#ifdef QT4 + .color() +#endif + ); + paint->drawLine(0,height()-1,23,height()-1); + paint->drawLine(0,height()-2,23,height()-2); + paint->fillRect(0,0,23,height()-3,QBrush(palette().light() +#ifdef QT4 + .color() +#endif + )); + paint->drawPixmap(10-pixmap.width()/2,10-pixmap.height()/2,pixmap); + if (m_showActiveTabText) + { + + if (height()<25+4) return; + + QPixmap tpixmap(height()-25-3, width()-2); + QPainter painter(&tpixmap); + + painter.fillRect(0,0,tpixmap.width(),tpixmap.height(),QBrush(palette().light() +#ifdef QT4 + .color() +#endif + )); + + painter.setPen(palette().text() +#ifdef QT4 + .color() +#endif + ); + painter.drawText(tpixmap.width()-QFontMetrics(QFont()).width(m_text),+width()/2+QFontMetrics(QFont()).height()/2,m_text); + + paint->rotate(-90); + //kdDebug()<<"tpixmap.width:"<drawPixmap(-24-tpixmap.width(),2,tpixmap); + + } + + } + + } +} + + + + + + + +KMultiTabBar::KMultiTabBar( Qt::Orientation o, QWidget *parent):QWidget(parent) +{ +#ifndef QT4 + m_buttons.setAutoDelete(false); +#endif + if (o==Qt::Vertical) + { + m_l=new QVBoxLayout(this); + setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding +#ifndef QT4 + , true +#endif + )); +// setFixedWidth(24); + } + else + { + m_l=new QHBoxLayout(this); + setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed +#ifndef QT4 + , true +#endif + )); +// setFixedHeight(24); + } + m_l->setMargin(0); +#ifndef QT4 + m_l->setAutoAdd(false); +#endif + m_internal=new KMultiTabBarInternal(this,o); + setPosition((o==Qt::Vertical)?KMultiTabBar::DockRight:KMultiTabBar::DockBottom); + setStyle(VSNET); + // setStyle(KDEV3); + //setStyle(KONQSBC); + m_l->insertWidget(0,m_internal); + m_l->insertWidget(0,m_btnTabSep=new QFrame(this)); + m_btnTabSep->setFixedHeight(4); + m_btnTabSep->setFrameStyle(QFrame::Panel | QFrame::Sunken); + m_btnTabSep->setLineWidth(2); + m_btnTabSep->hide(); + + updateGeometry(); +} + +KMultiTabBar::~KMultiTabBar() { +} + +/*int KMultiTabBar::insertButton(QPixmap pic,int id ,const QString&) +{ + (new KToolbarButton(pic,id,m_internal))->show(); + return 0; +}*/ + +int KMultiTabBar::appendButton(const QPixmap &pic ,int id,QMenu *popup,const QString&) +{ + KMultiTabBarButton *btn; + m_buttons.append(btn= new KMultiTabBarButton(pic,QString::null, + popup,id,this,m_position,m_internal->m_style)); + m_l->insertWidget(0,btn); + btn->show(); + m_btnTabSep->show(); + return 0; +} + +void KMultiTabBar::updateSeparator() { + bool hideSep=true; +#ifdef QT4 + for (QListIterator it(m_buttons);it.hasNext();){ + if (it.next()->isVisibleTo(this)) { + hideSep=false; + break; + } + } +#else + for (QPtrListIterator it(m_buttons);it.current();++it){ + if (it.current()->isVisibleTo(this)) { + hideSep=false; + break; + } + } +#endif + if (hideSep) m_btnTabSep->hide(); + else m_btnTabSep->show(); + +} + +int KMultiTabBar::appendTab(const QPixmap &pic ,int id ,const QString& text) +{ + m_internal->appendTab(pic,id,text); + return 0; +} + +KMultiTabBarButton* KMultiTabBar::button(int id) const +{ +#ifdef QT4 + for (QListIterator it(m_buttons);it.hasNext();it.next()){ + if (it.peekNext()->id()==id) return it.peekNext(); + } +#else + for (QPtrListIterator it(m_buttons);it.current();++it){ + if (it.current()->id()==id) return it.current(); + } +#endif + return 0; +} + +KMultiTabBarTab* KMultiTabBar::tab(int id) const +{ + return m_internal->tab(id); +} + + + +void KMultiTabBar::removeButton(int id) +{ + for (csize pos=0;posid()==id) + { + m_buttons.at(pos)->deleteLater(); +#ifdef QT4 + m_buttons.removeAt(pos); +#else + m_buttons.remove(pos); +#endif + //m_buttons.take(pos)->deleteLater(); + break; + } + } + if (m_buttons.count()==0) m_btnTabSep->hide(); +} + +void KMultiTabBar::removeTab(int id) +{ + m_internal->removeTab(id); +} + +void KMultiTabBar::setTab(int id,bool state) +{ + KMultiTabBarTab *ttab=tab(id); + if (ttab) + { + ttab->setState(state); + } +} + +bool KMultiTabBar::isTabRaised(int id) const +{ + KMultiTabBarTab *ttab=tab(id); + if (ttab) + { + return ttab->isChecked(); + } + + return false; +} + + +void KMultiTabBar::showActiveTabTexts(bool show) +{ + m_internal->showActiveTabTexts(show); +} + +void KMultiTabBar::setStyle(KMultiTabBarStyle style) +{ + m_internal->setStyle(style); +} + +void KMultiTabBar::setPosition(KMultiTabBarPosition pos) +{ + m_position=pos; + m_internal->setPosition(pos); + for (csize i=0;isetPosition(pos); +} +void KMultiTabBar::fontChange(const QFont& /* oldFont */) +{ + for (csize i=0;icount();i++) + tabs()->at(i)->resize(); + repaint(); +} + +tabList * KMultiTabBar::tabs() {return m_internal->tabs();} +buttonList * KMultiTabBar::buttons() {return &m_buttons;} + diff --git a/src/widgets/knob.cpp b/src/widgets/knob.cpp new file mode 100644 index 00000000000..0fd057fa227 --- /dev/null +++ b/src/widgets/knob.cpp @@ -0,0 +1,812 @@ +/* + * knob.cpp - powerful knob-widget + * + * This file is based on the knob-widget of the Qwt Widget Library from + * Josef Wilgen + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#else + +#include +#include +#include +#include +#include +#include +#include +#include + +#define addSeparator insertSeparator + +#endif + +#ifndef __USE_XOPEN +#define __USE_XOPEN +#endif +#include + +#include "knob.h" +#include "song_editor.h" +#include "midi_device.h" +#include "embed.h" +#include "spc_bg_hndl_widget.h" +//#include "tooltip.h" +#include "config_mgr.h" +#include "text_float.h" +#include "mixer.h" + + +const int WHEEL_DELTA = 120; + + +static double MinRelStep = 1.0e-10; +static double DefaultRelStep = 1.0e-2; +static double MinEps = 1.0e-10; + + +float knob::s_copiedValue = 0.0f; +textFloat * knob::s_textFloat = NULL; + + + +knob::knob( int _knob_num, QWidget * _parent, const QString & _name ) : + QWidget( _parent +#ifndef QT4 + , _name.ascii() +#endif + ), + m_scrollMode( ScrNone ), + m_mouseOffset( 0.0f ), + m_tracking( TRUE ), + m_angle( 0.0f ), + m_oldAngle( 0.0f ), + m_nTurns( 0.0f ), + m_knobNum( _knob_num ), + m_hintTextBeforeValue( "" ), + m_hintTextAfterValue( "" ), + m_label( "" ), + m_minValue( 0.0f ), + m_maxValue( 100.0f ), + m_value( 0.0f ), + m_exactValue( 0.0f ), + m_exactPrevValue( 0.0f ), + m_prevValue( 0.0f ), + m_initValue( 0.0f ) +{ + if( s_textFloat == NULL ) + { + s_textFloat = new textFloat( this ); + } + +#ifdef QT4 + setAccessibleName( _name ); +#endif + setRange( 0.0, 100.0, 1.0 ); + +#ifdef QT4 + m_knobPixmap = new QPixmap( embed::getIconPixmap( QString( "knob0" + + QString::number( m_knobNum + 1 ) ).toAscii().constData() ) ); +#else + m_knobPixmap = new QPixmap( embed::getIconPixmap( "knob0" + + QString::number( m_knobNum + 1 ) ) ); +#endif +#ifdef QT4 +// setAttribute( Qt::WA_NoBackground ); +#else + setBackgroundMode( Qt::NoBackground ); +#endif + + m_knobWidth = m_knobPixmap->width(); + + setFixedSize( m_knobPixmap->width(), m_knobPixmap->height() ); + setTotalAngle( 270.0f ); + recalcAngle(); + +} + + + + +// Destructor +knob::~knob() +{ + // make sure pointer to this knob isn't used anymore in active + // midi-device-class + if( mixer::inst()->getMIDIDevice()->pitchBendKnob() == this ) + { + mixer::inst()->getMIDIDevice()->setPitchBendKnob( NULL ); + } +} + + + + +void knob::setHintText( const QString & _txt_before, + const QString & _txt_after ) +{ + m_hintTextBeforeValue = _txt_before; + m_hintTextAfterValue = _txt_after; +/* toolTip::add( this, m_hintTextBeforeValue + QString::number( value() ) + + m_hintTextAfterValue );*/ +} + + + + +void knob::setLabel( const QString & _txt ) +{ + m_label = _txt; + setFixedSize( tMax( m_knobPixmap->width(), + QFontMetrics( pointSize<6>( font() + ) ).width( m_label ) ), + m_knobPixmap->height() + 10 ); + update(); +} + + + + +void knob::setTotalAngle( float _angle ) +{ + if( _angle < 10.0 ) + { + m_totalAngle = 10.0; + } + else + { + m_totalAngle = _angle; + } + + layoutKnob(); +} + + + + +void knob::drawKnob( QPainter * _p ) +{ + _p->drawPixmap( 0, 0, specialBgHandlingWidget::getBackground( this ) ); + + const float radius = m_knobPixmap->width() / 2 - 1; + const float xm = m_knobPixmap->width() / 2;//radius + 1; + const float ym = m_knobPixmap->height() / 2;//radius+1; + + const float rarc = m_angle * M_PI / 180.0; + const float ca = cos( rarc ); + const float sa = -sin( rarc ); + + _p->drawPixmap( static_cast( xm - m_knobPixmap->width() / 2 ), 0, + *m_knobPixmap ); + + _p->setPen( QPen( QColor( 200, 0, 0 ), 2 ) ); + + switch( m_knobNum ) + { + case knobSmall_17: + { + _p->drawLine( (int)( xm-sa ), (int)( ym-ca ), + (int)( xm - sa*radius ), + (int)( ym - ca*radius ) ); + break; + } + case knobBright_26: + { + _p->drawLine( (int)( xm-sa ), (int)( ym-ca ), + (int)( xm - sa*( radius-5 ) ), + (int)( ym - ca*( radius-5 ) ) ); + break; + } + case knobDark_28: + { + const float rb = tMax( ( radius - 10 ) / 3.0, + 0.0 ); + const float re = tMax( ( radius - 4 ), 0.0 ); + _p->drawLine( (int)( xm-sa*rb ) + 1, + (int)( ym - ca*rb ) + 1, + (int)( xm - sa*re ) + 1, + (int)( ym - ca*re ) + 1 ); + break; + } + } +} + + + + +void knob::valueChange( void ) +{ + recalcAngle(); + update(); +/* toolTip::add( this, m_hintTextBeforeValue + QString::number( value() ) + + m_hintTextAfterValue );*/ + if( m_tracking ) + { + emit valueChanged( value() ); + } +} + + + + +float knob::getValue( const QPoint & _p ) +{ + if( configManager::inst()->value( "knobs", "classicalusability" + ).toInt() ) + { + const float dx = float( ( rect().x() + rect().width() / 2 ) - + _p.x() ); + const float dy = float( ( rect().y() + rect().height() / 2 ) - + _p.y() ); + + const float arc = atan2( -dx, dy ) * 180.0 / M_PI; + + float new_value = 0.5 * ( m_minValue + m_maxValue ) + + ( arc + m_nTurns * 360.0 ) * + ( m_maxValue - m_minValue ) / + m_totalAngle; + + const float oneTurn = tAbs( m_maxValue - m_minValue ) * + 360.0 / m_totalAngle; + const float eqValue = value() + m_mouseOffset; + + if( tAbs( new_value - eqValue ) > 0.5 * oneTurn ) + { + if( new_value < eqValue ) + { + new_value += oneTurn; + } + else + { + new_value -= oneTurn; + } + } + return( new_value ); + } + return( ( _p.y() - m_origMousePos.y() ) * m_step ); +} + + + + +void knob::getScrollMode( const QPoint &, int & _scroll_mode, int & _direction ) +{ + _scroll_mode = ScrMouse; + _direction = 0; +} + + + + +void knob::rangeChange() +{ + layoutKnob(); + recalcAngle(); +} + + + + +void knob::resizeEvent( QResizeEvent * ) +{ + layoutKnob( FALSE ); +} + + + + +// Recalculate the slider's geometry and layout based on +// the current rect and fonts. +void knob::layoutKnob( bool _update_geometry ) +{ + if( _update_geometry ) + { + updateGeometry(); + update(); + } +} + + + + +void knob::paintEvent( QPaintEvent * _me ) +{ + // Use double-buffering + QRect ur = _me->rect(); +#ifndef QT4 + if( ur.isValid() ) + { +#endif +#ifdef QT4 + QPainter p( this ); +#else + QPixmap pix( ur.size() ); + pix.fill( this, ur.topLeft() ); + QPainter p( &pix, this ); +#endif + p.translate( -ur.x(), -ur.y() ); + drawKnob( &p ); + if( m_label != "" ) + { + p.setFont( pointSize<6>( p.font() ) ); + p.setPen( QColor( 255, 255, 255 ) ); + p.drawText( width() / 2 - + QFontMetrics( p.font() ).width( m_label ) / 2, + height() - 2, m_label ); + } +#ifndef QT4 + p.end(); + bitBlt( this, ur.topLeft(), &pix ); + } +#endif + +} + + + +void knob::recalcAngle( void ) +{ + m_oldAngle = m_angle; + + // + // calculate the angle corresponding to the value + // + if( m_maxValue == m_minValue ) + { + m_angle = 0; + m_nTurns = 0; + } + else + { + m_angle = ( value() - 0.5 * ( m_minValue + m_maxValue ) ) / + ( m_maxValue - m_minValue ) * m_totalAngle; + m_nTurns = floor( ( m_angle + 180.0 ) / 360.0 ); + m_angle = m_angle - m_nTurns * 360.0; + } +} + + + + +//! Mouse press event handler +void knob::mousePressEvent( QMouseEvent * _me ) +{ + const QPoint & p = _me->pos(); + m_origMousePos = p; + + getScrollMode( p, m_scrollMode, m_direction ); + + switch( m_scrollMode ) + { + case ScrMouse: + m_mouseOffset = getValue( p ) - value(); + emit sliderPressed(); + break; + + default: + m_mouseOffset = 0; + m_direction = 0; + break; + } + + if( _me->button() == Qt::LeftButton ) + { + if( !configManager::inst()->value( "knobs", "classicalusability" + ).toInt() ) + { + QApplication::setOverrideCursor( Qt::BlankCursor ); + } + s_textFloat->reparent( this ); + s_textFloat->setText( m_hintTextBeforeValue + + QString::number( value() ) + + m_hintTextAfterValue ); + s_textFloat->move( mapTo( topLevelWidget(), QPoint( 0, 0 ) ) + + QPoint( m_knobPixmap->width() + 2, 0 ) ); + s_textFloat->show(); + } +} + + + + +//! Emits a valueChanged() signal if necessary +void knob::buttonReleased( void ) +{ + if( ( !m_tracking ) || ( value() != m_prevValue ) ) + { + emit valueChanged( value() ); + } +} + + + + +//! Mouse Release Event handler +void knob::mouseReleaseEvent( QMouseEvent * _me ) +{ + m_scrollMode = ScrNone; + buttonReleased(); + + switch( m_scrollMode ) + { + case ScrMouse: + setPosition( _me->pos() ); + m_direction = 0; + m_mouseOffset = 0; + emit sliderReleased (); + break; + + case ScrDirect: + setPosition( _me->pos() ); + m_direction = 0; + m_mouseOffset = 0; + break; + + default: + break; + } + + if( !configManager::inst()->value( "knobs", "classicalusability" + ).toInt() ) + { + QApplication::restoreOverrideCursor(); + } + + s_textFloat->hide(); +} + + + + +void knob::setPosition( const QPoint & _p ) +{ + if( configManager::inst()->value( "knobs", "classicalusability" + ).toInt() ) + { + setNewValue( getValue( _p ) - m_mouseOffset, 1 ); + } + else + { + setNewValue( m_value - getValue( _p ), 1 ); + } +} + + + + +void knob::setTracking( bool _enable ) +{ + m_tracking = _enable; +} + + + + +//! Mouse Move Event handler +void knob::mouseMoveEvent( QMouseEvent * _me ) +{ + if( m_scrollMode == ScrMouse ) + { + setPosition( _me->pos() ); + if( value() != m_prevValue ) + { + emit sliderMoved( value() ); + } + if( !configManager::inst()->value( "knobs", "classicalusability" + ).toInt() ) + { + QCursor::setPos( mapToGlobal( m_origMousePos ) ); + } + } + songEditor::inst()->setModified(); + + s_textFloat->setText( m_hintTextBeforeValue + + QString::number( value() ) + + m_hintTextAfterValue ); + +} + + + +//! Qt wheel event +void knob::wheelEvent( QWheelEvent * _me ) +{ + _me->accept(); + const int inc = _me->delta() / WHEEL_DELTA; + incPages( inc ); + + songEditor::inst()->setModified(); + + s_textFloat->reparent( this ); + s_textFloat->setText( m_hintTextBeforeValue + + QString::number( value() ) + + m_hintTextAfterValue ); + s_textFloat->move( mapTo( topLevelWidget(), QPoint( 0, 0 ) ) + + QPoint( m_knobPixmap->width() + 2, 0 ) ); + s_textFloat->setVisibilityTimeOut( 1000 ); + +/* toolTip::add( this, m_hintTextBeforeValue+QString::number( value() ) + + m_hintTextAfterValue );*/ + + if( value() != m_prevValue ) + { + emit sliderMoved( value() ); + } +} + + + + +void knob::setValue( float _val, bool _is_init_value ) +{ + if( _is_init_value ) + { + m_initValue = _val; + } + + setNewValue( _val, 0 ); +} + + + + +void knob::fitValue( float _val ) +{ + setNewValue( _val, 1 ); +} + + + + +void knob::incValue( int _steps ) +{ + setNewValue( m_value + float( _steps ) * m_step, 1 ); +} + + + + +void knob::setRange( float _vmin, float _vmax, float _vstep, int _page_size ) +{ + int rchg = ( ( m_maxValue != _vmax ) || ( m_minValue != _vmin ) ); + + if( rchg ) + { + m_minValue = _vmin; + m_maxValue = _vmax; + } + + // + // look if the step width has an acceptable + // value or otherwise change it. + // + setStep( _vstep ); + + // + // limit page size + // +/* m_pageSize = tLimit( pageSize, 0, int( tAbs( ( m_maxValue - + m_minValue ) / m_step ) ) ); */ + m_pageSize = tMax( ( m_maxValue - m_minValue ) / 40.0f, _vstep ); + + // + // If the value lies out of the range, it + // will be changed. Note that it will not be adjusted to + // the new step width. + setNewValue( m_value, 0 ); + + // call notifier after the step width has been + // adjusted. + if( rchg ) + { + rangeChange(); + } +} + + + + +void knob::setNewValue( float _x, int _align ) +{ + m_prevValue = m_value; + + m_value = tLimit( _x, m_minValue, m_maxValue ); + + m_exactPrevValue = m_exactValue; + m_exactValue = m_value; + + // align to grid + if( _align ) + { + if( m_step != 0.0 ) + { + m_value = floorf( m_value / m_step ) * m_step; + } + else + { + m_value = m_minValue; + } + + // correct rounding error at the border + if( tAbs( m_value - m_maxValue ) < MinEps * + tAbs( m_step ) ) + { + m_value = m_maxValue; + } + + // correct rounding error if value = 0 + if( tAbs( m_value ) < MinEps * tAbs( m_step ) ) + { + m_value = 0.0; + } + } + + if( m_prevValue != m_value ) + { + valueChange(); + } +} + + + + +void knob::setStep( float _vstep ) +{ + float intv = m_maxValue - m_minValue; + + float newStep; + + if( _vstep == 0.0 ) + { + newStep = intv * DefaultRelStep; + } + else + { + if( ( intv > 0 ) && ( _vstep < 0 ) || ( intv < 0 ) && + ( _vstep > 0 ) ) + { + newStep = -_vstep; + } + else + { + newStep = _vstep; + } + if( tAbs( newStep ) < + tAbs( MinRelStep * intv ) ) + { + newStep = MinRelStep * intv; + } + } + if( newStep != m_step ) + { + m_step = newStep; + } +} + + + + +void knob::contextMenuEvent( QContextMenuEvent * ) +{ + QMenu contextMenu( this ); +#ifdef QT4 + contextMenu.setTitle( accessibleName() ); +#else + QLabel * caption = new QLabel( "" + + QString( accessibleName() ) + "", this ); + caption->setPaletteBackgroundColor( QColor( 0, 0, 192 ) ); + caption->setAlignment( Qt::AlignCenter ); + contextMenu.addAction( caption ); +#endif + contextMenu.addAction( embed::getIconPixmap( "reload" ), + tr( "&Reset (%1%2)" ).arg( m_initValue ).arg( + m_hintTextAfterValue ), + this, SLOT( reset() ) ); + contextMenu.addSeparator(); + contextMenu.addAction( embed::getIconPixmap( "edit_copy" ), + tr( "&Copy value (%1%2)" ).arg( value() ).arg( + m_hintTextAfterValue ), + this, SLOT( copyValue() ) ); + contextMenu.addAction( embed::getIconPixmap( "edit_paste" ), + tr( "&Paste value (%1%2)" + ).arg( s_copiedValue ).arg( + m_hintTextAfterValue ), + this, SLOT( pasteValue() ) ); + contextMenu.addSeparator(); + contextMenu.addAction( tr( "Connect to MIDI-device" ), this, + SLOT( connectToMidiDevice() ) ); + contextMenu.addSeparator(); + contextMenu.addAction( embed::getIconPixmap( "help" ), tr( "&Help" ), + this, SLOT( displayHelp() ) ); + contextMenu.exec( QCursor::pos() ); +} + + + + +void knob::reset( void ) +{ + setValue( m_initValue ); +} + + + + +void knob::copyValue( void ) +{ + s_copiedValue = value(); +} + + + + +void knob::pasteValue( void ) +{ + setValue( s_copiedValue ); +} + + + + +void knob::connectToMidiDevice( void ) +{ + mixer::inst()->getMIDIDevice()->setPitchBendKnob( this ); +} + + + + +void knob::displayHelp( void ) +{ +#ifdef QT4 + QWhatsThis::showText( mapToGlobal( rect().bottomRight() ), + whatsThis() ); +#else + QWhatsThis::display( QWhatsThis::textFor( this ), mapToGlobal( + rect().bottomRight() ) ); +#endif +} + + + + +#include "knob.moc" + + +#ifndef QT4 +#undef addSeparator +#endif diff --git a/src/widgets/lcd_spinbox.cpp b/src/widgets/lcd_spinbox.cpp new file mode 100644 index 00000000000..61ba76704c3 --- /dev/null +++ b/src/widgets/lcd_spinbox.cpp @@ -0,0 +1,176 @@ +/* + * lcd_spinbox.cpp - class lcdSpinBox, an improved QLCDNumber + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include +#include + +#else + +#include +#include +#include + +#endif + + +#include "lcd_spinbox.h" +#include "templates.h" + + + +lcdSpinBox::lcdSpinBox( int _min, int _max, int _num_digits, + QWidget * _parent ) : + QWidget( _parent ), + m_minValue( _min ), + m_maxValue( _max ), + m_step( 1 ), + m_label( NULL ), + m_origMousePos() +{ + m_number = new QLCDNumber( _num_digits, this ); + m_number->setFrameShape( QFrame::Panel ); + m_number->setFrameShadow( QFrame::Sunken ); + m_number->setSegmentStyle( QLCDNumber::Flat ); +#ifdef QT4 + QPalette pal = m_number->palette(); + pal.setColor( QPalette::Background, QColor( 32, 32, 32 ) ); + pal.setColor( QPalette::Foreground, QColor( 255, 180, 0 ) ); + m_number->setPalette( pal ); +#else + m_number->setPaletteBackgroundColor( QColor( 32, 32, 32 ) ); + m_number->setPaletteForegroundColor( QColor( 255, 180, 0 ) ); +#endif + // value is automatically limited to given range + setValue( 0 ); + + m_number->setFixedSize( m_number->sizeHint() * 0.9 ); + setFixedSize( m_number->size() ); +} + + + + +lcdSpinBox::~lcdSpinBox() +{ +} + + + +void lcdSpinBox::setStep( int _step ) +{ + m_step = tMax( _step, 1 ); +} + + + + +void lcdSpinBox::setValue( int _value ) +{ + _value = ( ( tLimit( _value, m_minValue, m_maxValue ) - m_minValue ) / + m_step ) * m_step + m_minValue; + QString s = QString::number( _value ); + while( (int) s.length() < m_number->numDigits() ) + { + s = "0" + s; + } + + m_number->display( s ); +} + + + + +void lcdSpinBox::setLabel( const QString & _txt ) +{ + if( m_label == NULL ) + { + m_label = new QLabel( _txt, this ); + m_label->setFont( pointSize<6>( m_label->font() ) ); + m_label->setGeometry( 0, y() + height(), + QFontMetrics( m_label->font() ).width( _txt ), 7 ); + setFixedSize( tMax( width(), m_label->width() ), + height() + m_label->height() ); + } + else + { + m_label->setText( _txt ); + } +} + + + + +void lcdSpinBox::mousePressEvent( QMouseEvent * _me ) +{ + if( _me->button() == Qt::LeftButton && _me->y() < m_number->height() ) + { + m_origMousePos = _me->globalPos(); + QApplication::setOverrideCursor( Qt::BlankCursor ); + } +} + + + +void lcdSpinBox::mouseMoveEvent( QMouseEvent * _me ) +{ + if( _me->modifiers() == Qt::LeftButton ) + { + int dy = _me->globalY() - m_origMousePos.y(); + if( dy > 1 || dy < -1 ) + { + setValue( value() - dy / 2 * m_step ); + emit valueChanged( value() ); + QCursor::setPos( m_origMousePos ); + } + } +} + + + + +void lcdSpinBox::mouseReleaseEvent( QMouseEvent * _me ) +{ + QCursor::setPos( m_origMousePos ); + QApplication::restoreOverrideCursor(); +} + + + + +void lcdSpinBox::wheelEvent( QWheelEvent * _we ) +{ + setValue( value() + _we->delta() / 120 * m_step ); +} + + + + +#include "lcd_spinbox.moc" + diff --git a/src/widgets/led_checkbox.cpp b/src/widgets/led_checkbox.cpp new file mode 100644 index 00000000000..117eb2ed9c5 --- /dev/null +++ b/src/widgets/led_checkbox.cpp @@ -0,0 +1,130 @@ +/* + * led_checkbox.cpp - class ledCheckBox, an improved QCheckBox + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include + +#define setChecked setOn +#define isChecked isOn + +#endif + + +#include "led_checkbox.h" +#include "embed.h" +#include "templates.h" +#include "spc_bg_hndl_widget.h" + + +static const QString names[ledCheckBox::TOTAL_COLORS] = +{ + "led_yellow", "led_green" +} ; + + + +ledCheckBox::ledCheckBox( const QString & _text, QWidget * _parent, + ledColors _color ) : + QCheckBox( _text, _parent ) +{ + if( _color >= TOTAL_COLORS || _color < YELLOW ) + { + _color = YELLOW; + } + m_ledOnPixmap = new QPixmap( embed::getIconPixmap( names[_color] +#ifdef QT4 + .toAscii().constData() +#endif + ) ); + m_ledOffPixmap = new QPixmap( embed::getIconPixmap( "led_off" ) ); + +#ifndef QT4 + setBackgroundMode( Qt::NoBackground ); +#endif + + setFont( pointSize<7>( font() ) ); + setFixedSize( m_ledOffPixmap->width() + 6 + + QFontMetrics( font() ).width( text() ), + m_ledOffPixmap->height() ); +} + + + + +ledCheckBox::~ledCheckBox() +{ + delete m_ledOnPixmap; + delete m_ledOffPixmap; +} + + + + +void ledCheckBox::paintEvent( QPaintEvent * ) +{ +#ifdef QT4 + QPainter p( this ); +#else + QPixmap draw_pm( rect().size() ); + draw_pm.fill( this, rect().topLeft() ); + + QPainter p( &draw_pm, this ); +#endif + p.drawPixmap( 0, 0, specialBgHandlingWidget::getBackground( this ) ); + +#ifdef QT4 + if( checkState() == Qt::Checked ) +#else + if( state() == On ) +#endif + { + p.drawPixmap( 0, 0, *m_ledOnPixmap ); + } + else + { + p.drawPixmap( 0, 0, *m_ledOffPixmap ); + } + + p.drawText( m_ledOffPixmap->width() + 2, 10, text() ); + +#ifndef QT4 + // and blit all the drawn stuff on the screen... + bitBlt( this, rect().topLeft(), &draw_pm ); +#endif +} + + +#undef setChecked +#undef isChecked + diff --git a/src/widgets/nstate_button.cpp b/src/widgets/nstate_button.cpp new file mode 100644 index 00000000000..2586214554f --- /dev/null +++ b/src/widgets/nstate_button.cpp @@ -0,0 +1,143 @@ +/* + * nstate_button.cpp - implementation of n-state-button + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include + +#endif + + +#include "nstate_button.h" +#include "embed.h" +#include "tooltip.h" + + + +nStateButton::nStateButton( QWidget * _parent ) : + QWidget( _parent ), + m_generalToolTip( "" ), + m_curState( -1 ) +{ +#ifndef QT4 + setBackgroundMode( Qt::NoBackground ); +#endif +} + + + + +nStateButton::~nStateButton() +{ + while( m_states.size() ) + { + delete m_states.first().first; + m_states.erase( m_states.begin() ); + } +} + + + + +void nStateButton::addState( const QPixmap & _pm, const QString & _tooltip ) +{ + m_states.push_back( qMakePair( new QPixmap( _pm ), _tooltip ) ); + // first inserted pixmap? + if( m_states.size() == 1 ) + { + // then resize ourself + resize( _pm.width(), _pm.height() ); + // and set state to first pixmap + changeState( 0 ); + } +} + + + + +void nStateButton::changeState( int _n ) +{ + if( _n >= 0 && _n < (int) m_states.size() ) + { + m_curState = _n; + + const QString & _tooltip = + ( m_states[m_curState].second != "" ) ? + m_states[m_curState].second : + m_generalToolTip; + toolTip::add( this, _tooltip ); + + emit stateChanged( m_curState ); + + update(); + } +} + + + + +void nStateButton::paintEvent( QPaintEvent * ) +{ +#ifdef QT4 + QPainter p( this ); +#else + QPixmap draw_pm( rect().size() ); + draw_pm.fill( this, rect().topLeft() ); + + QPainter p( &draw_pm, this ); +#endif + + if( m_curState >= 0 && m_curState < (int) m_states.size() ) + { + p.drawPixmap( 0, 0, *m_states[m_curState].first ); + } +#ifndef QT4 + // and blit all the drawn stuff on the screen... + bitBlt( this, rect().topLeft(), &draw_pm ); +#endif +} + + + + +void nStateButton::mousePressEvent( QMouseEvent * _me ) +{ + if( _me->button() == Qt::LeftButton && m_states.size() ) + { + changeState( ( ++m_curState ) % m_states.size() ); + } +} + + + + +#include "nstate_button.moc" + diff --git a/src/widgets/pixmap_button.cpp b/src/widgets/pixmap_button.cpp new file mode 100644 index 00000000000..f2a6e9abcba --- /dev/null +++ b/src/widgets/pixmap_button.cpp @@ -0,0 +1,175 @@ +/* + * pixmap_button.cpp - implementation of pixmap-button (often used as "themed" + * checkboxes/radiobuttons etc) + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#else + +#include + +#endif + + +#include "pixmap_button.h" +#include "embed.h" + + + +pixmapButton::pixmapButton( QWidget * _parent ) : + QPushButton( _parent ), + m_activePixmap( NULL ), + m_inactivePixmap( NULL ), + m_bgPixmap( NULL ) +{ + setActiveGraphic( embed::getIconPixmap( "led_yellow" ) ); + setInactiveGraphic( embed::getIconPixmap( "led_off" ), FALSE ); + +#ifndef QT4 + setBackgroundMode( Qt::NoBackground ); +#endif + + setCheckable( TRUE ); +} + + + + +pixmapButton::~pixmapButton() +{ + delete m_activePixmap; + delete m_inactivePixmap; + delete m_bgPixmap; +} + + + + +void pixmapButton::paintEvent( QPaintEvent * ) +{ +#ifdef QT4 + QPainter p( this ); +#else + QPixmap draw_pm( rect().size() ); + draw_pm.fill( this, rect().topLeft() ); + + QPainter p( &draw_pm, this ); +#endif + + if( m_bgPixmap != NULL ) + { + p.drawPixmap( 0, 0, *m_bgPixmap ); + } + +#ifdef QT4 + if( isChecked() ) +#else + if( isOn() ) +#endif + { + if( m_activePixmap != NULL ) + { + p.drawPixmap( 0, 0, *m_activePixmap ); + } + } + else + { + if( m_inactivePixmap != NULL ) + { + p.drawPixmap( 0, 0, *m_inactivePixmap ); + } + } +#ifndef QT4 + // and blit all the drawn stuff on the screen... + bitBlt( this, rect().topLeft(), &draw_pm ); +#endif +} + + + + + +void pixmapButton::mousePressEvent( QMouseEvent * _me) +{ + if( _me->button() == Qt::RightButton ) + { + emit( clickedRight() ); + } + else + { + QPushButton::mousePressEvent( _me ); + } +} + + + + +void pixmapButton::mouseDoubleClickEvent( QMouseEvent * ) +{ + emit doubleClicked(); +} + + + + +void pixmapButton::setActiveGraphic( const QPixmap & _pm ) +{ + delete m_activePixmap; + + m_activePixmap = new QPixmap( _pm ); + resize( m_activePixmap->width(), m_activePixmap->height() ); +} + + + + +void pixmapButton::setInactiveGraphic( const QPixmap & _pm, bool _update ) +{ + delete m_inactivePixmap; + + m_inactivePixmap = new QPixmap( _pm ); + if( _update ) + { + update(); + } +} + + + + +void pixmapButton::setBgGraphic( const QPixmap & _pm ) +{ + delete m_bgPixmap; + + m_bgPixmap = new QPixmap( _pm ); +} + + + +#include "pixmap_button.moc" + diff --git a/src/widgets/project_notes.cpp b/src/widgets/project_notes.cpp new file mode 100644 index 00000000000..6f85e875910 --- /dev/null +++ b/src/widgets/project_notes.cpp @@ -0,0 +1,571 @@ +/* + * project_notes.h - header for project-notes-editor + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define isChecked isOn +#define setChecked setOn +#define setFontWeight setBold +#define setFontUnderline setUnderline +#define setFontItalic setItalic +#define setFontFamily setFamily +#define setFontPointSize setPointSize +#define setTextColor setColor +#define textColor color +#define setHtml setText +#define toHtml text + +#endif + + +#include "project_notes.h" +#include "embed.h" +#include "lmms_main_win.h" +#include "song_editor.h" + + + +projectNotes::projectNotes() : + QMainWindow( lmmsMainWin::inst()->workspace() +#ifndef QT4 + , 0, Qt::WStyle_Title +#endif + ) +{ +#ifdef QT4 + lmmsMainWin::inst()->workspace()->addWindow( this ); +#endif + + m_edit = new QTextEdit( this ); +#ifdef QT4 + QPalette pal; + pal.setColor( m_edit->backgroundRole(), QColor( 64, 64, 64 ) ); + m_edit->setPalette( pal ); +#else + m_edit->setTextFormat( RichText ); + m_edit->setPaletteBackgroundColor( QColor( 64, 64, 64 ) ); +#endif + clear(); + + connect( m_edit, SIGNAL( currentFontChanged( const QFont & ) ), + this, SLOT( fontChanged( const QFont & ) ) ); + connect( m_edit, SIGNAL( currentColorChanged( const QColor & ) ), + this, SLOT( colorChanged( const QColor & ) ) ); + connect( m_edit, SIGNAL( currentAlignmentChanged( int ) ), + this, SLOT( alignmentChanged( int ) ) ); + connect( m_edit, SIGNAL( textChanged() ), + songEditor::inst(), SLOT( setModified() ) ); + + setupActions(); + + setCentralWidget( m_edit ); + setWindowTitle( tr( "Project notes" ) ); + setWindowIcon( embed::getIconPixmap( "project_notes" ) ); +} + + + + +void projectNotes::clear( void ) +{ + m_edit->setHtml( tr( "Put down your project notes here." ) ); +} + + + + +void projectNotes::setupActions() +{ + QToolBar * tb = new QToolBar( tr( "Edit Actions" ), this ); + QAction * a; + + // changes between qt3's toolbar-system and this of qt4 are too + // big, so we completely implement two versions +#ifdef QT4 + a = new QAction( embed::getIconPixmap( "edit_undo" ), tr( "&Undo" ), + tb ); + a->setShortcut( tr( "Ctrl+Z" ) ); + connect( a, SIGNAL( activated() ), m_edit, SLOT( undo() ) ); + + a = new QAction( embed::getIconPixmap( "edit_redo" ), tr( "&Redo" ), + tb ); + a->setShortcut( tr( "Ctrl+Y" ) ); + connect( a, SIGNAL( activated() ), m_edit, SLOT( redo() ) ); + + a = new QAction( embed::getIconPixmap( "edit_copy" ), tr( "&Copy" ), + tb ); + a->setShortcut( tr( "Ctrl+C" ) ); + connect( a, SIGNAL( activated() ), m_edit, SLOT( copy() ) ); + + a = new QAction( embed::getIconPixmap( "edit_cut" ), tr( "Cu&t" ), + tb ); + a->setShortcut( tr( "Ctrl+X" ) ); + connect( a, SIGNAL( activated() ), m_edit, SLOT( cut() ) ); + + a = new QAction( embed::getIconPixmap( "edit_paste" ), tr( "&Paste" ), + tb ); + a->setShortcut( tr( "Ctrl+V" ) ); + connect( a, SIGNAL( activated() ), m_edit, SLOT( paste() ) ); + + + tb = new QToolBar( tr( "Format Actions" ), this ); + + m_comboFont = new QComboBox( tb ); + m_comboFont->setEditable( TRUE ); + QFontDatabase db; + m_comboFont->addItems( db.families() ); + connect( m_comboFont, SIGNAL( activated( const QString & ) ), + m_edit, SLOT( setFontFamily( const QString & ) ) ); + m_comboFont->lineEdit()->setText( QApplication::font().family() ); + + m_comboSize = new QComboBox( tb ); + m_comboSize->setEditable( TRUE ); + vlist sizes = db.standardSizes(); + vlist::Iterator it = sizes.begin(); + for ( ; it != sizes.end(); ++it ) + { + m_comboSize->addItem( QString::number( *it ) ); + } + connect( m_comboSize, SIGNAL( activated( const QString & ) ), + this, SLOT( textSize( const QString & ) ) ); + m_comboSize->lineEdit()->setText( QString::number( + QApplication::font().pointSize() ) ); + + m_actionTextBold = new QAction( embed::getIconPixmap( "text_bold" ), + tr( "&Bold" ), tb ); + m_actionTextBold->setShortcut( tr( "Ctrl+B" ) ); + connect( m_actionTextBold, SIGNAL( activated() ), this, + SLOT( textBold() ) ); + + m_actionTextItalic = new QAction( embed::getIconPixmap( "text_italic" ), + tr( "&Italic" ), tb ); + m_actionTextItalic->setShortcut( tr( "Ctrl+I" ) ); + connect( m_actionTextItalic, SIGNAL( activated() ), this, + SLOT( textItalic() ) ); + + m_actionTextUnderline = new QAction( embed::getIconPixmap( + "text_under" ), + tr( "&Underline" ), tb ); + m_actionTextUnderline->setShortcut( tr( "Ctrl+U" ) ); + connect( m_actionTextUnderline, SIGNAL( activated() ), this, + SLOT( textUnderline() ) ); + + + QActionGroup * grp = new QActionGroup( tb ); + connect( grp, SIGNAL( selected( QAction* ) ), this, + SLOT( textAlign( QAction* ) ) ); + + m_actionAlignLeft = new QAction( embed::getIconPixmap( "text_left" ), + tr( "&Left" ), grp ); + m_actionAlignLeft->setShortcut( tr( "Ctrl+L" ) ); + + m_actionAlignCenter = new QAction( embed::getIconPixmap( + "text_center" ), + tr( "C&enter" ), grp ); + m_actionAlignCenter->setShortcut( tr( "Ctrl+E" ) ); + + m_actionAlignRight = new QAction( embed::getIconPixmap( "text_right" ), + tr( "&Right" ), grp ); + m_actionAlignRight->setShortcut( tr( "Ctrl+R" ) ); + + m_actionAlignJustify = new QAction( embed::getIconPixmap( + "text_block" ), + tr( "&Justify" ), grp ); + m_actionAlignJustify->setShortcut( tr( "Ctrl+J" ) ); + + + QPixmap pix( 16, 16 ); + pix.fill( Qt::black ); + m_actionTextColor = new QAction( pix, tr( "&Color..." ), tb ); + connect( m_actionTextColor, SIGNAL( activated() ), this, + SLOT( textColor() ) ); + +#else +#if QT_VERSION >= 0x030100 + a = new QAction( +#if QT_VERSION < 0x030200 + "", +#endif + embed::getIconPixmap( "edit_undo" ), tr( "&Undo" ), + CTRL + Key_Z, this ); + connect( a, SIGNAL( activated() ), m_edit, SLOT( undo() ) ); + a->addTo( tb ); + + a = new QAction( +#if QT_VERSION < 0x030200 + "", +#endif + embed::getIconPixmap( "edit_redo" ), tr( "&Redo" ), + CTRL + Key_Y, this ); + connect( a, SIGNAL( activated() ), m_edit, SLOT( redo() ) ); + a->addTo( tb ); + + a = new QAction( +#if QT_VERSION < 0x030200 + "", +#endif + embed::getIconPixmap( "edit_copy" ), tr( "&Copy" ), + CTRL + Key_C, this ); + connect( a, SIGNAL( activated() ), m_edit, SLOT( copy() ) ); + a->addTo( tb ); + + a = new QAction( +#if QT_VERSION < 0x030200 + "", +#endif + embed::getIconPixmap( "edit_cut" ), tr( "Cu&t" ), + CTRL + Key_X, this ); + connect( a, SIGNAL( activated() ), m_edit, SLOT( cut() ) ); + a->addTo( tb ); + + a = new QAction( +#if QT_VERSION < 0x030200 + "", +#endif + embed::getIconPixmap( "edit_paste" ), tr( "&Paste" ), + CTRL + Key_V, this ); + connect( a, SIGNAL( activated() ), m_edit, SLOT( paste() ) ); + a->addTo( tb ); + + + tb = new QToolBar( this ); + tb->setLabel( tr( "Format Actions" ) ); + + m_comboFont = new QComboBox( TRUE, tb ); + QFontDatabase db; + m_comboFont->insertStringList( db.families() ); + connect( m_comboFont, SIGNAL( activated( const QString & ) ), + m_edit, SLOT( setFamily( const QString & ) ) ); + m_comboFont->lineEdit()->setText( QApplication::font().family() ); + + m_comboSize = new QComboBox( TRUE, tb ); + vlist sizes = db.standardSizes(); + vlist::Iterator it = sizes.begin(); + for ( ; it != sizes.end(); ++it ) + { + m_comboSize->insertItem( QString::number( *it ) ); + } + connect( m_comboSize, SIGNAL( activated( const QString & ) ), + this, SLOT( textSize( const QString & ) ) ); + m_comboSize->lineEdit()->setText( QString::number( + QApplication::font().pointSize() ) ); + + m_actionTextBold = new QAction( +#if QT_VERSION < 0x030200 + "", +#endif + embed::getIconPixmap( "text_bold" ), + tr( "&Bold" ), CTRL + Key_B, this ); + connect( m_actionTextBold, SIGNAL( activated() ), this, + SLOT( textBold() ) ); + m_actionTextBold->addTo( tb ); + m_actionTextBold->setToggleAction( TRUE ); + + m_actionTextItalic = new QAction( +#if QT_VERSION < 0x030200 + "", +#endif + embed::getIconPixmap( "text_italic" ), + tr( "&Italic" ), CTRL + Key_I, this ); + connect( m_actionTextItalic, SIGNAL( activated() ), this, + SLOT( textItalic() ) ); + m_actionTextItalic->addTo( tb ); + m_actionTextItalic->setToggleAction( TRUE ); + + m_actionTextUnderline = new QAction( +#if QT_VERSION < 0x030200 + "", +#endif + embed::getIconPixmap( + "text_under" ), + tr( "&Underline" ), + CTRL + Key_U, this ); + connect( m_actionTextUnderline, SIGNAL( activated() ), this, + SLOT( textUnderline() ) ); + m_actionTextUnderline->addTo( tb ); + m_actionTextUnderline->setToggleAction( TRUE ); + + QActionGroup * grp = new QActionGroup( this ); + connect( grp, SIGNAL( selected( QAction* ) ), this, + SLOT( textAlign( QAction* ) ) ); + + m_actionAlignLeft = new QAction( +#if QT_VERSION < 0x030200 + "", +#endif + embed::getIconPixmap( "text_left" ), + tr( "&Left" ), CTRL + Key_L, + grp ); + m_actionAlignLeft->setToggleAction( TRUE ); + m_actionAlignCenter = new QAction( +#if QT_VERSION < 0x030200 + "", +#endif + embed::getIconPixmap( + "text_center" ), + tr( "C&enter" ), CTRL + Key_E, + grp ); + m_actionAlignCenter->setToggleAction( TRUE ); + + m_actionAlignRight = new QAction( +#if QT_VERSION < 0x030200 + "", +#endif + embed::getIconPixmap( "text_right" ), + tr( "&Right" ), CTRL + Key_R, + grp ); + m_actionAlignRight->setToggleAction( TRUE ); + + m_actionAlignJustify = new QAction( +#if QT_VERSION < 0x030200 + "", +#endif + embed::getIconPixmap( + "text_block" ), + tr( "&Justify" ), CTRL + Key_J, + grp ); + m_actionAlignJustify->setToggleAction( TRUE ); + + grp->addTo( tb ); + + + QPixmap pix( 16, 16 ); + pix.fill( Qt::black ); + m_actionTextColor = new QAction( +#if QT_VERSION < 0x030200 + "", +#endif + pix, tr( "&Color..." ), 0, this ); + connect( m_actionTextColor, SIGNAL( activated() ), this, + SLOT( textColor() ) ); + m_actionTextColor->addTo( tb ); +#endif +#endif +} + + + + +void projectNotes::textBold() +{ + m_edit->setFontWeight( m_actionTextBold->isChecked() ); + songEditor::inst()->setModified(); +} + + + + +void projectNotes::textUnderline() +{ + m_edit->setFontUnderline( m_actionTextUnderline->isChecked() ); + songEditor::inst()->setModified(); +} + + + + +void projectNotes::textItalic() +{ + m_edit->setFontItalic( m_actionTextItalic->isChecked() ); + songEditor::inst()->setModified(); +} + + + + +void projectNotes::textFamily( const QString & _f ) +{ + m_edit->setFontFamily( _f ); + m_edit->viewport()->setFocus(); + songEditor::inst()->setModified(); +} + + + + +void projectNotes::textSize( const QString & _p ) +{ + m_edit->setFontPointSize( _p.toInt() ); + m_edit->viewport()->setFocus(); + songEditor::inst()->setModified(); +} + + + + +void projectNotes::textColor() +{ + QColor col = QColorDialog::getColor( m_edit->textColor(), this ); + if ( !col.isValid() ) + { + return; + } + m_edit->setTextColor( col ); + QPixmap pix( 16, 16 ); + pix.fill( Qt::black ); +#ifdef QT4 + m_actionTextColor->setIcon( pix ); +#else + m_actionTextColor->setIconSet( pix ); +#endif +} + + + + +void projectNotes::textAlign( QAction * _a ) +{ + if( _a == m_actionAlignLeft ) + { + m_edit->setAlignment( Qt::AlignLeft ); + } + else if( _a == m_actionAlignCenter ) + { + m_edit->setAlignment( Qt::AlignHCenter ); + } + else if( _a == m_actionAlignRight ) + { + m_edit->setAlignment( Qt::AlignRight ); + } + else if( _a == m_actionAlignJustify ) + { + m_edit->setAlignment( Qt::AlignJustify ); + } +} + + + + +void projectNotes::fontChanged( const QFont & _f ) +{ + m_comboFont->lineEdit()->setText( _f.family() ); + m_comboSize->lineEdit()->setText( QString::number( _f.pointSize() ) ); + m_actionTextBold->setChecked( _f.bold() ); + m_actionTextItalic->setChecked( _f.italic() ); + m_actionTextUnderline->setChecked( _f.underline() ); + songEditor::inst()->setModified(); +} + + + + +void projectNotes::colorChanged( const QColor & _c ) +{ + QPixmap pix( 16, 16 ); + pix.fill( _c ); +#ifdef QT4 + m_actionTextColor->setIcon( pix ); +#else + m_actionTextColor->setIconSet( pix ); +#endif + songEditor::inst()->setModified(); +} + + + + +void projectNotes::alignmentChanged( int _a ) +{ + if ( +#ifndef QT4 + ( _a == Qt::AlignAuto ) || +#endif + ( _a & Qt::AlignLeft ) ) + { + m_actionAlignLeft->setChecked( TRUE ); + } + else if ( ( _a & Qt::AlignHCenter ) ) + { + m_actionAlignCenter->setChecked( TRUE ); + } + else if ( ( _a & Qt::AlignRight ) ) + { + m_actionAlignRight->setChecked( TRUE ); + } + else if ( ( _a & Qt::AlignJustify ) ) + { + m_actionAlignJustify->setChecked( TRUE ); + } + songEditor::inst()->setModified(); +} + + + + +void projectNotes::saveSettings( QDomDocument & _doc, QDomElement & _parent ) +{ + QDomElement pn_de = _doc.createElement( nodeName() ); + QDomCDATASection ds = _doc.createCDATASection( m_edit->toHtml() ); + pn_de.appendChild( ds ); + _parent.appendChild( pn_de ); +} + + + + +void projectNotes::loadSettings( const QDomElement & _this ) +{ + m_edit->setHtml( _this.text() ); +} + + +#include "project_notes.moc" + + + +#undef isChecked +#undef setChecked +#undef setFontWeight +#undef setFontUnderline +#undef setFontItalic +#undef setFontFamily +#undef setFontPointSize +#undef textColor +#undef setTextColor +#undef setHtml +#undef toHtml + diff --git a/src/widgets/rename_dialog.cpp b/src/widgets/rename_dialog.cpp new file mode 100644 index 00000000000..fb958ccc24f --- /dev/null +++ b/src/widgets/rename_dialog.cpp @@ -0,0 +1,89 @@ +/* + * rename_dialog.cpp - implementation of dialog for renaming something + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include + +#endif + + +#include "rename_dialog.h" + + + +renameDialog::renameDialog( QString & _string ) : + QDialog(), + m_stringToEdit( _string ), + m_originalString( _string ) +{ + setWindowTitle( tr("Rename...") ); + m_stringLE = new QLineEdit( this ); + m_stringLE->setText( _string ); + m_stringLE->setGeometry ( 10, 5, 220, 20 ); + connect( m_stringLE, SIGNAL( textChanged( const QString & ) ), this, + SLOT( textChanged( const QString & ) ) ); + connect( m_stringLE, SIGNAL( returnPressed() ), this, + SLOT( accept() ) ); +} + + + + +renameDialog::~renameDialog() +{ +} + + + + +void renameDialog::keyPressEvent( QKeyEvent * _ke ) +{ + if( _ke->key() == Qt::Key_Escape ) + { + m_stringLE->setText( m_originalString ); + accept(); + } +} + + + + +void renameDialog::textChanged( const QString & _new_string ) +{ + m_stringToEdit = _new_string; +} + + + + +#include "rename_dialog.moc" + diff --git a/src/widgets/side_bar_widget.cpp b/src/widgets/side_bar_widget.cpp new file mode 100644 index 00000000000..c7ac75969a1 --- /dev/null +++ b/src/widgets/side_bar_widget.cpp @@ -0,0 +1,123 @@ +/* + * side_bar_widget.cpp - implementation of base-widget for side-bar + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include +#include + +#endif + + +#include "side_bar_widget.h" +#include "types.h" +#include "templates.h" + + + +sideBarWidget::sideBarWidget( const QString & _title, const QPixmap & _icon, + QWidget * _parent ) : + QWidget( _parent ), + m_title( _title ), + m_icon( _icon ) +{ + m_contents = new QWidget( this ); + m_layout = new QVBoxLayout( m_contents ); + m_layout->setSpacing( 5 ); +} + + + + +sideBarWidget::~sideBarWidget() +{ +} + + + + +void sideBarWidget::paintEvent( QPaintEvent * ) +{ + const Uint16 TITLE_FONT_HEIGHT = 16; + +#ifdef QT4 + QPainter p( this ); + p.fillRect( 0, 0, width(), 27, palette().highlight().color() ); +#else + QPixmap draw_pm( rect().size() ); + draw_pm.fill( QApplication::palette().color( QPalette::Normal, + QColorGroup::Background ) ); + + QPainter p( &draw_pm, this ); + p.fillRect( 0, 0, width(), 27, QApplication::palette().color( + QPalette::Normal, + QColorGroup::Highlight ) ); +#endif + + QFont f = p.font(); + f.setBold( TRUE ); + p.setFont( pointSize( f ) ); + +#ifdef QT4 + p.setPen( palette().highlightedText().color() ); +#else + p.setPen( QApplication::palette().color( QPalette::Normal, + QColorGroup::HighlightedText ) ); +#endif + const Uint16 tx = m_icon.width()+4; + const Uint16 ty = 2+TITLE_FONT_HEIGHT; + p.drawText( tx, ty, m_title ); + p.drawLine( tx, ty+4, width()-4, ty+4 ); + + p.drawPixmap( 2, 2, m_icon ); + +#ifndef QT4 + // and blit all drawn stuff on the screen... + bitBlt( this, rect().topLeft(), &draw_pm ); +#endif +} + + + +void sideBarWidget::resizeEvent( QResizeEvent * ) +{ + const Uint16 MARGIN = 6; + m_contents->setGeometry( MARGIN, 40 + MARGIN, width() - MARGIN * 2, + height() - MARGIN * 2 - 40 ); +} + + + +#include "side_bar.moc" +#include "side_bar_widget.moc" + diff --git a/src/widgets/tab_bar.cpp b/src/widgets/tab_bar.cpp new file mode 100644 index 00000000000..be1e48b2c22 --- /dev/null +++ b/src/widgets/tab_bar.cpp @@ -0,0 +1,260 @@ +/* + * tab_bar.cpp - implementation of tab-bar + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "tab_bar.h" +#include "tab_button.h" +#include "templates.h" +#include "tooltip.h" + +#ifndef QT4 + +#define value data +#define setChecked setOn +#define isChecked isOn +#define removeWidget remove + +#endif + + + +tabBar::tabBar( QWidget * _parent, QBoxLayout::Direction _dir ) : + QWidget( _parent ), +#ifdef QT4 + m_layout( new QBoxLayout( _dir, this ) ), +#else + m_layout( new QBoxLayout( this, _dir ) ), +#endif + m_exclusive( FALSE ) +{ +} + + + + +tabBar::~tabBar() +{ +} + + + + +tabButton * tabBar::addTab( QWidget * _w, const QString & _text, int _id, + bool _add_stretch, bool _text_is_tooltip ) +{ + // already tab with id? + if( m_tabs.contains( _id ) ) + { + // then remove it + removeTab( _id ); + } + QString caption = ( _text_is_tooltip ) ? "" : _text; + // create tab-button + tabButton * b = new tabButton( caption, _id, this ); + connect( b, SIGNAL( clicked( int ) ), this, SLOT( tabClicked( int ) ) ); + b->show(); + if( _text_is_tooltip ) + { + toolTip::add( b, _text ); + } + + // small workaround, because QBoxLayout::addWidget(...) doesn't + // work properly, so we first have to remove all tabs from the + // layout and them add them in the correct order + QMap >::iterator it; + for( it = m_tabs.begin(); it != m_tabs.end(); ++it ) + { +#if QT_VERSION >= 0x030100 + m_layout->removeWidget( it.value().first ); +#endif + } + m_tabs.insert( _id, qMakePair( b, _w ) ); + for( it = m_tabs.begin(); it != m_tabs.end(); ++it ) + { + m_layout->addWidget( it.value().first ); + } + + if( _add_stretch ) + { + m_layout->addStretch(); + } + + + // we assume, parent-widget is a widget acting as widget-stack so all + // widgets have the same size and only the one on the top is visible + _w->setFixedSize( _w->parentWidget()->size() ); + + b->setFont( pointSize<7>( b->font() ) ); + + return( b ); +} + + + + +void tabBar::removeTab( int _id ) +{ + // find tab-button and delete it + if( m_tabs.find( _id ) != m_tabs.end() ) + { + delete m_tabs[_id].first; + m_tabs.erase( m_tabs.find( _id ) ); + } +} + + + + +void tabBar::setActiveTab( int _id ) +{ + setTabState( _id, TRUE ); + hideAll( _id ); + if( allHidden() ) + { + emit allWidgetsHidden(); + } + else + { + emit widgetShown(); + } +} + + + + +int tabBar::activeTab( void ) +{ + QMap >::iterator it; + for( it = m_tabs.begin(); it != m_tabs.end(); ++it ) + { + if( tabState( it.key() ) == TRUE ) + { + return( it.key() ); + } + } + return( -1 ); +} + + + + +bool tabBar::tabState( int _id ) +{ + if( m_tabs.find( _id ) == m_tabs.end() ) + { + return( FALSE ); + } + return( m_tabs[_id].first->isChecked() ); +} + + + + +void tabBar::setTabState( int _id, bool _checked ) +{ + if( m_tabs.find( _id ) != m_tabs.end() ) + { + m_tabs[_id].first->setChecked( _checked ); + } +} + + + + +void tabBar::hideAll( int _exception ) +{ + QMap >::iterator it; + for( it = m_tabs.begin(); it != m_tabs.end(); ++it ) + { + if( it.key() != _exception ) + { + setTabState( it.key(), FALSE ); + } + it.value().second->hide(); + } + if( m_tabs.find( _exception ) != m_tabs.end() ) + { + if( tabState( _exception ) ) + { + m_tabs[_exception].second->show(); + } + else + { + m_tabs[_exception].second->hide(); + } + } +} + + + + +void tabBar::tabClicked( int _id ) +{ + if( m_exclusive == TRUE && activeTab() == -1 ) + { + setActiveTab( _id ); + } + else + { + bool all_hidden_before = allHidden(); + // disable tabbar-buttons except the one clicked + hideAll( _id ); + bool now_hidden = allHidden(); + if( all_hidden_before == TRUE && now_hidden == FALSE ) + { + emit widgetShown(); + } + else if( all_hidden_before == FALSE && now_hidden == TRUE ) + { + emit allWidgetsHidden(); + } + } +} + + + + +bool tabBar::allHidden( void ) +{ + QMap >::iterator it; + for( it = m_tabs.begin(); it != m_tabs.end(); ++it ) + { + if( !it.value().second->isHidden() ) + { + return( FALSE ); + } + } + return( TRUE ); +} + + + +#undef value +#undef setChecked +#undef isChecked +#undef removeWidget + + +#include "tab_bar.moc" +#include "tab_button.moc" + diff --git a/src/widgets/tab_widget.cpp b/src/widgets/tab_widget.cpp new file mode 100644 index 00000000000..137f0c984e3 --- /dev/null +++ b/src/widgets/tab_widget.cpp @@ -0,0 +1,177 @@ +/* + * tabwidget.cpp - tabwidget for LMMS + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include + +#else + +#include +#include + +#endif + + +#include "tab_widget.h" +#include "templates.h" + + + +tabWidget::tabWidget( const QString & _caption, QWidget * _parent ) : + QWidget( _parent ), + m_curWidget( 0 ), + m_caption( _caption ) +{ + setFont( pointSize<7>( font() ) ); +#ifdef QT4 + QPalette pal = palette(); + pal.setColor( QPalette::Background, QColor( 96, 96, 96 ) ); + setPalette( pal ); +#else + setPaletteBackgroundColor( QColor( 96, 96, 96 ) ); + //setBackgroundMode( Qt::NoBackground ); +#endif +} + + + + +tabWidget::~tabWidget() +{ +} + + + +void tabWidget::addTab( QWidget * _w, const QString & _name ) +{ + widgetDesc d = { _w, _name, fontMetrics().width( _name ) + 10 } ; + m_widgets.push_back( d ); + // make sure new tab doesn't overlap current widget + m_widgets[m_curWidget].w->raise(); + _w->setFixedSize( width() - 4, height() - 14 ); + _w->move( 2, 12 ); +} + + + + +void tabWidget::mousePressEvent( QMouseEvent * _me ) +{ + if( _me->y() > 1 && _me->y() < 13 ) + { + int cx = 14 + fontMetrics().width( m_caption ); + for( widgetStack::iterator it = m_widgets.begin(); + it != m_widgets.end(); ++it ) + { + if( _me->x() >= cx && _me->x() <= cx + it->nwidth ) + { + it->w->raise(); + m_curWidget = it - m_widgets.begin(); + update(); + return; + } + cx += it->nwidth; + } + } +} + + + + +void tabWidget::resizeEvent( QResizeEvent * ) +{ + for( widgetStack::iterator it = m_widgets.begin(); + it != m_widgets.end(); ++it ) + { + it->w->setFixedSize( width() - 4, height() - 14 ); + } +} + + + + + +void tabWidget::paintEvent( QPaintEvent * _pe ) +{ +#ifdef QT4 + QPainter p( this ); +#else + QPixmap pm( size() ); + pm.fill( QColor( 96, 96, 96 ) ); + + QPainter p( &pm ); +#endif + + p.setPen( QColor( 64, 64, 64 ) ); + p.drawRect( 0, 0, width(), height() ); + + p.setPen( QColor( 160, 160, 160 ) ); + p.drawLine( width() - 1, 0, width() - 1, height() - 1 ); + p.drawLine( 0, height() - 1, width() - 1, height() - 1 ); + + p.setPen( QColor( 0, 0, 0 ) ); + p.drawRect( 1, 1, width() - 2, height() - 2 ); + + p.fillRect( 2, 2, width() - 4, 9, QColor( 30, 45, 60 ) ); + p.drawLine( 2, 11, width() - 3, 11 ); + + p.setPen( QColor( 255, 255, 255 ) ); + p.setFont( font() ); + p.drawText( 5, 10, m_caption ); + + int cx = 14 + fontMetrics().width( m_caption ); + + p.setFont( pointSize<6>( p.font() ) ); + + p.setPen( QColor( 160, 160, 160 ) ); + + for( widgetStack::iterator it = m_widgets.begin(); + it != m_widgets.end(); ++it ) + { + if( it - m_widgets.begin() == m_curWidget ) + { + p.setPen( QColor( 32, 48, 64 ) ); + p.fillRect( cx, 2, it->nwidth - 6, 9, + QColor( 160, 160, 160 ) ); + } + p.drawText( cx + 3, 9, it->name ); + p.setPen( QColor( 160, 160, 160 ) ); + cx += it->nwidth; + } + +#ifndef QT4 + bitBlt( this, rect().topLeft(), &pm ); +#endif +} + + + + +#include "tab_widget.moc" + diff --git a/src/widgets/text_float.cpp b/src/widgets/text_float.cpp new file mode 100644 index 00000000000..d7ac19b57aa --- /dev/null +++ b/src/widgets/text_float.cpp @@ -0,0 +1,152 @@ +/* + * text_float.cpp - class textFloat, a floating text-label + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include +#include + +#define setParent reparent + +#endif + + +#include "text_float.h" +#include "templates.h" + + + +textFloat::textFloat( QWidget * _parent ) : + QWidget( _parent +#ifndef QT4 + , "textFloat", WStyle_Customize | WStyle_NoBorder | WStyle_StaysOnTop +#endif + ), + m_text( "" ) +{ +#ifndef QT4 + setBackgroundMode( Qt::NoBackground ); +#endif + + reparent( parentWidget() ); + resize( 20, 20 ); + hide(); +} + + + + +void textFloat::reparent( QWidget * _new_parent ) +{ + QPoint position = _new_parent->pos(); + + // Get position and reparent to either top level or dialog + // + while( _new_parent->parentWidget() && !_new_parent->isTopLevel() + && +#ifdef QT4 + !_new_parent->windowType() == Qt::Dialog +#else + !_new_parent->isDialog() +#endif + ) + { + _new_parent = _new_parent->parentWidget(); + position += _new_parent->pos(); + } + + // Position this widget to the right of the parent + // + //move(pos + QPoint(parent->width() + 5, 5)); + + QWidget::setParent( _new_parent, +#ifdef QT4 + Qt::FramelessWindowHint | + Qt::WindowStaysOnTopHint ); +#else + WStyle_Customize | WStyle_NoBorder | + WStyle_StaysOnTop, + position + QPoint( 20, 5 ) ); +#endif +} + + + + +void textFloat::setVisibilityTimeOut( int _msecs ) +{ + QTimer::singleShot( _msecs, this, SLOT( hide() ) ); + show(); +} + + + + +void textFloat::paintEvent( QPaintEvent * _pe ) +{ +#ifdef QT4 + QPainter p( this ); +#else + QPixmap draw_pm( size() ); + QPainter p( &draw_pm ); +#endif + p.setPen( QColor( 0, 0, 0 ) ); + p.setBrush( QColor( 255, 255, 255 ) ); + + p.setFont( pointSize<8>( p.font() ) ); + + QFontMetrics metrics( p.fontMetrics() ); + QRect textBound = metrics.boundingRect( m_text ); + + resize( textBound.width() + 5, textBound.height() + 5 ); + p.drawRect( rect() ); + + p.setPen( Qt::black ); + p.drawText( 2, 10, m_text ); + +#ifndef QT4 + bitBlt( this, rect().topLeft(), &draw_pm ); +#endif +} + + + + +void textFloat::setText( const QString & _text ) +{ + m_text = _text; + repaint(); +} + + +#undef setParent + diff --git a/src/widgets/tooltip.cpp b/src/widgets/tooltip.cpp new file mode 100644 index 00000000000..2adecd3494d --- /dev/null +++ b/src/widgets/tooltip.cpp @@ -0,0 +1,59 @@ +/* + * tooltip.cpp - namespace toolTip, a tooltip-wrapper for LMMS + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include + +#endif + +#include "tooltip.h" +#include "config_mgr.h" + + +void toolTip::add( QWidget * _w, const QString & _txt ) +{ + if( !configManager::inst()->value( "tooltips", "disabled" ).toInt() ) + { +#ifdef QT4 + //_w->setToolTip( _txt ); +#else + QToolTip::add( _w, _txt ); +#endif + } +} + + +/* +void toolTip::remove( QWidget * _w ) +{ + QToolTip::remove( _w ); +} +*/ diff --git a/src/widgets/visualization_widget.cpp b/src/widgets/visualization_widget.cpp new file mode 100644 index 00000000000..a3e1ad9d4cf --- /dev/null +++ b/src/widgets/visualization_widget.cpp @@ -0,0 +1,221 @@ +/* + * visualization_widget.cpp - widget for visualization of waves + * + * Linux MultiMedia Studio + * Copyright (c) 2004-2005 Tobias Doerffel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include +#include +#include +#include + +#else + +#include +#include +#include + +#endif + + +#include "visualization_widget.h" +#include "embed.h" +#include "buffer_allocator.h" +#include "templates.h" +#include "tooltip.h" + + +const int UPDATE_TIME = 1000 / 20; // 20 fps + + + +visualizationWidget::visualizationWidget( const QPixmap & _bg, QWidget * _p, + visualizationTypes _vtype ) : + QWidget( _p ), + s_background( _bg ), + m_enabled( FALSE ) +{ +#ifndef QT4 + setBackgroundMode( Qt::NoBackground ); +#endif + + const Uint32 frames = mixer::inst()->framesPerAudioBuffer(); + m_buffer = bufferAllocator::alloc( frames ); + + for( Uint32 frame = 0; frame < frames; ++frame ) + { + for( Uint8 chnl = 0; chnl < SURROUND_CHANNELS; ++chnl ) + { + m_buffer[frame][chnl] = 0.0f; + } + } + + setFixedSize( s_background.width(), s_background.height() ); + + + m_updateTimer = new QTimer( this ); + connect( m_updateTimer, SIGNAL( timeout() ), this, SLOT( update() ) ); + if( m_enabled ) + { + m_updateTimer->start( UPDATE_TIME ); + } + + connect( mixer::inst(), SIGNAL( nextAudioBuffer( + const surroundSampleFrame *, Uint32 ) ), + this, SLOT( setAudioBuffer( + const surroundSampleFrame *, Uint32 ) ) ); + + toolTip::add( this, tr( "click to enable/disable visualization of " + "master-output" ) ); +} + + + + +visualizationWidget::~visualizationWidget() +{ +} + + + + +void visualizationWidget::setAudioBuffer( const surroundSampleFrame * _ab, + Uint32 _frames ) +{ + if( m_enabled ) + { + memcpy( m_buffer, *_ab, _frames * BYTES_PER_SURROUND_FRAME); + } +} + + + + +void visualizationWidget::paintEvent( QPaintEvent * ) +{ +#ifdef QT4 + QPainter p( this ); +#else + QPixmap draw_pm( rect().size() ); + //draw_pm.fill( this, rect().topLeft() ); + + QPainter p( &draw_pm, this ); +#endif + p.drawPixmap( 0, 0, s_background ); + + if( m_enabled ) + { + float master_output = mixer::inst()->masterOutput(); + Uint16 w = width()-4; + float half_h = -( height() - 6 ) / 3.0 * master_output - 1; + Uint16 x_base = 2; + Uint16 y_base = height()/2 - 1; + Uint16 old_y[DEFAULT_CHANNELS] = { y_base + (int)( + m_buffer[0][0]*half_h ), + y_base + (int)( + m_buffer[0][1]*half_h ) + } ; + + p.setClipRect( 2, 2, w, height()-4 ); + + float max_level = 0.0; + + const Uint32 frames = mixer::inst()->framesPerAudioBuffer(); + + // analyse wave-stream for max-level + for( Uint32 frame = 0; frame < frames; ++frame ) + { + for( Uint8 chnl = 0; chnl < SURROUND_CHANNELS; ++chnl ) + { + if( tAbs( m_buffer[frame][chnl] ) > + max_level ) + { + max_level = tAbs( + m_buffer[frame][chnl] ); + } + } + } + // and set color according to that... + if( max_level * master_output < 0.9 ) + { + p.setPen( QColor( 96, 255, 96 ) ); + } + else if( max_level * master_output < 1.1 ) + { + p.setPen( QColor( 255, 192, 64 ) ); + } + else + { + p.setPen( QColor( 255, 64, 64 ) ); + } + + // now draw all that stuff + for( Uint32 frame = 0; frame < frames; ++frame ) + { + for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl ) + { + Uint16 cur_y = y_base + + (Uint16)( m_buffer[frame][chnl] * + half_h ); + Uint16 xp = x_base + frame * w / frames; + p.drawLine( xp, old_y[chnl], xp, cur_y ); + old_y[chnl] = cur_y; + } + } + + } + +#ifndef QT4 + // and blit all drawn stuff on the screen... + bitBlt( this, rect().topLeft(), &draw_pm ); +#endif +} + + + + +void visualizationWidget::mousePressEvent( QMouseEvent * _me ) +{ + if( _me->button() == Qt::LeftButton ) + { + m_enabled = !m_enabled; + if( m_enabled ) + { + m_updateTimer->start( UPDATE_TIME ); + } + else + { + m_updateTimer->stop(); + // we have to update (remove last waves), + // because timer doesn't do that anymore + update(); + } + } +} + + + +#include +