qtractor-0.5.11/PaxHeaders.10084/AUTHORS0000644000175000001440000000007010211424560015520 xustar000000000000000026 atime=1381134666.08108 30 ctime=1381134666.081080034 qtractor-0.5.11/AUTHORS0000644000175000001440000000004210211424560015002 0ustar00rncbcusers00000000000000Rui Nuno Capela qtractor-0.5.11/PaxHeaders.10084/ChangeLog0000644000175000001440000000012312224470506016230 xustar000000000000000027 mtime=1381134662.966013 26 atime=1381134666.35408 30 ctime=1381134666.355080039 qtractor-0.5.11/ChangeLog0000644000175000001440000034345612224470506015536 0ustar00rncbcusers00000000000000Qtractor - An Audio/MIDI multi-track sequencer ---------------------------------------------- ChangeLog 0.5.11 2013-10-07 Lima Oscar - Adding a track now inserts it after the current one, if any; one can also drag and move a track below the last one in the track list (main view left pane). - Extended Edit/Select Mode/Automation: multi-selection mode, cut, copy, paste and delete of current track's automation curve nodes, now reached implementation ready status. - Another old silent bug bites the dust: changing track names were dropping any track gain/volume and panning automation curves when saving the session. - A primeval processing bug has been sorted out: aux-sends to audio output buses that just appear to be after the input bus where they're inserted were being left muted and silent (on a ticket follow-up by Holger Marzen, thanks). - Fixed a sure crash bug exposed when processing of aux-send plugins when inserted too early on audio input buses chain (after a ticket report by Holger Marzen, thanks). - Allow the build system to include an user specified CFLAGS (patch by Cristian Morales Vega, thanks). - Shift/Ctrl keyboard modifiers now set to extend current clip selection while in main track view's Edit/Select Mode/Range, Rectangle modes. - Main Edit/Select Mode/Automation icon retouched to look a bit more obvious and intuitive, hopefully ;) - Allow to change the velocities/values of the current selected events which have the exact same onset times and hide beyhond each other on the MIDI clip editor's pane below the main view piano-roll (ie. the one that represents MIDI event values as a bar chart). - Fixed some problematic playback/export muting and annoying cleanup freezing, due on audio tracks with too many clips eg. more than hundred clip splits (hopefully fixes an issue reported by Louigi Verona, thanks). - LV2 UI resize feature support/control added. - Fixed dedicated MIDI control and MIDI metronome port connection restore conflict (thanks to jhammen catch & patch:). - New user preference option added: reverse middle-button role to Shift/Ctrl keyboard state, in special regard to edit-head/tail vs. play-head positioning while on the main track and MIDI clip editor (aka. piano-roll) views. 0.5.10 2013-07-18 Kilo Papa - Default drum-key note names are now properly showing on MIDI tracks that are assigned to known drum/percussive instrument patches (eg. SoundFont 2 (.sf2) bank 128). - Time display format (frames, clock-time or BBT) may now be changed from the context-menu on any time entry spin-box. - LV2 plugin support is now tightly tied to liblilv; the same tie applies to LV2 plugin UI support and libsuil and vice-versa. - Mixer buses racks (ie. left/input and right/output panes) are now both kept fixed-width when whole mixer window is resized. - Unconditional LV2 Dyn(amic)-manifest support has been added. - Main track-view Edit/Insert, Remove/Range dialog is now being introduced with optional applicability to Clips, Loop, Punch in/out, Automation, Tempo-map and/or Markers. - New range removal editing tool, split/moving clips backward at the specified edit-head/tail interval (Edit/Remove/Range, Track Range)--by Tuomas Airaksinen, thanks. - Andy Fitzsimon's original icon from opencliparts.org makes it through as the default standard scalable format (SVG). - Automation's back in effect on Track/Export Tracks.../Audio. - Reversed Shift/Ctrl keyboard modifier roles on middle-button clicking over the main track and MIDI clip editor views (aka. piano-roll) in regression to original old semantics. - Color selection actions now have a brand new palette icon. - Make sure main track-view and MIDI clip editor selection is only cleared on specific discrete commands. - Try keeping the original session file in most recent files menu list, despite current version auto-incremental backup mode is in effect. - Fixed non-zero clip offsets upon tempo/time-scale changes. - Some sympathy to extreme dark color (read black) schemes is now indulged on empty backgrounds. 0.5.9 2013-06-06 Juliet Quebec - Auto-incremental version numbering of backup session files; brand new versioning mode option added. - Fixed one long as ever MIDI file export bug, which was about washing all self-induced MIDI bank-select (CC#0, CC#32) and program-change (PC#) events into MIDI channel 1, regardless of the source track/channel. - Fixed initial sample-rate settlement on plugin chains for all tracks and buses whenever a session file original sample-rate differs from the current audio device engine (ie. JACK). - New German (de) translation added (by Guido Scholz, thanks). - Now accepting JACK transport tempo and time-tignature changes while in slave transport mode. - Fix ref-count and auto-removal of created files that result from clip merge/export when session is closed but not saved. - MIDI track instrument bank/program selection, from plugin UIs that support it, is now effectively and complete. - Custom connections for dedicated audio outputs from all plugin chains in MIDI tracks or buses are back in business, hopefuly restored gain on session load (ticket by yuba, thanks). - Track Properties dialog now dirty after any plugin related change (another head-up by yuba, thanks again). - Tempo Map/Markers dialog is not set initially dirty anymore. - Audio buses plugin state's persistance were found AWOL: while being properly saved as usual, were being restored to default on every session reload (as noticed by yuba, thanks). - NSM (Non Session Management) support is being introduced. - The MIDI clip editor (aka. piano-roll) gets a brand new rescale mode: ctrl+dragging the right edge of a note now rescales all times and duration of all the subsequent selected notes (after an interesting idea/ticket by Joel Leclerc, thanks). - The new MIDI clip editor rescale mode also applicable to event values (eg. note velocities, pitch-bend), while ctrl+dragging the edges of an event vertical bar. - VST plugin (GUI) idle timer makes a comeback. - Hard-wired LV2 UI selection order for plugins which supply more than one option (lv2_external_ui gets always honored first then, as provided via libsuil, X11, GTK and last but not least, Qt4). 0.5.8 2013-03-19 India Romeo - Dropped old audio ramping spin-locks as its glitching reduction weren't that effective anymore. - Audio bus and track gain may now be set for amplification again, from +0dB up to +6dB, while using the Mixer strip sliders/faders (an old function found missing ever since pre-TYOQA). - Basic LV2 X11 UI support has been added through libSUIL but only really effective if plugins doesn't support the LV2 External UI extension in addition which takes precedence on any case. - Improved precision tolerance on the Tempo Map / Markers dialog. - Reinstated and fixed (old) warning and impending re-conversion on loading session files which the original sample-rate differs from current audio device engine (aka. JACK). - LV2 Plugin State/Preset name discrimination fix (after a ticket by Jiri Prochaszka aka. Anchakor, thanks:) - Linked/ref-counted audio clips must not overlap and now must have a buffer-size worth of a gap between each other. - Something fishy has been detected in the SSE (not so) optimized code from SoundTouch's-inspired WSOLA time-stretching. - Splitting clips apart is now easier than ever: a brand new entry enters the main menu scene: Edit/Split (Ctrl+Y) splits up clips according to current range/rectangular selection. - Audio clip offsets are now properly corrected when time-stretching is applied via Shift/Ctrl+dragging any of the clip edges. - One semi-colon typo was hiding proper descrimination of peak files used to draw distinct waveforms of time-stretched audio clips. - Track automation curves are now also affected by Edit/Insert/Range commands. - Finally, some visual feedback is shown while audio track export is running, in he form of a main status progress bar. - New user option: save backup versions of existing session files. - Default session directory now set to regular file's path on load. - A convenient minimum slack duration has been fixed for MIDI SysEx messages. - LV2 Time/position information is now asynchronously fed back into their parameter (control input) ports when designated. - LV2 State is now properly restored for plugins inserted on buses, probably solving the Calf Fluidsynth SoundFont information missing on buses ticket, reported by Albert Graef, thanks. - Fixed an immediate null pointer crash on creating a parentless new group while on the files organizer widget. - Preparations for future Qt5 migration. 0.5.7 2012-12-27 Hotel Sierra - Loop and punch in/out ranges may now get set simultaneously, may even overlap each other. However, punch in/out range recording will always prevail over any loop recording takes. - LV2 Worker/Schedule now supporting multi-instance vs. single-UI scenarios. - LV2 Options and Buf-size extension support added. - Fixed an off-by-one-tick bug on MIDI file input which was leaving spurious zero-length runt notes at the end of a MIDI clip, if a note-on coincides with the ending/split point (on ticket issued by Jonathan H. Pickard, thanks). - Good old SLV2 library support for LV2 plug-ins (libslv2) is now irrevocably deprecated, or better said, completely wiped-out from the LV2 host code, now considered extinct. - LV2 UI parameter updates are now asynchronously detached from the source GUI widget thread, in attempt to improve cross-GUI-toolkit responsiveness, specially focused on LV2 plugins with a GTK based UI (eg. amsynth, triceratops, etc.). - Make sure LV2 UI parameters (input control ports) get updated when loading a genuine LV2 state preset. - Improved the (custom) tempo spin-box widget signal(ing) processing and dispatching. - Show proper pointing cursor and location tool-tip while dragging any of the time ruler markers (including latest location markers/bar). - On saving as an archive/zip session file (suffix .qtz) include only those files that are actually referenced by live clips arrangement. - Ongoing integration of location markers infrastructure (time-scale and MIDI-file support). - Free-hand/linear retouching of event values, while on the MIDI clip editor's view pane below the main piano-roll (eg. note velocities), is now possible provided the target events are selected, otherwise the usual painting edit sub-mode applies (cf. menu Edit/Select Mode/ Edit Draw). - The MIDI clip editor now senses which target view pane has focus for general selection commands (cf. Edit/Select/None, All, Invert, Range) whether the main piano-roll or the event value (velocities) view. - Mouse middle-button clicking is back in business on main track-view and on MIDI clip editor views (piano-roll) as an immediate play-head (re)positioning command or merge/reset the edit-head/tail cursors if Shift/Ctrl keyboard modifiers are pressed. - Formerly protected, class qtractorClip::FadeFunctor is now public in an shot-in-the-dark attempt to fix clang builds (as reported by Jekyll Wu, thanks). - Override all sub-classed widgets mouse-pointer event handlers to be isolated from base widget style and/or window management. 0.5.6 2012-10-02 Golf Tango - Day 1 post-release fix: LV2 plugins with a GTK GUI were not shown due to their respective widget (GdkWidget) being prematurely and unexpectedly destroyed when raised (via libsuil). - The dedicated audio outputs setting for instrument plugins was not in effect as default global option for new MIDI tracks, now fixed, hopefully (thanks to danboid aka. Daniel MacDonald persistence). - An immediate Files widget cleanup option is now made available, as to select and remove all unused file entries. - MIDI track (un)solo/mute reset clip event sequence fixing; definite regression to MIDI track's occasional muting bug while clip editing and playback is rolling. - Apologies due on this one: Shift/Ctrl keyboard modifiers are back in business to change MIDI events currently selected in one single step while on MIDI clip editor (aka. piano-roll). Sorry. - Japanese (ja) translation added (by Takashi Sakamoto). - General time-scale bar, beat and tempo rounding fixing. - Keyboard shortcuts configuration (Help/Shortcuts...) now checks and warns for already assigned key sequences. - The View/Snap menu is now listed as fully accessible actions, making each snap-per-beat setting assignable to a keyboard shortcut (after a feature request by danboid aka. Daniel MacDonald, thanks). - Fixed MIDI resize tool, now applying symmetric proportional changes to pitch-bend event values [-8191, +8191]. - Fixed re-loading of LV2 Presets that are newly created/saved during current session; actually delete and remove a LV2 Preset if found in the file-system (as suggested by Jiri Prochaszka aka. Anchakor, thanks again). - Preset drop-down list is now sorted, on plugin properties dialog. - After a long absence, edit(blue) cursor vertical lines are back on the MIDI clip editor views (aka. piano-roll). - LV2 1.0.0 compliance phase II: LV2 State Files support completed. - Updated to newer LV2 External UI extension support (now maintained by Filipe Coelho aka. falktx). - Brand new editing tool: empty range insertion, split/moving clips or events forward the specified edit-head/tail interval, defaults to next measure or bar (cf. menu Edit/Insert/Range, Track Range). - Don't show the waiting cursor anymore when loading any plugins which might have a nice native editor (GUI) and options are set to show it. - MIDI clip editor now hopefully rid of random but persistent muting, a slight regression to editing while playback is rolling. - A MIDI file player's bug, evident while transport rolling in looped mode, has been fixed with yet another oneliner patch (kind by Jiri Prochaszka aka. Anchakor, thanks again). - LV2 plugins with a Qt4 GUI (guess what or whom?) are now guaranteed to some reasonable window type like Qt::Widget but not Qt::Dialog nor Qt::Popup, preventing those from standing always on top while on some window managers or desktop environments (a simple addition by Jiri Prochaszka aka. Anchakor, thanks). - MIME type icons support for session (*.qtr *.qtr), template (*.qtt) and zip/archive (*.qtz) are now being introduced. - LV2 State Files feature support is shamelessly getting real trial, now letting files referenced in LV2 plugin states to be seamlessly included when saving to a zip/archive file bundle (.qtz suffix). - Added some virtual destructor stubs to shut up gcc 4.7 warnings. - Improved plugin state resilience, now finally with parameter name matching, specifically targeted on loading old sessions or plugin preset files (.qtx), preserving old saved plugin states as much as possible in face of rogue or discrete parameter index renumbering, due naturally on any plugin's life cycle ie. upgrades etc.;) - Added some more snap-to-beat divisors (Beat/14, /21 and /28) due on feature request ticket, while dropping highest, probably useless one (Beat/128). - New French (fr) translation added (by Yann Collette, thanks). - Slight late optimization on vertical zebra/grid lines drawing. 0.5.5 2012-06-15 Foxtrot Uniform - Auto-monitored MIDI tracks were missing their pass-through to their respective MIDI output bus plugin chains, now fixed and letting any multi-timbral instrument plugin to get a peek from auto-monitoring. - New user option/preference to whether to open a plugin's editor (GUI) by default, when available (cf. View/Options.../Plugins/Editor). - Clicking and/or dragging for rubber-band selection on main track-view canvas doesn't change the edit-head and -tail positions anymore. - Backward and Forward transport commands now have an additional stop at first clip start point. - LV2 Atom/MIDI buffering support is finally entering the scene; LV2 Worker/Schedule support is also included in a bold attempt to convey non-MIDI event transfers between plugin and its UI. - MIDI Clip editor (aka. piano-roll) and MIDI Tools fix: avoid note-on events of zero velocity, which conventionally equates to a dangling note-off event and dropped into oblivion sooner or later. There's no more need for Shift/Ctrl keyboard modifier to change in one single step all the MIDI events that are currently selected (now consistent with drag-move). - LV2 Presets support now entering effective operational status; a new local option has been added (cf. View/Options.../Plugins/Paths/LV2 Presets directory; default is ~/.lv2). - Dropped XInitThreads() head call as it was never useful but on those early days of JUCE VST plugins. - Italian (it) translation added (by Massimo Callegari, thanks). - Clip fade-in/out dragging now follows snap-to-beat setting. - Late modern eye-candy indulgence: alternate shaded stripes, on every other bar as in a "zebra" background option for the main tracks and MIDI clip editor views (cf. View/Snap/Zebra). - LV2 Time/position information is now being supported through special designated plugin input ports (after suggestion by Filipe Coelho aka. falktx). Additionally, the time/position information report has been corrected and complemented for VST plugins. - Audio vs. MIDI time drift correction has been slightly improved against rogue tempo changes across looping cycles. - Honor tempo/timing on MIDI instrument plugins. Happy regression fix on getting MIDI note-offs at looping ends back in business; all the necessary bumming for MIDI plugins to play nice in face of tempo changes and whenever playback is started from anywhere but the beginning of the time-line (ie. frame zero); thanks to rvega aka. Rafael Vega, for the heads-up). - Audio clip wave-forms were being displayed in inverted phase (ie. upside-down) all this time ever since day one. What a shame! :) - LV2 Programs interface is getting initial experimental status, to let LV2 instrument plugins get on par with the DSSI and VST crowd for MIDI bank/program instrument inventory and selection support (a sidetrack complot with Filipe Coelho aka. falktx, thanks:). - Dropped the old but entirely useless LV2 URI-unmap feature, now being superseded by official LV2 URID (un)mapper. - Russian (ru) translation added (by Alexandre Prokoudine, thanks). - SLV2 deprecation process started, effective now at configure time. - Added include to shut up gcc 4.7 build failures (patch by Alessio Treglia). - Another approach avoiding recursive observer widget updates. Also applies to mixer, monitor and track state buttons. - Update to latest LV2 state extension (by David Robillard, thanks). - Loop-recording/take number displayed on clip title, respectively. - Make(ing) -jN parallel builds now available for the masses. - A one buffer period slack on audio engine's loop turn-around logic might just have fixed an illusive report on loop-recording/takes going progressively out-of-sync, most notably when recording under large audio buffer period sizes (>= 1024 frames/buffer). - Editing MIDI while playback is rolling, doesn't mute the track any more, adding a point to the live editing experience. - Finer granularity for direct access parameter mouse wheel changes. - Dropped a dumb optimization for short full-cached multiple linked /ref-counted audio clips which were incidentally out-of-sync after rewind/backward playback. Once again and uncertain to be the last take on this, got fixed (probably related to some oddity reported by Louigi Verona, thanks). 0.5.4 2012-03-01 Echo Victor - Direct access plugin/insert parameter changing tool-tip added. - A Transport/Panic action enters the scene, in a nostalgic attempt to emulate the all-MIDI-track-shut-off command of those drop-dead and primordial MIDI sequencers of all time. Now finally a keyboard shortcut and mouse click-away ;) - MIDI editor command redo/undo adjustment now effective on all other channel events besides notes, which overlap at the same event time. - A new File/Unlink menu action is now made available from the MIDI clip editor (aka. piano-roll) for detaching the current linked/ref- counted MIDI clip into a new auto-incremented SMF filename. - Some audio/MIDI content/media-file resource management is entering the scene, taking care of some file-system house-keeping, this gets evident on unsaved/dead recorded files being automaticaly removed from the file-system, on session close. - Killed the old and entirely deprecated LV2 Save/Restore and Persist feature/extensions support. - Auto-monitored MIDI events are now merged/queued correctly into the instrument plugin playback queue, avoiding sudden crashes, hopefully. - Awesome patch from Albert Graef, thanks, which makes most MIDI SysEx to get through MIDI instrument plugins at last; applies to DSSI and LV2 plugins only. - LV2 URID map/unmap feature support added. - Plugin parameter value redo/undo command aliasing fix. - Double-clicking in plugin list item now show/activates the plugin's editor window (was toggling visibility/activation). - Plugin path settings have been fixed again, with special regards to an effective LV2_PATH environment variable settlement. - Session properties dialog now asks to create a new session directory if the given one does not currently exist. - MIDI note names and their respective octave numbers are now compliant with the ISO standard where middle C (60) is now C4 (was C3). - Fixed audible glitch/pop at the beginning of an audio clip with long quadratic or cubic shaped fade-in (reported by Lougi Verona, thanks). - MIDI Controller Auto-Hook patch by Alessandro Preziosi, thanks. - Make sure all MIDI note-off are always queued after their respective note-on events when buffering for MIDI input of instrument plugins, event though for zero duration MIDI note events (hopefully fixing the hanging notes bug reported by Albert Graef, thanks). - LV2 MIDI-fx plugin support has been repaired. - Single-track clip selection logic corrected again, fixing multi-clip selection drag/move across an odd number of distinct tracks (after a bug report by Louigi Verona, on linux-audio-dev, thanks). - MMC Locate time-code hour bit-field fix; MMC Locate now also on loop turnarounds (patches by Albert Graef, thanks). - Looping across multiple linked/ref-counted audio clips was incredibly broken with complete out-of-sync playback. Hopefully fixed now, with auto-unlinking/cloning all the affected audio clip buffers. - Audio clip overlapping detection off-by-one(-frame) fix. - MIDI Tools/Resize value ramp mode has been added (mocking the 'resize to range' feature request by Daniel MacDonald aka. danboid). 0.5.3 2011-12-28 Delta Whisky - Fixed initial LV2 plugin UI widget/window titles. - Attempt to get any brand new LV2 plugins Qt4 enabled UI's working on either slv2 and lilv build modes ;) (nailed by falkTX, thanks). - Current clip is ultimately inferred from the one under the play-head position and current selected track; the last one clicked over and/or selected still has precedence (following request by Loiugi Verona). - Drag-moving clips horizontally with the keyboard arrow-keys just got a step better with a fixed minimum of one pixel, depending still on the current snap-per-beat setting and horizontal zoom level (as suggested by Louigi Verona, thanks). - Get maximum and minimum peak values back when drawing audio waveforms. - Automation play/feedback has been missed to show on those plugins that provide their own GUI, now on par with all the rest 'homebrew' widgets (eg. generic plugin properties dialog). - All plugin parameters automation and selection were left inaccessible until the generic native plugin dialog is eventually shown, now fixed. 0.5.2 2011-12-16 Charlie X-ray - Fixed a probably old lurking destructive bug, which was incidental to when an invalid or non audio file is imported, intentionally or by mistake, into new or existing audio clips (eg. importing a MIDI file where an audio file is expected). - Force audio file closing to occur on the very same disk-write (sync) thread, possibly mitigating an old random crash issue lurking in the vorbis reference encoder (recording) re. the non thread-safeness of the vorbis_analysis() final call. - Fixed extraordinary shadow-playback of audio clips which extent were longer than the respective audio file length. - Default session file format option now promoted (see View/Options.../General/Session) in the way of whether file suffix gets honored upon session open or save (.qtr, .qts or .qtz). This brand new option also applies for default state file format on a JACK-session salvage context. - The View/Options... (aka. user preferences) dialog sees a new arranjement in layout, with some options moving into this brand new tab page called General. - LV2 State extension support has been added, which shall replace old LV2 Persist extension interface in the near future. It also replaces the LV2 Files extension from now on (thanks to Dave Robillard). - Dirty MIDI clips are now auto-saved when MIDI track properties get changed through its own dialog. - Fixed one probable too old crash when canceling a new/add track dialog. - MIDI SysEx event list editing is now fixed. - Once again, make sure all recorded clips start and end at the very same position when multiple track recording is turned on/off, while playback is still rolling. - Fixed Makefile.in handling installation directories to the configure script eg. --datadir, --localedir. - Possible attempt to improve in-flight recording clip display, especially when looping and MIDI clips are involved. - MIDI clip revision (re)numbering paranoia has been improved as much to avoid MIDI file clashes as much as possible while editing multiple MIDI clips which reference the same SMF and track/channel. - Creating new or updating existing buses with exact same names of any current dedicated inputs/outputs (which are implemented as special covert buses) is now disallowed. - Loop-recording/takes functionality is now ready for the masses and accessible from brand new Clip/Take menu (Select, First, Previous, Next, Last, Reset and Range...; the latter is actually being provided as bonus feature :) as to fold any given clip into so-called takes, simulating loop-recording mode over an arbitrary range). - Loop-recording/takes infrastructure integration is sneaking in: all clips recorded under a loop/cycle range may now get split (folded) into one or more so-called takes. A new option is now provided, as to select which take is about to retain after the recording ends, either the First or the Last one. Just turn this mode off (None) and keep with the old recording behavior, where clips are laid out unfolded through the timeline, as usual (see menu View/Options.../Display/Loop recording mode). - Improved robustness in face of disabled audio buses when global maximum number of JACK (audio) ports is surpassed. - Improved single-track clip selection status logic. - Clip/Unlink action is now available for detaching linked/ref-counted MIDI clips, renaming and saving into auto-incremental SMF filenames. - Temporary session archive directory now (pre)fixed with program name (eg. /tmp/qtractor). - Fixed VST GUI editor window title on first show. - Fixed build for ancient VST-SDK 2.3 (32bit only). 0.5.1 2011-10-05 Bravo Yankee - More LADISH support: SIGTERM signal is nowrapped for graceful application close. - Improved paste-repeat snap precision when dealing with large repeat counts. - Czech (cs) translation added, by Pavel Fric. - Added a few snap-to-beat divisors (unusual Beat/5, Beat/7, Beat/9 and Beat/10) for completeness sake. - Such a simple change of mind with a visual twist: the "A" track automation button/menu has now been moved to the right-most, as it belongs ;) - Auto-connection of dedicated audio outputs is now optional for default audio master bus, metronome, player and MIDI instrument plugin dedicated audio outputs. - Finally, after a pitiful large brain-dead period, generic plugin forms are now showing all possible controllable plugin parameters featuring a paged, tabbed dialog, whenever applicable. - Special hack/fix for JUCE based native VST plugins, which are the most actually found with a GUI editor, skipping explicit shared library unloading and thus avoiding some mysterious crashes on session close and/or application exit. - Support for MIDI-fx plugins (native VST and/or LV2) is now implemented and functional (intra-chain only).Instrument plugin bank/program selection was found broken or dead in the water, specially on VSTi, now finally fixed again. - VST plugin parameter value display on generic form is now back in business (were dead regarding value changes). - All plugin's provided GUI editors are now honored by being popped up first, instead of the usual but good old generic plugin form. - Long overdue implementation of a dedicated MIDI file player is now accessible from the MIDI files widget; one can play the whole SMF or just a single track or channel. - Update to a newer VeSTige header, probably fixing an old 32 vs. 64 bit mismatch. - Avoid JACK session filenames/paths to be ever shown; also avoid all buses ports (re)connections when JACK sessions are (re)loaded, given the fact that session management will take care of just that; more also, untitled/default session names are now also picked up to match current LADISH project name, obviously given by LADISH_PROJECT_NAME environment variable, whenever present (as suggested by Nedko Ardaunov). - Paste-repeat floating selection has been fixed (was showing only the last repeated selection). - Coherence of tempo changes on audio and MIDI clips, whether automatic time-stretching is in effect, has been slightly improved, hopefully fixed. - Bold attempt to get linked (aka. ref-counted) audio and MIDI clips into practice. - Main track view now showing all clips above the grid. - Added support for both new and older (deprecated uri) lv2_external_ui extension (by Nedko Ardaunov). - Following yet another great idea, and implementation, by Holger Dehnhardt, who already brought us the new aux-send insert plugin, thanks again, the so-called direct access control option is now featured for any plugin parameter right from plugin listings eg. mixer strips. - General resource consumption and management has been slightly improved, due to internal buses allocation optimization. - Fixed nasty crash-bug that was severely affecting all sessions that had at least one insert (pseudo-)plugin on any audio input bus. - All automation curve nodes are now relocated whenever disparate session sample-rate is detected on load. - New aux-send/insert pseudo-plugin is now introduced, allowing to route any track audio output to any other audio output bus besides the nominal one -- thanks to an original implementation from Holger Dehnhardt. - New immediate edit/loop-range settings from current clip extents, accessible on the main menu (Clip/Range Set, Loop Set) and from MIDI clip editor menu as well (File/Range Set, Loop Set). - MIDI Names XML files (*.midnam) may now be imported into MIDI instrument definitions. - Avoid cursor reset while editing MIDI events list (fixes bug reported by Frank Neumann). - Just some typos fixing (patch by c-korn). - Track view automation curve editing mode has been slightly fixed, now allowing for other previously existing point-and-click mouse operations. - Default automation curve mode is now preserved (following a suggestion by Alexandre Prokoudine, thanks). 0.5.0 2011-07-22 Alpha Zulu (TYOQA) - MIDI controller learn/catch-up sees the way in: MIDI controller changes are now only effective after catching-up with their respective program parameters, avoiding abrupt jumps and keeping a safe and continuous behavior. - Track/Height menu is now featured, giving access to Increase, Decrease or Reset the current track height. - All changes to audio gain and panning on tracks and buses are now applied following a piece-wise linear ramp, reducing the old nasty clicks, pops or zipper artifacts that might be awfully audible on some situations, most specially on automation. - All zooming in/out is now relative to either the viewport center or current mouse cursor position if found laying inside. - TYOQA! the underground sources have emerged:... after years in the making, track automation, or dynamic curves as some like to call, is finally a reality, tricky but real ;) - Audio clip anti-glitch/ramp-smoothing effect is now slightly independent of current buffer-size period. - Once buried under the Edit menu, Clip menu has been finally promoted to top main menu. - Debugging stacktrace now applies to all working threads. - Fixed muted loop playback on audio clips ending coincidentally with the loop-turn/end point. - Old/deprecated JACK port latency support added to audio recording latency compensation. - Audio clip merge/export lock-ups now untangled. - LV2 extension headers update. - Fixed configure of newer LV2 host implementation stack (LILV) when older (SLV2) is not present. 0.4.9 2011-05-26 The Final Dudette - Session file format saved on JACK session has been reverted to archive/zip bundle one (.qtz) now using temporary extraction directory when loading an existing JACK session. - Main toolbar time and tempo widgets get their visual extents a bit more theme-friendlier ;). - Some current working directory trickery is now in place avoiding JACK session directories to ever be picked as default, as much as possible. - Ghost-playbacks are now avoided on audio clips that are artificially extended beyond their own audio file lengths. - Recording clips now shown in a reddish shade; also, it's all now shown a bit more correctly, regarding the lead and within looping range. - Custom tempo spin-box widgets now honoring the decimal point cursor positioning for integral up/down tempo value stepping. - Audio recording latency is now compensated via automatic clip offsetting. - Audio peak file generation is now pipelined on a single unique thread, instead of old one per audio clip file basis. - MIDI tempo/time-signature map import problem has been hopefully fixed. - Session and track names are now sanitized from slashes (fixes bug# 625798@bugs.debian.org). - Mouse wheel effect to sliders is now reversed. - An appropriate export filename is now suggested as default (Track/export Tracks...). - Follow-playhead automatism is now temporarily suspended while mouse cursor hovering prompts for any editing action (applies to main track- view and MIDI clip editor/piano-roll). - Audio vs. MIDI time drift correction now takes jack_frame_time() as audio time reference. - Audio buffering internal synchronization logic gets it bartered: three bools for a single byte flag. - Connections are now preserved as possible when changing bus properties (View/Buses.../Update). - A rare audio clip looping out-of-sync condition got squared, hopefully the last ;) - Yet again, the audio clip buffer/disk-streaming optimization has been almost completely redrawn: now there's one thread per audio track. - Not replacing a session directory that already exists on loading an archive file (.qtz) is now fixed with an usable brand new untitled session. - The major thread optimization has been slightly improved: the audio clip buffer/disk-streaming thread is now served in a FIFO manner (was LIFO). - Custom time/tempo spin-box widget change fixup. - Audio clip filename change segfault/crash fixed. - Make sure all clips in multiple recording tracks start and end at the very same position whenever recording is already engaged and rolling. - Hopeful fix to a potential audio buffering race condition, which was a probable cause of random muted clips. - Avoid recursive observer widget value updates. - Almost complete rewrite of the main track-view selection and redrawing logic, taking advantage of the fundamentally static graphical backstore. - Autonomic resizing of mixer bus splitter sizes. - Improved timing for monitored MIDI events being buffered though MIDI instrument plugins, while playback/transport is rolling. - Audio peak/waveform is now slightly tweaked from the early optimization days (master C++ guru has always said that was root of all evil anyway :). - MIDI controller mapping now with "Invert" value option. Also, new "Inputs" and "Outputs" buttons have been added as helpers for MIDI control port connections access. - Main left pane vertical splitter resize hack, avoiding some track list update re-entrancy. - Inserting a LV2 instrument/synth plugin on an audio track or bus were causing immediate crash, now fixed (give or take some event buffer stub). - Plugin Activate All/Deactivate All menu fixing. - Make sure given session directory has all the necessary access permission (read/write) while on session properties dialog. - Dedicated audio outputs setting for instrument plugins inserted on the MIDI track properties dialog were not being honored, now fixed. - Force update/close of all MIDI clips and their respective editors (piano-roll) if open, when changing the global session tempo (BPM). - Removed the misleading "(Any)" special channel value while on MIDI controllers/learn dialog. - Floating tool-tips now being shown also while on mouse rubber-banding (drag-select). - Audio clip pitch-shifting change fixing; also, tooltips now showing semitones units instead of a clueless percentage. - Rendering audio wave-forms while recording is now a little bit smoother than before. - New main track-view clip selection tool: invert current selection (Edit/Select/Invert). The MIDI clip editor (piano-roll) also gets proper range selection tool (Edit/Select/Range). - More eye-candy: muted/non-soloed tracks are now slightly shaded on the main track-view. - A major hidden optimization has been implanted: all audio clip buffer/disk-streaming threads are finally merged into a single multiplexing thread (was one thread per audio clip longer than 3 sec. which was quite wasteful and creepy;). - All plugin list view changes are now properly signaled to track properties and bus manager dialogs and enable their respective acceptance. - Two brand new MIDI tools make their appearance: Scale-Quantize and Snap-to-Scale. The later may be readily accessible from the MIDI clip editor toolbar and menu (check View/Toolbars/Scale and View/Scale). - Mixer track strips are now completely redone whenever a track gets moved or re-ordered on main track list-view. - Transport auto-backward option is now honored whenever a new session gets loaded. - LV2 extension headers update. - Got rid of recent QX11EmbedContainer bloating, while introducing gtk_init() as for LV2 GTK UI support stabilization. - Tempo tap helper button was added to View/Tempo Map... dialog. - Executable DSSI plug-in GUI detection fixed. - Backout default session directory after cleaning up extracted archive/zip bundle session (.qtz). - Files widget item selection feedback/focus fix. - MIDI editor anchor event floating tool-tip fix. - Probable fix for GtkStyle usage detection (might be gentoo specific). 0.4.8 2011-01-18 The Fiery Demigoddess - MIDI controller mapping/learn is now possible on all mixer controls (monitor, gain, panning, record, mute, solo). - An internal rewrite (aka. refactoring) have been carried out, making sure that all track state action buttons (R, M, S) are now all under the observer pattern umbrella. - Single track range selection is now available on main menu (Edit/Select/Track Range; default keyboard shortcut: Ctrl+Shift+R); additionally to vertical range and horizontal track actions (Edit/Select/Range, Track) all these operations can now toggle over the previous selection. - Direct clip selection from Files list item has been brute-forcefully implemented (after being challenged by Jiri Prochaszka aka Anchakor:). - Files tree widget sticky "New Group" item fixed. - A new menu option has been added (View/Tool Tips) to show/hide a floating tool-tip while dragging, moving, resizing or pasting selected clips or events over the main tracks view and MIDI clip editor (piano-roll) respectively, displaying current target position and status. - Attempt to reset audio/MIDI time drift compensator on every engine start and loop turnaround. - Moving the punch-out marker over the main track time ruler was failing to shrink the punch-in/out range, now it does (not). - MIDI clip tools (quantize, transpose, normalize, randomize, resize, rescale and the new timeshift) are now all accessible from the main tracks view (Edit/Clip/Tools menu) and apply to all events on current selected clip(s). - LV2 Persist extension support is being introduced. - A new timeshift MIDI tool has been added, after an awesome patch by Jiri Prochaszka aka Anchakor; applies to selected events between edit markers, distorting their time and duration (optionally), either slowing down and accelerating, based on a given parameter P value. - Audio clip/buffer pitch-shifting fixes with regard to latency correction due on the RubberBand library one-pass (real-time) processing mode. - New Send Gain and Dry/Wet control parameters have been implemented for audio Inserts pseudo-plugins. - MIDI channel/master volume enqueued events are now affected by the current track/bus volume (0-100%). - Prevent old rounding error when resetting to plugin parameter default value with the mouse middle-button click while hovering a slider widget (observer). - A quantize percentage has been added to MIDI clip editor quantize tool (Tool/Quantize...) for time and duration quantization (0% for none; 100% for full regular quantization). - Metronome bus/ports are now created at engine start and not when user switches it on anymore. - Make sure all audio clip buffers are in sync upon smooth-ramping going off and playback is rolling. - Copy-pasting across controller event types is now possible on the MIDI clip editor (aka piano-roll). - Finally indulged, the genuine transport stop button makes its appearance on main toolbar and menu. - Main tracks grid visibility option (View/Snap/Grid). - Yet another off-by-one (frame) audio buffer bug got squashed away: rare symptom was that some audio clips were being left dead silent right after playback of their first looping period. - Plugin parameter name/label now a proper attribute of its respective MIDI Controller observer instance, allowing to be shown on dialog title (MIDI learn). - Default session file format saved on JACK session demand is now the bundle archive/zip one (.qtz). - Plugin selection dialog now shows whether a plugin features its own editor (GUI) and/or external state configuration (EXT). - Help/Shortcuts... window positioning and sizing are now preserved. - All plugin chain changes over the track properties dialog now sure counts as a dirty action. - Newly extracted archive/zip session directories are now removed automatically from the file-system on session close, prompting the user for confirmation (cf. View/Options.../Display/Confirm Removals). - Ctrl+mouse-wheel is now set for zooming in/out, on main track-view and all applicable MIDI clip editor views (piano-roll), according to current zoom mode (see View/Zoom Horizontal, Vertical or All for both ways simultaneously). - New MIDI clip editor (piano-roll) mouse hovering effect (eye-candy++). - After too many a user request, a brand new session archive file type is being introduced (.qtz) which tries to bundle in one single zip archive all the media and contents of a session. - Add that to eye-candy: either loop or punch-in/out outer ranges are now shaded on the main track-view, thumb-view and MIDI clip editor (piano-roll) views. - LV2 GTK UI plug-in hosting is now roaring its ugly head. - Ignore all initial and decremental notifications of audio engine's buffer-size changes. - Internal audio buffer loop points were not being set properly for non-zero clip offsets, leaving some as severely out-of-sync while rolling over loop turns. Now fixed again, hopefully. - Avoid audio peak file clashing when deriving from audio sample files with distinct absolute paths but the very same file (base)name. - A new MIDI editor (piano-roll) tool has been added: Rescale event times, durations and/or values by a percentage between 1 and 1000% (adapted thanks to patch by Jesse Lucas). - Attempt to mitigate audio clip sequencing glitches on single-core/single-thread machines. 0.4.7 2010-09-30 The Furious Desertrix - While moving multi-selected MIDI events around the clip editor (aka piano-roll), with help of keyboard arrow keys, that is, was not clear which one was the so-called "anchor" event, the one which positioning gets honored for snap-to-beat business. Not anymore: the anchor event now defaults to the earliest in time or the one the user's last point(-click)ed. - MIDI control observer pattern implementation has sneaked in, making it ready for the so-called and long-awaited "MIDI Learn" feature and arbitrary MIDI controller assignment, for plugin parameters in particular. - MMC DEFERRED PLAY doesn't cause transport state to stop if currently rolling. - Audio clip merge processing might have been skipping a few initial frame blocks, now fixed. - Clip selection and plugin parameter hash optimization. - Anti-glitch audio clip macro fade-in/out fixed again. - New clip fade-in/out slopes (curves) are introduced, partially adapted and refactored from those easing equations of Robert Penner's fame. - Clip fade-in/out non-linear slopes are now shown as actual WYSIWYG curves. - Escape key now closes generic plugin widgets as ever found usual elsewhere. - Picking nits: unselect current track when clicking on any gray empty area, also accessible from a new menu item: Track/Navigate/None. - A nasty and deadly MIDI resolution overflow has been finally fixed, allowing for long MIDI sequences (1h+) to load correctly on 32bit machines from now on (was perfectly fine on 64bit though). - MIDI editor selection hash optimization in face of reasonably huge event sequences. - MIDI controller mapping finally refactored to support some other MIDI event types than just CC (0xBn) ones. - Nitpicking fix: corrected main track-list (left pane) display when no track is currently selected. - libX11 is now being added explicitly to the build link phase, as seen necessary on some bleeding-edge distros eg. Fedora 13, Debian 6. - New audio metronome bar and beat sample gain options. - Progressively, the observer pattern is being finally introduced, targeting all potentially automation controls and widgets as plain ground-zero for the (ultra-)long overdue automation feature. - MIDI controller mapping of still non-existing tracks were being implicitly assigned to the last, highly numbered, existing track. Now fixed. - Moving from old deprecated Qt3'ish custom event post handling into regular asynchronous signal/slot strategy. - Muting/soloing tracks while playback is looping was leaving current audio clip out-of-sync whenever that same track is later un-muted on any other preceding clip. Now hopefully fixed. - MIDI Clock support makes its first appearance. - All tempo (BPM) calculations are now compliant to the MIDI conventional equivalence between beat and quarter note (1/4, crotchet) as common standard time division. - Automatic audio time-stretch option is not enabled by default anymore. - Standard warning Apply button is now only shown when dismissing dialog changes are actually valid. - Make sure non-dedicated metronome and player buses are properly reset and reopen when changing regular audio buses (hopefully fixing bug re. crash after changing audio bus). - Hopefully, an outrageously old bug got squashed away, which was causing random impromptu crashes, most often when importing audio clips while looping and play-head is any near the loop end point. - General standard dialog buttons layout is now in place. - Fixed main track view off-limits play-head positioning. - Main tool-bar Time and Tempo spin-boxes, may now have their colors correct, as for most non-Qt based theme engines (ie. Gnome). Green text on black background has been and still is the the intended aspect design ;) - MIDI file import and internal sequence representation has been changed to be inclusive on all bank-select (CC#0,32) and program-change events which were previously discarded while honoring MIDI track properties. Interleaved SysEx events are now also preserved on their original sequence positions instead of squashing a duplicate into the MIDI bus SysEx setup. - Attempt to include the VeSTige header by default, as for minimal VST plugin support. - JACK transport support has been slightly rewritten, in fact the sync callback is now in effect for repositioning. - The MIDI clip editor (piano roll) widget won't be flagged as a tool window anymore. - A tempo adjustment tool is making inroads from the menu, as Edit/Clip/Tempo... (factory shortcut: F7). - Audio tracks auto-monitoring is now effective on playback. - Make sure to ask whether a dirty MIDI clip should be saved, upon resizing or stretching its edges. - Backward and Forward transport commands are now taking additional stops on loop points. - Attempt to optimize track solo/mute redundant transactions, in special regard to MIDI track events which were being duplicated on soloing and temporarily muted on unsoloing. 0.4.6 2010-05-21 The Funky Deviless - Introducing a non-painting edit sub-mode on the MIDI clip editor's piano-roll (see Edit/Select Mode/Edit Draw menu). - The MIDI clip editor (aka piano-roll) is now a lot more quiet about saving its own dirty content, delegating all salvage questions to main session control. - Don't show session restart message box when changing JACK transport mode option anymore. - Dedicated MIDI control bus switching fixed. Was closing the wrong bus eventually and crashing the whole show with it. - MIDI bank/program backout has been corrected on MIDI track properties dialog rejection (ie. user cancellation). - MIDI bank select method has been corrected for tracks with no instrument defined. - LV2 UI Instance and Data Access extension support added; reduce LV2 external UI parameter value update flickering. - JACK session infrastructure support. - Initial widget geometry and visibility persistence logic has been slightly revised as much to avoid crash failures due to wrong main widget hidden state. - Initial mixer widget extents are now set reasonably larger. - General source tree layout and build configuration change. - Ever since smooth-ramping introduction that having at least one input-only buses were causing immediate playback crashes, now hopefully fixed. - Refactored for common engine client nomenclature, primarily provided by JACK, then secondarily passed to ALSA Sequencer, getting rid of the JackUseExactName requirement and lifting the unique/single instance restriction in the process. - Current JACK Transport, MMC Device, and MIDI Song Position pointer (SPP) control modes are now saved/loaded as part of session option properties. - MIDI clip editor's context menu crash on Qt >= 4.6 has been fixed. - An ancient double-free corruption has been finally fixed at the audio/MIDI bus connection persistence logic. - Improved visibility of track state buttons text (R, M, S) when turned on dark colored themes. - LV2 Save/Restore extension support kicks off. - MIDI engine read-ahead period has been shortened to half than it was since inception--now it's a 500msec cycle. - MIDI clip editor event list gets its due inline editing, for time, note, value/velocity and duration columns, just one double-click away over the target cell ;) - Add-plugin selection dialog position and extent are now remembered across invocations and application sessions (tipping by Frank Neumann). - MIDI clip time-stretching is now made available through the same gestures as audio ones, by just shift+dragging either of the clip edges. - Drag-and-copying plug-in instances (cloning) is now fixed with regard to parameter value replication. - MIDI clip editor snap-per-beat setting is now independent from main multi-track view; File/Save As... dialog fixed; the current event selection is now kept floating as long as it's possible after editing command actions; finally, edit mode has been extended to free-hand event drawing, chalking off (piano roll) draw mode from the TODO list. - Swing-quantize has finally made its overdue debut as an additional MIDI clip editor tool (see Tools/Quantize...). - Almost since its inception, audio inserts were injecting garbage random noise when not being activated, now fixed. - Dedicated audio output ports for MIDI track plugins, now have their connection persistence back in business due on session load. 0.4.5 2010-01-23 A Friskier Demivierge ;) - Changing loop points while playback is rolling, with the play-head any near, was leaving audio clips out-of-sync. - MIDI event list view was missing some selected items with the very same onset time, now fixed. - When failing to detect a SSE enabled build, the CFLAGS variables are now properly restored to their previous sane state, preventing all subsequent dependency tests from false positives (bug# 565860 @bugs.debian.org). - MIDI clip editor (aka piano-roll) multiple selection has been fixed (again) re. move/paste-snapping consistency. 0.4.4 2010-01-16 The Frisky Demivierge - For all the DSSI plugins that have output control ports, a host feedback/update process cycle is now being finally provided: all output control ports are now marshaled to their respective GUI process, rather often and when found open/visible. - MIDI clip editor (aka piano-roll) snap-to-beat behavior on edit mode is now kind of more like 'filling-in-the-blanks' (as Frank Neumann et al. wishes ;) - Fixed MIDI clip editor mistake when reverting to initial clip length, before closing and discard changes (thanks to Frank Neumann, for spotting this one). - LADISH Level 1 support has been added: SIGUSR1 signal trap just makes it a shortcut to File/Save. - Avoid parameter value flickering, due to duplicate command invocation, most evident when changing values massively on native Linux VSTi plugin editor GUIs (thanks to a detailed report on this odd behavior, from Mike of linuxDSP.co.uk). - Another TODO item bites the dust: MIDI event list editor, now acessible from the MIDI clip editor menu (View/Events) - Last used session directory is now made current on startup only when no filename is given on the command line. - Current snap-to-beat setting (time quantization) now affects the anchor event only, while dragging, moving and/or pasting multiple events over the MIDI clip editor (aka piano-roll). - Make anti-glitch audio clip micro fade-in/outs independent from current buffer size as much as possible. - Audio/MIDI engine drift correction gets really sophisticated, with the help of (now old) ALSA MIDI tempo skew facility. - Edit/Clip/Import... menu option is now available for expedite clip insertion from audio and MIDI file requesters. - Set default session directory effective to file's location. - Audio track/clip recording process has been target to special refactorization across the internal audio engine process cycle, in a late attempt to get self-bounce/recording effective and working consistently for all track layouts. - All session related dialogs are now set to window modality, (were set to default application modality before) allowing for continued input focus and interaction on all plugin/tool windows. - An off-by-one nasty old bug fixed in audio clip drawing, was causing instant crashes on certain zoom levels of the main track view. - Graphical MIDI clip representation regarding note/pitch range is now kept as much as possible across clip edits (cut, copy, paste, drag, move, delete, etc.) - LV2 plug-in hosting has finally come into actual implementation; only some and the most basic LV2 plug-in features are supported at the moment; probably there's no big advantage against the old LADSPA ones; there's some support for external UIs though; also, LV2 MIDI/Event bare-bones support is included but chances are it won't build nor work right on most of the setups out there. It's a WIP host implementation anyways, as is the whole LV2 spec. for that matter ;) - Connections filter is now reset when widget is shown through the View/Connections main menu or toolbar button. - Audio bus auto-connection option is now applied when creating or updating, newer or existing buses, respectively. - Global configuration state is now explicitly saved/committed to disk whenever View/Options... dialog changes are applied or when a session is loaded or saved. - Audio ramping spin-locking makes its smooth stuff, in an attempt to reduce glitching and crackling when editing (due to its own pseudo spin-locking) and toggling playback states. - JACK Transport, MMC Device, and MIDI Song Position pointer (SPP) control modes are now made optional (View/Options...), allowing for discretionary configuration: None/Disabled, Slave/Input, Master/Output or Full/Duplex (default). - Session files may now be dragged and dropped over the main track view and get loaded for business as usual (once quietly ignored). - In an attempt to mitigate potential stack corruption and sudden crashes, old commented out session pseudo-locks are now back in business while executing clip editing commands (cut, paste, drag, move, insert, delete) and playback is currently rolling. - Adjusted first-time application window size to fit into 800x600 screen size and with reasonable initial dockables layout. - Avoid duplicate snap-to-grid effect when changing the length of MIDI clip editor events across non-zero clip offsets (after a glitch reported by Ralf Mardorf). - Late audio track processing optimization, suppressing all plugin, mixer and monitor pass-through activity when given track is muted, either explicitly or implicitly (ie. other track is in solo state). - Entering System Exclusive events (SysEx) on the MIDI clip editor (aka matrix/piano-roll widget), yet something not fully supported anyway, even though allowed in edit mode, doesn't crash the whole damn thing anymore, while saving the clip to a file. - Strict aliasing avoidance, with plain and demanded use of 'union', as much as to stop nagging warnings from gcc >= 4.4.1 (last seen on src/qtractorMidiEvent.h hackery). - Visual correct play-head position while changing zoom levels, applicable to both main track and MIDI clip editor views. 0.4.3 2009-10-05 The Fussy Doula - External preset files are not removed nor deleted from the file-system anymore. - Connections support for UTF-8 encoded client/port names. - Force track and clip properties dialog widget to be modal as it should from their beginning dawn. - Audio effect send/return aux. inserts are implemented as special pseudo-plugins (Plugins/Inserts). - Reset play-head position on auto-backward and keep playback rolling when continue past end transport option is not set. - MIDI clip editor (aka piano-roll/matrix aditor) gets better on the virtual piano keyboard eye-candy side of things ;). - Plugins are now also referenced by label, avoiding plugin index clash/misses eg. when plugin object file/path changes or is moved externally. - Keyboard focus is now cleared/reset from the main toolbar time and tempo spin-boxes when editing gets finished (eg. Enter key is pressed). - First audio metronome beat/bar now played back correctly. - Client to/from port (dis)connections now found consistent as good ol'QjackCtl behavior. - All dirty open MIDI clip editors are now prompted to save before the main application closes. - Mixer level meters get their long deserved gradient look. - Fixed any ghost clip selections that were haunting the main track view, specially after undo/redo. - Increased tolerance on reading corrupt MIDI files (SMF). - A MIDI SysEx manager is being finally introduced, in some primordial rather basic form though. MIDI System Exclusive (SysEx) event strings may now be freely assigned to MIDI output buses only, allowing for proper setup of external outboard MIDI equipment. Each bus may have an unlimited SysEx queue that gets sent out on every connection change (see View/Buses.../MIDI/SysEx...). - A default MIDI instrument name may now be assigned to any MIDI output bus (see View/Buses.../MIDI). - More legacy headers, stdio.h and stdlib.h, are yet again necessary to build with gcc/g++ >= 4.4 (as patch noted by Alexis Ballier on Gentoo bug report #274168, thanks). - Bus manager dialog (View/Buses...) gets new columns on the left pane buses list as for displaying number of channels and bus mode. - Crash when updating bus probably fixed. - Fixed glitch displaying beat snap/grid lines on MIDI clip editor, incidental to clips located at absolute zero time. - Overlapped MIDI clips were rendering garbled note events to DSSI/VSTi plugins, now fixed. - New MIDI Playback/Queue timer (resolution) option is now available (see View/Options.../MIDI). - MIDI instrument definitions may now be imported from plain SoundFont files. 0.4.2 2009-06-04 The Flaunty Demoness - The MIDI clip editor (piano-roll/matrix editor), the main track view as well, have been subject to usability fixing, the most notable avoids clearing current selection as much as possible when updating view contents (eg. changing zoom levels does not reset current selection anymore). - MIDI tracks channel bank/program and controller stuff are now only issued when the respective bus connections have changed, seldom on every playback start. - MIDI controller mapping infrastructure, with file based configuration management (see View/Controllers...), is now in place, following an original contribution from gizzmo aka Mathias Krause. - Plugin chain buffer reset on playback start/stop is not guarded by a momentary plugin de/activation anymore. - Clip export may now be applied to multiple clips, sharing common refactored code and same semantics as merging of current selected clips. - Improved, may be just fixed yet again, audio track export synchronization and reliability. - Clip merge is now featured both for audio and MIDI tracks (see Edit/Clip/Merge...). - Improved, or better said, fixed (again) the precision of multi-clip final positioning as result of drag/move and paste operations in main track view. - MIDI track program number is now listed in 1-128 range, in an attempt to be consistent with corresponding MIDI track dialog drop-down list. - MIDI editor snap grid lines get slight different color then regular beat divisions. - Reset local tempo map cursor on newer MIDI file imports in a tentative to fix incidental but random crashes. 0.4.1 2009-04-04 The Funky Dominatrix - MIDI editor command item execution order has been fixed, correcting the redo/undo adjustment of overlapping note events. - MIDI clip editor (aka. piano-roll/matrix editor) sees one of its most wanted features introduced: visual snap grid, now accessible through View/Snap/Grid option toggle. - Actual non-zero session length gets back to status bar of main application window. - One potential buffer-overflow/memory-corruption crash bug has been fixed, long due on most audio (down) sample-rate conversions and affecting audio export in particular. - MIDI track/channel patch information, ie. bank-select and program-change events, are now being properly set on MIDI track/clip export. - SSE optimization is back in town after being mysteriously disabled since its dawn :/ - Looping and punch-recording now actively mutual exclusive states: setting either one unsets the other off and vice- versa. Also, punch-in/out is now made an undoable command. - Moving tracks, any track, up or down, were leaving MIDI playback and meter monitoring completely out-of-sync, now fixed. - Automatic crash-dump reports, debugger stack-traces (gdb), back-traces, whatever, are being introduced as a brand new configure option (--enable-stacktrace) and default enabled on debug build targets (--enable-debug). - Audio/MIDI drift correction is now progressive, taking a least significant differential approach, on every read- ahead cycle and swallowed on loop turn-arounds, as before. - Improved Edit/Clip/Normalize and Quantize commands, now affecting the whole extended multi-clip selection. - Playback is now being temporarily suspended while either transport rewind or fast-forward rolling is engaged. - A bad and shame-on-me bug was fixed: this was hideously affecting any track/clip playback synchronization, most noticeable after toggling solo/mute track states while playback is rolling and skipping the play-head backward over more than one clip under the same track. - A floating-rectangle flip that showed while dragging new files beyond the left of main track view is now gone. - MIDI note event truncation on both track and clip export has been fixed. 0.4.0 2009-03-13 The Foxy Dryad - MIDI (re)connections fix; now caring for the ALSA client and port textual names only, avoiding as much as possible, any reliance on those volatile client and port numbers. - Transport/Backward and Forward commands may now reset to immediate full start or end of session locations, by just pressing the Shift or Ctrl keyboard modifiers and clicking their respective toolbar buttons. - Default session/MIDI resolution has been set to 960 ticks per beat (960 TPQN, where a beat equals a quarter-note); it is worth of note that the previous default resolution was set to one order of magnitude lower, ie. 96 TPQN ;). - Making (dis)connections now also flags session as dirty. - Internal Audio/MIDI engines queue/time drift correction takes a brand new approach, specially adapted to rolling tempo/time-signature changes. - MIDI monitor refresh-cycle slight internal optimization. - Converted obsolete QMessageBox forms to standard buttons. - Transport/Rewind and Fast-forward commands may now be set to double -speed, by pressing the Shift or Ctrl modifiers while clicking their respective tool buttons. - MIDI clip editor zoom ratios are now saved and preserved across sessions. - Time-signature is now directly accessible from the main tempo spin-box which also reflects current tempo status. - Time/frame spin-boxes now allow to step change each field individually, depending on the cursor beam position. - Make sure that Transport/Follow playhead option is only effective when playback is actually rolling. - Primordial attempt to include MIDI Song Position Pointer (SPP), Song Start, Stop and Continue sequencing support. - A completely new time-scale infrastructure is now in place, with full support for session tempo and time-signature map; this long due feature is primarily accessible through the main menu, View/Tempo Map...; also by double-clicking on the the main window and MIDI clip editor time rulers and left-clicking on the main toolbar tempo/signature spin-box. - Moving and resizing individual clips now cares for track proper ordering and overlapping changes, avoiding nasty out of sequence clips and other unpredictable effects. - An expedite MIDI clip quantize command is now available from the main track view menu (Edit/Clip/Quantize), which simply applies the current snap-to-beat setting to a MIDI clip range selection. - Fixed that hideous bug affecting overlapped audio clips when playhead gets moved backward, causing the playback of those audio clips in particular, go out of sync. - Tracks are now limited to their minimum height, specially effective in face of vertical zooming. - Zoom mode option introduced (on menu View/Zoom/Horizontal, Vertical, All). - Tempo beat type is a new session property; however it is not yet user modifiable and currently disabled to default MIDI quarter note (1/4). - All open MIDI clip editor time-scales are now updated and corrected when the main session time base changes (tempo, time-signature, resolution, etc.) - MIDI metronome fixed, preventing duplicate click events. - MP3 audio file decoding was broken for way too long and falling short for every file with custom frames, ID3 tags and comments. Got shamefully fixed. - Time signature denominator (ie. beat divisor) is now an accessible and effective session property. - Attempt to retain original size (clip length) of all audio clips when changing the global session tempo and automatic time-stretching is not an option. 0.3.0 2008-12-25 The Fluffy Doll - Almost complete rewrite of the plugin configuration and parameter initialization logic. - MIDI bank/program selection is now taken into account on plugins initialization and replication. - Fixed initial parameter values for native VST plugins. - Track form plugin lists are now properly (re)initialized when track type changes. - Generic plugin forms now have the option to show/hide the parameter widgets through the new "Params" button. - New auto-monitor toggle option (menu Track/Auto Monitor): the current selected track is now set on monitor and MIDI channel omni-mode automagically, as a convenient workflow feature (kindly suggested by Holborn). - MIDI clip editor Tools menu is not disabled anymore when there's no selection, drop-down menu items are instead. - Make all recorded clips to honor either the punch-out or play-head accumulated position; resolve all pending MIDI sequence note events on record stop/close. - Major silent move: audio plugins chain are now applied in a pre-fader/meter basis as is usually implied from the mixer strip layout ie. signal flows from the top to the bottom. - All MIDI buses may now have plugins inserted so that multi-timbral synth/sampler plugins get driven to their fullness. - MIDI track plugin's dedicated audio output bus may now be effective, as it seems, good old master audio output bus was being used, no matter what. - Paste-repeat command has been introduced, now allowing to replicate and concatenate the clipboard contents over the time-line, with a given repeat-count and optional period (see menu Edit/Paste Repeat... on the main and MIDI clip editor windows). - Normalize tool on MIDI clip editor got rewritten from its previous brain-dead, useless and utterly wrong operation. - All time offsets and lengths are now zero-bar/beat based when displayed in the BBT (bar.beat.ticks) format. - MMC STEP gets adjusted to current snap-per-beat setting. - Fixed broken initial buffering that was randomly crippling those audio clips that fit integrally in cached and while on playback. - Fix initialization of multiple instances of DSSI plugins which implement run_multiple_synths (eg. fluidsynth-dssi), preventing an instant crash on activation. - Exclude deprecated VST elements from compilation. - Export tracks dialog has new punch in/out range option. - Somehow realized that looping and punch-recording are two mutually exclusive states, at least until loop recording (ie. takes) gets real. - Fixed crash on tempo change; affecting the WSOLA based time-stretching on all non-stereo audio clips. - Incomplete audio peaks were being cached prematurely, fixed. - Make way for paste/dropping items from the system clipboard over the main track view. Cut/Copy/Paste/Delete of file items have now this workaround fixed, wrt. Files widget keyboard shortcuts, respectively. - Clip gain/volume propriety is now in place and reflected in audio clip waveform drawing in particular. - A new hideous progress bar is now lurking in the main status line, as found convenient to display progress of the also new clip tools (normalize, export, etc.). - Clip normalize tool is now available (Edit/Clip/Normalize). - Audio and MIDI clip file export is now available as a tool (see Edit/Clip/Export...). - Punch in/out (range) recording is now in experimental shape, with minimal settings and functionality, already accessible through the main menus, transport toolbars and visible on main tracks view and MIDI editors as magenta colored line markers. - External MIDI control events for channel volume (7) and channel panning (10) are now handled properly through session tracks. - Session file templates make its debut with new usability option, on whether new sessions are created based on existing template file (see View/Options.../Display/Session/New session template; nb. session templates are just regular session files but loaded and saved with no media content (no clips nor files). - Grayed/disabled palette color group fix for dark color themes. - Implicit attempt to flush all pending notes for some, if not most plugin instruments (eg. VSTi), on playback stop. - Fait-divers: desktop menu file touched to openSUSE conventions. - Internal refactoring alert: Session and Options instances are now being redesigned as singletons, preparing to get out of the way from the master GUI/MainForm instance. - Clip drawing methods refactored so let the fade-in/out handles get seen with transparency over the clip graphics content. - Reset and continue looping even still when continue past end transport option is not set and playback is rolling. 0.2.2 2008-10-05 The Flirty Ditz - Slight optimization in audio and MIDI meters refresh rate. - Another ancient bug has been squashed: MIDI events were being recorded even though recording wasn't rolling; spurious event times were being recorded due to an absent started queue. - Major fix applied to audio track monitor metering, and most importantly to plugin processing, correcting tentatively all audio buffer offsetting and slicing due on loop turnarounds. - Fixed a potential crash and/or simple record dismissal when changing properties of a track already armed for recording; prevent record engaged tracks from editing or removal. - Lighten up the connections line and highlight colors, as seen to fit best on some darker background themes. - Several icons refined with slight transparent shadowing. - Send/reset all MIDI buses and track controllers (ie. volume and panning) only when main transport playback is started, avoiding the pouring on eg. loop, playhead or tempo changes. - Pressing the Escape key also clears current selection in the main track-view and MIDI clip editor; resizing multiple events at once doesn't need help from Shift or Ctrl modifiers anymore. - DSSI and VSTi plugins get all their default parameters values reset on MIDI program change. - Several major fixes have been applied to the MIDI clip editor, regarding snap precision and correctness, most specially due on clips which weren't located on exact bar boundaries. - Brand new usability feature introduced: mute, solo and monitor toggling may now be applied to all tracks in session at once, when issued with either the Shift or Ctrl keyboard modifiers, which will set or reverse respectively all other tracks state. - Audio buses plugin chain may be also accessed and edited from the extended bus management dialog (View/Buses...). - MIDI meter level default color is now set distinct from the old lime-green one as in audio level meters. - MIDI clip editor is now a genuine top-level window, fixing all keyboard shortcut ambiguities with main application window. - Mixer splitter panes are now collapsible and optionally hidden. - Make MIDI instrument patch management a little more sane, as for preventing the accidental insertion of blank instrument names and automatic default bank/program selection in track properties. - All connections are now based exclusively on the textual client and port names, effective in particular to match MIDI bus ports with disregard to their volatile numerical identification. - MIDI file (SMF) header endianess fix (PPC users rejoyce:)) - Record armed tracks aren't muted for playback anymore, as this was a severe crippling nuisance regarding input monitoring and all mighty user experience after recording a simple take; for instance, as the bottom line goes, there's no need to un-arm a track from its record -enabled state anymore, for just recorded material get heard on immediate playback; kick on the jam! - Playhead position overflow fixed on negative MMC STEP commands. - Thumb-view width proportions now based on minimal slack session length instead of the auto-extending track-view contents width. - Optimize audio clip drawing, most specially on zoomed-out levels. - Bring the audio peak frames into some sort of cache, preventing recurrent peak frame buffer reallocation and trashing. 0.2.1 2008-08-30 The Fainty Diva - Gradient eye-candy now featured for clips, tracks and mixer strips widget backgrounds, disabled on configure time (--disable-gradient). - MIDI pitch-bend/wheel events are now captured/recorded properly; in fact, there was this ancient bug, now squashed, as all MIDI clips weren't being stored at all if there weren't a single note event captured. - MIDI channel translation is finally in effect on monitored tracks, specially the ones set in omni-channel input mode. - MIDI open files dialog gets a few more file filter types now. - Playhead position is now shown, updated and can be also set on the main toolbar session thumb-view (Shift-click to set the playhead). - The floating selection, as shown for a clipboard pasting operation, has been corrected regarding time scale (horizontal zoom) changes, while in the main track-view. Also fixed final position snapping precision. - Current tempo and snap-per-beat setting now survive session cycling. - DSSI plugins implementing run_multiple_synths (eg. fluidsynth-dssi) are now formally supported according to the DSSI spec (hopefully); note that previously one could only have one DSSI plugin instance loaded in session in any given time, otherwise a sudden crash was in sure demand when either plugin got activated. - Audio plugin outputs now overrides each other when the number of output ports does not match the number of mix-down audio channels and thus fixing a nasty crash bug in the process. - All custom font sizes are now set relative to default global font. - Changing loop points by dragging on the time rulers is now mapped as undoable/redoable commands as it ought to be ever since. - Drop-span option (View/Options.../Drop multiple audio files into the same track) now takes into effect the current session snap-per-beat setting when concatenating multiple audio clips. - All plugins get their default bank/program selected on insertion. - Make record armed tracks muted for playback, a needed regression to let both audio and MIDI tracks behave consistently regarding input monitor switching through output. - Fixed a pretty old and shameless bug regarding MIDI clip recording, in which cases the queue start time offset was not taken into account, with captured events being recorded with erratic long delays. - Almost complete refactoring of the clumsy audio peak file classes, possibly making it even clumsier but straight neverthless, with the noble and final aim to build it in-flight and draw the waveforms while recording is rolling. - Recording clips get their initial name labels drawn while fade-in/out handles are dropped as found pretty useless while recording. - Escape key now closes connections and mixer widgets as found usual. 0.2.0 2008-07-18 The Frolic Demoiselle - MIDI clip filename revision logic is now introduced, thus avoiding the proliferation of several numbered SMF's on each edit/save; some lurking bugs were exposed in the MIDI clip externalization method but promptly squashed. - Fixed a mouse release event glitch while in drag-and-drop items in the Files tree list widget. - A dummy plugin type option has been devised, just to bear with some troubled behavior of the lovely JUCETICE plugins (View/Options.../ Plugins/Experimental/Dummy VST plugin scan). Bad news are that all, yes all as in every native VST plugins, are indistinguishable from being just pure audio effects, either mono or stereo, whatever, and thus all being considered full-blown stereo VSTi instruments (which are the vast mainstream and rather interesting majority, nevertheless:). - The plugin selection dialog (Add Plugin...) now features the option whether the selected plugins should be activated on insert. - Mixer strip titles now have distinguishable type icons, either for audio or MIDI, and shown on all buses and track strips. - Major optimization breakthrough: muted audio tracks aren't streamed any longer, saving precious CPU cycles from decoding, resampling, pitch-shifting, time-stretching, plugin effects, whatever. - Incredible as it might be, audio/MIDI track record monitoring is now mixed (or merged) with rolling playback content, thus not as mutually exclusive between record and playback states anymore; also, track mute/solo states doesn't apply to recording material anymore. - Main form timer slot gets corrected and now independent of current process buffer-size in regard to JACK transport synchronization. - All file references in session state file are now stored as relative paths to main session directory. - DSSI/VSTi plugin presets can now be explicitly recalled from file (ie. Open/load preset) through this new tool button whether visible while in the generic plugin form. - Due to some trouble with newer Qt >= 4.4 applications regarding font size configuration, a new global user option is now available to the rescue: View/Options... /Display/Base font size (default is no-op). - Logarithmic scale is now taken into effect by control parameter sliders, in the generic plugin editor dialog as provided by LADSPA and DSSI plugin types. - MIDI track bank/program does not default to zero (PC#0) anymore. - Second attempt for Qt4.4 build support, regarding the bundled atomic primitives, now corrected and way more seriously :). - Long due DSSI/VSTi plugin host implementation has taken shape for MIDI instruments (eg. soft-synth plugins); DSSI reached its full host implementation and VSTi is already kicking as well. - DSSI/VSTi plugin presets may now be stored to external XML files, which should include all parameter values and configuration data chunks, taken as proper state snapshot and subject for recall. - Dedicated audio output bus option is now also accessible for all MIDI instrument plugins, either set globally as a default mode in View/Options.../Plugins/Instruments or in the plugin context menu for MIDI tracks, as an undoable command. - Fixed a potential crash-exception due to freeing a null-pointer, raised on some ever stringent platforms and while adding tracks to empty sessions, which is the same to say this was crashing more than always:). - Loop turn-around is now taken care of, as this has been found missing and causing noticeable gapping when un-muting or changing MIDI track events while in playback. - An off-by-one bug was fixed while inside MIDI cursor backward seek method, which was missing all other events that have the same exact onset timing. - Attempt to load Qt's own translation support and get rid of the ever warning startup message, unless built in debug mode. (transaction by Guido Scholz, while on qsynth-devel, thanks). - Only one application instance is now allowed to be up and running, with immediate but graceful termination upon startup iif an already running instance is detected, which will see its main widget shown up automatically (Qt/X11 platform only). - Clip fades have now a slight transparency. - Avoid loop read-ahead on initial audio clip loading. - Messages file logging makes its first long overdue appearance, with user configurable settings in View/Options.../Logging; options dialog was slightly rearranged and moved the Plugins section into a new tab page. - Audio/MIDI drifting correction was missing its own correct and due (re)initialization whenever playback is (re)started; also, MIDI metering synchronization has been fixed once again. - Fixed session cursor backward seeking, specially applicable when playback passes the end of overlapped clips. - Fixed potential crash when opening bogus audio files. - Time-stretch FIFO buffer implementation is now made generic, as template, fixing a destructor memory leak in the process. - Include legacy headers, stdlib.h and string.h, where necessary to build with stricter gcc/g++ >= 4.3. 0.1.3 2008-05-02 The Frugal Damsel - As one may find convenient sometimes, the global time display format (frames, time or BBT) may now be changed on the main transport time spin-box context menu. - Left-clicking on the track list number column now toggles all track content clip selection. - Prevent audio-buffer initialization mashups when editing short audio clips while playback is rolling and within clip region. - Audio peak files gets a bit simplified, dropping the peak frame count from its header; peak waveform graphics are now rendered as straight lines when over the end of audio file. - The drop-span option (View/Options.../Drop multiple audio files into the same track) now also applies when importing tracks (as in Track/Import Tracks/Audio...) to concatenate multiple audio clips into one and the same new track. - Audio and MIDI meter level colors are now user configurable (as global configuration options, View/Options.../Display/Meters) - First attempt for Qt4.4 build support, regarding the bundled atomic primitives, which have changed upstream as advertised (thanks to Paul Thomas, for spotting this one first time). - Record monitor switch is now an accessible button option on all track mixer strips; for visual consistency, the old bus "thru" switch button has been renamed to "monitor". - Force track-view position reset to origin on session close. - Fixed segfault on inserting an external file into files widget. - Mixer splitter sizes are now better saved/restored when closed. - Track record monitoring is now a state option, being toggled from the Track/State/Monitor menu; applies both to audio end MIDI tracks: when set all input will be pass-through to the current assigned output bus, including track plug-ins chain. - Session dialog gets split in its own tab components, between descriptive, time and view configuration ones. - Drifting correction among audio and MIDI engines is now back, but avoided while recording or should it be while looping? - Time-stretching percent value gets its semantics inverted, as thought consistent with ones general sense for relative stretching ie., lower to shrink and higher to make longer. this is a major up-side-down change and should affect all sessions saved with time-stretched audio clips. - Slack space in main tracks and MIDI clip editor views are now proportional to viewport width, leaving enough room for drag and moving content past the current session length, specially at the lower zoom levels. - Clip end time is now also shown on tool-tip. - When armed for recording, MIDI tracks are now monitored and filtered through their own output bus, thus having the same behavior as audio tracks; this also implies that all record armed tracks won't playback their current content material when recording is engaged and rolling; track mute and solo states are now honored on record monitoring. - Audio clip pitch-shifting makes its first appearance, with the optional help from Chris Cannam's RubberBand library. - A new MIDI editor tool is available: note/pitch randomize. - Avoid (re)setting the default session directory if a session cannot be open or loaded for some reason. - Another nastiness bites the dust: a subtle but progressive drifting has been swept away from the audio buffer looping; zero buffer flushing is now also taken into account, which was the cause for serious drifting on time-stretched clips. - A major digital audio processing bug was tamed: audio clip fade-in/outs are now linearly piece-wise applied, even at the clip edges, giving a much smoother rendering and thus mitigating the nasty click-and-pop artifacts that were in fact due to some early design optimization with a poor and sloppy implementation. 0.1.2 2008-03-23 The Frantic Dame - Session length fixed (yet again) while extend recording; also improved follow-playhead switching while playback/recording. - Whitespace sanitization gets leaner for all recorded filenames. - Run-time SSE optimization detection has been improved while on configure; additionally, IEEE 32bit float specific optimizations have also sneaked in. - SSE optimization is now featured over all audio monitoring, and most specially on audio bus buffering, lowering the CPU burden a bit while doing track and bus gain, pan, metering and mix-down. - Fixed MIDI clip move into new track, preserving the original channel, bank and program whenever possible. - Fixed session cursor seeking, specially regarding overlapped clips, once gain. - The MIDI editor gets new menu access to current MIDI clip track (see File/Track/Inputs, Outputs, Properties); selection of MIDI events has also been improved, specially regarding overlapped note events. - Clip split command enters the stage (see Edit/Clip/Split) about splitting the current (selected) clip at the current playhead position (red cursor line). - Creating new clips from scratch is now finally permitted (see Edit/Clip/New...); additionally, the clip properties dialog is now also allowing for changing the filename (and track/channel as special to MIDI clips). - Record armed tracks are now properly monitored and fed through their own output audio bus on mix-down, which includes plug-in effects processing. - The files widget get alternating coloured rows. - VST plug-in preset values are now being restored properly; individual parameter changes are now being queued for the also convenient undo/redo command pattern. - Some audio clip buffer-sync tweaks have sneaked in, improving and fixing the rendering of full-overlapped, integrally cached and/or offset clips altogether. - Stuffed one primordial shot on XInitThreads() at the main head, and let native VST plug-ins start behaving as they should, or not; this might be in fact problematic and dangerous for people who won't ever try the JUCE based plugins as from JUCETICE (http://www.anticore.org/jucetice), due to some broken locking mechanism in xcb; thanks anyway to mighty kRAkEn/gORe@JUCETICE for this precious hint and from who knows best. - True deterministic session length update has due fixed. - Track menu has new accessible actions: Track/Inputs - show current track input bus connections; Track/Outputs - show current track output bus connections; Track/State/Record - arm current track for recording; Track/State/Mute - mute current track; Track/State/Solo - solo current track; Track/Navigate/First - make current the first track; Track/Navigate/Previous - make current the previous track; Track/Navigate/Next - make current the next track; Track/Navigate/Last - make current the last track; Track/Move/Top - move current track to top; Track/Move/Up - move current track up; Track/Move/Down - move current track down; Track/Move/Bottom - move current track to bottom; - View menus have new accessible actions: View/Zoom/In - horizontal and vertical zoom-in (Ctrl +); View/Zoom/Out - horizontal and vertical zoom-out (Ctrl -); View/Zoom/Reset - reset both zoom levels to default; View/Snap - select current snap-per-beat setting; - Plug-in forms don't auto-open on session reload anymore. - Keyboard shortcuts icon item (Help/Shortcuts...) sneaks in. 0.1.1 2008-02-16 The Futile Duchess - After some great user demand, keyboard shortcuts are finally configurable, as found provisionally under Help/Shortcuts..., for the main application menu and for the MIDI editor as well. - Debian package gets SSE optimization disabled as default. - At least some transport actions get to be non auto-repeatable when pressed for much too long, as Play and Record, avoiding the tumbling imposed from the keyboard. - For the first time ever, jackd auto-start is now allowed (!). - OSC service support through liblo gets optional at configure time, now leading the way to proper DSSI plug-in hosting. - All plug-in widget controls count are now capped to one hundred. - Plugin paths setup is now made available on the options dialog, overriding each of respective default settings, as implicit from the LADSPA_PATH, DSSI_PATH and VST_PATH environment variables (see View/Options.../Display/Plugin Paths). - Clip fade-in/out lengths are now kept relative to tempo changes and also to clip offset and length changes (clip resizes). - Automatic time-stretching for all audio clips when session tempo changes, may now be disabled/enabled as a global session option (see View/Options.../Audio/Playback/Automatic time-stretching). - Double-clicking on an empty area (de)selects all clips on track. - MIDI capture (record) quantization is now an option, possibly handy for some jerky performance musicians, as the one found in myself ;) (see View/Options.../MIDI/Capture/Quantize). - The global options dialog (View/Options...) has seen its Display tab page being moved back and to the right. - Major rewrite of the plug-in infrastructure, adding primordial support for DSSI and native VST plug-in flavors. - Drag-and-drop of plug-in instances are now allowed intra- and inter-mixer strip chains, either on tracks or buses. - Turning track record off while recording is rolling was leaving the session in a inconsistent recording status, now fixed. - A random but instant crash upon audition/pre-listening player onset was hopefully fixed. 0.1.0 2008-01-05 The Frivolous Debutante. - Audio clip time-stretching makes its debut, with code adapted and refactored from the SoundTouch library, under the (L)GPL umbrella. - New "Options.../Audio/Playback/Quick seek time-stretching" global option, providing a quick seek mode (hierarchical search) while doing all audio buffer time-stretching. - Changing session tempo will automatically apply the corresponding time-stretch percent factor to all in-place audio clips. Audio clip dialog also includes a new time-stretch property setting. - Tempo changes are now affecting clip offsets correctly, keeping the clip offset constant in time units (ticks), as are clip start and length properties already. - Mixer splitter sizes are now properly saved/restored when hidden. - Extended multi-selection is now featured on the files widget; all drag and drop functionality has been almost completely rewritten. - SSE optimization is now enabled where available (via configure). - Options for having separate dedicated ports for the audition/pre- listening player output, audio metronome output, MIDI control input/output and MIDI metronome output, are now in place. - A brand new subtle option sneaks in, affecting the drag-and-drop of the main track-view: View/Options.../Drop multiple audio files into the same track, whether to drop multiple external files into new or existing track as concatenated audio clips. - The audio metronome makes its debut as an alternative to the MIDI existing one; parameters include bar and beat audio sample files, accessible from the View/Options.../Audio/Metronome dialog. - Files widget action refactorization; the files context menu gets its due item icons and a new menu item for direct audio player accessibility. - MIDI time resolution changes (ppqn, ticks per beat) now tries to keep all session MIDI clip times unchanged as far as possible. - MIDI channel volume and panning control change events, CC#7 and CC#10 respectively, are now rendered unfiltered on playback. - First rendition of the long due implementation of an audition or pre-listening audio player is now in place; the files window got this new play/stop control button on its lower-right corner. - Actual instrument definition note (keys) and controller names are now in effect on the MIDI editor, whenever applicable. - Fixed instrument bank selection method, "Bank MSB" (2), which was broken enough to never send the correct bank number. - Mouse-wheel horizontal scrolling is now accessible on every view, while pressing a modifier key (Shift or Ctrl). - New auto-backward transport option: when enabled the playhead will be reset backward automatically whenever transport stops playing. - A suicide-crash has been fixed while invoking the bus dialog from the respective mixer bus strip context menu. - Master (default) buses are always set to Duplex mode, being now an enforced update policy while on the Buses dialog. - A stupid lockup bug (infinite loop) was spotted on the track bus assignment method and squashed (thanks, lexridge). - New keyboard shortcuts for toggling the Connections tool (F8) and the mighty Mixer tool (F9) windows. - Avoid showing a context menu while right-clicking on time rulers. - Audio clip waveform drawing gets additional closing points. - It is now possible to change the length/size of a clip by dragging its left or right edges, while in the main track-view. Shift/Ctrl+drag will also time-stretch to the resulting audio clip length. - Another off-by-one mistake was corrected, which was causing audio clips to go out-of-sync on loop turnover boundary; also changed the loop turnaround strategy, now honoring already cached periods. - A race-condition has been mitigated in the audio-buffer thread, that was exposed and lead to sudden application freezing upon changing some composite audio clip commands. - Take absolute audio peak values only, making peak files a little bit shorter and hopefully faster to load and draw as waveforms. 0.0.9 2007-11-30 The Adolescence Prime - Drag-and-dropping of MIDI files without specific track or channel, into existing tracks, is now rejected. The drop operation is now allowed on the track-view blank area only, meaning the same as the complete MIDI file import into session. - Record actual MIDI clip length to last play-head position, instead of time of last event in the recorded sequence. - Connections item lists gets properly sorted, as intended. - Clear connection persistance once an explicit discconnection is issued on any of the (intrinsic) bus ports. - MIDI output buses now get the panning slider to spit out some GM system master balance (sysex) messages, being now enabled. - Mouse hovering on the clip fade-in/out handles, while in the main track-view, gets its long due cursor pointer feedback. - Fixed a off-by-one boundary issue on MIDI clip event playback, which were enqueuing duplicated MIDI events on every read-ahead output thread processing cycle (1 sec). - Transport menu and toolbar are now featured on the MIDI Editor. - Use actual session name when asking to save changed session. - Transport loop setting keyboard shortcuts swapped: Ctrl+L will set the loop immediately, and Shift+Ctrl+L will toggle on/off. - Changing MIDI event duration may now affect MIDI clip duration. - Alternate sharp-note color lines have returned to MIDI Editor canvas, as was the shadow color marking the end of MIDI clip. 0.0.8 2007-11-12 The Twelfth Tight - Bus context menu is now accessible from respective mixer strip. - Fixed a subtle crash-suicide issue when invoking the bus dialog with a double-click over the corresponding mixer bus strip; also fixed the sloppy ganguing mistake when changing mixer bus gain (volume) and panning values. - MIDI Omni mode (sort of) makes its entrance as a new MIDI track property, meaning that is now finally possible for the capture of any unfiltered MIDI channel event, without regard to the current channel assignment, which still applies for playback purposes. - Audio (pass-)through has been also implemented, now being a common and consistent property of both audio and MIDI buses, provided those are set in duplex mode (input and output). - Re-touched follow-playhead and continue-past-end tool icons, again to be a bit softer and not so bright as to hurt someones eyes. 0.0.7 2007-10-31 The Eleventh Tower - Suspend auto-follow-playhead while dragging or moving content over the main track and midi editor views; re-touched follow-playhead and new continue-past-end tool icons. - Playback is now forced complete full-stop whenever play-head goes behind the current session length and/or loop-end and the newer "continue past end" option is enabled from transport menu. - Tool/child windows position and size preservation fixed. - MIDI (pass-)through has been finally implemented, after several kind requests, it applies as a property of duplex-mode MIDI buses; this new setting is configurable from the View/Buses... dialog; also from respective new input bus mixer-strip button; when enabled, implies all incoming MIDI events at the input bus will pass-through unchanged to the corresponding output bus, as found useful just for direct monitoring one's performance without the help of any extra circumvent or kludgy connections. - Mouse cursor shape changes accordingly while hovering in header time-scale rulers, both in main track-view and MIDI editor. - Track-view clipboard paste action has been refactored, with the user interface consistent with the same functionality featured on the MIDI editor: the clipboard selection being pasted now floats at the mouse pointer and can be moved around before placed into its final position, either with the mouse or keyboard arrow keys. - A unitialized member variable bug affecting all MIDI clips has been discovered and squashed; this one has been lurking for quite some time and was causing wrong clip editing results, specially when tempo or meter differs between session and the MIDI file. - Keyboard step-moving is now allowed while pasting in MIDI editor. - Track-view clip selection can now be drag-moved into the void (bottom) view area creating brand new tracks automagically. - Losing focus resets all current keyboard step-moves in progress, affecting the main track-view and all MIDI editor as well. - As done before on the MIDI editor, the main track-view current selection may be step-wise moved using the keyboard arrow keys and the enter /insert keys for final placement; horizontal step movement is quantized according to current snap setting; vertical key-step movement is only allowed to selected clips belonging to one single and the same track. - Immediate session loop setting, accessible from the main menu. - Track properties dialog gets fixed again in its auto-size treat. - Another audio-buffer thread bug was scrubbed off, which was causing spurious and audible garbage on certain loop workloads. 0.0.6 2007-10-09 The Tenth Commencement - A bit more of precision is achieved over the metronome regular ticking and both the audio and MIDI monitor meters. - A rudimentary MIDI metronome is now in place; parameters, like MIDI channel, bar and beat accent note, velocity and duration, are readily configurable from the main menu, View/Options... /MIDI/Metronome dialog. - Track properties dialog now gets tightly auto-sized, depending whether its an audio or a MIDI track. - MIDI clips are now auto-extendable when adding or moving events beyond the clip length and while in the MIDI Editor, of course. - MIDI editor current selection can now be step-wise moved using the keyboard arrow keys and the enter/insert keys as for final placement; horizontal step movement is subordinated to current snap per beat setting, no less than unity; vertical step moves are obviously quantized to the next semitone. - Get configure to try and detect the correct qmake location and insert it the search order, so let the qt4 tools take precedence when --with-qt option is given and older qt3 ones coexist and are found located ahead in the PATH. - Drifting correction on audio and MIDI engines was seriously infected in some kind of snafu conception, as evidence lead to even worse drifting being detected to much of great despair, specially after recording and/or bouncing audio tracks from MIDI sequenced material. Credit must certainly go to Christian Schoenebeck on splatting this sloppy one on the face. - MIDI editing actions while playing now get immediate feedback; this was possible to some internal interface redesign of all MIDI editor accessory classes, making the MIDI clip now being the main editing target object instead of just the MIDI event sequence as it was previously. - Simple as it could ever be, the build executive summary report is now given on configure. - The internal decoded frame list for MPEG 1Audio Layer III (mp3) audio files (ie. via libmad) has been made one-time cached as global shared objects, benefitting from the fact that the list is always completely (re)built during the peak file computation, and thus speeding up all frame accurate access operations (seek) over this specific audio file format. - More eye-candy is sneaking in the MIDI editor: there's new view options on the View menu: Note Color and Value Color, affecting note event colors according to pitch and/or velocity. - New view option on the MIDI editor: on menu View/Note Duration switches whether events are shown proportional to their durations or as simple vertical candlesticks. - New snap-per-beat divisors are now available (Beat/3, 6, 12, 24 and 48), giving support for triplets for the very first time (after a heads-up suggested patch from Marko, thanks). 0.0.5 2007-09-08 The Ninth Hitch Nail - MIDI edit tools (quantize, transpose, normalize, randomize, resize) are all functional and ready for experimentalism; gets in its own top-level menu and form with named preset store and recall functionality. - Main form backward and rewind transport actions are now being immediately enabled when playing from the session (zero-time) start position. - Audio and MIDI export sneaks in and in form and accessible from the main Track menu. - MIDI track channel is now properly set on session (re)load; track background color changes was missing the alpha setting. - The mix-down buffering was fixed again, now taking multi-track overlapping clips into consideration (was a lot more broken since the recent glitch-looping fix). - Dirty MIDI clip editing control has been fixed but still somewhat hacky nevertheless. - First attempt on solving a nasty MIDI editor bug, which was quietly and severely crippling MIDI files while saving offset edited clips. - Session loop (re)setting is finally now an undoable command. - Yet another insidious bug has been swept away from under the carpet: once again on audio looping, some astonishing old and crappy session cursor seek-backward statement was lurking to be laid off. Gone now, simply as it is, growing old on this :) - A tremendous bug has been fixed: audio looping is now a little more glitch-free as the mix-down buffering was badly broken even since its primordial implementation. Rejoice. - Minor improvements on track-view cursor updates and visual tracking while recording. - MIDI editor windows get their keyboard accelerator/shortcuts back in business, whether opted as tools always on top or not. - The infamous "Keep tool windows always on top" global option is now infecting the Connections, Mixer, Plugin and MIDI Editor window instances with no probable regrets. To be used with discretion, of course. - Session update/initialization gets it clean on startup. - Range selection action (Ctrl+R) is now back in business with the added bonus of being accessible from all MIDI editor instances too. - Common edit-head and tail cursor positions are now under common control and display from all MIDI editor instances; the session loop-start/end points are now also shown on every time-line and share the same control behavior across all MIDI editor instances. 0.0.4 2007-07-19 The Eighth Wanderer - Main toolbar tempo spin-box gets loose from keyboard change tracking (Qt >= 4.3); custom spin-box compilation fix for Qt 4.1. - Illusive but nasty Connections/Patchbay item tooltip crash bug has been hopefully fixed (Qt >= 4.3); QComboBox::editTextChanged() signal replaces old QComboBox::textChanged(). - Combo-box setup history has been corrected on restore, which was discarding the very initial default (factory) contents. - Make debian package build depend on libqt4-dev; win32 console flag is back to qmake project file. - MIDI instrument selection (e.g. on track form) gets fixed and improved. - Sorting method for the connections port list has been refactored; potential crash bug fix on connections sorting method. - Messages class accessor methods constness fix. - Got rid of some autoconf redundand thingies on configure; late debian changelog update. - Desktop categories update: AudioVideo. - README correction. 0.0.3 2007-06-23 The Seventh Draught - Crash fix on the connections widget, was a matter of refactoring the refresh/clear slots. - Help menu added to MIDI editor form (redirected and same to main form anyway). - Clip properties form gets its proper sanity check, querying any existing clip editor whether its safe to apply the new settings. - Mixer sliders get their long due valued correction, hopefully. - Transport backward and play/stop are now made accessible from the MIDI editor widget, through their keyboard accelerator shortcuts (backspace and space, respectively). - Transport actions (play, rec, rew and ffwd) are now kept stable on a single point, instead of being scattered all over the main form code; transport visual feedback might get affected, specially regarding the MMC processing. - Application icon is now officially installed into ${prefix}/share/pixmaps. - Spec file is now a bit more openSUSE compliant; just made RPM requirements as exigent as the new debian ones. - Paste cursor is now properly preserved after leaving MIDI editor views. - Amazingly why this was not spotted before, the main application logo-icon has been downscaled to the 32x32 pixel standard icon size. - MIDI clip editor clipboard gets singleton status and is now shared on all MIDI editor instances. Similarly to the main track-view, Shift/Ctrl-left-clicking on the MIDI editor views sets the current session play-head position. - A desktop entry file has been included on install, at last. - Clips in main track-view get more info in the form of tooltips. - Major rounding fix to time-scaling and most specially on all those internal MIDI I/O methods. - Extended range selection from the time-ruler and key-list headers is now possible by click-and-drag the mouse pointer. - Play-head cursor is now also displayed and/or set position on all open MIDI clip editors time line view. As in the main application form, a new local follow play-head option is also featured on the MIDI editor view menu and toolbar. - All MIDI file save operations are now logged to main messages and files are added to the main files list view. - Initial debianization. - MIDI capture/record file format (SMF Format 0 or 1) is now an user option, introducing the new MIDI tab on the global View/Options dialog. - A bad old-time session cursor glitch has been apparently fixed. - Make sure the generic clip properties form is modal. - Major rewrite and adaptation to the session time-scale properties, making its way for a brand new command instance: the session-tempo command. - Changing the snap-per-beat combobox value on the main window toolbar does not make it as an undoable command anymore. - Long due MIDI clip editor integration has come to reality. - Major rewrite on the MIDI sequence file read/write methods, in preparation to the coming MIDI clip editor. - Status-bar session length label now gets rightly updated, while extended recording, of course. - Clip properties fade-in/out lengths, gets their old due constraints. - Main transport time display is now an editable custom spin-box; the Tempo (BPM) spin-box has seen new colors (green on black). - Transport time display format option adds the new choice of absolute frame number, alternative to previous time and BBT. - The frame-time based spin-boxes, on the clip properties form, were replaced with a new custom one, allowing for alternate frame, time and bbt input/display formats. - Time-scale helper class has been introduced. 0.0.2 2007-05-26 The Sixth Lord - Audio/MIDI connections gets slightly refactored, contributing for whole robustness, specially in case of incidental engine shutdown. - Mixer window gets a minimum default height bump. - Clip fade-in/out type changes have been properly fixed. - Complete refactoring of the command class pattern, making it now derived from QObject and not having a reference to the main form anymore. - Inoperative context menu event handler has been removed from the track-view. - MIDI sequence note-on event tracking now uses faster QHash class, instead of original QMap. - Off-by-one bug fix on MIDI track write method, while parsing co-incident note-on/off events in the wrong order and thus leaving note events with an invalid (zero) duration; obviously affecting MIDI recording in very special circumstances. - Minor and rather innocuous drop at this time in the MIDI event class structure: the flags member field. - Port connections now get their lines correctly drawn; strangely enough, the connection lines were being painted only for the parent client items, probably since the Qt4 migration (aka. Halloween files). - Early clip editing is in place (clip name, start, offset and length parameters, fade in/out length and type). - Some menu item text capitalization. 0.0.1 2007-05-07 The Filthy Fifth - Newer JACK 0.105.0 seems to bitch, probably correctly, about the return value of the process callback. Make it to bitch no more by ensuring the JACK client is always issuing the innocuous 0 (zero) return value. - Important fixes have been issued, affecting MIDI recording: MIDI sequence zero-time event insertion; MIDI file pending note-off processing on write-track method. - Qt4 migration complete. 0.0.0 2006-10-31 The Halloween Files qtractor-0.5.11/PaxHeaders.10084/configure0000644000175000001440000000013012224470520016354 xustar000000000000000029 mtime=1381134672.12908013 30 atime=1381134671.986080128 29 ctime=1381134672.12908013 qtractor-0.5.11/configure0000755000175000001440000067303212224470520015663 0ustar00rncbcusers00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for Qtractor 0.5.11. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and rncbc@rncbc.org $0: about your system, including any error possibly output $0: before this message. Then install a modern shell, or $0: manually run the script under such a shell if you do $0: have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='Qtractor' PACKAGE_TARNAME='qtractor' PACKAGE_VERSION='0.5.11' PACKAGE_STRING='Qtractor 0.5.11' PACKAGE_BUGREPORT='rncbc@rncbc.org' PACKAGE_URL='' ac_unique_file="src/qtractor.cpp" ac_default_prefix=/usr/local # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS ac_cflags ac_incpath ac_libs ac_pkg_config ac_lrelease ac_lupdate ac_uic ac_moc ac_qmake EGREP GREP CXXCPP ac_ct_CXX CXXFLAGS CXX CPP OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC ac_debug ac_prefix target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_debug enable_libvorbis enable_libmad enable_libsamplerate enable_librubberband enable_liblo enable_libz enable_lilv enable_suil enable_sse enable_ladspa enable_dssi enable_vst enable_vestige enable_lv2 enable_lv2_event enable_lv2_atom enable_lv2_worker enable_lv2_ui enable_lv2_external_ui enable_lv2_state enable_lv2_state_files enable_lv2_programs enable_lv2_presets enable_lv2_time enable_lv2_options enable_lv2_buf_size enable_jack_session enable_jack_latency enable_nsm enable_xunique enable_gradient enable_stacktrace with_qt with_jack with_alsa with_libsndfile with_libvorbis with_libmad with_libsamplerate with_librubberband with_liblo with_libz with_liblilv with_libsuil with_ladspa with_dssi with_vst with_lv2 ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP CXX CXXFLAGS CCC CXXCPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures Qtractor 0.5.11 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/qtractor] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of Qtractor 0.5.11:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-debug enable debugging (default=no) --enable-libvorbis enable libvorbis interface (default=yes) --enable-libmad enable libmad interface (default=yes) --enable-libsamplerate enable libsamplerate interface (default=yes) --enable-librubberband enable librubberband interface (default=yes) --enable-liblo enable liblo interface (default=yes) --enable-libz enable libz interface (default=yes) --enable-lilv enable LILV interface support (default=yes) --enable-suil enable SUIL interface support (default=yes) --enable-sse enable SSE optimization (default=yes) --enable-ladspa enable LADSPA plug-in support (default=yes) --enable-dssi enable DSSI plug-in support (default=yes) --enable-vst enable VST plug-in support (default=yes) --enable-vestige enable VeSTige header support (default=yes) --enable-lv2 enable LV2 plug-in support (default=yes) --enable-lv2-event enable LV2 plug-in MIDI/Event support (default=yes) --enable-lv2-atom enable LV2 plug-in MIDI/Atom support (default=yes) --enable-lv2-worker enable LV2 plug-in Worker/schedule support (default=yes) --enable-lv2-ui enable LV2 plug-in UI support (default=yes) --enable-lv2-external-ui enable LV2 plug-in External UI support (default=yes) --enable-lv2-state enable LV2 plug-in State support (default=yes) --enable-lv2-state-files enable LV2 plug-in State Files support (default=yes) --enable-lv2-programs enable LV2 plug-in Programs support (default=yes) --enable-lv2-presets enable LV2 plug-in Presets support (default=yes) --enable-lv2-time enable LV2 plug-in Time/position support (default=yes) --enable-lv2-options enable LV2 plug-in Options support (default=yes) --enable-lv2-buf-size enable LV2 plug-in Buf-size support (default=yes) --enable-jack-session enable JACK session support (default=yes) --enable-jack-latency enable JACK latency support (default=yes) --enable-nsm enable NSM support (default=yes) --enable-xunique enable X11 unique/single instance (default=no) --enable-gradient enable gradient eye-candy (default=yes) --enable-stacktrace enable debugger stack-trace (default=no) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-qt=PATH use alternate Qt install path --with-jack=PATH use alternate JACK install path --with-alsa=PATH use alternate ALSA install path --with-libsndfile=PATH use alternate libsndfile path --with-libvorbis=PATH use alternate libvorbis path --with-libmad=PATH use alternate libmad path --with-libsamplerate=PATH use alternate libsamplerate path --with-librubberband=PATH use alternate librubberband path --with-liblo=PATH use alternate liblo path --with-libz=PATH use alternate libz path --with-liblilv=PATH use alternate liblilv path --with-libsuil=PATH use alternate libsuil path --with-ladspa=PATH use alternate LADSPA header path --with-dssi=PATH use alternate DSSI header path --with-vst=PATH use alternate VST header path --with-lv2=PATH use alternate LV2 header path Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor CXX C++ compiler command CXXFLAGS C++ compiler flags CXXCPP C++ preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF Qtractor configure 0.5.11 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp # ac_fn_cxx_try_link LINENO # ------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_link # ac_fn_cxx_try_run LINENO # ------------------------ # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_cxx_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_run # ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES # --------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_cxx_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ------------------------------ ## ## Report this to rncbc@rncbc.org ## ## ------------------------------ ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_header_mongrel # ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES # --------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_cxx_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_header_compile # ac_fn_cxx_check_func LINENO FUNC VAR # ------------------------------------ # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_cxx_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by Qtractor $as_me 0.5.11, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers src/config.h" ac_config_files="$ac_config_files Makefile qtractor.spec src/src.pri src/qtractor.desktop" # Set default installation prefix. ac_prefix=$prefix if test "x$ac_prefix" = "xNONE"; then ac_prefix=$ac_default_prefix fi cat >>confdefs.h <<_ACEOF #define CONFIG_PREFIX "$ac_prefix" _ACEOF # Enable debugging argument option. # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; ac_debug="$enableval" fi if test "x$ac_debug" = "xyes"; then $as_echo "#define CONFIG_DEBUG 1" >>confdefs.h ac_stacktrace="yes" ac_debug="debug" else ac_stacktrace="no" ac_debug="release" fi # Enable libvorbis(file) availability. # Check whether --enable-libvorbis was given. if test "${enable_libvorbis+set}" = set; then : enableval=$enable_libvorbis; ac_libvorbis="$enableval" else ac_libvorbis="yes" fi # Enable libmad availability. # Check whether --enable-libmad was given. if test "${enable_libmad+set}" = set; then : enableval=$enable_libmad; ac_libmad="$enableval" else ac_libmad="yes" fi # Enable libsamplerate availability. # Check whether --enable-libsamplerate was given. if test "${enable_libsamplerate+set}" = set; then : enableval=$enable_libsamplerate; ac_libsamplerate="$enableval" else ac_libsamplerate="yes" fi # Enable librubberband availability. # Check whether --enable-librubberband was given. if test "${enable_librubberband+set}" = set; then : enableval=$enable_librubberband; ac_librubberband="$enableval" else ac_librubberband="yes" fi # Enable liblo availability. # Check whether --enable-liblo was given. if test "${enable_liblo+set}" = set; then : enableval=$enable_liblo; ac_liblo="$enableval" else ac_liblo="yes" fi # Enable libz availability. # Check whether --enable-libz was given. if test "${enable_libz+set}" = set; then : enableval=$enable_libz; ac_libz="$enableval" else ac_libz="yes" fi # Enable LILV support. # Check whether --enable-lilv was given. if test "${enable_lilv+set}" = set; then : enableval=$enable_lilv; ac_lilv="$enableval" else ac_lilv="yes" fi # Enable SUIL support. # Check whether --enable-suil was given. if test "${enable_suil+set}" = set; then : enableval=$enable_suil; ac_suil="$enableval" else ac_suil="yes" fi # Enable SSE optimization. # Check whether --enable-sse was given. if test "${enable_sse+set}" = set; then : enableval=$enable_sse; ac_sse="$enableval" else ac_sse="yes" fi # Enable LADSPA support. # Check whether --enable-ladspa was given. if test "${enable_ladspa+set}" = set; then : enableval=$enable_ladspa; ac_ladspa="$enableval" else ac_ladspa="yes" fi # Enable DSSI support. # Check whether --enable-dssi was given. if test "${enable_dssi+set}" = set; then : enableval=$enable_dssi; ac_dssi="$enableval" else ac_dssi="yes" fi # Enable VST support. # Check whether --enable-vst was given. if test "${enable_vst+set}" = set; then : enableval=$enable_vst; ac_vst="$enableval" else ac_vst="yes" fi # Check whether --enable-vestige was given. if test "${enable_vestige+set}" = set; then : enableval=$enable_vestige; ac_vestige="$enableval" else ac_vestige="yes" fi # Enable LV2 support. # Check whether --enable-lv2 was given. if test "${enable_lv2+set}" = set; then : enableval=$enable_lv2; ac_lv2="$enableval" else ac_lv2="yes" fi # Check whether --enable-lv2-event was given. if test "${enable_lv2_event+set}" = set; then : enableval=$enable_lv2_event; ac_lv2_event="$enableval" else ac_lv2_event="yes" fi # Check whether --enable-lv2-atom was given. if test "${enable_lv2_atom+set}" = set; then : enableval=$enable_lv2_atom; ac_lv2_atom="$enableval" else ac_lv2_atom="yes" fi # Check whether --enable-lv2-worker was given. if test "${enable_lv2_worker+set}" = set; then : enableval=$enable_lv2_worker; ac_lv2_worker="$enableval" else ac_lv2_worker="yes" fi # Check whether --enable-lv2-ui was given. if test "${enable_lv2_ui+set}" = set; then : enableval=$enable_lv2_ui; ac_lv2_ui="$enableval" else ac_lv2_ui="yes" fi # Check whether --enable-lv2-external-ui was given. if test "${enable_lv2_external_ui+set}" = set; then : enableval=$enable_lv2_external_ui; ac_lv2_external_ui="$enableval" else ac_lv2_external_ui="yes" fi # Check whether --enable-lv2-state was given. if test "${enable_lv2_state+set}" = set; then : enableval=$enable_lv2_state; ac_lv2_state="$enableval" else ac_lv2_state="yes" fi # Check whether --enable-lv2-state-files was given. if test "${enable_lv2_state_files+set}" = set; then : enableval=$enable_lv2_state_files; ac_lv2_state_files="$enableval" else ac_lv2_state_files="yes" fi # Check whether --enable-lv2-programs was given. if test "${enable_lv2_programs+set}" = set; then : enableval=$enable_lv2_programs; ac_lv2_programs="$enableval" else ac_lv2_programs="yes" fi # Check whether --enable-lv2-presets was given. if test "${enable_lv2_presets+set}" = set; then : enableval=$enable_lv2_presets; ac_lv2_presets="$enableval" else ac_lv2_presets="yes" fi # Check whether --enable-lv2-time was given. if test "${enable_lv2_time+set}" = set; then : enableval=$enable_lv2_time; ac_lv2_time="$enableval" else ac_lv2_time="yes" fi # Check whether --enable-lv2-options was given. if test "${enable_lv2_options+set}" = set; then : enableval=$enable_lv2_options; ac_lv2_options="$enableval" else ac_lv2_options="yes" fi # Check whether --enable-lv2-buf-size was given. if test "${enable_lv2_buf_size+set}" = set; then : enableval=$enable_lv2_buf_size; ac_lv2_buf_size="$enableval" else ac_lv2_buf_size="yes" fi # Enable JACK session support. # Check whether --enable-jack-session was given. if test "${enable_jack_session+set}" = set; then : enableval=$enable_jack_session; ac_jack_session="$enableval" else ac_jack_session="yes" fi # Enable JACK latency support. # Check whether --enable-jack-latency was given. if test "${enable_jack_latency+set}" = set; then : enableval=$enable_jack_latency; ac_jack_latency="$enableval" else ac_jack_latency="yes" fi # Enable NSM support. # Check whether --enable-nsm was given. if test "${enable_nsm+set}" = set; then : enableval=$enable_nsm; ac_nsm="$enableval" else ac_nsm="yes" fi # Enable X11 unique/single instance. # Check whether --enable-xunique was given. if test "${enable_xunique+set}" = set; then : enableval=$enable_xunique; ac_xunique="$enableval" else ac_xunique="no" fi # Enable gradient eye-candy. # Check whether --enable-gradient was given. if test "${enable_gradient+set}" = set; then : enableval=$enable_gradient; ac_gradient="$enableval" else ac_gradient="yes" fi # Enable debugger stack-trace option (assumes --enable-debug). # Check whether --enable-stacktrace was given. if test "${enable_stacktrace+set}" = set; then : enableval=$enable_stacktrace; ac_stacktrace="$enableval" fi # Standard installation base dirs. ac_with_paths="/usr /usr/local" # Some a-la-debian alternatives... for X in /usr/lib /usr/lib64 /usr/share; do for Y in qt qt4; do if test -d $X/$Y/bin; then ac_with_paths="$ac_with_paths $X/$Y" fi done done # Set for alternate Qt installation dir. # Check whether --with-qt was given. if test "${with_qt+set}" = set; then : withval=$with_qt; ac_with_paths="$ac_with_paths $withval" fi # Set for alternate JACK installation dir. # Check whether --with-jack was given. if test "${with_jack+set}" = set; then : withval=$with_jack; ac_with_paths="$ac_with_paths $withval" fi # Set for alternate ALSA installation dir. # Check whether --with-alsa was given. if test "${with_alsa+set}" = set; then : withval=$with_alsa; ac_with_paths="$ac_with_paths $withval" fi # Set for alternate libsndfile installation dir. # Check whether --with-libsndfile was given. if test "${with_libsndfile+set}" = set; then : withval=$with_libsndfile; ac_with_paths="$ac_with_paths $withval" fi # Set for alternate libvorbis installation dir. # Check whether --with-libvorbis was given. if test "${with_libvorbis+set}" = set; then : withval=$with_libvorbis; ac_with_paths="$ac_with_paths $withval" fi # Set for alternate libmad installation dir. # Check whether --with-libmad was given. if test "${with_libmad+set}" = set; then : withval=$with_libmad; ac_with_paths="$ac_with_paths $withval" fi # Set for alternate libsamplerate installation dir. # Check whether --with-libsamplerate was given. if test "${with_libsamplerate+set}" = set; then : withval=$with_libsamplerate; ac_with_paths="$ac_with_paths $withval" fi # Set for alternate librubberband installation dir. # Check whether --with-librubberband was given. if test "${with_librubberband+set}" = set; then : withval=$with_librubberband; ac_with_paths="$ac_with_paths $withval" fi # Set for alternate liblo installation dir. # Check whether --with-liblo was given. if test "${with_liblo+set}" = set; then : withval=$with_liblo; ac_with_paths="$ac_with_paths $withval" fi # Set for alternate libz installation dir. # Check whether --with-libz was given. if test "${with_libz+set}" = set; then : withval=$with_libz; ac_with_paths="$ac_with_paths $withval" fi # Set for alternate liblilv installation dir. # Check whether --with-liblilv was given. if test "${with_liblilv+set}" = set; then : withval=$with_liblilv; ac_with_paths="$ac_with_paths $withval" fi # Set for alternate libsuil installation dir. # Check whether --with-libsuil was given. if test "${with_libsuil+set}" = set; then : withval=$with_libsuil; ac_with_paths="$ac_with_paths $withval" fi # Set for alternate LADSPA include dir. # Check whether --with-ladspa was given. if test "${with_ladspa+set}" = set; then : withval=$with_ladspa; ac_with_ladspa="$withval" fi # Set for alternate DSSI include dir. # Check whether --with-dssi was given. if test "${with_dssi+set}" = set; then : withval=$with_dssi; ac_with_dssi="$withval" fi # Set for alternate VST include dir. # Check whether --with-vst was given. if test "${with_vst+set}" = set; then : withval=$with_vst; ac_with_vst="$withval" fi # Set for alternate LV2 include dir. # Check whether --with-lv2 was given. if test "${with_lv2+set}" = set; then : withval=$with_lv2; ac_with_lv2="$withval" fi # Honor user specified CFLAGS. ac_cflags=$CFLAGS # Checks for programs. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 $as_echo_n "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if ${ac_cv_prog_CXXCPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 $as_echo "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" if test $ac_cv_c_compiler_gnu = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5 $as_echo_n "checking whether $CC needs -traditional... " >&6; } if ${ac_cv_prog_gcc_traditional+:} false; then : $as_echo_n "(cached) " >&6 else ac_pattern="Autoconf.*'x'" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Autoconf TIOCGETP _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "$ac_pattern" >/dev/null 2>&1; then : ac_cv_prog_gcc_traditional=yes else ac_cv_prog_gcc_traditional=no fi rm -f conftest* if test $ac_cv_prog_gcc_traditional = no; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Autoconf TCGETA _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "$ac_pattern" >/dev/null 2>&1; then : ac_cv_prog_gcc_traditional=yes fi rm -f conftest* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5 $as_echo "$ac_cv_prog_gcc_traditional" >&6; } if test $ac_cv_prog_gcc_traditional = yes; then CC="$CC -traditional" fi fi # Checks for languages. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu # Prepend alternate dependencies paths. ac_path=$PATH for X in $ac_with_paths; do if test -d $X/bin; then ac_path="$X/bin:$ac_path" fi # if test -x $X/qmake; then # ac_path="$X:$ac_path" # fi if test -d $X/include; then for Y in qt qt4; do if test -d $X/include/$Y; then CFLAGS="-I$X/include/$Y $CFLAGS" CPPFLAGS="-I$X/include/$Y $CPPFLAGS" ac_incpath="$X/include/$Y $ac_incpath" fi done CFLAGS="-I$X/include $CFLAGS" CPPFLAGS="-I$X/include $CPPFLAGS" ac_incpath="$X/include $ac_incpath" fi if test -d $X/lib64; then LIBS="-L$X/lib64 $LIBS" ac_libs="-L$X/lib64 $ac_libs" fi if test -d $X/lib; then LIBS="-L$X/lib $LIBS" ac_libs="-L$X/lib $ac_libs" fi done # Check for proper Qt version. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Qt library version >= 4.4" >&5 $as_echo_n "checking for Qt library version >= 4.4... " >&6; } if ${ac_cv_qtversion+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include "QtCore/qglobal.h" int main () { #if QT_VERSION < 0x040400 #error Qt library 4.4 or greater required. #endif ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_qtversion="yes" else echo "no; Qt 4.4 or greater is required" exit 1 fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_qtversion" >&5 $as_echo "$ac_cv_qtversion" >&6; } # Check for IEEE 32bit float optimizations. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IEEE 32bit float optimizations" >&5 $as_echo_n "checking for IEEE 32bit float optimizations... " >&6; } if ${ac_cv_float32+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main() { return (sizeof(float) == 4 ? 0 : 1); } _ACEOF if ac_fn_cxx_try_run "$LINENO"; then : ac_cv_float32="yes" else ac_cv_float32="no" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_float32" >&5 $as_echo "$ac_cv_float32" >&6; } ac_float32=$ac_cv_float32 if test "x$ac_float32" = "xyes"; then $as_echo "#define CONFIG_FLOAT32 1" >>confdefs.h fi # Check for SSE optimization. if test "x$ac_sse" = "xyes"; then ac_sse_cflags="-msse -mfpmath=sse -ffast-math" ac_old_cflags=$CFLAGS ac_old_cppflags=$CPPFLAGS CFLAGS="$ac_sse_cflags $CFLAGS" CPPFLAGS="$ac_sse_cflags $CPPFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSE optimization" >&5 $as_echo_n "checking for SSE optimization... " >&6; } if ${ac_cv_sse+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #if !defined(__SSE__) #error SSE optimization disabled. #endif int main() { unsigned int a, b, c, d; __asm__ __volatile__ ("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (1)); return ((d & (1 << 25)) ? 0 : 1); } _ACEOF if ac_fn_cxx_try_run "$LINENO"; then : ac_cv_sse="yes" else ac_cv_sse="no" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sse" >&5 $as_echo "$ac_cv_sse" >&6; } ac_sse=$ac_cv_sse if test "x$ac_sse" = "xyes"; then ac_cflags="$ac_sse_cflags $ac_cflags" else CPPFLAGS=$ac_old_cppflags CFLAGS=$ac_old_cflags fi fi # A common error message: ac_errmsg="not found in current PATH. Maybe QT development environment isn't available (qt-devel)." # Check for Qt qmake utility. # Extract the first word of "qmake", so it can be a program name with args. set dummy qmake; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_qmake+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_qmake in [\\/]* | ?:[\\/]*) ac_cv_path_ac_qmake="$ac_qmake" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $ac_path do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_qmake="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_ac_qmake" && ac_cv_path_ac_qmake="no" ;; esac fi ac_qmake=$ac_cv_path_ac_qmake if test -n "$ac_qmake"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_qmake" >&5 $as_echo "$ac_qmake" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_qmake" = "xno"; then as_fn_error $? "qmake $ac_errmsg" "$LINENO" 5 fi # Check for Qt moc utility. # Extract the first word of "moc", so it can be a program name with args. set dummy moc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_moc+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_moc in [\\/]* | ?:[\\/]*) ac_cv_path_ac_moc="$ac_moc" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $ac_path do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_moc="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_ac_moc" && ac_cv_path_ac_moc="no" ;; esac fi ac_moc=$ac_cv_path_ac_moc if test -n "$ac_moc"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_moc" >&5 $as_echo "$ac_moc" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_moc" = "xno"; then as_fn_error $? "moc $ac_errmsg" "$LINENO" 5 fi # Check for Qt uic utility. # Extract the first word of "uic", so it can be a program name with args. set dummy uic; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_uic+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_uic in [\\/]* | ?:[\\/]*) ac_cv_path_ac_uic="$ac_uic" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $ac_path do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_uic="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_ac_uic" && ac_cv_path_ac_uic="no" ;; esac fi ac_uic=$ac_cv_path_ac_uic if test -n "$ac_uic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_uic" >&5 $as_echo "$ac_uic" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_uic" = "xno"; then as_fn_error $? "uic $ac_errmsg" "$LINENO" 5 fi # Check for Qt lupdate utility. # Extract the first word of "lupdate", so it can be a program name with args. set dummy lupdate; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_lupdate+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_lupdate in [\\/]* | ?:[\\/]*) ac_cv_path_ac_lupdate="$ac_lupdate" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $ac_path do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_lupdate="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_ac_lupdate" && ac_cv_path_ac_lupdate="no" ;; esac fi ac_lupdate=$ac_cv_path_ac_lupdate if test -n "$ac_lupdate"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_lupdate" >&5 $as_echo "$ac_lupdate" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_lupdate" = "xno"; then as_fn_error $? "lupdate $ac_errmsg" "$LINENO" 5 fi # Check for Qt lrelease utility. # Extract the first word of "lrelease", so it can be a program name with args. set dummy lrelease; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_lrelease+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_lrelease in [\\/]* | ?:[\\/]*) ac_cv_path_ac_lrelease="$ac_lrelease" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $ac_path do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_lrelease="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_ac_lrelease" && ac_cv_path_ac_lrelease="no" ;; esac fi ac_lrelease=$ac_cv_path_ac_lrelease if test -n "$ac_lrelease"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_lrelease" >&5 $as_echo "$ac_lrelease" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_release" = "xno"; then as_fn_error $? "lrelease $ac_errmsg" "$LINENO" 5 fi # Check for pkg-config utility (needed for LV2 GTK UI support). # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pkg_config+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pkg_config in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pkg_config="$ac_pkg_config" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $ac_path do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pkg_config="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_ac_pkg_config" && ac_cv_path_ac_pkg_config="no" ;; esac fi ac_pkg_config=$ac_cv_path_ac_pkg_config if test -n "$ac_pkg_config"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pkg_config" >&5 $as_echo "$ac_pkg_config" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pkg_config" = "xno"; then ac_lv2="no" ac_lilv="no" ac_suil="no" fi # Checks for libraries. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lm" >&5 $as_echo_n "checking for main in -lm... " >&6; } if ${ac_cv_lib_m_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_m_main=yes else ac_cv_lib_m_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_main" >&5 $as_echo "$ac_cv_lib_m_main" >&6; } if test "x$ac_cv_lib_m_main" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBM 1 _ACEOF LIBS="-lm $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lX11" >&5 $as_echo_n "checking for main in -lX11... " >&6; } if ${ac_cv_lib_X11_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lX11 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_X11_main=yes else ac_cv_lib_X11_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_X11_main" >&5 $as_echo "$ac_cv_lib_X11_main" >&6; } if test "x$ac_cv_lib_X11_main" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBX11 1 _ACEOF LIBS="-lX11 $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lXext" >&5 $as_echo_n "checking for main in -lXext... " >&6; } if ${ac_cv_lib_Xext_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lXext $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_Xext_main=yes else ac_cv_lib_Xext_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xext_main" >&5 $as_echo "$ac_cv_lib_Xext_main" >&6; } if test "x$ac_cv_lib_Xext_main" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBXEXT 1 _ACEOF LIBS="-lXext $LIBS" fi # Check for round math function. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for round in -lm" >&5 $as_echo_n "checking for round in -lm... " >&6; } if ${ac_cv_lib_m_round+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char round (); int main () { return round (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_m_round=yes else ac_cv_lib_m_round=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_round" >&5 $as_echo "$ac_cv_lib_m_round" >&6; } if test "x$ac_cv_lib_m_round" = xyes; then : ac_round="yes" else ac_round="no" fi if test "x$ac_round" = "xyes"; then $as_echo "#define CONFIG_ROUND 1" >>confdefs.h fi # Check for JACK libraries. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ljack" >&5 $as_echo_n "checking for main in -ljack... " >&6; } if ${ac_cv_lib_jack_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ljack $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_jack_main=yes else ac_cv_lib_jack_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jack_main" >&5 $as_echo "$ac_cv_lib_jack_main" >&6; } if test "x$ac_cv_lib_jack_main" = xyes; then : ac_libjack="yes" else ac_libjack="no" fi if test "x$ac_libjack" = "xno"; then as_fn_error $? "JACK library not found." "$LINENO" 5 else ac_libs="$ac_libs -ljack" fi # Check for ALSA libraries. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lasound" >&5 $as_echo_n "checking for main in -lasound... " >&6; } if ${ac_cv_lib_asound_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lasound $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_asound_main=yes else ac_cv_lib_asound_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_asound_main" >&5 $as_echo "$ac_cv_lib_asound_main" >&6; } if test "x$ac_cv_lib_asound_main" = xyes; then : ac_libasound="yes" else ac_libasound="no" fi if test "x$ac_libasound" = "xno"; then as_fn_error $? "ALSA library not found." "$LINENO" 5 else ac_libs="$ac_libs -lasound" fi # Check for sndfile library. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsndfile" >&5 $as_echo_n "checking for main in -lsndfile... " >&6; } if ${ac_cv_lib_sndfile_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsndfile $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_sndfile_main=yes else ac_cv_lib_sndfile_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sndfile_main" >&5 $as_echo "$ac_cv_lib_sndfile_main" >&6; } if test "x$ac_cv_lib_sndfile_main" = xyes; then : ac_libsndfile="yes" else ac_libsndfile="no" fi if test "x$ac_libsndfile" = "xno"; then as_fn_error $? "sndfile library not found." "$LINENO" 5 else ac_libs="$ac_libs -lsndfile" fi # Check for option libvorbis libraries. if test "x$ac_libvorbis" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -logg" >&5 $as_echo_n "checking for main in -logg... " >&6; } if ${ac_cv_lib_ogg_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-logg $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_ogg_main=yes else ac_cv_lib_ogg_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ogg_main" >&5 $as_echo "$ac_cv_lib_ogg_main" >&6; } if test "x$ac_cv_lib_ogg_main" = xyes; then : ac_libvorbis="yes" else ac_libvorbis="no" fi if test "x$ac_libvorbis" = "xyes"; then ac_libs="$ac_libs -logg" else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** ogg library not found." >&5 $as_echo "$as_me: WARNING: *** ogg library not found." >&2;} fi fi if test "x$ac_libvorbis" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lvorbis" >&5 $as_echo_n "checking for main in -lvorbis... " >&6; } if ${ac_cv_lib_vorbis_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lvorbis $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_vorbis_main=yes else ac_cv_lib_vorbis_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vorbis_main" >&5 $as_echo "$ac_cv_lib_vorbis_main" >&6; } if test "x$ac_cv_lib_vorbis_main" = xyes; then : ac_libvorbis="yes" else ac_libvorbis="no" fi if test "x$ac_libvorbis" = "xyes"; then ac_libs="$ac_libs -lvorbis" else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** vorbis library not found." >&5 $as_echo "$as_me: WARNING: *** vorbis library not found." >&2;} fi fi if test "x$ac_libvorbis" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lvorbisenc" >&5 $as_echo_n "checking for main in -lvorbisenc... " >&6; } if ${ac_cv_lib_vorbisenc_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lvorbisenc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_vorbisenc_main=yes else ac_cv_lib_vorbisenc_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vorbisenc_main" >&5 $as_echo "$ac_cv_lib_vorbisenc_main" >&6; } if test "x$ac_cv_lib_vorbisenc_main" = xyes; then : ac_libvorbis="yes" else ac_libvorbis="no" fi if test "x$ac_libvorbis" = "xyes"; then ac_libs="$ac_libs -lvorbisenc" else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** vorbisenc library not found." >&5 $as_echo "$as_me: WARNING: *** vorbisenc library not found." >&2;} fi fi if test "x$ac_libvorbis" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lvorbisfile" >&5 $as_echo_n "checking for main in -lvorbisfile... " >&6; } if ${ac_cv_lib_vorbisfile_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lvorbisfile $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_vorbisfile_main=yes else ac_cv_lib_vorbisfile_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vorbisfile_main" >&5 $as_echo "$ac_cv_lib_vorbisfile_main" >&6; } if test "x$ac_cv_lib_vorbisfile_main" = xyes; then : ac_libvorbis="yes" else ac_libvorbis="no" fi if test "x$ac_libvorbis" = "xyes"; then ac_libs="$ac_libs -lvorbisfile" else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** vorbisfile library not found." >&5 $as_echo "$as_me: WARNING: *** vorbisfile library not found." >&2;} fi fi if test "x$ac_libvorbis" = "xyes"; then $as_echo "#define CONFIG_LIBVORBIS 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Ogg Vorbis audio file support will be disabled." >&5 $as_echo "$as_me: WARNING: *** Ogg Vorbis audio file support will be disabled." >&2;} fi # Check for optional libmad library. if test "x$ac_libmad" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lmad" >&5 $as_echo_n "checking for main in -lmad... " >&6; } if ${ac_cv_lib_mad_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmad $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_mad_main=yes else ac_cv_lib_mad_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mad_main" >&5 $as_echo "$ac_cv_lib_mad_main" >&6; } if test "x$ac_cv_lib_mad_main" = xyes; then : ac_libmad="yes" else ac_libmad="no" fi if test "x$ac_libmad" = "xyes"; then $as_echo "#define CONFIG_LIBMAD 1" >>confdefs.h ac_libs="$ac_libs -lmad" else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** mad library not found." >&5 $as_echo "$as_me: WARNING: *** mad library not found." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** MPEG Layer III audio file support will be disabled." >&5 $as_echo "$as_me: WARNING: *** MPEG Layer III audio file support will be disabled." >&2;} fi fi # Check for optional libsamplerate library. if test "x$ac_libsamplerate" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsamplerate" >&5 $as_echo_n "checking for main in -lsamplerate... " >&6; } if ${ac_cv_lib_samplerate_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsamplerate $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_samplerate_main=yes else ac_cv_lib_samplerate_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_samplerate_main" >&5 $as_echo "$ac_cv_lib_samplerate_main" >&6; } if test "x$ac_cv_lib_samplerate_main" = xyes; then : ac_libsamplerate="yes" else ac_libsamplerate="no" fi if test "x$ac_libsamplerate" = "xyes"; then $as_echo "#define CONFIG_LIBSAMPLERATE 1" >>confdefs.h ac_libs="$ac_libs -lsamplerate" else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** samplerate library not found." >&5 $as_echo "$as_me: WARNING: *** samplerate library not found." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Sample-rate conversion support will be disabled." >&5 $as_echo "$as_me: WARNING: *** Sample-rate conversion support will be disabled." >&2;} fi fi # Check for optional librubberband library. if test "x$ac_librubberband" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lrubberband" >&5 $as_echo_n "checking for main in -lrubberband... " >&6; } if ${ac_cv_lib_rubberband_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrubberband $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_rubberband_main=yes else ac_cv_lib_rubberband_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rubberband_main" >&5 $as_echo "$ac_cv_lib_rubberband_main" >&6; } if test "x$ac_cv_lib_rubberband_main" = xyes; then : ac_librubberband="yes" else ac_librubberband="no" fi if test "x$ac_librubberband" = "xyes"; then $as_echo "#define CONFIG_LIBRUBBERBAND 1" >>confdefs.h ac_libs="$ac_libs -lrubberband" else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** rubberband library not found." >&5 $as_echo "$as_me: WARNING: *** rubberband library not found." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Pitch-shifting support will be disabled." >&5 $as_echo "$as_me: WARNING: *** Pitch-shifting support will be disabled." >&2;} fi fi # Check for optional liblo library. if test "x$ac_liblo" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -llo" >&5 $as_echo_n "checking for main in -llo... " >&6; } if ${ac_cv_lib_lo_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-llo $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_lo_main=yes else ac_cv_lib_lo_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lo_main" >&5 $as_echo "$ac_cv_lib_lo_main" >&6; } if test "x$ac_cv_lib_lo_main" = xyes; then : ac_liblo="yes" else ac_liblo="no" fi if test "x$ac_liblo" = "xyes"; then $as_echo "#define CONFIG_LIBLO 1" >>confdefs.h ac_libs="$ac_libs -llo" else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** lo library not found." >&5 $as_echo "$as_me: WARNING: *** lo library not found." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** OSC service support will be disabled." >&5 $as_echo "$as_me: WARNING: *** OSC service support will be disabled." >&2;} ac_nsm="no" fi else ac_nsm="no" fi # Check for optional libz library. if test "x$ac_libz" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lz" >&5 $as_echo_n "checking for main in -lz... " >&6; } if ${ac_cv_lib_z_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_z_main=yes else ac_cv_lib_z_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_main" >&5 $as_echo "$ac_cv_lib_z_main" >&6; } if test "x$ac_cv_lib_z_main" = xyes; then : ac_libz="yes" else ac_libz="no" fi if test "x$ac_libz" = "xyes"; then $as_echo "#define CONFIG_LIBZ 1" >>confdefs.h ac_libs="$ac_libs -lz" else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** z library not found." >&5 $as_echo "$as_me: WARNING: *** z library not found." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Archive/Zip file support will be disabled." >&5 $as_echo "$as_me: WARNING: *** Archive/Zip file support will be disabled." >&2;} fi fi # Check for optional liblilv library. if test "x$ac_lilv" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -llilv-0" >&5 $as_echo_n "checking for main in -llilv-0... " >&6; } if ${ac_cv_lib_lilv_0_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-llilv-0 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_lilv_0_main=yes else ac_cv_lib_lilv_0_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lilv_0_main" >&5 $as_echo "$ac_cv_lib_lilv_0_main" >&6; } if test "x$ac_cv_lib_lilv_0_main" = xyes; then : ac_lilv="yes" else ac_lilv="no" fi fi if test "x$ac_lilv" = "xyes"; then ac_lilv_libs=`$ac_pkg_config --libs lilv-0 2>/dev/null` if test -n "$ac_lilv_libs"; then ac_libs="$ac_libs $ac_lilv_libs" $as_echo "#define CONFIG_LIBLILV 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** lilv library not found." >&5 $as_echo "$as_me: WARNING: *** lilv library not found." >&2;} ac_lilv="no" ac_suil="no" fi else ac_suil="no" fi # Check for LV2 support. if test "x$ac_lv2_ui" = "xno"; then ac_suil="no" ac_lv2_external_ui="no" fi # Check for LV2 new UI instantiation availability (libsuil). if test "x$ac_suil" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsuil-0" >&5 $as_echo_n "checking for main in -lsuil-0... " >&6; } if ${ac_cv_lib_suil_0_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsuil-0 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_suil_0_main=yes else ac_cv_lib_suil_0_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_suil_0_main" >&5 $as_echo "$ac_cv_lib_suil_0_main" >&6; } if test "x$ac_cv_lib_suil_0_main" = xyes; then : ac_suil="yes" else ac_suil="no" fi fi if test "x$ac_suil" = "xyes"; then ac_suil_libs=`$ac_pkg_config --libs suil-0 2>/dev/null` if test -n "$ac_suil_libs"; then ac_libs="$ac_libs $ac_suil_libs" $as_echo "#define CONFIG_LIBSUIL 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** suil library not found." >&5 $as_echo "$as_me: WARNING: *** suil library not found." >&2;} ac_suil="no" ac_lv2_ui="no" ac_lv2_external_ui="no" fi fi if test "x$ac_suil" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suil_instance_get_handle in -lsuil-0" >&5 $as_echo_n "checking for suil_instance_get_handle in -lsuil-0... " >&6; } if ${ac_cv_lib_suil_0_suil_instance_get_handle+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsuil-0 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char suil_instance_get_handle (); int main () { return suil_instance_get_handle (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_suil_0_suil_instance_get_handle=yes else ac_cv_lib_suil_0_suil_instance_get_handle=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_suil_0_suil_instance_get_handle" >&5 $as_echo "$ac_cv_lib_suil_0_suil_instance_get_handle" >&6; } if test "x$ac_cv_lib_suil_0_suil_instance_get_handle" = xyes; then : ac_suil_instance_get_handle="yes" else ac_suil_instance_get_handle="no" fi if test "x$ac_suil_instance_get_handle" = "xyes"; then $as_echo "#define CONFIG_SUIL_INSTANCE_GET_HANDLE 1" >>confdefs.h fi else ac_suil="no" ac_lv2_ui="no" ac_lv2_external_ui="no" fi # Check for LV2 host library (liblilv). if test "x$ac_lilv" = "xno"; then ac_lv2="no" ac_lv2_ui="no" ac_lv2_event="no" ac_lv2_atom="no" ac_lv2_worker="no" ac_lv2_external_ui="no" ac_lv2_state="no" ac_lv2_state_files="no" ac_lv2_programs="no" ac_lv2_presets="no" ac_lv2_time="no" ac_lv2_options="no" ac_lv2_buf_size="no" fi # Check for JACK session event callback availability. if test "x$ac_jack_session" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jack_set_session_callback in -ljack" >&5 $as_echo_n "checking for jack_set_session_callback in -ljack... " >&6; } if ${ac_cv_lib_jack_jack_set_session_callback+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ljack $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char jack_set_session_callback (); int main () { return jack_set_session_callback (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_jack_jack_set_session_callback=yes else ac_cv_lib_jack_jack_set_session_callback=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jack_jack_set_session_callback" >&5 $as_echo "$ac_cv_lib_jack_jack_set_session_callback" >&6; } if test "x$ac_cv_lib_jack_jack_set_session_callback" = xyes; then : ac_jack_session="yes" else ac_jack_session="no" fi else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** JACK session support will be disabled." >&5 $as_echo "$as_me: WARNING: *** JACK session support will be disabled." >&2;} fi # Check for (new) JACK latency support availability. if test "x$ac_jack_latency" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jack_port_get_latency_range in -ljack" >&5 $as_echo_n "checking for jack_port_get_latency_range in -ljack... " >&6; } if ${ac_cv_lib_jack_jack_port_get_latency_range+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ljack $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char jack_port_get_latency_range (); int main () { return jack_port_get_latency_range (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_jack_jack_port_get_latency_range=yes else ac_cv_lib_jack_jack_port_get_latency_range=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jack_jack_port_get_latency_range" >&5 $as_echo "$ac_cv_lib_jack_jack_port_get_latency_range" >&6; } if test "x$ac_cv_lib_jack_jack_port_get_latency_range" = xyes; then : ac_jack_latency="yes" else ac_jack_latency="no" fi if test "x$ac_jack_latency" = "xyes"; then $as_echo "#define CONFIG_JACK_LATENCY 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** JACK latency support will be disabled." >&5 $as_echo "$as_me: WARNING: *** JACK latency support will be disabled." >&2;} fi fi # Some recent distros (eg. fedora, debian) require this. ac_libs="$ac_libs -lX11" # Checks for header files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_cxx_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5 $as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; } if ${ac_cv_header_sys_wait_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif int main () { int s; wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_header_sys_wait_h=yes else ac_cv_header_sys_wait_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5 $as_echo "$ac_cv_header_sys_wait_h" >&6; } if test $ac_cv_header_sys_wait_h = yes; then $as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in fcntl.h sys/ioctl.h sys/stat.h unistd.h signal.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Check for JACK headers. ac_fn_cxx_check_header_mongrel "$LINENO" "jack/jack.h" "ac_cv_header_jack_jack_h" "$ac_includes_default" if test "x$ac_cv_header_jack_jack_h" = xyes; then : ac_jack_h="yes" else ac_jack_h="no" fi if test "x$ac_jack_h" = "xno"; then as_fn_error $? "JACK headers not found." "$LINENO" 5 fi # Check for ALSA headers. ac_fn_cxx_check_header_mongrel "$LINENO" "alsa/asoundlib.h" "ac_cv_header_alsa_asoundlib_h" "$ac_includes_default" if test "x$ac_cv_header_alsa_asoundlib_h" = xyes; then : ac_alsa_h="yes" else ac_alsa_h="no" fi if test "x$ac_alsa_h" = "xno"; then as_fn_error $? "ALSA headers not found." "$LINENO" 5 fi # Check for sndfile headers. ac_fn_cxx_check_header_mongrel "$LINENO" "sndfile.h" "ac_cv_header_sndfile_h" "$ac_includes_default" if test "x$ac_cv_header_sndfile_h" = xyes; then : ac_sndfile_h="yes" else ac_sndfile_h="no" fi if test "x$ac_sndfile_h" = "xno"; then as_fn_error $? "sndfile.h header file not found." "$LINENO" 5 fi # Check for vorbisfile headers. if test "x$ac_libvorbis" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "vorbis/vorbisenc.h" "ac_cv_header_vorbis_vorbisenc_h" "$ac_includes_default" if test "x$ac_cv_header_vorbis_vorbisenc_h" = xyes; then : ac_vorbisenc_h="yes" else ac_vorbisenc_h="no" fi if test "x$ac_vorbisenc_h" = "xno"; then as_fn_error $? "vorbisenc.h header file not found." "$LINENO" 5 fi ac_fn_cxx_check_header_mongrel "$LINENO" "vorbis/vorbisfile.h" "ac_cv_header_vorbis_vorbisfile_h" "$ac_includes_default" if test "x$ac_cv_header_vorbis_vorbisfile_h" = xyes; then : ac_vorbisfile_h="yes" else ac_vorbisfile_h="no" fi if test "x$ac_vorbisfile_h" = "xno"; then as_fn_error $? "vorbisfile.h header file not found." "$LINENO" 5 fi fi # Check for mad headers. if test "x$ac_libmad" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "mad.h" "ac_cv_header_mad_h" "$ac_includes_default" if test "x$ac_cv_header_mad_h" = xyes; then : ac_mad_h="yes" else ac_mad_h="no" fi if test "x$ac_mad_h" = "xno"; then as_fn_error $? "mad.h header file not found." "$LINENO" 5 fi fi # Check for samplerate headers. if test "x$ac_libsamplerate" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "samplerate.h" "ac_cv_header_samplerate_h" "$ac_includes_default" if test "x$ac_cv_header_samplerate_h" = xyes; then : ac_samplerate_h="yes" else ac_samplerate_h="no" fi if test "x$ac_samplerate_h" = "xno"; then as_fn_error $? "samplerate.h header file not found." "$LINENO" 5 fi fi # Check for rubberband headers. if test "x$ac_librubberband" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "rubberband/RubberBandStretcher.h" "ac_cv_header_rubberband_RubberBandStretcher_h" "$ac_includes_default" if test "x$ac_cv_header_rubberband_RubberBandStretcher_h" = xyes; then : ac_rubberband_h="yes" else ac_rubberband_h="no" fi if test "x$ac_rubberband_h" = "xno"; then as_fn_error $? "RubberBandStretcher.h header file not found." "$LINENO" 5 fi fi # Check for lo headers. if test "x$ac_liblo" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "lo/lo.h" "ac_cv_header_lo_lo_h" "$ac_includes_default" if test "x$ac_cv_header_lo_lo_h" = xyes; then : ac_lo_h="yes" else ac_lo_h="no" fi if test "x$ac_lo_h" = "xno"; then as_fn_error $? "lo.h header file not found." "$LINENO" 5 ac_nsm="no" fi fi # Check for zlib headers. if test "x$ac_libz" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes; then : ac_zlib_h="yes" else ac_zlib_h="no" fi if test "x$ac_zlib_h" = "xno"; then as_fn_error $? "zlib.h header file not found." "$LINENO" 5 fi fi # Check for lilv headers. if test "x$ac_lilv" = "xyes"; then ac_lilv_cflags=`$ac_pkg_config --cflags lilv-0 2>/dev/null` if test -n "$ac_lilv_cflags"; then CFLAGS="$ac_lilv_cflags $CFLAGS" CPPFLAGS="$ac_lilv_cflags $CPPFLAGS" fi ac_fn_cxx_check_header_mongrel "$LINENO" "lilv/lilv.h" "ac_cv_header_lilv_lilv_h" "$ac_includes_default" if test "x$ac_cv_header_lilv_lilv_h" = xyes; then : ac_lilv_h="yes" else ac_lilv_h="no" fi if test "x$ac_lilv_h" = "xno"; then as_fn_error $? "lilv.h header file not found." "$LINENO" 5 else ac_cflags="$ac_lilv_cflags $ac_cflags" fi fi # Check for suil headers. if test "x$ac_suil" = "xyes"; then ac_suil_cflags=`$ac_pkg_config --cflags suil-0 2>/dev/null` if test -n "$ac_suil_cflags"; then CFLAGS="$ac_suil_cflags $CFLAGS" CPPFLAGS="$ac_suil_cflags $CPPFLAGS" fi ac_fn_cxx_check_header_mongrel "$LINENO" "suil/suil.h" "ac_cv_header_suil_suil_h" "$ac_includes_default" if test "x$ac_cv_header_suil_suil_h" = xyes; then : ac_suil_h="yes" else ac_suil_h="no" fi if test "x$ac_suil_h" = "xno"; then as_fn_error $? "suil.h header file not found." "$LINENO" 5 else ac_cflags="$ac_suil_cflags $ac_cflags" fi fi # Check for LADSPA headers. if test -n "$ac_with_ladspa"; then CFLAGS="-I$ac_with_ladspa $CFLAGS" CPPFLAGS="-I$ac_with_ladspa $CPPFLAGS" ac_ladspa="yes" fi if test "x$ac_ladspa" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "ladspa.h" "ac_cv_header_ladspa_h" "$ac_includes_default" if test "x$ac_cv_header_ladspa_h" = xyes; then : ac_ladspa="yes" else ac_ladspa="no" fi if test "x$ac_ladspa" = "xyes"; then $as_echo "#define CONFIG_LADSPA 1" >>confdefs.h ac_incpath="$ac_with_ladspa $ac_incpath" else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** ladspa.h header file not found." >&5 $as_echo "$as_me: WARNING: *** ladspa.h header file not found." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** LADSPA plug-in support will be disabled." >&5 $as_echo "$as_me: WARNING: *** LADSPA plug-in support will be disabled." >&2;} fi fi # Check for DSSI headers. if test -n "$ac_with_dssi"; then CFLAGS="-I$ac_with_dssi $CFLAGS" CPPFLAGS="-I$ac_with_dssi $CPPFLAGS" ac_dssi="yes" fi if test "x$ac_dssi" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "dssi.h" "ac_cv_header_dssi_h" "$ac_includes_default" if test "x$ac_cv_header_dssi_h" = xyes; then : ac_dssi="yes" else ac_dssi="no" fi if test "x$ac_dssi" = "xyes"; then $as_echo "#define CONFIG_DSSI 1" >>confdefs.h ac_incpath="$ac_with_dssi $ac_incpath" else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** dssi.h header file not found." >&5 $as_echo "$as_me: WARNING: *** dssi.h header file not found." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** DSSI plug-in support will be disabled." >&5 $as_echo "$as_me: WARNING: *** DSSI plug-in support will be disabled." >&2;} fi fi # Pre-check for VeSTige header. if test "$ac_vestige" = "xyes"; then ac_vst="yes" fi # Check for VST headers. if test -n "$ac_with_vst"; then CFLAGS="-I$ac_with_vst $CFLAGS" CPPFLAGS="-I$ac_with_vst $CPPFLAGS" ac_incpath="$ac_with_vst $ac_incpath" ac_vst="yes" fi if test "x$ac_vst" = "xyes"; then CFLAGS="-D__cdecl= $CFLAGS" CPPFLAGS="-D__cdecl= $CPPFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for VST headers" >&5 $as_echo_n "checking for VST headers... " >&6; } if ${ac_cv_vst+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { // Checking for VST headers... ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_vst="yes" else ac_cv_vst="no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_vst" >&5 $as_echo "$ac_cv_vst" >&6; } ac_vst=$ac_cv_vst if test "x$ac_vst" = "xno" -a "x$ac_vestige" = "xyes"; then CFLAGS="$CFLAGS -Isrc/vestige" CPPFLAGS="$CPPFLAGS -Isrc/vestige" ac_incpath="$ac_incpath vestige" ac_fn_cxx_check_header_mongrel "$LINENO" "aeffectx.h" "ac_cv_header_aeffectx_h" "$ac_includes_default" if test "x$ac_cv_header_aeffectx_h" = xyes; then : ac_vst="yes" else ac_vst="no" fi else ac_vestige="no" fi if test "x$ac_vst" = "xyes"; then $as_echo "#define CONFIG_VST 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** aeffectx.h header file not found." >&5 $as_echo "$as_me: WARNING: *** aeffectx.h header file not found." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** VST plug-in support will be disabled." >&5 $as_echo "$as_me: WARNING: *** VST plug-in support will be disabled." >&2;} ac_vestige="no" fi else ac_vestige="no" fi # Post-check for VeSTige header. if test "x$ac_vestige" = "xyes"; then $as_echo "#define CONFIG_VESTIGE 1" >>confdefs.h fi # Check for LV2 headers. if test -n "$ac_with_lv2"; then ac_lv2="yes" fi if test "x$ac_lv2" = "xyes"; then if test -n "$ac_with_lv2"; then CFLAGS="-I$ac_with_lv2 $CFLAGS" CPPFLAGS="-I$ac_with_lv2 $CPPFLAGS" ac_incpath="$ac_with_lv2 $ac_incpath" else CFLAGS="$CFLAGS -Isrc/lv2" CPPFLAGS="$CPPFLAGS -Isrc/lv2" ac_incpath="$ac_incpath lv2" fi ac_fn_cxx_check_header_mongrel "$LINENO" "lv2.h" "ac_cv_header_lv2_h" "$ac_includes_default" if test "x$ac_cv_header_lv2_h" = xyes; then : ac_lv2="yes" else ac_lv2="no" fi if test "x$ac_lv2" = "xyes"; then for ac_header in lv2/lv2plug.in/ns/ext/urid/urid.h \ lv2/lv2plug.in/ns/ext/uri-map/uri-map.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF ac_lv2="yes" else ac_lv2="no" fi done fi if test "x$ac_lv2" = "xyes"; then $as_echo "#define CONFIG_LV2 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** LV2 header files not found." >&5 $as_echo "$as_me: WARNING: *** LV2 header files not found." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** LV2 plug-in support will be disabled." >&5 $as_echo "$as_me: WARNING: *** LV2 plug-in support will be disabled." >&2;} ac_lv2_ui="no" ac_lv2_event="no" ac_lv2_atom="no" ac_lv2_worker="no" ac_lv2_external_ui="no" ac_lv2_state="no" ac_lv2_state_files="no" ac_lv2_programs="no" ac_lv2_presets="no" ac_lv2_time="no" ac_lv2_options="no" ac_lv2_buf_size="no" fi fi if test "x$ac_lv2_ui" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "lv2/lv2plug.in/ns/extensions/ui/ui.h" "ac_cv_header_lv2_lv2plug_in_ns_extensions_ui_ui_h" "$ac_includes_default" if test "x$ac_cv_header_lv2_lv2plug_in_ns_extensions_ui_ui_h" = xyes; then : ac_lv2_ui="yes" else ac_lv2_ui="no" fi if test "x$ac_lv2_ui" = "xyes"; then $as_echo "#define CONFIG_LV2_UI 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** LV2 UI support will be disabled." >&5 $as_echo "$as_me: WARNING: *** LV2 UI support will be disabled." >&2;} ac_lv2_external_ui="no" fi else ac_lv2_external_ui="no" fi if test "x$ac_lv2_event" = "xyes"; then for ac_header in lv2/lv2plug.in/ns/ext/event/event.h \ lv2/lv2plug.in/ns/ext/event/event-helpers.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF ac_lv2_event="yes" else ac_lv2_event="no" fi done if test "x$ac_lv2_event" = "xyes"; then $as_echo "#define CONFIG_LV2_EVENT 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** LV2 Event/MIDI support will be disabled." >&5 $as_echo "$as_me: WARNING: *** LV2 Event/MIDI support will be disabled." >&2;} fi fi if test "x$ac_lv2_atom" = "xyes"; then for ac_header in lv2_atom_helpers.h do : ac_fn_cxx_check_header_mongrel "$LINENO" "lv2_atom_helpers.h" "ac_cv_header_lv2_atom_helpers_h" "$ac_includes_default" if test "x$ac_cv_header_lv2_atom_helpers_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LV2_ATOM_HELPERS_H 1 _ACEOF ac_lv2_atom="yes" else ac_lv2_atom="no" fi done if test "x$ac_lv2_atom" = "xyes"; then $as_echo "#define CONFIG_LV2_ATOM 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** LV2 Atom/MIDI support will be disabled." >&5 $as_echo "$as_me: WARNING: *** LV2 Atom/MIDI support will be disabled." >&2;} ac_lv2_options="no" ac_lv2_buf_size="no" fi else ac_options="no" ac_buf_size="no" fi if test "x$ac_lv2_worker" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "lv2/lv2plug.in/ns/ext/worker/worker.h" "ac_cv_header_lv2_lv2plug_in_ns_ext_worker_worker_h" "$ac_includes_default" if test "x$ac_cv_header_lv2_lv2plug_in_ns_ext_worker_worker_h" = xyes; then : ac_lv2_worker="yes" else ac_lv2_worker="no" fi if test "x$ac_lv2_worker" = "xyes"; then $as_echo "#define CONFIG_LV2_WORKER 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** LV2 Worker/Schedule support will be disabled." >&5 $as_echo "$as_me: WARNING: *** LV2 Worker/Schedule support will be disabled." >&2;} fi fi if test "x$ac_lv2_external_ui" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "lv2_external_ui.h" "ac_cv_header_lv2_external_ui_h" "$ac_includes_default" if test "x$ac_cv_header_lv2_external_ui_h" = xyes; then : ac_lv2_external_ui="yes" else ac_lv2_external_ui="no" fi if test "x$ac_lv2_external_ui" = "xyes"; then for ac_header in lv2/lv2plug.in/ns/ext/data-access/data-access.h \ lv2/lv2plug.in/ns/ext/instance-access/instance-access.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF ac_lv2_external_ui="yes" else ac_lv2_external_ui="no" fi done fi if test "x$ac_lv2_external_ui" = "xyes"; then $as_echo "#define CONFIG_LV2_EXTERNAL_UI 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** LV2 External UI extension will be disabled." >&5 $as_echo "$as_me: WARNING: *** LV2 External UI extension will be disabled." >&2;} fi fi if test "x$ac_lv2_state" = "xyes"; then for ac_header in lv2/lv2plug.in/ns/ext/atom/atom.h \ lv2/lv2plug.in/ns/ext/state/state.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF ac_lv2_state="yes" else ac_lv2_state="no" fi done if test "x$ac_lv2_state" = "xyes"; then $as_echo "#define CONFIG_LV2_STATE 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** LV2 State extension will be disabled." >&5 $as_echo "$as_me: WARNING: *** LV2 State extension will be disabled." >&2;} ac_lv2_state_files="no" ac_lv2_presets="no" fi if test "x$ac_lv2_state_files" = "xyes"; then $as_echo "#define CONFIG_LV2_STATE_FILES 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** LV2 State Files feature will be disabled." >&5 $as_echo "$as_me: WARNING: *** LV2 State Files feature will be disabled." >&2;} fi else ac_lv2_state_files="no" ac_lv2_presets="no" fi if test "x$ac_lv2_programs" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "lv2_programs.h" "ac_cv_header_lv2_programs_h" "$ac_includes_default" if test "x$ac_cv_header_lv2_programs_h" = xyes; then : ac_lv2_programs="yes" else ac_lv2_programs="no" fi if test "x$ac_lv2_programs" = "xyes"; then $as_echo "#define CONFIG_LV2_PROGRAMS 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** LV2 Programs extension will be disabled." >&5 $as_echo "$as_me: WARNING: *** LV2 Programs extension will be disabled." >&2;} fi fi if test "x$ac_lv2_presets" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "lv2/lv2plug.in/ns/ext/presets/presets.h" "ac_cv_header_lv2_lv2plug_in_ns_ext_presets_presets_h" "$ac_includes_default" if test "x$ac_cv_header_lv2_lv2plug_in_ns_ext_presets_presets_h" = xyes; then : ac_lv2_presets="yes" else ac_lv2_presets="no" fi if test "x$ac_lv2_presets" = "xyes"; then $as_echo "#define CONFIG_LV2_PRESETS 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** LV2 Presets will be disabled." >&5 $as_echo "$as_me: WARNING: *** LV2 Presets will be disabled." >&2;} fi fi if test "x$ac_lv2_time" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "lv2/lv2plug.in/ns/ext/time/time.h" "ac_cv_header_lv2_lv2plug_in_ns_ext_time_time_h" "$ac_includes_default" if test "x$ac_cv_header_lv2_lv2plug_in_ns_ext_time_time_h" = xyes; then : ac_lv2_time="yes" else ac_lv2_time="no" fi if test "x$ac_lv2_time" = "xyes"; then $as_echo "#define CONFIG_LV2_TIME 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** LV2 Time support will be disabled." >&5 $as_echo "$as_me: WARNING: *** LV2 Time support will be disabled." >&2;} fi fi if test "x$ac_lv2_options" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "lv2/lv2plug.in/ns/ext/options/options.h" "ac_cv_header_lv2_lv2plug_in_ns_ext_options_options_h" "$ac_includes_default" if test "x$ac_cv_header_lv2_lv2plug_in_ns_ext_options_options_h" = xyes; then : ac_lv2_options="yes" else ac_lv2_options="no" fi if test "x$ac_lv2_options" = "xyes"; then $as_echo "#define CONFIG_LV2_OPTIONS 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** LV2 Options support will be disabled." >&5 $as_echo "$as_me: WARNING: *** LV2 Options support will be disabled." >&2;} ac_lv2_buf_size="no" fi else ac_lv2_buf_size="no" fi if test "x$ac_lv2_buf_size" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "lv2/lv2plug.in/ns/ext/buf-size/buf-size.h" "ac_cv_header_lv2_lv2plug_in_ns_ext_buf_size_buf_size_h" "$ac_includes_default" if test "x$ac_cv_header_lv2_lv2plug_in_ns_ext_buf_size_buf_size_h" = xyes; then : ac_lv2_buf_size="yes" else ac_lv2_buf_size="no" fi if test "x$ac_lv2_buf_size" = "xyes"; then $as_echo "#define CONFIG_LV2_BUF_SIZE 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** LV2 Buf-size support will be disabled." >&5 $as_echo "$as_me: WARNING: *** LV2 Buf-size support will be disabled." >&2;} fi fi # Check for JACK session headers availability. if test "x$ac_jack_session" = "xyes"; then ac_fn_cxx_check_header_mongrel "$LINENO" "jack/session.h" "ac_cv_header_jack_session_h" "$ac_includes_default" if test "x$ac_cv_header_jack_session_h" = xyes; then : ac_jack_session="yes" else ac_jack_session="no" fi if test "x$ac_jack_session" = "xyes"; then $as_echo "#define CONFIG_JACK_SESSION 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** jack/session.h file not found." >&5 $as_echo "$as_me: WARNING: *** jack/session.h file not found." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** JACK session support will be disabled." >&5 $as_echo "$as_me: WARNING: *** JACK session support will be disabled." >&2;} fi fi # Check for NSM support. if test "x$ac_nsm" = "xyes"; then $as_echo "#define CONFIG_NSM 1" >>confdefs.h fi # Check for X11 unique/single instance. if test "x$ac_xunique" = "xyes"; then $as_echo "#define CONFIG_XUNIQUE 1" >>confdefs.h fi # Check for gradient eye-candy. if test "x$ac_gradient" = "xyes"; then $as_echo "#define CONFIG_GRADIENT 1" >>confdefs.h fi # Check for debugging stack-trace. if test "x$ac_stacktrace" = "xyes"; then $as_echo "#define CONFIG_STACKTRACE 1" >>confdefs.h fi # Checks for typedefs, structures, and compiler characteristics. # AC_C_CONST # Checks for library functions. for ac_func in system do : ac_fn_cxx_check_func "$LINENO" "system" "ac_cv_func_system" if test "x$ac_cv_func_system" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYSTEM 1 _ACEOF fi done # Finally produce a configure header file and the makefiles. cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by Qtractor $as_me 0.5.11, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ Qtractor config.status 0.5.11 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "src/config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "qtractor.spec") CONFIG_FILES="$CONFIG_FILES qtractor.spec" ;; "src/src.pri") CONFIG_FILES="$CONFIG_FILES src/src.pri" ;; "src/qtractor.desktop") CONFIG_FILES="$CONFIG_FILES src/qtractor.desktop" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi # make clean > /dev/null 2>&1 # Output summary message echo echo " $PACKAGE_NAME $PACKAGE_VERSION" echo echo " Build target . . . . . . . . . . . . . . . . . . .: $ac_debug" echo echo " JACK Audio Connection Kit support . . . . . . . .: $ac_libjack" echo " ALSA MIDI Sequencer support . . . . . . . . . . .: $ac_libasound" echo " General audio file support (libsndfile) . . . . .: $ac_libsndfile" echo " Ogg Vorbis audio file support (libvorbis) . . . .: $ac_libvorbis" echo " MPEG-1 Audio Layer 3 file support (libmad) . . . .: $ac_libmad" echo " Sample-rate conversion support (libsamplerate) . .: $ac_libsamplerate" echo " Pitch-shifting support (librubberband) . . . . . .: $ac_librubberband" echo " OSC service support (liblo) . . . . . . . . . . .: $ac_liblo" echo " Archive/Zip file support (zlib) . . . . . . . . .: $ac_libz" echo " IEEE 32bit float optimizations . . . . . . . . . .: $ac_float32" echo " SSE optimization support (x86) . . . . . . . . . .: $ac_sse" echo " LADSPA plug-in support . . . . . . . . . . . . . .: $ac_ladspa" echo " DSSI plug-in support . . . . . . . . . . . . . . .: $ac_dssi" echo " VST plug-in support . . . . . . . . . . . . . . .: $ac_vst" echo " LV2 plug-in support (liblilv) . . . . . . . . . .: $ac_lv2" echo " LV2 plug-in UI support (libsuil) . . . . . . . . .: $ac_lv2_ui" echo " LV2 plug-in External UI support . . . . . . . . .: $ac_lv2_external_ui" echo " LV2 plug-in MIDI/Event support . . . . . . . . . .: $ac_lv2_event" echo " LV2 plug-in MIDI/Atom support . . . . . . . . . .: $ac_lv2_atom" echo " LV2 plug-in Worker/Schedule support . . . . . . .: $ac_lv2_worker" echo " LV2 plug-in State support . . . . . . . . . . . .: $ac_lv2_state" echo " LV2 plug-in State Files support . . . . . . . . .: $ac_lv2_state_files" echo " LV2 plug-in Programs support . . . . . . . . . . .: $ac_lv2_programs" echo " LV2 plug-in Presets support . . . . . . . . . . .: $ac_lv2_presets" echo " LV2 plug-in Time support . . . . . . . . . . . . .: $ac_lv2_time" echo " LV2 plug-in Options support . . . . . . . . . . .: $ac_lv2_options" echo " LV2 plug-in Buf-size support . . . . . . . . . . .: $ac_lv2_buf_size" echo echo " JACK Session support . . . . . . . . . . . . . . .: $ac_jack_session" echo " JACK Latency support . . . . . . . . . . . . . . .: $ac_jack_latency" echo echo " Non Session Management (NSM) support . . . . . . .: $ac_nsm" echo echo " X11 Unique/Single instance . . . . . . . . . . . .: $ac_xunique" echo " VeSTige header support . . . . . . . . . . . . . .: $ac_vestige" echo " Gradient eye-candy . . . . . . . . . . . . . . . .: $ac_gradient" echo " Debugger stack-trace (gdb) . . . . . . . . . . . .: $ac_stacktrace" echo echo " Install prefix . . . . . . . . . . . . . . . . . .: $ac_prefix" echo echo "Now type 'make', followed by 'make install' as root." echo qtractor-0.5.11/PaxHeaders.10084/configure.ac0000644000175000001440000000012312224470506016744 xustar000000000000000027 mtime=1381134662.966013 26 atime=1381134666.08008 30 ctime=1381134666.081080034 qtractor-0.5.11/configure.ac0000644000175000001440000010766612224470506016253 0ustar00rncbcusers00000000000000# Process this file with utoconf to produce a configure script. AC_INIT(Qtractor, 0.5.11, rncbc@rncbc.org, qtractor) AC_CONFIG_SRCDIR(src/qtractor.cpp) AC_CONFIG_HEADERS(src/config.h) AC_CONFIG_FILES(Makefile qtractor.spec src/src.pri src/qtractor.desktop) # Set default installation prefix. AC_PREFIX_DEFAULT(/usr/local) ac_prefix=$prefix if test "x$ac_prefix" = "xNONE"; then ac_prefix=$ac_default_prefix fi AC_SUBST(ac_prefix) AC_DEFINE_UNQUOTED(CONFIG_PREFIX, ["$ac_prefix"], [Default installation prefix.]) # Enable debugging argument option. AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [enable debugging (default=no)]), [ac_debug="$enableval"]) if test "x$ac_debug" = "xyes"; then AC_DEFINE(CONFIG_DEBUG, 1, [Define if debugging is enabled.]) ac_stacktrace="yes" ac_debug="debug" else ac_stacktrace="no" ac_debug="release" fi AC_SUBST(ac_debug) # Enable libvorbis(file) availability. AC_ARG_ENABLE(libvorbis, AC_HELP_STRING([--enable-libvorbis], [enable libvorbis interface (default=yes)]), [ac_libvorbis="$enableval"], [ac_libvorbis="yes"]) # Enable libmad availability. AC_ARG_ENABLE(libmad, AC_HELP_STRING([--enable-libmad], [enable libmad interface (default=yes)]), [ac_libmad="$enableval"], [ac_libmad="yes"]) # Enable libsamplerate availability. AC_ARG_ENABLE(libsamplerate, AC_HELP_STRING([--enable-libsamplerate], [enable libsamplerate interface (default=yes)]), [ac_libsamplerate="$enableval"], [ac_libsamplerate="yes"]) # Enable librubberband availability. AC_ARG_ENABLE(librubberband, AC_HELP_STRING([--enable-librubberband], [enable librubberband interface (default=yes)]), [ac_librubberband="$enableval"], [ac_librubberband="yes"]) # Enable liblo availability. AC_ARG_ENABLE(liblo, AC_HELP_STRING([--enable-liblo], [enable liblo interface (default=yes)]), [ac_liblo="$enableval"], [ac_liblo="yes"]) # Enable libz availability. AC_ARG_ENABLE(libz, AC_HELP_STRING([--enable-libz], [enable libz interface (default=yes)]), [ac_libz="$enableval"], [ac_libz="yes"]) # Enable LILV support. AC_ARG_ENABLE(lilv, AC_HELP_STRING([--enable-lilv], [enable LILV interface support (default=yes)]), [ac_lilv="$enableval"], [ac_lilv="yes"]) # Enable SUIL support. AC_ARG_ENABLE(suil, AC_HELP_STRING([--enable-suil], [enable SUIL interface support (default=yes)]), [ac_suil="$enableval"], [ac_suil="yes"]) # Enable SSE optimization. AC_ARG_ENABLE(sse, AC_HELP_STRING([--enable-sse], [enable SSE optimization (default=yes)]), [ac_sse="$enableval"], [ac_sse="yes"]) # Enable LADSPA support. AC_ARG_ENABLE(ladspa, AC_HELP_STRING([--enable-ladspa], [enable LADSPA plug-in support (default=yes)]), [ac_ladspa="$enableval"], [ac_ladspa="yes"]) # Enable DSSI support. AC_ARG_ENABLE(dssi, AC_HELP_STRING([--enable-dssi], [enable DSSI plug-in support (default=yes)]), [ac_dssi="$enableval"], [ac_dssi="yes"]) # Enable VST support. AC_ARG_ENABLE(vst, AC_HELP_STRING([--enable-vst], [enable VST plug-in support (default=yes)]), [ac_vst="$enableval"], [ac_vst="yes"]) AC_ARG_ENABLE(vestige, AC_HELP_STRING([--enable-vestige], [enable VeSTige header support (default=yes)]), [ac_vestige="$enableval"], [ac_vestige="yes"]) # Enable LV2 support. AC_ARG_ENABLE(lv2, AC_HELP_STRING([--enable-lv2], [enable LV2 plug-in support (default=yes)]), [ac_lv2="$enableval"], [ac_lv2="yes"]) AC_ARG_ENABLE(lv2-event, AC_HELP_STRING([--enable-lv2-event], [enable LV2 plug-in MIDI/Event support (default=yes)]), [ac_lv2_event="$enableval"], [ac_lv2_event="yes"]) AC_ARG_ENABLE(lv2-atom, AC_HELP_STRING([--enable-lv2-atom], [enable LV2 plug-in MIDI/Atom support (default=yes)]), [ac_lv2_atom="$enableval"], [ac_lv2_atom="yes"]) AC_ARG_ENABLE(lv2-worker, AC_HELP_STRING([--enable-lv2-worker], [enable LV2 plug-in Worker/schedule support (default=yes)]), [ac_lv2_worker="$enableval"], [ac_lv2_worker="yes"]) AC_ARG_ENABLE(lv2-ui, AC_HELP_STRING([--enable-lv2-ui], [enable LV2 plug-in UI support (default=yes)]), [ac_lv2_ui="$enableval"], [ac_lv2_ui="yes"]) AC_ARG_ENABLE(lv2-external-ui, AC_HELP_STRING([--enable-lv2-external-ui], [enable LV2 plug-in External UI support (default=yes)]), [ac_lv2_external_ui="$enableval"], [ac_lv2_external_ui="yes"]) AC_ARG_ENABLE(lv2-state, AC_HELP_STRING([--enable-lv2-state], [enable LV2 plug-in State support (default=yes)]), [ac_lv2_state="$enableval"], [ac_lv2_state="yes"]) AC_ARG_ENABLE(lv2-state-files, AC_HELP_STRING([--enable-lv2-state-files], [enable LV2 plug-in State Files support (default=yes)]), [ac_lv2_state_files="$enableval"], [ac_lv2_state_files="yes"]) AC_ARG_ENABLE(lv2-programs, AC_HELP_STRING([--enable-lv2-programs], [enable LV2 plug-in Programs support (default=yes)]), [ac_lv2_programs="$enableval"], [ac_lv2_programs="yes"]) AC_ARG_ENABLE(lv2-presets, AC_HELP_STRING([--enable-lv2-presets], [enable LV2 plug-in Presets support (default=yes)]), [ac_lv2_presets="$enableval"], [ac_lv2_presets="yes"]) AC_ARG_ENABLE(lv2-time, AC_HELP_STRING([--enable-lv2-time], [enable LV2 plug-in Time/position support (default=yes)]), [ac_lv2_time="$enableval"], [ac_lv2_time="yes"]) AC_ARG_ENABLE(lv2-options, AC_HELP_STRING([--enable-lv2-options], [enable LV2 plug-in Options support (default=yes)]), [ac_lv2_options="$enableval"], [ac_lv2_options="yes"]) AC_ARG_ENABLE(lv2-buf-size, AC_HELP_STRING([--enable-lv2-buf-size], [enable LV2 plug-in Buf-size support (default=yes)]), [ac_lv2_buf_size="$enableval"], [ac_lv2_buf_size="yes"]) # Enable JACK session support. AC_ARG_ENABLE(jack-session, AC_HELP_STRING([--enable-jack-session], [enable JACK session support (default=yes)]), [ac_jack_session="$enableval"], [ac_jack_session="yes"]) # Enable JACK latency support. AC_ARG_ENABLE(jack-latency, AC_HELP_STRING([--enable-jack-latency], [enable JACK latency support (default=yes)]), [ac_jack_latency="$enableval"], [ac_jack_latency="yes"]) # Enable NSM support. AC_ARG_ENABLE(nsm, AC_HELP_STRING([--enable-nsm], [enable NSM support (default=yes)]), [ac_nsm="$enableval"], [ac_nsm="yes"]) # Enable X11 unique/single instance. AC_ARG_ENABLE(xunique, AC_HELP_STRING([--enable-xunique], [enable X11 unique/single instance (default=no)]), [ac_xunique="$enableval"], [ac_xunique="no"]) # Enable gradient eye-candy. AC_ARG_ENABLE(gradient, AC_HELP_STRING([--enable-gradient], [enable gradient eye-candy (default=yes)]), [ac_gradient="$enableval"], [ac_gradient="yes"]) # Enable debugger stack-trace option (assumes --enable-debug). AC_ARG_ENABLE(stacktrace, AC_HELP_STRING([--enable-stacktrace], [enable debugger stack-trace (default=no)]), [ac_stacktrace="$enableval"]) # Standard installation base dirs. ac_with_paths="/usr /usr/local" # Some a-la-debian alternatives... for X in /usr/lib /usr/lib64 /usr/share; do for Y in qt qt4; do if test -d $X/$Y/bin; then ac_with_paths="$ac_with_paths $X/$Y" fi done done # Set for alternate Qt installation dir. AC_ARG_WITH(qt, AC_HELP_STRING([--with-qt=PATH], [use alternate Qt install path]), [ac_with_paths="$ac_with_paths $withval"]) # Set for alternate JACK installation dir. AC_ARG_WITH(jack, AC_HELP_STRING([--with-jack=PATH], [use alternate JACK install path]), [ac_with_paths="$ac_with_paths $withval"]) # Set for alternate ALSA installation dir. AC_ARG_WITH(alsa, AC_HELP_STRING([--with-alsa=PATH], [use alternate ALSA install path]), [ac_with_paths="$ac_with_paths $withval"]) # Set for alternate libsndfile installation dir. AC_ARG_WITH(libsndfile, AC_HELP_STRING([--with-libsndfile=PATH], [use alternate libsndfile path]), [ac_with_paths="$ac_with_paths $withval"]) # Set for alternate libvorbis installation dir. AC_ARG_WITH(libvorbis, AC_HELP_STRING([--with-libvorbis=PATH], [use alternate libvorbis path]), [ac_with_paths="$ac_with_paths $withval"]) # Set for alternate libmad installation dir. AC_ARG_WITH(libmad, AC_HELP_STRING([--with-libmad=PATH], [use alternate libmad path]), [ac_with_paths="$ac_with_paths $withval"]) # Set for alternate libsamplerate installation dir. AC_ARG_WITH(libsamplerate, AC_HELP_STRING([--with-libsamplerate=PATH], [use alternate libsamplerate path]), [ac_with_paths="$ac_with_paths $withval"]) # Set for alternate librubberband installation dir. AC_ARG_WITH(librubberband, AC_HELP_STRING([--with-librubberband=PATH], [use alternate librubberband path]), [ac_with_paths="$ac_with_paths $withval"]) # Set for alternate liblo installation dir. AC_ARG_WITH(liblo, AC_HELP_STRING([--with-liblo=PATH], [use alternate liblo path]), [ac_with_paths="$ac_with_paths $withval"]) # Set for alternate libz installation dir. AC_ARG_WITH(libz, AC_HELP_STRING([--with-libz=PATH], [use alternate libz path]), [ac_with_paths="$ac_with_paths $withval"]) # Set for alternate liblilv installation dir. AC_ARG_WITH(liblilv, AC_HELP_STRING([--with-liblilv=PATH], [use alternate liblilv path]), [ac_with_paths="$ac_with_paths $withval"]) # Set for alternate libsuil installation dir. AC_ARG_WITH(libsuil, AC_HELP_STRING([--with-libsuil=PATH], [use alternate libsuil path]), [ac_with_paths="$ac_with_paths $withval"]) # Set for alternate LADSPA include dir. AC_ARG_WITH(ladspa, AC_HELP_STRING([--with-ladspa=PATH], [use alternate LADSPA header path]), [ac_with_ladspa="$withval"]) # Set for alternate DSSI include dir. AC_ARG_WITH(dssi, AC_HELP_STRING([--with-dssi=PATH], [use alternate DSSI header path]), [ac_with_dssi="$withval"]) # Set for alternate VST include dir. AC_ARG_WITH(vst, AC_HELP_STRING([--with-vst=PATH], [use alternate VST header path]), [ac_with_vst="$withval"]) # Set for alternate LV2 include dir. AC_ARG_WITH(lv2, AC_HELP_STRING([--with-lv2=PATH], [use alternate LV2 header path]), [ac_with_lv2="$withval"]) # Honor user specified CFLAGS. ac_cflags=$CFLAGS # Checks for programs. AC_PROG_CC AC_PROG_CPP AC_PROG_CXX AC_PROG_CXXCPP AC_PROG_GCC_TRADITIONAL # Checks for languages. AC_LANG_C AC_LANG_CPLUSPLUS # Prepend alternate dependencies paths. ac_path=$PATH for X in $ac_with_paths; do if test -d $X/bin; then ac_path="$X/bin:$ac_path" fi # if test -x $X/qmake; then # ac_path="$X:$ac_path" # fi if test -d $X/include; then for Y in qt qt4; do if test -d $X/include/$Y; then CFLAGS="-I$X/include/$Y $CFLAGS" CPPFLAGS="-I$X/include/$Y $CPPFLAGS" ac_incpath="$X/include/$Y $ac_incpath" fi done CFLAGS="-I$X/include $CFLAGS" CPPFLAGS="-I$X/include $CPPFLAGS" ac_incpath="$X/include $ac_incpath" fi if test -d $X/lib64; then LIBS="-L$X/lib64 $LIBS" ac_libs="-L$X/lib64 $ac_libs" fi if test -d $X/lib; then LIBS="-L$X/lib $LIBS" ac_libs="-L$X/lib $ac_libs" fi done # Check for proper Qt version. AC_CACHE_CHECK([for Qt library version >= 4.4], ac_cv_qtversion, [ AC_TRY_LINK([#include "QtCore/qglobal.h"], [ #if QT_VERSION < 0x040400 #error Qt library 4.4 or greater required. #endif ], ac_cv_qtversion="yes", [ echo "no; Qt 4.4 or greater is required" exit 1 ]) ]) # Check for IEEE 32bit float optimizations. AC_CACHE_CHECK([for IEEE 32bit float optimizations], ac_cv_float32, [ AC_TRY_RUN([ int main() { return (sizeof(float) == 4 ? 0 : 1); } ], ac_cv_float32="yes", ac_cv_float32="no") ]) ac_float32=$ac_cv_float32 if test "x$ac_float32" = "xyes"; then AC_DEFINE(CONFIG_FLOAT32, 1, [Define if IEEE 32bit float optimizations are enabled.]) fi # Check for SSE optimization. if test "x$ac_sse" = "xyes"; then ac_sse_cflags="-msse -mfpmath=sse -ffast-math" ac_old_cflags=$CFLAGS ac_old_cppflags=$CPPFLAGS CFLAGS="$ac_sse_cflags $CFLAGS" CPPFLAGS="$ac_sse_cflags $CPPFLAGS" AC_CACHE_CHECK([for SSE optimization], ac_cv_sse, [ AC_TRY_RUN([ #include #if !defined(__SSE__) #error SSE optimization disabled. #endif int main() { unsigned int a, b, c, d; __asm__ __volatile__ ("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (1)); return ((d & (1 << 25)) ? 0 : 1); } ], ac_cv_sse="yes", ac_cv_sse="no") ]) ac_sse=$ac_cv_sse if test "x$ac_sse" = "xyes"; then ac_cflags="$ac_sse_cflags $ac_cflags" else CPPFLAGS=$ac_old_cppflags CFLAGS=$ac_old_cflags fi fi # A common error message: ac_errmsg="not found in current PATH. Maybe QT development environment isn't available (qt-devel)." # Check for Qt qmake utility. AC_PATH_PROG(ac_qmake, qmake, [no], $ac_path) if test "x$ac_qmake" = "xno"; then AC_MSG_ERROR([qmake $ac_errmsg]) fi AC_SUBST(ac_qmake) # Check for Qt moc utility. AC_PATH_PROG(ac_moc, moc, [no], $ac_path) if test "x$ac_moc" = "xno"; then AC_MSG_ERROR([moc $ac_errmsg]) fi AC_SUBST(ac_moc) # Check for Qt uic utility. AC_PATH_PROG(ac_uic, uic, [no], $ac_path) if test "x$ac_uic" = "xno"; then AC_MSG_ERROR([uic $ac_errmsg]) fi AC_SUBST(ac_uic) # Check for Qt lupdate utility. AC_PATH_PROG(ac_lupdate, lupdate, [no], $ac_path) if test "x$ac_lupdate" = "xno"; then AC_MSG_ERROR([lupdate $ac_errmsg]) fi AC_SUBST(ac_lupdate) # Check for Qt lrelease utility. AC_PATH_PROG(ac_lrelease, lrelease, [no], $ac_path) if test "x$ac_release" = "xno"; then AC_MSG_ERROR([lrelease $ac_errmsg]) fi AC_SUBST(ac_lrelease) # Check for pkg-config utility (needed for LV2 GTK UI support). AC_PATH_PROG(ac_pkg_config, pkg-config, [no], $ac_path) if test "x$ac_pkg_config" = "xno"; then ac_lv2="no" ac_lilv="no" ac_suil="no" fi # Checks for libraries. AC_CHECK_LIB(m, main) AC_CHECK_LIB(X11, main) AC_CHECK_LIB(Xext, main) # Check for round math function. AC_CHECK_LIB(m, round, [ac_round="yes"], [ac_round="no"]) if test "x$ac_round" = "xyes"; then AC_DEFINE(CONFIG_ROUND, 1, [Define if round is available.]) fi # Check for JACK libraries. AC_CHECK_LIB(jack, main, [ac_libjack="yes"], [ac_libjack="no"]) if test "x$ac_libjack" = "xno"; then AC_MSG_ERROR([JACK library not found.]) else ac_libs="$ac_libs -ljack" fi # Check for ALSA libraries. AC_CHECK_LIB(asound, main, [ac_libasound="yes"], [ac_libasound="no"]) if test "x$ac_libasound" = "xno"; then AC_MSG_ERROR([ALSA library not found.]) else ac_libs="$ac_libs -lasound" fi # Check for sndfile library. AC_CHECK_LIB(sndfile, main, [ac_libsndfile="yes"], [ac_libsndfile="no"]) if test "x$ac_libsndfile" = "xno"; then AC_MSG_ERROR([sndfile library not found.]) else ac_libs="$ac_libs -lsndfile" fi # Check for option libvorbis libraries. if test "x$ac_libvorbis" = "xyes"; then AC_CHECK_LIB(ogg, main, [ac_libvorbis="yes"], [ac_libvorbis="no"]) if test "x$ac_libvorbis" = "xyes"; then ac_libs="$ac_libs -logg" else AC_MSG_WARN([*** ogg library not found.]) fi fi if test "x$ac_libvorbis" = "xyes"; then AC_CHECK_LIB(vorbis, main, [ac_libvorbis="yes"], [ac_libvorbis="no"]) if test "x$ac_libvorbis" = "xyes"; then ac_libs="$ac_libs -lvorbis" else AC_MSG_WARN([*** vorbis library not found.]) fi fi if test "x$ac_libvorbis" = "xyes"; then AC_CHECK_LIB(vorbisenc, main, [ac_libvorbis="yes"], [ac_libvorbis="no"]) if test "x$ac_libvorbis" = "xyes"; then ac_libs="$ac_libs -lvorbisenc" else AC_MSG_WARN([*** vorbisenc library not found.]) fi fi if test "x$ac_libvorbis" = "xyes"; then AC_CHECK_LIB(vorbisfile, main, [ac_libvorbis="yes"], [ac_libvorbis="no"]) if test "x$ac_libvorbis" = "xyes"; then ac_libs="$ac_libs -lvorbisfile" else AC_MSG_WARN([*** vorbisfile library not found.]) fi fi if test "x$ac_libvorbis" = "xyes"; then AC_DEFINE(CONFIG_LIBVORBIS, 1, [Define if libvorbis is available.]) else AC_MSG_WARN([*** Ogg Vorbis audio file support will be disabled.]) fi # Check for optional libmad library. if test "x$ac_libmad" = "xyes"; then AC_CHECK_LIB(mad, main, [ac_libmad="yes"], [ac_libmad="no"]) if test "x$ac_libmad" = "xyes"; then AC_DEFINE(CONFIG_LIBMAD, 1, [Define if libmad is available.]) ac_libs="$ac_libs -lmad" else AC_MSG_WARN([*** mad library not found.]) AC_MSG_WARN([*** MPEG Layer III audio file support will be disabled.]) fi fi # Check for optional libsamplerate library. if test "x$ac_libsamplerate" = "xyes"; then AC_CHECK_LIB(samplerate, main, [ac_libsamplerate="yes"], [ac_libsamplerate="no"]) if test "x$ac_libsamplerate" = "xyes"; then AC_DEFINE(CONFIG_LIBSAMPLERATE, 1, [Define if libsamplerate is available.]) ac_libs="$ac_libs -lsamplerate" else AC_MSG_WARN([*** samplerate library not found.]) AC_MSG_WARN([*** Sample-rate conversion support will be disabled.]) fi fi # Check for optional librubberband library. if test "x$ac_librubberband" = "xyes"; then AC_CHECK_LIB(rubberband, main, [ac_librubberband="yes"], [ac_librubberband="no"]) if test "x$ac_librubberband" = "xyes"; then AC_DEFINE(CONFIG_LIBRUBBERBAND, 1, [Define if librubberband is available.]) ac_libs="$ac_libs -lrubberband" else AC_MSG_WARN([*** rubberband library not found.]) AC_MSG_WARN([*** Pitch-shifting support will be disabled.]) fi fi # Check for optional liblo library. if test "x$ac_liblo" = "xyes"; then AC_CHECK_LIB(lo, main, [ac_liblo="yes"], [ac_liblo="no"]) if test "x$ac_liblo" = "xyes"; then AC_DEFINE(CONFIG_LIBLO, 1, [Define if liblo is available.]) ac_libs="$ac_libs -llo" else AC_MSG_WARN([*** lo library not found.]) AC_MSG_WARN([*** OSC service support will be disabled.]) ac_nsm="no" fi else ac_nsm="no" fi # Check for optional libz library. if test "x$ac_libz" = "xyes"; then AC_CHECK_LIB(z, main, [ac_libz="yes"], [ac_libz="no"]) if test "x$ac_libz" = "xyes"; then AC_DEFINE(CONFIG_LIBZ, 1, [Define if libz is available.]) ac_libs="$ac_libs -lz" else AC_MSG_WARN([*** z library not found.]) AC_MSG_WARN([*** Archive/Zip file support will be disabled.]) fi fi # Check for optional liblilv library. if test "x$ac_lilv" = "xyes"; then AC_CHECK_LIB(lilv-0, main, [ac_lilv="yes"], [ac_lilv="no"]) fi if test "x$ac_lilv" = "xyes"; then ac_lilv_libs=`$ac_pkg_config --libs lilv-0 2>/dev/null` if test -n "$ac_lilv_libs"; then ac_libs="$ac_libs $ac_lilv_libs" AC_DEFINE(CONFIG_LIBLILV, 1, [Define if liblilv is available.]) else AC_MSG_WARN([*** lilv library not found.]) ac_lilv="no" ac_suil="no" fi else ac_suil="no" fi # Check for LV2 support. if test "x$ac_lv2_ui" = "xno"; then ac_suil="no" ac_lv2_external_ui="no" fi # Check for LV2 new UI instantiation availability (libsuil). if test "x$ac_suil" = "xyes"; then AC_CHECK_LIB(suil-0, main, [ac_suil="yes"], [ac_suil="no"]) fi if test "x$ac_suil" = "xyes"; then ac_suil_libs=`$ac_pkg_config --libs suil-0 2>/dev/null` if test -n "$ac_suil_libs"; then ac_libs="$ac_libs $ac_suil_libs" AC_DEFINE(CONFIG_LIBSUIL, 1, [Define if libsuil is available.]) else AC_MSG_WARN([*** suil library not found.]) ac_suil="no" ac_lv2_ui="no" ac_lv2_external_ui="no" fi fi if test "x$ac_suil" = "xyes"; then AC_CHECK_LIB(suil-0, suil_instance_get_handle, [ac_suil_instance_get_handle="yes"], [ac_suil_instance_get_handle="no"]) if test "x$ac_suil_instance_get_handle" = "xyes"; then AC_DEFINE(CONFIG_SUIL_INSTANCE_GET_HANDLE, 1, [Define if suil_instance_get_handle is available.]) fi else ac_suil="no" ac_lv2_ui="no" ac_lv2_external_ui="no" fi # Check for LV2 host library (liblilv). if test "x$ac_lilv" = "xno"; then ac_lv2="no" ac_lv2_ui="no" ac_lv2_event="no" ac_lv2_atom="no" ac_lv2_worker="no" ac_lv2_external_ui="no" ac_lv2_state="no" ac_lv2_state_files="no" ac_lv2_programs="no" ac_lv2_presets="no" ac_lv2_time="no" ac_lv2_options="no" ac_lv2_buf_size="no" fi # Check for JACK session event callback availability. if test "x$ac_jack_session" = "xyes"; then AC_CHECK_LIB(jack, jack_set_session_callback, [ac_jack_session="yes"], [ac_jack_session="no"]) else AC_MSG_WARN([*** JACK session support will be disabled.]) fi # Check for (new) JACK latency support availability. if test "x$ac_jack_latency" = "xyes"; then AC_CHECK_LIB(jack, jack_port_get_latency_range, [ac_jack_latency="yes"], [ac_jack_latency="no"]) if test "x$ac_jack_latency" = "xyes"; then AC_DEFINE(CONFIG_JACK_LATENCY, 1, [Define if JACK latency support is available.]) else AC_MSG_WARN([*** JACK latency support will be disabled.]) fi fi # Some recent distros (eg. fedora, debian) require this. ac_libs="$ac_libs -lX11" AC_SUBST(ac_libs) # Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_CHECK_HEADERS(fcntl.h sys/ioctl.h sys/stat.h unistd.h signal.h) # Check for JACK headers. AC_CHECK_HEADER(jack/jack.h, [ac_jack_h="yes"], [ac_jack_h="no"]) if test "x$ac_jack_h" = "xno"; then AC_MSG_ERROR([JACK headers not found.]) fi # Check for ALSA headers. AC_CHECK_HEADER(alsa/asoundlib.h, [ac_alsa_h="yes"], [ac_alsa_h="no"]) if test "x$ac_alsa_h" = "xno"; then AC_MSG_ERROR([ALSA headers not found.]) fi # Check for sndfile headers. AC_CHECK_HEADER(sndfile.h, [ac_sndfile_h="yes"], [ac_sndfile_h="no"]) if test "x$ac_sndfile_h" = "xno"; then AC_MSG_ERROR([sndfile.h header file not found.]) fi # Check for vorbisfile headers. if test "x$ac_libvorbis" = "xyes"; then AC_CHECK_HEADER(vorbis/vorbisenc.h, [ac_vorbisenc_h="yes"], [ac_vorbisenc_h="no"]) if test "x$ac_vorbisenc_h" = "xno"; then AC_MSG_ERROR([vorbisenc.h header file not found.]) fi AC_CHECK_HEADER(vorbis/vorbisfile.h, [ac_vorbisfile_h="yes"], [ac_vorbisfile_h="no"]) if test "x$ac_vorbisfile_h" = "xno"; then AC_MSG_ERROR([vorbisfile.h header file not found.]) fi fi # Check for mad headers. if test "x$ac_libmad" = "xyes"; then AC_CHECK_HEADER(mad.h, [ac_mad_h="yes"], [ac_mad_h="no"]) if test "x$ac_mad_h" = "xno"; then AC_MSG_ERROR([mad.h header file not found.]) fi fi # Check for samplerate headers. if test "x$ac_libsamplerate" = "xyes"; then AC_CHECK_HEADER(samplerate.h, [ac_samplerate_h="yes"], [ac_samplerate_h="no"]) if test "x$ac_samplerate_h" = "xno"; then AC_MSG_ERROR([samplerate.h header file not found.]) fi fi # Check for rubberband headers. if test "x$ac_librubberband" = "xyes"; then AC_CHECK_HEADER(rubberband/RubberBandStretcher.h, [ac_rubberband_h="yes"], [ac_rubberband_h="no"]) if test "x$ac_rubberband_h" = "xno"; then AC_MSG_ERROR([RubberBandStretcher.h header file not found.]) fi fi # Check for lo headers. if test "x$ac_liblo" = "xyes"; then AC_CHECK_HEADER(lo/lo.h, [ac_lo_h="yes"], [ac_lo_h="no"]) if test "x$ac_lo_h" = "xno"; then AC_MSG_ERROR([lo.h header file not found.]) ac_nsm="no" fi fi # Check for zlib headers. if test "x$ac_libz" = "xyes"; then AC_CHECK_HEADER(zlib.h, [ac_zlib_h="yes"], [ac_zlib_h="no"]) if test "x$ac_zlib_h" = "xno"; then AC_MSG_ERROR([zlib.h header file not found.]) fi fi # Check for lilv headers. if test "x$ac_lilv" = "xyes"; then ac_lilv_cflags=`$ac_pkg_config --cflags lilv-0 2>/dev/null` if test -n "$ac_lilv_cflags"; then CFLAGS="$ac_lilv_cflags $CFLAGS" CPPFLAGS="$ac_lilv_cflags $CPPFLAGS" fi AC_CHECK_HEADER(lilv/lilv.h, [ac_lilv_h="yes"], [ac_lilv_h="no"]) if test "x$ac_lilv_h" = "xno"; then AC_MSG_ERROR([lilv.h header file not found.]) else ac_cflags="$ac_lilv_cflags $ac_cflags" fi fi # Check for suil headers. if test "x$ac_suil" = "xyes"; then ac_suil_cflags=`$ac_pkg_config --cflags suil-0 2>/dev/null` if test -n "$ac_suil_cflags"; then CFLAGS="$ac_suil_cflags $CFLAGS" CPPFLAGS="$ac_suil_cflags $CPPFLAGS" fi AC_CHECK_HEADER(suil/suil.h, [ac_suil_h="yes"], [ac_suil_h="no"]) if test "x$ac_suil_h" = "xno"; then AC_MSG_ERROR([suil.h header file not found.]) else ac_cflags="$ac_suil_cflags $ac_cflags" fi fi # Check for LADSPA headers. if test -n "$ac_with_ladspa"; then CFLAGS="-I$ac_with_ladspa $CFLAGS" CPPFLAGS="-I$ac_with_ladspa $CPPFLAGS" ac_ladspa="yes" fi if test "x$ac_ladspa" = "xyes"; then AC_CHECK_HEADER(ladspa.h, [ac_ladspa="yes"], [ac_ladspa="no"]) if test "x$ac_ladspa" = "xyes"; then AC_DEFINE(CONFIG_LADSPA, 1, [Define if LADSPA header is available.]) ac_incpath="$ac_with_ladspa $ac_incpath" else AC_MSG_WARN([*** ladspa.h header file not found.]) AC_MSG_WARN([*** LADSPA plug-in support will be disabled.]) fi fi # Check for DSSI headers. if test -n "$ac_with_dssi"; then CFLAGS="-I$ac_with_dssi $CFLAGS" CPPFLAGS="-I$ac_with_dssi $CPPFLAGS" ac_dssi="yes" fi if test "x$ac_dssi" = "xyes"; then AC_CHECK_HEADER(dssi.h, [ac_dssi="yes"], [ac_dssi="no"]) if test "x$ac_dssi" = "xyes"; then AC_DEFINE(CONFIG_DSSI, 1, [Define if DSSI header is available.]) ac_incpath="$ac_with_dssi $ac_incpath" else AC_MSG_WARN([*** dssi.h header file not found.]) AC_MSG_WARN([*** DSSI plug-in support will be disabled.]) fi fi # Pre-check for VeSTige header. if test "$ac_vestige" = "xyes"; then ac_vst="yes" fi # Check for VST headers. if test -n "$ac_with_vst"; then CFLAGS="-I$ac_with_vst $CFLAGS" CPPFLAGS="-I$ac_with_vst $CPPFLAGS" ac_incpath="$ac_with_vst $ac_incpath" ac_vst="yes" fi if test "x$ac_vst" = "xyes"; then CFLAGS="-D__cdecl= $CFLAGS" CPPFLAGS="-D__cdecl= $CPPFLAGS" AC_CACHE_CHECK([for VST headers], ac_cv_vst, [ AC_TRY_LINK([#include ], [ // Checking for VST headers... ], ac_cv_vst="yes", ac_cv_vst="no") ]) ac_vst=$ac_cv_vst if test "x$ac_vst" = "xno" -a "x$ac_vestige" = "xyes"; then CFLAGS="$CFLAGS -Isrc/vestige" CPPFLAGS="$CPPFLAGS -Isrc/vestige" ac_incpath="$ac_incpath vestige" AC_CHECK_HEADER(aeffectx.h, [ac_vst="yes"], [ac_vst="no"]) else ac_vestige="no" fi if test "x$ac_vst" = "xyes"; then AC_DEFINE(CONFIG_VST, 1, [Define if VST header is available.]) else AC_MSG_WARN([*** aeffectx.h header file not found.]) AC_MSG_WARN([*** VST plug-in support will be disabled.]) ac_vestige="no" fi else ac_vestige="no" fi # Post-check for VeSTige header. if test "x$ac_vestige" = "xyes"; then AC_DEFINE(CONFIG_VESTIGE, 1, [Define if VeSTige header is available.]) fi # Check for LV2 headers. if test -n "$ac_with_lv2"; then ac_lv2="yes" fi if test "x$ac_lv2" = "xyes"; then if test -n "$ac_with_lv2"; then CFLAGS="-I$ac_with_lv2 $CFLAGS" CPPFLAGS="-I$ac_with_lv2 $CPPFLAGS" ac_incpath="$ac_with_lv2 $ac_incpath" else CFLAGS="$CFLAGS -Isrc/lv2" CPPFLAGS="$CPPFLAGS -Isrc/lv2" ac_incpath="$ac_incpath lv2" fi AC_CHECK_HEADER(lv2.h, [ac_lv2="yes"], [ac_lv2="no"]) if test "x$ac_lv2" = "xyes"; then AC_CHECK_HEADERS( lv2/lv2plug.in/ns/ext/urid/urid.h \ lv2/lv2plug.in/ns/ext/uri-map/uri-map.h, [ac_lv2="yes"], [ac_lv2="no"]) fi if test "x$ac_lv2" = "xyes"; then AC_DEFINE(CONFIG_LV2, 1, [Define if LV2 headers are available.]) else AC_MSG_WARN([*** LV2 header files not found.]) AC_MSG_WARN([*** LV2 plug-in support will be disabled.]) ac_lv2_ui="no" ac_lv2_event="no" ac_lv2_atom="no" ac_lv2_worker="no" ac_lv2_external_ui="no" ac_lv2_state="no" ac_lv2_state_files="no" ac_lv2_programs="no" ac_lv2_presets="no" ac_lv2_time="no" ac_lv2_options="no" ac_lv2_buf_size="no" fi fi if test "x$ac_lv2_ui" = "xyes"; then AC_CHECK_HEADER( lv2/lv2plug.in/ns/extensions/ui/ui.h, [ac_lv2_ui="yes"], [ac_lv2_ui="no"]) if test "x$ac_lv2_ui" = "xyes"; then AC_DEFINE(CONFIG_LV2_UI, 1, [Define if LV2 UI support is available.]) else AC_MSG_WARN([*** LV2 UI support will be disabled.]) ac_lv2_external_ui="no" fi else ac_lv2_external_ui="no" fi if test "x$ac_lv2_event" = "xyes"; then AC_CHECK_HEADERS( lv2/lv2plug.in/ns/ext/event/event.h \ lv2/lv2plug.in/ns/ext/event/event-helpers.h, [ac_lv2_event="yes"], [ac_lv2_event="no"]) if test "x$ac_lv2_event" = "xyes"; then AC_DEFINE(CONFIG_LV2_EVENT, 1, [Define if LV2 Event/MIDI support is available.]) else AC_MSG_WARN([*** LV2 Event/MIDI support will be disabled.]) fi fi if test "x$ac_lv2_atom" = "xyes"; then AC_CHECK_HEADERS(lv2_atom_helpers.h, [ac_lv2_atom="yes"], [ac_lv2_atom="no"]) if test "x$ac_lv2_atom" = "xyes"; then AC_DEFINE(CONFIG_LV2_ATOM, 1, [Define if LV2 Atom/MIDI aupport is available.]) else AC_MSG_WARN([*** LV2 Atom/MIDI support will be disabled.]) ac_lv2_options="no" ac_lv2_buf_size="no" fi else ac_options="no" ac_buf_size="no" fi if test "x$ac_lv2_worker" = "xyes"; then AC_CHECK_HEADER( lv2/lv2plug.in/ns/ext/worker/worker.h, [ac_lv2_worker="yes"], [ac_lv2_worker="no"]) if test "x$ac_lv2_worker" = "xyes"; then AC_DEFINE(CONFIG_LV2_WORKER, 1, [Define if LV2 Worker/Schedule aupport is available.]) else AC_MSG_WARN([*** LV2 Worker/Schedule support will be disabled.]) fi fi if test "x$ac_lv2_external_ui" = "xyes"; then AC_CHECK_HEADER(lv2_external_ui.h, [ac_lv2_external_ui="yes"], [ac_lv2_external_ui="no"]) if test "x$ac_lv2_external_ui" = "xyes"; then AC_CHECK_HEADERS( lv2/lv2plug.in/ns/ext/data-access/data-access.h \ lv2/lv2plug.in/ns/ext/instance-access/instance-access.h, [ac_lv2_external_ui="yes"], [ac_lv2_external_ui="no"]) fi if test "x$ac_lv2_external_ui" = "xyes"; then AC_DEFINE(CONFIG_LV2_EXTERNAL_UI, 1, [Define if LV2 External UI extension is available.]) else AC_MSG_WARN([*** LV2 External UI extension will be disabled.]) fi fi if test "x$ac_lv2_state" = "xyes"; then AC_CHECK_HEADERS( lv2/lv2plug.in/ns/ext/atom/atom.h \ lv2/lv2plug.in/ns/ext/state/state.h, [ac_lv2_state="yes"], [ac_lv2_state="no"]) if test "x$ac_lv2_state" = "xyes"; then AC_DEFINE(CONFIG_LV2_STATE, 1, [Define if LV2 State extension is available.]) else AC_MSG_WARN([*** LV2 State extension will be disabled.]) ac_lv2_state_files="no" ac_lv2_presets="no" fi if test "x$ac_lv2_state_files" = "xyes"; then AC_DEFINE(CONFIG_LV2_STATE_FILES, 1, [Define if LV2 State Files feature is available.]) else AC_MSG_WARN([*** LV2 State Files feature will be disabled.]) fi else ac_lv2_state_files="no" ac_lv2_presets="no" fi if test "x$ac_lv2_programs" = "xyes"; then AC_CHECK_HEADER(lv2_programs.h, [ac_lv2_programs="yes"], [ac_lv2_programs="no"]) if test "x$ac_lv2_programs" = "xyes"; then AC_DEFINE(CONFIG_LV2_PROGRAMS, 1, [Define if LV2 Programs extension is available.]) else AC_MSG_WARN([*** LV2 Programs extension will be disabled.]) fi fi if test "x$ac_lv2_presets" = "xyes"; then AC_CHECK_HEADER( lv2/lv2plug.in/ns/ext/presets/presets.h, [ac_lv2_presets="yes"], [ac_lv2_presets="no"]) if test "x$ac_lv2_presets" = "xyes"; then AC_DEFINE(CONFIG_LV2_PRESETS, 1, [Define if LV2 Presets are supported.]) else AC_MSG_WARN([*** LV2 Presets will be disabled.]) fi fi if test "x$ac_lv2_time" = "xyes"; then AC_CHECK_HEADER( lv2/lv2plug.in/ns/ext/time/time.h, [ac_lv2_time="yes"], [ac_lv2_time="no"]) if test "x$ac_lv2_time" = "xyes"; then AC_DEFINE(CONFIG_LV2_TIME, 1, [Define if LV2 Time/position is supported.]) else AC_MSG_WARN([*** LV2 Time support will be disabled.]) fi fi if test "x$ac_lv2_options" = "xyes"; then AC_CHECK_HEADER( lv2/lv2plug.in/ns/ext/options/options.h, [ac_lv2_options="yes"], [ac_lv2_options="no"]) if test "x$ac_lv2_options" = "xyes"; then AC_DEFINE(CONFIG_LV2_OPTIONS, 1, [Define if LV2 Options is supported.]) else AC_MSG_WARN([*** LV2 Options support will be disabled.]) ac_lv2_buf_size="no" fi else ac_lv2_buf_size="no" fi if test "x$ac_lv2_buf_size" = "xyes"; then AC_CHECK_HEADER( lv2/lv2plug.in/ns/ext/buf-size/buf-size.h, [ac_lv2_buf_size="yes"], [ac_lv2_buf_size="no"]) if test "x$ac_lv2_buf_size" = "xyes"; then AC_DEFINE(CONFIG_LV2_BUF_SIZE, 1, [Define if LV2 Buf-size is supported.]) else AC_MSG_WARN([*** LV2 Buf-size support will be disabled.]) fi fi # Check for JACK session headers availability. if test "x$ac_jack_session" = "xyes"; then AC_CHECK_HEADER(jack/session.h, [ac_jack_session="yes"], [ac_jack_session="no"]) if test "x$ac_jack_session" = "xyes"; then AC_DEFINE(CONFIG_JACK_SESSION, 1, [Define if JACK session support is available.]) else AC_MSG_WARN([*** jack/session.h file not found.]) AC_MSG_WARN([*** JACK session support will be disabled.]) fi fi # Check for NSM support. if test "x$ac_nsm" = "xyes"; then AC_DEFINE(CONFIG_NSM, 1, [Define if NSM support is available.]) fi # Check for X11 unique/single instance. if test "x$ac_xunique" = "xyes"; then AC_DEFINE(CONFIG_XUNIQUE, 1, [Define if X11 unique/single instance is enabled.]) fi # Check for gradient eye-candy. if test "x$ac_gradient" = "xyes"; then AC_DEFINE(CONFIG_GRADIENT, 1, [Define if gradient eye-candy is enabled.]) fi # Check for debugging stack-trace. if test "x$ac_stacktrace" = "xyes"; then AC_DEFINE(CONFIG_STACKTRACE, 1, [Define if debugger stack-trace is enabled.]) fi AC_SUBST(ac_incpath) AC_SUBST(ac_cflags) # Checks for typedefs, structures, and compiler characteristics. # AC_C_CONST # Checks for library functions. AC_CHECK_FUNCS(system) # Finally produce a configure header file and the makefiles. AC_OUTPUT # make clean > /dev/null 2>&1 # Output summary message echo echo " $PACKAGE_NAME $PACKAGE_VERSION" echo echo " Build target . . . . . . . . . . . . . . . . . . .: $ac_debug" echo echo " JACK Audio Connection Kit support . . . . . . . .: $ac_libjack" echo " ALSA MIDI Sequencer support . . . . . . . . . . .: $ac_libasound" echo " General audio file support (libsndfile) . . . . .: $ac_libsndfile" echo " Ogg Vorbis audio file support (libvorbis) . . . .: $ac_libvorbis" echo " MPEG-1 Audio Layer 3 file support (libmad) . . . .: $ac_libmad" echo " Sample-rate conversion support (libsamplerate) . .: $ac_libsamplerate" echo " Pitch-shifting support (librubberband) . . . . . .: $ac_librubberband" echo " OSC service support (liblo) . . . . . . . . . . .: $ac_liblo" echo " Archive/Zip file support (zlib) . . . . . . . . .: $ac_libz" echo " IEEE 32bit float optimizations . . . . . . . . . .: $ac_float32" echo " SSE optimization support (x86) . . . . . . . . . .: $ac_sse" echo " LADSPA plug-in support . . . . . . . . . . . . . .: $ac_ladspa" echo " DSSI plug-in support . . . . . . . . . . . . . . .: $ac_dssi" echo " VST plug-in support . . . . . . . . . . . . . . .: $ac_vst" echo " LV2 plug-in support (liblilv) . . . . . . . . . .: $ac_lv2" echo " LV2 plug-in UI support (libsuil) . . . . . . . . .: $ac_lv2_ui" echo " LV2 plug-in External UI support . . . . . . . . .: $ac_lv2_external_ui" echo " LV2 plug-in MIDI/Event support . . . . . . . . . .: $ac_lv2_event" echo " LV2 plug-in MIDI/Atom support . . . . . . . . . .: $ac_lv2_atom" echo " LV2 plug-in Worker/Schedule support . . . . . . .: $ac_lv2_worker" echo " LV2 plug-in State support . . . . . . . . . . . .: $ac_lv2_state" echo " LV2 plug-in State Files support . . . . . . . . .: $ac_lv2_state_files" echo " LV2 plug-in Programs support . . . . . . . . . . .: $ac_lv2_programs" echo " LV2 plug-in Presets support . . . . . . . . . . .: $ac_lv2_presets" echo " LV2 plug-in Time support . . . . . . . . . . . . .: $ac_lv2_time" echo " LV2 plug-in Options support . . . . . . . . . . .: $ac_lv2_options" echo " LV2 plug-in Buf-size support . . . . . . . . . . .: $ac_lv2_buf_size" echo echo " JACK Session support . . . . . . . . . . . . . . .: $ac_jack_session" echo " JACK Latency support . . . . . . . . . . . . . . .: $ac_jack_latency" echo echo " Non Session Management (NSM) support . . . . . . .: $ac_nsm" echo echo " X11 Unique/Single instance . . . . . . . . . . . .: $ac_xunique" echo " VeSTige header support . . . . . . . . . . . . . .: $ac_vestige" echo " Gradient eye-candy . . . . . . . . . . . . . . . .: $ac_gradient" echo " Debugger stack-trace (gdb) . . . . . . . . . . . .: $ac_stacktrace" echo echo " Install prefix . . . . . . . . . . . . . . . . . .: $ac_prefix" echo echo "Now type 'make', followed by 'make install' as root." echo qtractor-0.5.11/PaxHeaders.10084/COPYING0000644000175000001440000000007010505473142015511 xustar000000000000000026 atime=1381134671.24408 30 ctime=1381134671.244080116 qtractor-0.5.11/COPYING0000644000175000001440000004310310505473142015000 0ustar00rncbcusers00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. qtractor-0.5.11/PaxHeaders.10084/INSTALL0000644000175000001440000000012311720473615015513 xustar000000000000000027 mtime=1329756045.845128 26 atime=1381134666.08208 30 ctime=1381134666.082080034 qtractor-0.5.11/INSTALL0000644000175000001440000003634011720473615015010 0ustar00rncbcusers00000000000000Installation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. 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, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. 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 you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' 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. Running `configure' might take a while. 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, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. 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. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. 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 can use 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 `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer 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. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' 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. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= 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'. 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. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS 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 machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. 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. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--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. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. qtractor-0.5.11/PaxHeaders.10084/Makefile.in0000644000175000001440000000012312213640715016522 xustar000000000000000027 mtime=1378828749.720565 26 atime=1381134665.94608 30 ctime=1381134665.946080032 qtractor-0.5.11/Makefile.in0000644000175000001440000002174212213640715016017 0ustar00rncbcusers00000000000000prefix = @ac_prefix@ qmake = @ac_qmake@ lupdate = @ac_lupdate@ lrelease = @ac_lrelease@ name = qtractor target = src/$(name) headers = \ src/config.h \ src/qtractorAbout.h \ src/qtractorAtomic.h \ src/qtractorAudioBuffer.h \ src/qtractorAudioClip.h \ src/qtractorAudioConnect.h \ src/qtractorAudioEngine.h \ src/qtractorAudioFile.h \ src/qtractorAudioListView.h \ src/qtractorAudioMadFile.h \ src/qtractorAudioMeter.h \ src/qtractorAudioMonitor.h \ src/qtractorAudioPeak.h \ src/qtractorAudioSndFile.h \ src/qtractorAudioVorbisFile.h \ src/qtractorClip.h \ src/qtractorClipFadeFunctor.h \ src/qtractorClipCommand.h \ src/qtractorClipSelect.h \ src/qtractorCommand.h \ src/qtractorConnect.h \ src/qtractorConnections.h \ src/qtractorCtlEvent.h \ src/qtractorCurve.h \ src/qtractorCurveCommand.h \ src/qtractorCurveFile.h \ src/qtractorCurveSelect.h \ src/qtractorDocument.h \ src/qtractorDssiPlugin.h \ src/qtractorEngine.h \ src/qtractorEngineCommand.h \ src/qtractorFifoBuffer.h \ src/qtractorFileList.h \ src/qtractorFileListView.h \ src/qtractorFiles.h \ src/qtractorInsertPlugin.h \ src/qtractorInstrument.h \ src/qtractorLadspaPlugin.h \ src/qtractorList.h \ src/qtractorLv2Plugin.h \ src/qtractorMessages.h \ src/qtractorMeter.h \ src/qtractorMidiBuffer.h \ src/qtractorMidiClip.h \ src/qtractorMidiConnect.h \ src/qtractorMidiControl.h \ src/qtractorMidiControlObserver.h \ src/qtractorMidiCursor.h \ src/qtractorMidiEditor.h \ src/qtractorMidiEditCommand.h \ src/qtractorMidiEditEvent.h \ src/qtractorMidiEditList.h \ src/qtractorMidiEditSelect.h \ src/qtractorMidiEditTime.h \ src/qtractorMidiEditView.h \ src/qtractorMidiEngine.h \ src/qtractorMidiEvent.h \ src/qtractorMidiEventList.h \ src/qtractorMidiFile.h \ src/qtractorMidiFileTempo.h \ src/qtractorMidiListView.h \ src/qtractorMidiMeter.h \ src/qtractorMidiMonitor.h \ src/qtractorMidiSequence.h \ src/qtractorMidiSysex.h \ src/qtractorMidiTimer.h \ src/qtractorMixer.h \ src/qtractorMonitor.h \ src/qtractorNsmClient.h \ src/qtractorObserver.h \ src/qtractorObserverWidget.h \ src/qtractorOptions.h \ src/qtractorPlugin.h \ src/qtractorPluginCommand.h \ src/qtractorPluginListView.h \ src/qtractorPropertyCommand.h \ src/qtractorRingBuffer.h \ src/qtractorRubberBand.h \ src/qtractorScrollView.h \ src/qtractorSession.h \ src/qtractorSessionCommand.h \ src/qtractorSessionCursor.h \ src/qtractorSessionDocument.h \ src/qtractorSpinBox.h \ src/qtractorThumbView.h \ src/qtractorTimeScale.h \ src/qtractorTimeScaleCommand.h \ src/qtractorTimeStretch.h \ src/qtractorTimeStretcher.h \ src/qtractorTrack.h \ src/qtractorTrackButton.h \ src/qtractorTrackCommand.h \ src/qtractorTrackList.h \ src/qtractorTrackTime.h \ src/qtractorTrackView.h \ src/qtractorTracks.h \ src/qtractorVstPlugin.h \ src/qtractorZipFile.h \ src/qtractorBusForm.h \ src/qtractorClipForm.h \ src/qtractorConnectForm.h \ src/qtractorEditRangeForm.h \ src/qtractorExportForm.h \ src/qtractorInstrumentForm.h \ src/qtractorMainForm.h \ src/qtractorMidiControlForm.h \ src/qtractorMidiControlObserverForm.h \ src/qtractorMidiEditorForm.h \ src/qtractorMidiSysexForm.h \ src/qtractorMidiToolsForm.h \ src/qtractorOptionsForm.h \ src/qtractorPasteRepeatForm.h \ src/qtractorPluginForm.h \ src/qtractorPluginSelectForm.h \ src/qtractorSessionForm.h \ src/qtractorShortcutForm.h \ src/qtractorTakeRangeForm.h \ src/qtractorTempoAdjustForm.h \ src/qtractorTimeScaleForm.h \ src/qtractorTrackForm.h sources = \ src/qtractor.cpp \ src/qtractorAudioBuffer.cpp \ src/qtractorAudioClip.cpp \ src/qtractorAudioConnect.cpp \ src/qtractorAudioEngine.cpp \ src/qtractorAudioFile.cpp \ src/qtractorAudioListView.cpp \ src/qtractorAudioMadFile.cpp \ src/qtractorAudioMeter.cpp \ src/qtractorAudioMonitor.cpp \ src/qtractorAudioPeak.cpp \ src/qtractorAudioSndFile.cpp \ src/qtractorAudioVorbisFile.cpp \ src/qtractorClip.cpp \ src/qtractorClipCommand.cpp \ src/qtractorClipFadeFunctor.cpp \ src/qtractorClipSelect.cpp \ src/qtractorCommand.cpp \ src/qtractorConnect.cpp \ src/qtractorConnections.cpp \ src/qtractorCurve.cpp \ src/qtractorCurveCommand.cpp \ src/qtractorCurveFile.cpp \ src/qtractorCurveSelect.cpp \ src/qtractorDocument.cpp \ src/qtractorDssiPlugin.cpp \ src/qtractorEngine.cpp \ src/qtractorEngineCommand.cpp \ src/qtractorFileList.cpp \ src/qtractorFileListView.cpp \ src/qtractorFiles.cpp \ src/qtractorInsertPlugin.cpp \ src/qtractorInstrument.cpp \ src/qtractorLadspaPlugin.cpp \ src/qtractorLv2Plugin.cpp \ src/qtractorMessages.cpp \ src/qtractorMeter.cpp \ src/qtractorMidiBuffer.cpp \ src/qtractorMidiClip.cpp \ src/qtractorMidiConnect.cpp \ src/qtractorMidiControl.cpp \ src/qtractorMidiControlObserver.cpp \ src/qtractorMidiCursor.cpp \ src/qtractorMidiEditor.cpp \ src/qtractorMidiEditCommand.cpp \ src/qtractorMidiEditEvent.cpp \ src/qtractorMidiEditList.cpp \ src/qtractorMidiEditSelect.cpp \ src/qtractorMidiEditTime.cpp \ src/qtractorMidiEditView.cpp \ src/qtractorMidiEngine.cpp \ src/qtractorMidiEventList.cpp \ src/qtractorMidiFile.cpp \ src/qtractorMidiFileTempo.cpp \ src/qtractorMidiListView.cpp \ src/qtractorMidiMeter.cpp \ src/qtractorMidiMonitor.cpp \ src/qtractorMidiSequence.cpp \ src/qtractorMidiTimer.cpp \ src/qtractorMixer.cpp \ src/qtractorNsmClient.cpp \ src/qtractorObserver.cpp \ src/qtractorObserverWidget.cpp \ src/qtractorOptions.cpp \ src/qtractorPlugin.cpp \ src/qtractorPluginCommand.cpp \ src/qtractorPluginListView.cpp \ src/qtractorRubberBand.cpp \ src/qtractorScrollView.cpp \ src/qtractorSession.cpp \ src/qtractorSessionCommand.cpp \ src/qtractorSessionCursor.cpp \ src/qtractorSessionDocument.cpp \ src/qtractorSpinBox.cpp \ src/qtractorThumbView.cpp \ src/qtractorTimeScale.cpp \ src/qtractorTimeScaleCommand.cpp \ src/qtractorTimeStretch.cpp \ src/qtractorTimeStretcher.cpp \ src/qtractorTrack.cpp \ src/qtractorTrackButton.cpp \ src/qtractorTrackCommand.cpp \ src/qtractorTrackList.cpp \ src/qtractorTrackTime.cpp \ src/qtractorTrackView.cpp \ src/qtractorTracks.cpp \ src/qtractorVstPlugin.cpp \ src/qtractorZipFile.cpp \ src/qtractorBusForm.cpp \ src/qtractorClipForm.cpp \ src/qtractorConnectForm.cpp \ src/qtractorEditRangeForm.cpp \ src/qtractorExportForm.cpp \ src/qtractorInstrumentForm.cpp \ src/qtractorMainForm.cpp \ src/qtractorMidiControlForm.cpp \ src/qtractorMidiControlObserverForm.cpp \ src/qtractorMidiEditorForm.cpp \ src/qtractorMidiSysexForm.cpp \ src/qtractorMidiToolsForm.cpp \ src/qtractorOptionsForm.cpp \ src/qtractorPasteRepeatForm.cpp \ src/qtractorPluginForm.cpp \ src/qtractorPluginSelectForm.cpp \ src/qtractorSessionForm.cpp \ src/qtractorShortcutForm.cpp \ src/qtractorTakeRangeForm.cpp \ src/qtractorTempoAdjustForm.cpp \ src/qtractorTimeScaleForm.cpp \ src/qtractorTrackForm.cpp forms = \ src/qtractorBusForm.ui \ src/qtractorClipForm.ui \ src/qtractorConnectForm.ui \ src/qtractorEditRangeForm.ui \ src/qtractorExportForm.ui \ src/qtractorInstrumentForm.ui \ src/qtractorMainForm.ui \ src/qtractorMidiControlForm.ui \ src/qtractorMidiControlObserverForm.ui \ src/qtractorMidiEditorForm.ui \ src/qtractorMidiSysexForm.ui \ src/qtractorMidiToolsForm.ui \ src/qtractorOptionsForm.ui \ src/qtractorPasteRepeatForm.ui \ src/qtractorPluginForm.ui \ src/qtractorPluginSelectForm.ui \ src/qtractorSessionForm.ui \ src/qtractorShortcutForm.ui \ src/qtractorTakeRangeForm.ui \ src/qtractorTempoAdjustForm.ui \ src/qtractorTimeScaleForm.ui \ src/qtractorTrackForm.ui resources = \ src/qtractor.qrc translations_sources = \ src/translations/qtractor_cs.ts \ src/translations/qtractor_de.ts \ src/translations/qtractor_fr.ts \ src/translations/qtractor_it.ts \ src/translations/qtractor_ja.ts \ src/translations/qtractor_ru.ts translations_targets = \ src/translations/qtractor_cs.qm \ src/translations/qtractor_de.qm \ src/translations/qtractor_fr.qm \ src/translations/qtractor_it.qm \ src/translations/qtractor_ja.qm \ src/translations/qtractor_ru.qm export datarootdir = @datarootdir@ export localedir = @localedir@ all: $(target) $(target): $(name).mak $(resources) ${forms} $(sources) $(headers) @$(MAKE) -f $(name).mak $(name).mak: $(name).pro @$(qmake) -o $(name).mak $(name).pro translations_lupdate: $(name).pro @$(lupdate) -verbose $(name).pro translations_lrelease: translations_lupdate $(translations_targets) %.qm: %.ts @$(lrelease) -verbose $< -qm $@ install: $(target) translations_lrelease @$(MAKE) INSTALL_ROOT=$(DESTDIR) -f $(name).mak install @install -d -v -m 0755 $(DESTDIR)$(localedir) @install -v -m 0644 $(translations_targets) $(DESTDIR)$(localedir) uninstall: $(DESTDIR)$(prefix)/bin/$(name) @$(MAKE) INSTALL_ROOT=$(DESTDIR) -f $(name).mak uninstall @rm -vf $(DESTDIR)$(localedir)/$(translations_targets) @for x in $(translations_targets); do \ rm -vf $(DESTDIR)$(localedir)/`basename $$x`; done clean: $(name).mak @$(MAKE) -f $(name).mak clean @rm -f $(target) $(target).mak $(name).mak @rm -rf *.cache *.log *.status $(translations_targets) qtractor-0.5.11/PaxHeaders.10084/Makefile.svn0000644000175000001440000000012311541163473016726 xustar000000000000000027 mtime=1300555579.897926 26 atime=1381134665.94608 30 ctime=1381134665.946080032 qtractor-0.5.11/Makefile.svn0000644000175000001440000000050411541163473016214 0ustar00rncbcusers00000000000000all: configure configure: Makefile.in configure.ac @autoheader @autoconf @rm -rf *.cache clean: @if [ -f Makefile ]; then make clean; fi @rm -rvf Makefile configure config.* src/.ui src/.obj src/.moc @rm -rvf src/Makefile src/config.* src/*.pri src/*.desktop src/*.mak @rm -rvf *.cache *.log *.status *.spec *.mak qtractor-0.5.11/PaxHeaders.10084/qtractor.pro0000644000175000001440000000012311354101152017026 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134671.25708 30 ctime=1381134671.257080116 qtractor-0.5.11/qtractor.pro0000644000175000001440000000034211354101152016314 0ustar00rncbcusers00000000000000# qtractor.pro # QMAKEVERSION = $$[QMAKE_VERSION] ISQT4 = $$find(QMAKEVERSION, ^[2-9]) isEmpty( ISQT4 ) { error("Use the qmake include with Qt4.4 or greater, on Debian that is qmake-qt4"); } TEMPLATE = subdirs SUBDIRS = src qtractor-0.5.11/PaxHeaders.10084/qtractor.spec.in0000644000175000001440000000012312224470506017576 xustar000000000000000027 mtime=1381134662.966013 26 atime=1381134671.25708 30 ctime=1381134671.257080116 qtractor-0.5.11/qtractor.spec.in0000644000175000001440000001216512224470506017072 0ustar00rncbcusers00000000000000%define name @PACKAGE_TARNAME@ %define version @PACKAGE_VERSION@ %define release 7 %define _prefix @ac_prefix@ Summary: An Audio/MIDI multi-track sequencer Name: %{name} Version: %{version} Release: %{release} License: GPL-2.0+ Group: Productivity/Multimedia/Sound/Midi Source0: %{name}-%{version}.tar.gz URL: http://qtractor.sourceforge.net/ #Packager: rncbc.org BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot BuildRequires: libqt4-devel >= 4.4 BuildRequires: libjack-devel >= 0.100.0 BuildRequires: alsa-devel BuildRequires: libsndfile-devel >= 1.0.11 BuildRequires: libvorbis-devel #BuildRequires: libmad-devel BuildRequires: libsamplerate-devel BuildRequires: librubberband-devel >= 1.0.1 BuildRequires: liblo-devel BuildRequires: ladspa-devel BuildRequires: dssi-devel BuildRequires: lv2-devel BuildRequires: libserd-devel BuildRequires: libsord-devel BuildRequires: libsratom-devel BuildRequires: liblilv-devel BuildRequires: libsuil-devel Requires(post): desktop-file-utils, shared-mime-info Requires(postun): desktop-file-utils, shared-mime-info %description Qtractor is an Audio/MIDI multi-track sequencer application written in C++ around the Qt4 toolkit using Qt Designer. The initial target platform will be Linux, where the Jack Audio Connection Kit (JACK) for audio, and the Advanced Linux Sound Architecture (ALSA) for MIDI, are the main infrastructures to evolve as a fairly-featured Linux Desktop Audio Workstation GUI, specially dedicated to the personal home-studio. %prep %setup [ -f Makefile.svn ] && %__make -f Makefile.svn %build %configure %__make %install %__make DESTDIR=%{buildroot} install %post %mime_database_post %desktop_database_post %postun %mime_database_postun %desktop_database_postun %clean [ -d %{buildroot} -a "%{buildroot}" != "" ] && %__rm -rf %{buildroot} %files %defattr(-,root,root) %doc AUTHORS COPYING ChangeLog README TODO #dir %{_datadir}/mime #dir %{_datadir}/mime/packages #dir %{_datadir}/applications %dir %{_datadir}/icons/hicolor %dir %{_datadir}/icons/hicolor/32x32 %dir %{_datadir}/icons/hicolor/32x32/apps %dir %{_datadir}/icons/hicolor/32x32/mimetypes %dir %{_datadir}/icons/hicolor/scalable %dir %{_datadir}/icons/hicolor/scalable/apps %dir %{_datadir}/icons/hicolor/scalable/mimetypes %{_bindir}/%{name} %{_datadir}/mime/packages/%{name}.xml %{_datadir}/applications/%{name}.desktop %{_datadir}/icons/hicolor/32x32/apps/%{name}.png %{_datadir}/icons/hicolor/32x32/mimetypes/application-x-%{name}*.png %{_datadir}/icons/hicolor/scalable/apps/%{name}.svgz %{_datadir}/icons/hicolor/scalable/mimetypes/application-x-%{name}*.svgz %{_datadir}/locale/%{name}_*.qm %changelog * Mon Oct 7 2013 Rui Nuno Capela - 0.5.11 - Lima Oscar release. * Thu Jul 18 2013 Rui Nuno Capela - 0.5.10 - Kilo Papa release. * Thu Jun 6 2013 Rui Nuno Capela - 0.5.9 - Juliet Quebec release. * Tue Mar 19 2013 Rui Nuno Capela - 0.5.8 - India Romeo release. * Thu Dec 27 2012 Rui Nuno Capela - 0.5.7 - Hotel Sierra release. * Tue Oct 02 2012 Rui Nuno Capela - 0.5.6 - Golf Tango release. * Fri Jun 15 2012 Rui Nuno Capela - 0.5.5 - Foxtrot Uniform release. * Thu Mar 01 2012 Rui Nuno Capela - 0.5.4 - Echo Victor release. * Wed Dec 28 2011 Rui Nuno Capela - 0.5.3 - Delta Whisky release. * Fri Dec 16 2011 Rui Nuno Capela - 0.5.2 - Charlie X-ray release. * Wed Oct 05 2011 Rui Nuno Capela - 0.5.1 - Bravo Yankee release. * Fri Jul 22 2011 Rui Nuno Capela - 0.5.0 - Alpha Zulu (TYOQA) release. * Thu May 26 2011 Rui Nuno Capela - 0.4.9 - Final Dudette release. * Tue Jan 19 2011 Rui Nuno Capela - 0.4.8 - Fiery Demigoddess release. * Thu Sep 30 2010 Rui Nuno Capela - 0.4.7 - Furious Desertrix release. * Fri May 21 2010 Rui Nuno Capela - 0.4.6 - Funky Deviless release. * Sat Jan 23 2010 Rui Nuno Capela - 0.4.5 - A Friskier Demivierge release. * Sat Jan 16 2010 Rui Nuno Capela - 0.4.4 - Frisky Demivierge release. * Mon Oct 05 2009 Rui Nuno Capela - 0.4.3 - Fussy Doula release. * Thu Jun 04 2009 Rui Nuno Capela - 0.4.2 - Flaunty Demoness release. * Sat Apr 04 2009 Rui Nuno Capela - 0.4.1 - Funky Dominatrix release. * Fri Mar 13 2009 Rui Nuno Capela - 0.4.0 - Foxy Dryad release. * Thu Dec 25 2008 Rui Nuno Capela - 0.3.0 - Fluffy Doll release. * Sun Oct 05 2008 Rui Nuno Capela - 0.2.2 - Flirty Ditz release. * Sat Aug 30 2008 Rui Nuno Capela - 0.2.1 - Fainty Diva release. * Fri Jul 18 2008 Rui Nuno Capela - 0.2.0 - Frolic Demoiselle release. * Fri May 02 2008 Rui Nuno Capela - 0.1.3 - Frugal Damsel release. * Sun Mar 23 2008 Rui Nuno Capela - 0.1.2 - Frantic Dame release. * Sat Feb 16 2008 Rui Nuno Capela - 0.1.1 - Futile Duchess release. * Sat Jan 5 2008 Rui Nuno Capela - 0.1.0 - Frivolous Debutante release. qtractor-0.5.11/PaxHeaders.10084/README0000644000175000001440000000012312172000023015317 xustar000000000000000027 mtime=1374158867.116607 26 atime=1381134671.25708 30 ctime=1381134671.257080116 qtractor-0.5.11/README0000644000175000001440000002135612172000023014615 0ustar00rncbcusers00000000000000Qtractor - An Audio/MIDI multi-track sequencer ---------------------------------------------- Qtractor is an audio/MIDI multi-track sequencer application written in C++ with the Qt4 framework [1]. Target platform is Linux, where the Jack Audio Connection Kit (JACK) for audio [2] and the Advanced Linux Sound Architecture (ALSA) for MIDI [3] are the main infrastructures to evolve as a fairly-featured Linux desktop audio workstation GUI, specially dedicated to the personal home-studio. Website: http://qtractor.sourceforge.net Project page: http://sourceforge.net/projects/qtractor Weblog: http://www.rncbc.org Qtractor is free, open-source software, distributed under the terms of the GNU General Public License (GPL) [17] version 2 or later. Features -------- - Multi-track audio and MIDI sequencing and recording. - Developed on pure Qt4 C++ application framework [1] (no Qt3 nor KDE dependencies). - Uses JACK [2] for audio and ALSA [3] sequencer for MIDI as multimedia infrastructures. - Traditional multi-track tape recorder control paradigm. - Audio file formats support: OGG (via libvorbis [6]), MP3 (via libmad [7], playback only), WAV, FLAC, AIFF and many, many more (via libsndfile [4]). - Standard MIDI files support (format 0 and 1). - Non-destructive, non-linear editing. - Unlimited number of tracks per session/project. - Unlimited number of overlapping clips per track. - XML encoded session/project description files (SDI). - Point-and-click, multi-select, drag-and-drop interaction (drag, move, drop, cut, copy, paste, paste-repeat, delete, split, merge). - Unlimited undo/redo. - Built-in mixer and monitor controls. - Built-in connection patchbay control and persistence (a-la QjackCtl [16]). - LADSPA [5], DSSI [11], native VST [12] and LV2 [13] plug-ins support. - Unlimited number of plug-ins per track or bus. - Plug-in presets, programs and chunk/configurations support. - Unlimited audio effect send/return inserts per track or bus. - Loop-recording/takes. - Audio/MIDI clip fade-in/out (linear, quadratic, cubic). - Audio/MIDI clip gain/volume, normalize, export. - Audio/MIDI track and plugin parameter automation (dynamic curves, sample&hold, linear and spline modes). - Audio clip time-stretching (WSOLA-like or via librubberband [9]), pitch-shifting (via librubberband [9]) and seamless sample-rate conversion (via libsamplerate [8]). - Audio/MIDI track export (mix-down, merge). - Audio/MIDI metronome bar/beat clicks. - Unlimited tempo/time-signature map. - Unlimited location/bar markers. - MIDI clip editor (matrix/piano roll). - MIDI instrument definitions (a-la Cakewalk(tm) (*.ins) [18]); SoundFont (*.sf2) and MIDI Names XML (*.midnam) files also supported. - MIDI controller mapping/learn/assignment (mixer and plug-in parameters). - MIDI system exclusive (SysEx) setups. - JACK transport sync master/slave. - JACK session support. - NSM (Non Session Management) support [15]. - MMC control surface enabled. - MIDI Song Position cueing support. - Configurable keyboard shortcuts. Requirements ------------ The software requirements for build and runtime are listed as follows: Mandatory: [1] Qt4 (core, gui, xml), C++ class library and tools for crossplatform development and internationalization http://qt-project.org/ [2] JACK Audio Connection Kit http://jackaudio.org/ [3] ALSA, Advanced Linux Sound Architecture http://www.alsa-project.org/ [4] libsndfile, C library for reading and writing files containing sampled sound http://www.mega-nerd.com/libsndfile/ [5] LADSPA, Linux Audio Developer's Simple Plugin API http://www.ladspa.org/ Optional (opted-in at build time): [6] libvorbis (enc, file), Ogg Vorbis audio compression http://xiph.org/vorbis/ [7] libmad, High-quality MPEG audio decoder http://www.underbit.com/products/mad/ [8] libsamplerate, The secret rabbit code, C library for audio sample rate conversion http://www.mega-nerd.com/SRC/ [9] librubberband, Rubber Band Audio Time Stretcher, an audio time-stretching and pitch-shifting library http://breakfastquay.com/rubberband/ [10] liblo, Lightweight OSC implementation (needed for DSSI GUI [11] and/or NSM support [15]) http://liblo.sourceforge.net/ [11] DSSI, An API for soft synth plugins with custom user interfaces http://dssi.sourceforge.net/ [12] VST SDK, Steinberg's Virtual Studio Technology (see README.VST) http://www.steinberg.net/ [13] LV2, Audio Plugin Standard, the extensible successor of LADSPA http://lv2plug.in/ [14] liblilv, Lightweight LV2 host implementation stack http://drobilla.net/software/lilv/ http://drobilla.net/software/suil/ http://drobilla.net/software/sratom/ http://drobilla.net/software/sord/ http://drobilla.net/software/serd/ [15] Non Session Management (NSM) http://non.tuxfamily.org/nsm/ Installation ------------ The installation procedure follows the standard for source distributions. Unpack the tarball and in the extracted source directory: ./configure [--prefix=/usr/local] make and optionally as root: make install This procedure will end installing the following couple of files: ${prefix}/bin/qtractor ${prefix}/share/applications/qtractor.desktop ${prefix}/share/icons/hicolor/32x32/apps/qtractor.png Just launch ${prefix}/bin/qtractor and you're off (hopefully). Note that the default installation path ${prefix} is /usr/local. If you're checking out from Subversion (SVN), you'll have to prepare the configure script just before you proceed with the above instructions: make -f Makefile.svn Configuration ------------- Qtractor holds its settings and configuration state per user, in a file located as $HOME/.config/rncbc.org/Qtractor.conf . Normally, there's no need to edit this file, as it is recreated and rewritten everytime qtractor is run. Bugs ---- Plenty still, after all this is alpha software ;) Support ------- Qtractor is open source free software. For bug reports, feature requests, discussion forums, mailling lists, or any other matter related to the development of this piece of software, please use the Sourceforge project page (http://sourceforge.net/projects/qtractor). You can also find timely and closer contact information on my personal web site (http://www.rncbc.org). Acknowledgments --------------- Qtractor user manual has been co-authored by James Laco Hines and Stephen Doonan. Qtractor logo/icon is an original work of Andy Fitzsimon, borrowed from the public domain openclipart.org gallery. A special mention should also go to the translators of Qtractor (see TRANSLATORS). References ---------- [1] Qt4 (core, gui, xml), C++ class library and tools for crossplatform development and internationalization http://qt-project.org/ [2] JACK Audio Connection Kit http://jackaudio.org/ [3] ALSA, Advanced Linux Sound Architecture http://www.alsa-project.org/ [4] libsndfile, C library for reading and writing files containing sampled sound http://www.mega-nerd.com/libsndfile/ [5] LADSPA, Linux Audio Developer's Simple Plugin API http://www.ladspa.org/ [6] libvorbis (enc, file), Ogg Vorbis audio compression http://xiph.org/vorbis/ [7] libmad, High-quality MPEG audio decoder http://www.underbit.com/products/mad/ [8] libsamplerate, The secret rabbit code, C library for audio sample rate conversion http://www.mega-nerd.com/SRC/ [9] librubberband, Rubber Band Audio Time Stretcher, an audio time-stretching and pitch-shifting library http://breakfastquay.com/rubberband/ [10] liblo, Lightweight OSC implementation (needed for DSSI GUI support) http://liblo.sourceforge.net/ [11] DSSI, an API for soft synth plugins with custom user interfaces http://dssi.sourceforge.net/ [12] VST SDK, Steinberg's Virtual Studio Technology (see README.VST) http://www.steinberg.net/ [13] LV2, Audio Plugin Standard, the extensible successor of LADSPA http://lv2plug.in/ [14] liblilv, Lightweight LV2 host implementation stack (needed for LV2 support) http://drobilla.net/software/lilv/ http://drobilla.net/software/suil/ http://drobilla.net/software/sratom/ http://drobilla.net/software/sord/ http://drobilla.net/software/serd/ [15] Non Session Management (NSM) http://non.tuxfamily.org/nsm/ [16] QjackCtl - JACK Qt GUI Interface http://qjackctl.sourceforge.net [17] GNU General Public License http://www.gnu.org/copyleft/gpl.html [18] Cakewalk (by Roland), powerful and easy-to-use tools for Windows-based music and sound production http://www.cakewalk.com/ Enjoy && have (lots of) fun. -- rncbc aka Rui Nuno Capela rncbc at rncbc dot org http://www.rncbc.org qtractor-0.5.11/PaxHeaders.10084/README.VST0000644000175000001440000000012312102155164016004 xustar000000000000000027 mtime=1359534708.011491 26 atime=1381134671.24508 30 ctime=1381134671.245080116 qtractor-0.5.11/README.VST0000644000175000001440000000343212102155164015275 0ustar00rncbcusers00000000000000Native VST plug-in support -------------------------- Building for VST support is not that easy. To say the least, it might not work out of the box. First, due to its licensing issues, you'll have to go through the nuisance and download yourself the VST SDK, from its site: Steinberg Media Technologies GmbH http://www.steinberg.net It doesn't really matter much whether you pick the VST 2.3 or VST 2.4 version, you need to pick one and just one only. Do not ask for the more recent VST 3.0 or later. It won't work and I won't care :) Once you have downloaded the VST SDK zip-archive, for which you'll have to accept their license and supply some personal data, you'll have to unpack the pertinent header files, which are found under the respective folder: - VST SDK 2.3: vstsdk2.3/source/common/ aeffectx.h AEffect.h - VST SDK 2.4: vstsdk2.4/pluginterfaces/vst2.x/ aeffectx.h aeffect.h Just copy those couple of files to somewhere on your system. You may choose to copy those files into some of the system standard include directories (eg. /usr/local/include or /usr/include). That way, all will be handled automagically by the usual build steps. Otherwise, you'll need do supply the include path yourself, as in the following: ./configure --with-vst=/path/to/vstsdk2.x/include Next step, once properly built, you'll need to tell where the actual native VST plug-ins can be found in your file system. The directories where plug-ins can be picked up by qtractor at run-time are specified respectively in the View/Options.../Display/Plugin Paths dialog. Last warning notice: leave that VST_PATH environment variable alone. That variable is most precious for DSSI-VST, in finding Windows(tm) VST plug-ins (.dll's) on its own. Have a glass of WINE and relax ;) Enjoy. qtractor-0.5.11/PaxHeaders.10084/src0000644000175000001440000000013212224470517015172 xustar000000000000000030 mtime=1381134671.802080125 30 atime=1381134666.355080039 30 ctime=1381134671.802080125 qtractor-0.5.11/src/0000755000175000001440000000000012224470517014536 5ustar00rncbcusers00000000000000qtractor-0.5.11/src/PaxHeaders.10084/qtractorSessionCursor.cpp0000644000175000001440000000012311701044034022342 xustar000000000000000027 mtime=1325680668.688662 26 atime=1381134671.08908 30 ctime=1381134671.089080114 qtractor-0.5.11/src/qtractorSessionCursor.cpp0000644000175000001440000001775011701044034021643 0ustar00rncbcusers00000000000000// qtractorSessionCursor.cpp // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorSessionCursor.h" #include "qtractorSession.h" #include "qtractorClip.h" //---------------------------------------------------------------------- // class qtractorSessionCursor - implementation. // // Constructor. qtractorSessionCursor::qtractorSessionCursor ( qtractorSession *pSession, unsigned long iFrame, qtractorTrack::TrackType syncType ) { m_pSession = pSession; m_iFrame = iFrame; m_syncType = syncType; m_iTracks = 0; m_ppClips = NULL; m_iSize = 0; resetClips(); reset(); } // Destructor. qtractorSessionCursor::~qtractorSessionCursor (void) { m_pSession->unlinkSessionCursor(this); if (m_ppClips) delete [] m_ppClips; } // Session accessor. qtractorSession *qtractorSessionCursor::session (void) const { return m_pSession; } // Clip sync flag accessor. void qtractorSessionCursor::setSyncType ( qtractorTrack::TrackType syncType ) { m_syncType = syncType; } qtractorTrack::TrackType qtractorSessionCursor::syncType (void) const { return m_syncType; } // General bi-directional locate method. void qtractorSessionCursor::seek ( unsigned long iFrame, bool bSync ) { if (iFrame == m_iFrame) return; unsigned int iTrack = 0; qtractorTrack *pTrack = m_pSession->tracks().first(); while (pTrack && iTrack < m_iTracks) { qtractorClip *pClip = NULL; qtractorClip *pClipLast = m_ppClips[iTrack]; // Optimize if seeking forward... if (iFrame > m_iFrame) pClip = pClipLast; // Locate first clip not past the target frame position.. pClip = seekClip(pTrack, pClip, iFrame); // Update cursor track clip... m_ppClips[iTrack] = pClip; // Now something fulcral for clips around... if (pTrack->trackType() == m_syncType) { // Tell whether play-head is after loop-start position... bool bLooping = (iFrame >= m_pSession->loopStart()); // Care for old/previous clip... if (pClipLast && pClipLast != pClip) pClipLast->reset(bLooping); // Set final position within target clip... if (pClip && bSync) { // Take care of overlapping clips... unsigned long iClipEnd = pClip->clipStart() + pClip->clipLength(); while (pClip) { unsigned long iClipStart = pClip->clipStart(); if (iClipStart > iClipEnd) break; if (iFrame >= iClipStart && iFrame < iClipStart + pClip->clipLength()) { pClip->seek(iFrame - iClipStart); } else { pClip->reset(bLooping); } pClip = pClip->next(); } } } // Next track... pTrack = pTrack->next(); ++iTrack; } // Done. m_iFrame = iFrame; } // Current frame position accessor. unsigned long qtractorSessionCursor::frame (void) const { return m_iFrame; } // Absolute frame-time position accessors. void qtractorSessionCursor::setFrameTime ( unsigned long iFrameTime ) { m_iFrameTime = iFrameTime; m_iFrameDelta = m_iFrame - iFrameTime; } unsigned long qtractorSessionCursor::frameTime (void) const { return m_iFrameTime; } unsigned long qtractorSessionCursor::frameTimeEx (void) const { return m_iFrameTime + m_iFrameDelta; } // Current track clip accessor. qtractorClip *qtractorSessionCursor::clip ( unsigned int iTrack ) const { return (iTrack < m_iTracks ? m_ppClips[iTrack] : NULL); } // Clip locate method. qtractorClip *qtractorSessionCursor::seekClip ( qtractorTrack *pTrack, qtractorClip *pClip, unsigned long iFrame ) const { if (pClip == NULL) pClip = pTrack->clips().first(); while (pClip && iFrame > pClip->clipStart() + pClip->clipLength()) { // if (pTrack->trackType() == m_syncType) // pClip->reset(m_pSession->isLooping()); pClip = pClip->next(); } if (pClip == NULL) pClip = pTrack->clips().last(); return pClip; } // Add a track to cursor. void qtractorSessionCursor::addTrack ( qtractorTrack *pTrack ) { if (pTrack == NULL) pTrack = m_pSession->tracks().last(); unsigned int iTracks = m_iTracks + 1; if (iTracks < m_iSize) { updateClips(m_ppClips, iTracks); } else { m_iSize += iTracks; qtractorClip **ppOldClips = m_ppClips; qtractorClip **ppNewClips = new qtractorClip * [m_iSize]; updateClips(ppNewClips, iTracks); m_ppClips = ppNewClips; if (ppOldClips) delete [] ppOldClips; } m_iTracks = iTracks; } // Update track after adding/removing a clip from cursor. void qtractorSessionCursor::updateTrack ( qtractorTrack *pTrack ) { int iTrack = m_pSession->tracks().find(pTrack); if (iTrack >= 0) { qtractorClip *pClip = seekClip(pTrack, NULL, m_iFrame); if (pClip && pTrack->trackType() == m_syncType && m_iFrame >= pClip->clipStart() && m_iFrame < pClip->clipStart() + pClip->clipLength()) { pClip->seek(m_iFrame - pClip->clipStart()); } m_ppClips[iTrack] = pClip; } } // Remove a track from cursor. void qtractorSessionCursor::removeTrack ( qtractorTrack *pTrack ) { int iTrack = m_pSession->tracks().find(pTrack); if (iTrack >= 0) removeTrack((unsigned int) iTrack); } void qtractorSessionCursor::removeTrack ( unsigned int iTrack ) { --m_iTracks; for ( ; iTrack < m_iTracks; ++iTrack) m_ppClips[iTrack] = m_ppClips[iTrack + 1]; m_ppClips[iTrack] = NULL; } // Update current track clip under cursor. void qtractorSessionCursor::updateTrackClip ( qtractorTrack *pTrack ) { int iTrack = m_pSession->tracks().find(pTrack); if (iTrack >= 0) { qtractorClip *pClip = m_ppClips[iTrack]; if (pClip && pTrack->trackType() == m_syncType) { if (m_iFrame >= pClip->clipStart() && m_iFrame < pClip->clipStart() + pClip->clipLength()) { pClip->seek(m_iFrame - pClip->clipStart()); } else { pClip->reset(m_iFrame >= m_pSession->loopStart()); } } } } // Update (stabilize) cursor. void qtractorSessionCursor::updateClips ( qtractorClip **ppClips, unsigned int iTracks ) { // Reset clip positions... unsigned int iTrack = 0; qtractorTrack *pTrack = m_pSession->tracks().first(); while (pTrack && iTrack < iTracks) { qtractorClip *pClip = seekClip(pTrack, NULL, m_iFrame); if (pClip && pTrack->trackType() == m_syncType && m_iFrame >= pClip->clipStart() && m_iFrame < pClip->clipStart() + pClip->clipLength()) { pClip->seek(m_iFrame - pClip->clipStart()); } ppClips[iTrack] = pClip; pTrack = pTrack->next(); ++iTrack; } } // Reset cursor. void qtractorSessionCursor::reset (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorSessionCursor[%p,%d]::reset()", this, (int) m_syncType); #endif m_iFrameTime = 0; m_iFrameDelta = m_iFrame; } // Reset track/clips cache. void qtractorSessionCursor::resetClips (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorSessionCursor[%p,%d]::resetClips()", this, (int) m_syncType); #endif // Free existing clip references. if (m_ppClips) { qtractorClip **ppOldClips = m_ppClips; m_ppClips = NULL; delete [] ppOldClips; } // Rebuild the whole bunch... m_iTracks = m_pSession->tracks().count(); m_iSize = (m_iTracks << 1); if (m_iSize > 0) { qtractorClip **ppNewClips = new qtractorClip * [m_iSize]; updateClips(ppNewClips, m_iTracks); m_ppClips = ppNewClips; } } // Frame-time processor (increment only). void qtractorSessionCursor::process ( unsigned int nframes ) { m_iFrameTime += nframes; } // end of qtractorSessionCursor.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorList.h0000644000175000001440000000012312052463213020105 xustar000000000000000027 mtime=1353344651.117057 26 atime=1381134667.92608 30 ctime=1381134667.927080064 qtractor-0.5.11/src/qtractorList.h0000644000175000001440000001556712052463213017412 0ustar00rncbcusers00000000000000// qtractorList.h // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorList_h #define __qtractorList_h //---------------------------------------------------------------------- // class qtractorList -- Doubly-linked list base. // template class qtractorList { public: // Default constructor. qtractorList() : m_pFirst(0), m_pLast(0), m_iCount(0), m_pFreeList(0), m_bAutoDelete(false) {} // Default destructor. ~qtractorList() { clear(); } // Accessors. Node *first() const { return m_pFirst; } Node *last() const { return m_pLast; } int count() const { return m_iCount; } // Property accessors. void setAutoDelete(bool bAutoDelete) { m_bAutoDelete = bAutoDelete; } bool autoDelete() const { return m_bAutoDelete; } // Insert methods. void insertAfter(Node *pNode, Node *pPrevNode = 0); void insertBefore(Node *pNode, Node *pNextNode = 0); // Unlink/remove methods. void unlink(Node *pNode); void remove(Node *pNode); // Reset method. void clear(); // Random accessors. Node *at (int iNode) const; // Aliased methods and operators. void prepend(Node *pNode) { insertBefore(pNode); } void append(Node *pNode) { insertAfter(pNode); } Node *operator[] (int iNode) const { return at(iNode); } // Node searcher. int find(Node *pNode) const; //---------------------------------------------------------------------- // class qtractorList::Link -- Base list node. // class Link { public: // Constructor. Link() : m_pPrev(0), m_pNext(0), m_pNextFree(0) {} // Linked node getters. Node *prev() const { return m_pPrev; } Node *next() const { return m_pNext; } // Linked node setters. void setPrev(Node *pPrev) { m_pPrev = pPrev; } void setNext(Node *pNext) { m_pNext = pNext; } // Linked free node accessors. Node *nextFree() const { return m_pNextFree; } void setNextFree(Node *pNextFree) { m_pNextFree = pNextFree; } private: // Instance variables. Node *m_pPrev; Node *m_pNext; Node *m_pNextFree; }; //---------------------------------------------------------------------- // class qtractorList::Iterator -- List iterator (aka cursor). // class Iterator { public: // Constructors. Iterator(qtractorList& list) : m_list(list), m_pNode(0) {} Iterator(const Iterator& it) : m_list(it.list()), m_pNode(it.node()) {} // Iterator methods. Iterator& first() { m_pNode = m_list.first(); return *this; } Iterator& next() { m_pNode = m_pNode->next(); return *this; } Iterator& prev() { m_pNode = m_pNode->prev(); return *this; } Iterator& last() { m_pNode = m_list.last(); return *this; } // Operator methods Iterator& operator= (const Iterator& iter) { m_pNode = iter.m_pNode; return *this; } Iterator& operator= (Node *pNode) { m_pNode = pNode; return *this; } Iterator& operator++ () { return next(); } Iterator operator++ (int) { Iterator it(*this); next(); return it; } Iterator& operator-- () { return prev(); } Iterator operator-- (int) { Iterator it(*this); prev(); return it; } // Simple accessors. const qtractorList& list() const { return m_list; } Node *node() const { return m_pNode; } private: // Instance variables. qtractorList& m_list; // Current cursory node reference. Node *m_pNode; }; private: // Instance variables. Node *m_pFirst; Node *m_pLast; int m_iCount; // The reclaimed freelist. Node *m_pFreeList; bool m_bAutoDelete; }; // Insert methods. template void qtractorList::insertAfter ( Node *pNode, Node *pPrevNode ) { if (pPrevNode == 0) pPrevNode = m_pLast; pNode->setPrev(pPrevNode); if (pPrevNode) { pNode->setNext(pPrevNode->next()); if (pPrevNode->next()) (pPrevNode->next())->setPrev(pNode); else m_pLast = pNode; pPrevNode->setNext(pNode); } else { m_pFirst = m_pLast = pNode; pNode->setNext(0); } ++m_iCount; } template void qtractorList::insertBefore ( Node *pNode, Node *pNextNode ) { if (pNextNode == 0) pNextNode = m_pFirst; pNode->setNext(pNextNode); if (pNextNode) { pNode->setPrev(pNextNode->prev()); if (pNextNode->prev()) (pNextNode->prev())->setNext(pNode); else m_pFirst = pNode; pNextNode->setPrev(pNode); } else { m_pLast = m_pFirst = pNode; pNode->setPrev(0); } ++m_iCount; } // Unlink method. template void qtractorList::unlink ( Node *pNode ) { if (pNode->prev()) (pNode->prev())->setNext(pNode->next()); else m_pFirst = pNode->next(); if (pNode->next()) (pNode->next())->setPrev(pNode->prev()); else m_pLast = pNode->prev(); --m_iCount; } // Remove method. template void qtractorList::remove ( Node *pNode ) { unlink(pNode); // Add it to the alternate free list. if (m_bAutoDelete) { Node *pNextFree = m_pFreeList; pNode->setNextFree(pNextFree); m_pFreeList = pNode; } } // Reset methods. template void qtractorList::clear (void) { // Remove pending items. Node *pLast = m_pLast; while (pLast) { remove(pLast); pLast = m_pLast; } // Free the free-list altogether... Node *pFreeList = m_pFreeList; while (pFreeList) { Node *pNextFree = pFreeList->nextFree(); delete pFreeList; pFreeList = pNextFree; } // Force clen up. m_pFirst = m_pLast = 0; m_iCount = 0; m_pFreeList = 0; } // Random accessor. template Node *qtractorList::at ( int iNode ) const { int i; Node *pNode; if (iNode < 0 || iNode >= m_iCount) return 0; if (iNode > (m_iCount >> 1)) { for (i = m_iCount - 1, pNode = m_pLast; pNode && i > iNode; --i, pNode = pNode->prev()) ; } else { for (i = 0, pNode = m_pFirst; pNode && i < iNode; ++i, pNode = pNode->next()) ; } return pNode; } // Node searcher. template int qtractorList::find ( Node *pNode ) const { int iNode = 0; Node *pNextNode = m_pFirst; while (pNextNode) { if (pNode == pNextNode) return iNode; pNextNode = pNextNode->next(); ++iNode; } return (-1); } #endif // __qtractorList_h // end of qtractorList.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorFileListView.cpp0000644000175000001440000000012312166526620022103 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134667.62908 30 ctime=1381134667.630080059 qtractor-0.5.11/src/qtractorFileListView.cpp0000644000175000001440000011341312166526620021375 0ustar00rncbcusers00000000000000// qtractorFileListView.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorFileListView.h" #include "qtractorRubberBand.h" #include "qtractorDocument.h" #include "qtractorOptions.h" #include "qtractorSession.h" #include "qtractorClip.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #include #endif //---------------------------------------------------------------------- // class qtractorFileGroupItem -- custom group list view item. // // Constructors. qtractorFileGroupItem::qtractorFileGroupItem ( const QString& sName, int iType ) : QTreeWidgetItem(iType) { QTreeWidgetItem::setIcon(0, QIcon(":/images/itemGroup.png")); QTreeWidgetItem::setText(0, sName); Qt::ItemFlags flags = QTreeWidgetItem::flags(); if (iType == qtractorFileListView::GroupItem) { flags |= Qt::ItemIsEditable; flags &= ~Qt::ItemIsSelectable; } QTreeWidgetItem::setFlags(flags); } // Default destructor. qtractorFileGroupItem::~qtractorFileGroupItem (void) { } // Instance accessors. void qtractorFileGroupItem::setName ( const QString& sName ) { QTreeWidgetItem::setText(0, sName); } QString qtractorFileGroupItem::name (void) const { return QTreeWidgetItem::text(0); } qtractorFileGroupItem *qtractorFileGroupItem::groupItem (void) const { QTreeWidgetItem *pParent = QTreeWidgetItem::parent(); while (pParent && pParent->type() != qtractorFileListView::GroupItem) pParent = pParent->parent(); return static_cast (pParent); } qtractorFileListView *qtractorFileGroupItem::listView (void) const { return static_cast (QTreeWidgetItem::treeWidget()); } // To show up whether its open or not. void qtractorFileGroupItem::setOpen ( bool bOpen ) { // Set the proper pixmap of this... if (type() == qtractorFileListView::GroupItem) { QTreeWidgetItem::setIcon(0, QIcon( bOpen ? ":/images/itemGroupOpen.png" : ":/images/itemGroup.png")); } // Open it up... QTreeWidgetItem::setExpanded(bOpen); // All ancestors should be also visible. if (bOpen) { qtractorFileGroupItem *pGroupItem = groupItem(); if (pGroupItem) pGroupItem->setOpen(true); } } bool qtractorFileGroupItem::isOpen (void) const { return QTreeWidgetItem::isExpanded(); } // Tooltip renderer. QString qtractorFileGroupItem::toolTip (void) const { return name(); } //---------------------------------------------------------------------- // class qtractorFileListItem -- custom file list view item. // // Constructors. qtractorFileListItem::qtractorFileListItem ( const QString& sPath ) : qtractorFileGroupItem(QFileInfo(sPath).fileName(), qtractorFileListView::FileItem) { m_sPath = sPath; } // Default destructor. qtractorFileListItem::~qtractorFileListItem (void) { } // Full path accessor. const QString& qtractorFileListItem::path (void) const { return m_sPath; } //---------------------------------------------------------------------- // class qtractorFileChannelItem -- custom channel list view item. // // Constructors. qtractorFileChannelItem::qtractorFileChannelItem ( qtractorFileListItem *pFileItem, const QString& sName, unsigned short iChannel ) : qtractorFileGroupItem(sName, qtractorFileListView::ChannelItem) { m_iChannel = iChannel; pFileItem->addChild(this); } // Default destructor. qtractorFileChannelItem::~qtractorFileChannelItem (void) { } // File channel accessor. unsigned short qtractorFileChannelItem::channel (void) const { return m_iChannel; } // Full path accessor. const QString qtractorFileChannelItem::path (void) const { QString sPath; qtractorFileListItem *pFileItem = static_cast (QTreeWidgetItem::parent()); if (pFileItem) sPath = pFileItem->path(); return sPath; } //---------------------------------------------------------------------- // class qtractorFileChannelDrag -- custom file channel drag object. // static const char *c_pszFileChannelMimeType = "qtractor/file-channel"; // Encoder method. void qtractorFileChannelDrag::encode ( QMimeData *pMimeData, const qtractorFileChannelDrag::List& items ) { // First, compute total serialized data size... unsigned int iSize = sizeof(unsigned short); QListIterator iter(items); while (iter.hasNext()) { const Item& item = iter.next(); iSize += sizeof(unsigned short); iSize += item.path.length() + 1; } // Allocate the data array... QByteArray data(iSize, (char) 0); char *pData = data.data(); // Header says how much items there are... unsigned short iCount = items.count(); ::memcpy(pData, &iCount, sizeof(unsigned short)); pData += sizeof(unsigned short); // No for actual serialization... iter.toFront(); while (iter.hasNext()) { const Item& item = iter.next(); ::memcpy(pData, &item.channel, sizeof(unsigned short)); pData += sizeof(unsigned short); unsigned int cchPath = item.path.length() + 1; ::memcpy(pData, item.path.toUtf8().constData(), cchPath); pData += cchPath; } // Ok, done. pMimeData->setData(c_pszFileChannelMimeType, data); } // Decode trial method. bool qtractorFileChannelDrag::canDecode ( const QMimeData *pMimeData ) { return pMimeData->hasFormat(c_pszFileChannelMimeType); } // Decode method. qtractorFileChannelDrag::List qtractorFileChannelDrag::decode ( const QMimeData *pMimeData ) { List items; QByteArray data = pMimeData->data(c_pszFileChannelMimeType); if (data.size() < (int) sizeof(unsigned short) + 1) return items; const char *pData = data.constData(); unsigned short iCount = 0; ::memcpy(&iCount, pData, sizeof(unsigned short)); pData += sizeof(unsigned short); Item item; for (unsigned short i = 0; i < iCount; ++i) { ::memcpy(&item.channel, pData, sizeof(unsigned short)); pData += sizeof(unsigned short); item.path = pData; pData += item.path.length() + 1; items.append(item); } return items; } //---------------------------------------------------------------------------- // qtractorFileListView -- Group/File list view, supporting drag-n-drop. // // Constructor. qtractorFileListView::qtractorFileListView ( qtractorFileList::Type iFileType, QWidget *pParent ) : QTreeWidget(pParent), m_iFileType(iFileType) { m_pAutoOpenTimer = NULL; m_iAutoOpenTimeout = 0; m_pDragItem = NULL; m_pDropItem = NULL; m_pRubberBand = NULL; QTreeWidget::setRootIsDecorated(false); QTreeWidget::setUniformRowHeights(true); QTreeWidget::setAlternatingRowColors(true); // QTreeWidget::setDragEnabled(true); QTreeWidget::setAcceptDrops(true); QTreeWidget::setDropIndicatorShown(true); QTreeWidget::setAutoScroll(true); QTreeWidget::setSelectionMode(QAbstractItemView::ExtendedSelection); QTreeWidget::setSizePolicy( QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); QTreeWidget::setSortingEnabled(false); QHeaderView *pHeader = QTreeWidget::header(); pHeader->setDefaultAlignment(Qt::AlignLeft); // pHeader->setDefaultSectionSize(160); #if QT_VERSION >= 0x050000 // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionsMovable(false); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setMovable(false); #endif pHeader->setStretchLastSection(true); // Trap for help/tool-tips events. QTreeWidget::viewport()->installEventFilter(this); setAutoOpenTimeout(800); QObject::connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)), SLOT(itemClickedSlot(QTreeWidgetItem*))); QObject::connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), SLOT(itemActivatedSlot(QTreeWidgetItem*))); // QObject::connect(this, // SIGNAL(itemActivated(QTreeWidgetItem*,int)), // SLOT(itemActivatedSlot(QTreeWidgetItem*))); QObject::connect(this, SIGNAL(itemExpanded(QTreeWidgetItem*)), SLOT(itemExpandedSlot(QTreeWidgetItem*))); QObject::connect(this, SIGNAL(itemCollapsed(QTreeWidgetItem*)), SLOT(itemCollapsedSlot(QTreeWidgetItem*))); QObject::connect(QTreeWidget::itemDelegate(), SIGNAL(commitData(QWidget*)), SLOT(itemRenamedSlot())); } // Default destructor. qtractorFileListView::~qtractorFileListView (void) { clear(); setAutoOpenTimeout(0); } // File list type property. void qtractorFileListView::setFileType ( qtractorFileList::Type iFileType ) { m_iFileType = iFileType; } qtractorFileList::Type qtractorFileListView::fileType (void) const { return m_iFileType; } // Add a new file item, optionally under a given group. qtractorFileListItem *qtractorFileListView::addFileItem ( const QString& sPath, bool bAutoRemove, qtractorFileGroupItem *pParentItem ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return NULL; qtractorFileListItem *pFileItem = findFileItem(sPath); if (pFileItem == NULL) { pFileItem = createFileItem(sPath); if (pFileItem) { // Add to file/path registry... pSession->files()->addFileItem(m_iFileType, pFileItem, bAutoRemove); // Insert the new file item in place... if (pParentItem) { if (pParentItem->type() == GroupItem) { pParentItem->insertChild(0, pFileItem); } else { // It must be a group item... QTreeWidgetItem *pItem = static_cast (pParentItem); pParentItem = groupItem(pParentItem); if (pParentItem) { int iItem = pParentItem->indexOfChild(pItem); if (iItem >= 0) pParentItem->insertChild(iItem + 1, pFileItem); else pItem->addChild(pFileItem); } else { int iItem = QTreeWidget::indexOfTopLevelItem(pItem); if (iItem >= 0) QTreeWidget::insertTopLevelItem(iItem + 1, pFileItem); else QTreeWidget::addTopLevelItem(pFileItem); } } } else QTreeWidget::addTopLevelItem(pFileItem); } } #if 0 if (pFileItem) QTreeWidget::setCurrentItem(pFileItem); #endif return pFileItem; } // Add a new group item, optionally under another group. qtractorFileGroupItem *qtractorFileListView::addGroupItem ( const QString& sName, qtractorFileGroupItem *pParentItem ) { qtractorFileGroupItem *pGroupItem = findGroupItem(sName); if (pGroupItem == NULL) { pGroupItem = new qtractorFileGroupItem(sName); if (pParentItem) pParentItem->addChild(pGroupItem); else addTopLevelItem(pGroupItem); emit contentsChanged(); } #if 0 QTreeWidget::setCurrentItem(pGroupItem); #endif return pGroupItem; } // Current group item accessor... qtractorFileGroupItem *qtractorFileListView::currentGroupItem (void) const { return groupItem(QTreeWidget::currentItem()); } // Current file item accessor... qtractorFileListItem *qtractorFileListView::currentFileItem (void) const { QTreeWidgetItem *pItem = QTreeWidget::currentItem(); if (pItem && pItem->type() == FileItem) return static_cast (pItem); return NULL; } // Make as current selection an existing file item. qtractorFileListItem *qtractorFileListView::selectFileItem ( const QString& sPath, int iChannel ) { qtractorFileListItem *pFileItem = findFileItem(sPath); if (pFileItem == NULL) return NULL; // Shall we go deep further intto a channel item? if (iChannel > 0) { // Open file item... pFileItem->setOpen(true); // Select channel item... int iChildCount = pFileItem->childCount(); for (int i = 0; i < iChildCount; ++i) { QTreeWidgetItem *pItem = pFileItem->child(i); if (pItem->type() == qtractorFileListView::ChannelItem) { qtractorFileChannelItem *pChannelItem = static_cast (pItem); if (pChannelItem && pChannelItem->channel() == iChannel) { QTreeWidget::setCurrentItem(pChannelItem); return pFileItem; } } } } // Open file group, if any... qtractorFileGroupItem *pGroupItem = pFileItem->groupItem(); if (pGroupItem) pGroupItem->setOpen(true); // Nothing else than select file item... QTreeWidget::setCurrentItem(pFileItem); return pFileItem; } // Open and add a new file item below the current group one. void qtractorFileListView::openFile (void) { // Ask for the filename to open... QStringList files = openFileNames(); // Check if its a valid file... if (files.isEmpty()) return; // Find a proper group parent group item... qtractorFileListItem *pFileItem = NULL; qtractorFileGroupItem *pParentItem = currentGroupItem(); // Pick each one of the selected files... int iUpdate = 0; QStringListIterator iter(files); while (iter.hasNext()) { const QString& sPath = iter.next(); // Add the new file item... pFileItem = addFileItem(sPath, pParentItem); // Make all this new open and visible. if (pFileItem) { ++iUpdate; if (pParentItem) pParentItem->setOpen(true); } } // Make the last one current... if (pFileItem) QTreeWidget::setCurrentItem(pFileItem); // Make proper notifications... if (iUpdate > 0) emit contentsChanged(); } // Add a new group item below the current one. void qtractorFileListView::newGroup (void) { qtractorFileGroupItem *pParentItem = currentGroupItem(); if (pParentItem && !pParentItem->isOpen()) pParentItem = pParentItem->groupItem(); qtractorFileGroupItem *pGroupItem = addGroupItem(tr("New Group"), pParentItem); if (pGroupItem) { pParentItem = pGroupItem->groupItem(); if (pParentItem) pParentItem->setOpen(true); editItem(pGroupItem, 0); } } // Copy/cut current file item(s) to clipboard. void qtractorFileListView::copyItem ( bool bCut ) { // Build URL list... QList urls; int iUpdate = 0; QList items = selectedItems(); QListIterator iter(items); while (iter.hasNext()) { QTreeWidgetItem *pItem = iter.next(); if (pItem->type() == qtractorFileListView::FileItem) { qtractorFileListItem *pFileItem = static_cast (pItem); if (pFileItem) { urls.append(QUrl::fromLocalFile(pFileItem->path())); if (bCut) { delete pFileItem; ++iUpdate; } } } } // Copy it to system clipboard... if (!urls.isEmpty()) { QMimeData *pMimeData = new QMimeData(); pMimeData->setUrls(urls); QApplication::clipboard()->setMimeData(pMimeData); } // Make proper notifications... if (iUpdate > 0) emit contentsChanged(); } // Paste file item(s9 from clipboard. void qtractorFileListView::pasteItem (void) { const QMimeData *pMimeData = QApplication::clipboard()->mimeData(); if (!pMimeData->hasUrls()) return; // Find a proper group parent group item... qtractorFileGroupItem *pParentItem = currentGroupItem(); int iUpdate = 0; QListIterator iter(pMimeData->urls()); while (iter.hasNext()) { const QString& sPath = iter.next().toLocalFile(); if (!sPath.isEmpty()) { qtractorFileListItem *pFileItem = addFileItem(sPath, pParentItem); // Make all this new open and visible. if (pFileItem) { ++iUpdate; if (pParentItem) pParentItem->setOpen(true); } } } // Make proper notifications... if (iUpdate > 0) emit contentsChanged(); } // Rename current group/file item. void qtractorFileListView::renameItem (void) { qtractorFileGroupItem *pGroupItem = currentGroupItem(); if (pGroupItem) editItem(pGroupItem, 0); } // Remove current group/file item. void qtractorFileListView::removeItem (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; int iUpdate = 0; QList items = selectedItems(); if (items.count() > 0) { // Prompt user if he/she's sure about this... if (pOptions->bConfirmRemove) { if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("About to remove %1 file item(s).\n\n" "Are you sure?") .arg(items.count()), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; } // Definite multi-delete... QListIterator iter(items); while (iter.hasNext()) { QTreeWidgetItem *pItem = iter.next(); // Remove from file registry, when applicable... if (pItem->type() == FileItem) { qtractorFileListItem *pFileItem = static_cast (pItem); if (pFileItem) pSession->files()->removeFileItem(m_iFileType, pFileItem); } // Scrap view item... delete pItem; ++iUpdate; } } else { QTreeWidgetItem *pItem = QTreeWidget::currentItem(); if (pItem) { // Prompt user if he/she's sure about this... if (pOptions->bConfirmRemove) { if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("About to remove %1 item:\n\n" "\"%2\"\n\n" "Are you sure?") .arg(pItem->type() == GroupItem ? tr("group") : tr("file")) .arg(pItem->text(0)), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; } // Remove from file registry, when applicable... if (pItem->type() == FileItem) { if (pItem->type() == FileItem) { qtractorFileListItem *pFileItem = static_cast (pItem); if (pFileItem) pSession->files()->removeFileItem(m_iFileType, pFileItem); } } // Scrap view item... delete pItem; ++iUpdate; } } if (iUpdate > 0) emit contentsChanged(); } // Emit actiovation signal for given item... void qtractorFileListView::activateItem ( QTreeWidgetItem *pItem ) { if (pItem == NULL) pItem = QTreeWidget::currentItem(); if (pItem == NULL) return; if (pItem->type() == FileItem) { qtractorFileListItem *pFileItem = static_cast (pItem); if (pFileItem) emit activated(pFileItem->path(), -1); } else if (pItem->type() == ChannelItem) { qtractorFileChannelItem *pChannelItem = static_cast (pItem); if (pChannelItem) emit activated(pChannelItem->path(), pChannelItem->channel()); } } // Clean-up unused file items. void qtractorFileListView::cleanupItem ( QTreeWidgetItem *pItem ) { if (pItem == NULL) return; switch (pItem->type()) { case GroupItem: { int iChildCount = pItem->childCount(); for (int i = 0; i < iChildCount; ++i) cleanupItem(pItem->child(i)); break; } case FileItem: { qtractorSession *pSession = qtractorSession::getInstance(); qtractorFileListItem *pFileItem = static_cast (pItem); if (pSession && pFileItem) { const QString& sPath = pFileItem->path(); qtractorFileList::Item *pFileListItem = pSession->files()->findItem(m_iFileType, sPath); if (pFileListItem && pFileListItem->clipRefCount() < 1) pItem->setSelected(true); } break; } default: break; } } void qtractorFileListView::cleanup (void) { QTreeWidget::setCurrentItem(NULL); QTreeWidget::selectionModel()->clearSelection(); int iItemCount = QTreeWidget::topLevelItemCount(); for (int i = 0; i < iItemCount; ++i) cleanupItem(QTreeWidget::topLevelItem(i)); removeItem(); } // Master clean-up. void qtractorFileListView::clear (void) { dragLeaveEvent(NULL); m_pDragItem = NULL; QTreeWidget::clear(); } // Find a group item, given its name. qtractorFileGroupItem *qtractorFileListView::findGroupItem ( const QString& sName ) const { return static_cast (findItem(sName, GroupItem)); } // Find a file item, given its name. qtractorFileListItem *qtractorFileListView::findFileItem ( const QString& sPath ) const { return static_cast (findItem(sPath, FileItem)); } // Find a list view item, given its type and name. QTreeWidgetItem *qtractorFileListView::findItem ( const QString& sText, int iType ) const { // Iterate all over the place to search for the item... QList items = QTreeWidget::findItems(sText, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), (iType == GroupItem ? 0 : pathColumn())); // Really check if it's of the intended type... QListIterator iter(items); while (iter.hasNext()) { QTreeWidgetItem *pItem = iter.next(); if (pItem->type() == iType) return pItem; } // Not found. return NULL; } // Find and return the nearest group item... qtractorFileGroupItem *qtractorFileListView::groupItem ( QTreeWidgetItem *pItem ) const { while (pItem && pItem->type() != GroupItem) pItem = pItem->parent(); return static_cast (pItem); } // Prompt for proper file list open. QStringList qtractorFileListView::openFileNames (void) { // Ask for the filename to open... QStringList files = getOpenFileNames(); // Remember recent directory... if (!files.isEmpty()) setRecentDir(QFileInfo(files.first()).absolutePath()); return files; } // In-place toggle slot. void qtractorFileListView::itemClickedSlot ( QTreeWidgetItem *pItem ) { if (pItem == NULL) return; if (pItem->type() == GroupItem) { qtractorFileGroupItem *pGroupItem = static_cast (pItem); if (pGroupItem) pGroupItem->setOpen(!pGroupItem->isOpen()); } else if (pItem->type() == FileItem) { qtractorFileListItem *pFileItem = static_cast (pItem); if (pFileItem) emit selected(pFileItem->path(), -1, pFileItem->isSelected()); if (pFileItem && pFileItem->childCount() > 0) pFileItem->setOpen(!pFileItem->isOpen()); } else if (pItem->type() == ChannelItem) { qtractorFileChannelItem *pChannelItem = static_cast (pItem); if (pChannelItem) emit selected(pChannelItem->path(), pChannelItem->channel(), pChannelItem->isSelected()); } } // In-place activation slot. void qtractorFileListView::itemActivatedSlot ( QTreeWidgetItem *pItem ) { activateItem(pItem); } // In-place open/close slot. void qtractorFileListView::itemExpandedSlot ( QTreeWidgetItem *pItem ) { if (pItem->type() == GroupItem) pItem->setIcon(0, QIcon(":/images/itemGroupOpen.png")); } void qtractorFileListView::itemCollapsedSlot ( QTreeWidgetItem *pItem ) { if (pItem->type() == GroupItem) pItem->setIcon(0, QIcon(":/images/itemGroup.png")); } // Tracking of item changes (e.g in-place edits). void qtractorFileListView::itemRenamedSlot (void) { // We just know that something is in edit mode... emit contentsChanged(); } // Auto-open timeout method. void qtractorFileListView::setAutoOpenTimeout ( int iAutoOpenTimeout ) { m_iAutoOpenTimeout = iAutoOpenTimeout; if (m_pAutoOpenTimer) delete m_pAutoOpenTimer; m_pAutoOpenTimer = 0; if (m_iAutoOpenTimeout > 0) { m_pAutoOpenTimer = new QTimer(this); QObject::connect(m_pAutoOpenTimer, SIGNAL(timeout()), SLOT(timeoutSlot())); } } // Auto-open timeout accessor. int qtractorFileListView::autoOpenTimeout (void) const { return m_iAutoOpenTimeout; } // Auto-open timer slot. void qtractorFileListView::timeoutSlot (void) { if (m_pAutoOpenTimer) { m_pAutoOpenTimer->stop(); qtractorFileGroupItem *pGroupItem = groupItem(m_pDropItem); if (pGroupItem && !pGroupItem->isOpen()) pGroupItem->setOpen(true); } } // Recently used directory, if any. void qtractorFileListView::setRecentDir ( const QString& sRecentDir ) { m_sRecentDir = sRecentDir; } const QString& qtractorFileListView::recentDir (void) const { return m_sRecentDir; } // Trap for help/tool-tip events. bool qtractorFileListView::eventFilter ( QObject *pObject, QEvent *pEvent ) { QWidget *pViewport = QTreeWidget::viewport(); if (static_cast (pObject) == pViewport && pEvent->type() == QEvent::ToolTip) { QHelpEvent *pHelpEvent = static_cast (pEvent); if (pHelpEvent) { QTreeWidgetItem *pItem = QTreeWidget::itemAt(pHelpEvent->pos()); qtractorFileGroupItem *pFileItem = static_cast (pItem); if (pFileItem) { QToolTip::showText(pHelpEvent->globalPos(), pFileItem->toolTip(), pViewport); return true; } } } // Not handled here. return QTreeWidget::eventFilter(pObject, pEvent); } // Handle mouse events for drag-and-drop stuff. void qtractorFileListView::mousePressEvent ( QMouseEvent *pMouseEvent ) { dragLeaveEvent(NULL); m_pDragItem = NULL; if (pMouseEvent->button() == Qt::LeftButton) { m_posDrag = pMouseEvent->pos(); m_pDragItem = QTreeWidget::itemAt(m_posDrag); #if 0 if (m_pDragItem && m_pDragItem->isSelected() && (pMouseEvent->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) == 0) return; #endif } QTreeWidget::mousePressEvent(pMouseEvent); } void qtractorFileListView::mouseMoveEvent ( QMouseEvent *pMouseEvent ) { QTreeWidget::mouseMoveEvent(pMouseEvent); if ((pMouseEvent->buttons() & Qt::LeftButton) && m_pDragItem && ((pMouseEvent->pos() - m_posDrag).manhattanLength() >= QApplication::startDragDistance())) { // We'll start dragging something alright... QMimeData *pMimeData = NULL; switch (m_pDragItem->type()) { case GroupItem: { pMimeData = new QMimeData(); pMimeData->setText(m_pDragItem->text(0)); break; } case FileItem: { // Selected items must only be file items... QList urls; QListIterator iter(selectedItems()); while (iter.hasNext()) { QTreeWidgetItem *pItem = iter.next(); if (pItem->type() == FileItem) { qtractorFileListItem *pFileItem = static_cast (pItem); if (pFileItem) urls.append(QUrl::fromLocalFile(pFileItem->path())); } } // Have we got something? if (!urls.isEmpty()) { pMimeData = new QMimeData(); pMimeData->setUrls(urls); } break; } case ChannelItem: { qtractorFileChannelDrag::List items; QListIterator iter(selectedItems()); while (iter.hasNext()) { QTreeWidgetItem *pItem = iter.next(); if (pItem->type() == ChannelItem) { qtractorFileChannelItem *pChannelItem = static_cast (pItem); if (pChannelItem) { qtractorFileChannelDrag::Item item; item.channel = pChannelItem->channel(); item.path = pChannelItem->path(); items.append(item); } } } if (!items.isEmpty()) { pMimeData = new QMimeData(); qtractorFileChannelDrag::encode(pMimeData, items); } break; } default: break; } // Have we got it right? if (pMimeData) { QDrag *pDrag = new QDrag(this); pDrag->setMimeData(pMimeData); pDrag->setPixmap(m_pDragItem->icon(0).pixmap(16)); pDrag->setHotSpot(QPoint(-4, -12)); pDrag->start(Qt::CopyAction | Qt:: MoveAction); // We've dragged and maybe dropped it by now... dragLeaveEvent(NULL); m_pDragItem = NULL; } } } void qtractorFileListView::mouseReleaseEvent ( QMouseEvent *pMouseEvent ) { QTreeWidget::mouseReleaseEvent(pMouseEvent); dragLeaveEvent(NULL); m_pDragItem = NULL; } // Drag-n-drop stuff. bool qtractorFileListView::canDecodeEvent ( QDropEvent *pDropEvent ) { if (m_pDragItem && pDropEvent->source() != this) m_pDragItem = NULL; return (pDropEvent->mimeData()->hasText() || pDropEvent->mimeData()->hasUrls()); } bool qtractorFileListView::canDropItem ( QTreeWidgetItem *pDropItem ) const { // if (pDropItem == NULL) // return false; if (m_pDragItem) { while (pDropItem) { if (pDropItem == m_pDragItem) return false; QTreeWidgetItem *pParentItem = pDropItem->parent(); if (pParentItem == m_pDragItem) return false; pDropItem = pParentItem; } } return true; } // Ensure given item is brought to viewport visibility... void qtractorFileListView::ensureVisibleItem ( QTreeWidgetItem *pItem ) { QTreeWidgetItem *pItemAbove = pItem->parent(); if (pItemAbove) { int iItem = pItemAbove->indexOfChild(pItem); if (iItem > 0) pItemAbove = pItemAbove->child(iItem - 1); } else { int iItem = QTreeWidget::indexOfTopLevelItem(pItem); if (iItem > 0) { pItemAbove = QTreeWidget::topLevelItem(iItem - 1); if (pItemAbove) { int iItemCount = pItemAbove->childCount(); if (pItemAbove->isExpanded()) pItemAbove = pItemAbove->child(iItemCount - 1); } } } if (pItemAbove) QTreeWidget::scrollToItem(pItemAbove); QTreeWidget::scrollToItem(pItem); } // Track on the current drop item position. QTreeWidgetItem *qtractorFileListView::dragDropItem ( const QPoint& pos ) { QTreeWidgetItem *pDropItem = QTreeWidget::itemAt(pos); if (pDropItem && pDropItem->type() != ChannelItem) { if (pDropItem != m_pDropItem) { m_pDropItem = pDropItem; ensureVisibleItem(m_pDropItem); if (m_pAutoOpenTimer) m_pAutoOpenTimer->start(m_iAutoOpenTimeout); } } else { m_pDropItem = NULL; if (m_pAutoOpenTimer) m_pAutoOpenTimer->stop(); } moveRubberBand(m_pDropItem, pos.x() < QTreeWidget::indentation()); return pDropItem; } void qtractorFileListView::dragEnterEvent ( QDragEnterEvent *pDragEnterEvent ) { #if 0 if (!canDecodeEvent(pDragEnterEvent)) { pDragEnterEvent->ignore(); return; } QTreeWidgetItem *pDropItem = dragDropItem(pDragEnterEvent->pos()); if (canDropItem(pDropItem)) { if (!pDragEnterEvent->isAccepted()) { pDragEnterEvent->setDropAction(Qt::MoveAction); pDragEnterEvent->accept(); } } else { pDragEnterEvent->ignore(); } #else // Always accept the drag-enter event, // so let we deal with it during move later... pDragEnterEvent->accept(); #endif } void qtractorFileListView::dragMoveEvent ( QDragMoveEvent *pDragMoveEvent ) { if (!canDecodeEvent(pDragMoveEvent)) { pDragMoveEvent->ignore(); return; } QTreeWidgetItem *pDropItem = dragDropItem(pDragMoveEvent->pos()); if (canDropItem(pDropItem)) { if (!pDragMoveEvent->isAccepted()) { pDragMoveEvent->setDropAction(Qt::MoveAction); pDragMoveEvent->accept(); } } else { pDragMoveEvent->ignore(); } } void qtractorFileListView::dragLeaveEvent ( QDragLeaveEvent */*pDragLeaveEvent*/ ) { if (m_pRubberBand) delete m_pRubberBand; m_pRubberBand = NULL; m_pDropItem = NULL; if (m_pAutoOpenTimer) m_pAutoOpenTimer->stop(); } void qtractorFileListView::dropEvent ( QDropEvent *pDropEvent ) { QTreeWidgetItem *pDropItem = dragDropItem(pDropEvent->pos()); if (!canDropItem(pDropItem)) { dragLeaveEvent(NULL); m_pDragItem = NULL; return; } // Not quite parent, but the exact drop target... qtractorFileGroupItem *pParentItem = static_cast (pDropItem); bool bOutdent = (pDropEvent->pos().x() < QTreeWidget::indentation()); // Get access to the pertinent drop data... int iUpdate = 0; const QMimeData *pMimeData = pDropEvent->mimeData(); // Let's see how many files there are... if (pMimeData->hasUrls()) { QListIterator iter(pMimeData->urls()); iter.toBack(); while (iter.hasPrevious()) { const QString& sPath = iter.previous().toLocalFile(); // Is it one from ourselves (file item) ?... if (m_pDragItem && m_pDragItem->type() == FileItem) { if (dropItem(pDropItem, findItem(sPath, FileItem), bOutdent)) ++iUpdate; } else if (addFileItem(sPath, pParentItem)) ++iUpdate; } } else if (pMimeData->hasText()) { // Maybe its just a new convenience group... const QString& sText = pMimeData->text(); // Is it one from ourselves (group item) ?... if (m_pDragItem && m_pDragItem->type() == GroupItem) { if (dropItem(pDropItem, findItem(sText, GroupItem), bOutdent)) ++iUpdate; } else if (addGroupItem(sText, pParentItem)) ++iUpdate; } // Teke care of change modification... if (iUpdate > 0) { // Make parent open, anyway... qtractorFileGroupItem *pGroupItem = groupItem(pDropItem); if (pGroupItem) pGroupItem->setOpen(true); // Notify that we've changed something. emit contentsChanged(); } dragLeaveEvent(NULL); m_pDragItem = NULL; } // Drag-and-drop target method... QTreeWidgetItem *qtractorFileListView::dropItem ( QTreeWidgetItem *pDropItem, QTreeWidgetItem *pDragItem, bool bOutdent ) { // We must be dropping something... if (pDragItem == NULL) return NULL; // Take the item from list... int iItem; QTreeWidgetItem *pParentItem = pDragItem->parent(); if (pParentItem) { iItem = pParentItem->indexOfChild(pDragItem); if (iItem >= 0) pDragItem = pParentItem->takeChild(iItem); } else { iItem = QTreeWidget::indexOfTopLevelItem(pDragItem); if (iItem >= 0) pDragItem = QTreeWidget::takeTopLevelItem(iItem); } // Insert it back... if (pDropItem) { if (pDropItem->type() == GroupItem && !bOutdent) { pDropItem->insertChild(0, pDragItem); } else { pParentItem = pDropItem->parent(); if (pParentItem) { iItem = pParentItem->indexOfChild(pDropItem); pParentItem->insertChild(iItem + 1, pDragItem); } else { iItem = QTreeWidget::indexOfTopLevelItem(pDropItem); QTreeWidget::insertTopLevelItem(iItem + 1, pDragItem); } } } else { QTreeWidget::addTopLevelItem(pDragItem); } // Return the new item... return pDragItem; } // Draw a dragging separator line. void qtractorFileListView::moveRubberBand ( QTreeWidgetItem *pDropItem, bool bOutdent ) { // Is there any item upon we migh drop anything? if (pDropItem == NULL) { if (m_pRubberBand) m_pRubberBand->hide(); return; } // Create the rubber-band if there's none... if (m_pRubberBand == NULL) { m_pRubberBand = new qtractorRubberBand( QRubberBand::Line, QTreeWidget::viewport()); // QPalette pal(m_pRubberBand->palette()); // pal.setColor(m_pRubberBand->foregroundRole(), Qt::blue); // m_pRubberBand->setPalette(pal); // m_pRubberBand->setBackgroundRole(QPalette::NoRole); } // Just move it QRect rect = QTreeWidget::visualItemRect(pDropItem); if (pDropItem->type() == GroupItem && !bOutdent) rect.setX(rect.x() + QTreeWidget::indentation()); rect.setTop(rect.bottom()); rect.setHeight(2); m_pRubberBand->setGeometry(rect); // Ah, and make it visible, of course... if (!m_pRubberBand->isVisible()) m_pRubberBand->show(); } // Custom file list loaders. bool qtractorFileListView::loadListElement ( qtractorDocument *pDocument, QDomElement *pElement, QTreeWidgetItem *pItem ) { if (pItem && pItem->type() != GroupItem) return false; qtractorFileGroupItem *pParentItem = static_cast (pItem); // Make it all relative to session directory... QDir dir; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) dir.setPath(pSession->sessionDir()); // Load children... for (QDomNode nChild = pElement->firstChild(); !nChild.isNull(); nChild = nChild.nextSibling()) { // Convert node to element... QDomElement eChild = nChild.toElement(); if (eChild.isNull()) continue; // Now it depends on item tag/type... if (eChild.tagName() == "group") { qtractorFileGroupItem *pGroupItem = new qtractorFileGroupItem(eChild.attribute("name")); if (pParentItem) pParentItem->addChild(pGroupItem); else addTopLevelItem(pGroupItem); if (!loadListElement(pDocument, &eChild, pGroupItem)) return false; pGroupItem->setOpen( qtractorDocument::boolFromText(eChild.attribute("open"))); } else if (eChild.tagName() == "file") { qtractorFileListItem *pFileItem = createFileItem( QDir::cleanPath(dir.absoluteFilePath(eChild.text()))); if (pFileItem) { pFileItem->setText(0, eChild.attribute("name")); if (pParentItem) pParentItem->addChild(pFileItem); else QTreeWidget::addTopLevelItem(pFileItem); if (pSession) pSession->files()->addFileItem(m_iFileType, pFileItem, false); } } } return true; } // The elemental loader implementation. bool qtractorFileListView::loadElement ( qtractorDocument *pDocument, QDomElement *pElement ) { clear(); return loadListElement(pDocument, pElement, NULL); } // Custom file list saver. bool qtractorFileListView::saveListElement ( qtractorDocument *pDocument, QDomElement *pElement, QTreeWidgetItem *pItem ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // Create the new child element... switch (pItem->type()) { case GroupItem: { qtractorFileGroupItem *pGroupItem = static_cast (pItem); QDomElement eGroup = pDocument->document()->createElement("group"); eGroup.setAttribute("name", pGroupItem->text(0)); eGroup.setAttribute("open", qtractorDocument::textFromBool(pGroupItem->isOpen())); int iChildCount = pItem->childCount(); for (int i = 0; i < iChildCount; ++i) saveListElement(pDocument, &eGroup, pGroupItem->child(i)); pElement->appendChild(eGroup); break; } case FileItem: { qtractorFileListItem *pFileItem = static_cast (pItem); QDomElement eFile = pDocument->document()->createElement("file"); eFile.setAttribute("name", pFileItem->text(0)); // Make it all relative to archive or session directory... QString sPath = pFileItem->path(); if (pDocument->isArchive()) { qtractorFileList::Item *pFileListItem = pSession->files()->findItem(m_iFileType, sPath); if (pFileListItem && pFileListItem->clipRefCount() > 0) sPath = pDocument->addFile(sPath); } else { QDir dir; dir.setPath(pSession->sessionDir()); sPath = dir.relativeFilePath(sPath); } eFile.appendChild(pDocument->document()->createTextNode(sPath)); pElement->appendChild(eFile); break; }} return true; } // The elemental saver implementation. bool qtractorFileListView::saveElement ( qtractorDocument *pDocument, QDomElement *pElement ) { int iItemCount = QTreeWidget::topLevelItemCount(); for (int i = 0; i < iItemCount; ++i) saveListElement(pDocument, pElement, QTreeWidget::topLevelItem(i)); return true; } // end of qtractorFileListView.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorSessionForm.h0000644000175000001440000000012312166526620021451 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134666.56608 30 ctime=1381134666.566080042 qtractor-0.5.11/src/qtractorSessionForm.h0000644000175000001440000000354712166526620020751 0ustar00rncbcusers00000000000000// qtractorSessionForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorSessionForm_h #define __qtractorSessionForm_h #include "ui_qtractorSessionForm.h" #include "qtractorSession.h" //---------------------------------------------------------------------------- // qtractorSessionForm -- UI wrapper form. class qtractorSessionForm : public QDialog { Q_OBJECT public: // Constructor. qtractorSessionForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorSessionForm(); void setSession(qtractorSession *pSession); const qtractorSession::Properties& properties(); protected slots: void accept(); void reject(); void changed(); void stabilizeForm(); void browseSessionDir(); private: // The Qt-designer UI struct... Ui::qtractorSessionForm m_ui; // Instance variables... qtractorSession::Properties m_props; int m_iDirtyCount; }; #endif // __qtractorSessionForm_h // end of qtractorSessionForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorShortcutForm.h0000644000175000001440000000012312073012112021620 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134666.81808 30 ctime=1381134666.818080046 qtractor-0.5.11/src/qtractorShortcutForm.h0000644000175000001440000001036112073012112021110 0ustar00rncbcusers00000000000000// qtractorShortcutForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorShortcutForm_h #define __qtractorShortcutForm_h #include "ui_qtractorShortcutForm.h" #include #include #include class QAction; class QToolButton; //------------------------------------------------------------------------- // qtractorShortcutTableItemEdit class qtractorShortcutTableItemEdit : public QLineEdit { Q_OBJECT public: // Constructor. qtractorShortcutTableItemEdit(QWidget *pParent = NULL) : QLineEdit(pParent) {} signals: // Custom cancel signal. void editingCanceled(); protected: // Shortcut key to text event translation. void keyPressEvent(QKeyEvent *pKeyEvent); }; //------------------------------------------------------------------------- // qtractorShortcutTableItemEditor class qtractorShortcutTableItemEditor : public QWidget { Q_OBJECT public: // Constructor. qtractorShortcutTableItemEditor(QWidget *pParent = NULL); // Shortcut text accessors. void setText(const QString& sText); QString text() const; // Index model row accessors. void setIndex(const QModelIndex& index) { m_index = index; } const QModelIndex& index() const { return m_index; } // Default (initial) shortcut text accessors. void setDefaultText(const QString& sDefaultText) { m_sDefaultText = sDefaultText; } const QString& defaultText() const { return m_sDefaultText; } signals: void editingFinished(); void editingCanceled(); public slots: void clear(); protected slots: void finish(); void cancel(); private: // Instance variables. qtractorShortcutTableItemEdit *m_pItemEdit; QToolButton *m_pToolButton; QString m_sDefaultText; QModelIndex m_index; }; //------------------------------------------------------------------------- // qtractorShortcutTableItemDelegate class qtractorShortcutForm; class qtractorShortcutTableItemDelegate : public QItemDelegate { Q_OBJECT public: // Constructor. qtractorShortcutTableItemDelegate(qtractorShortcutForm *pShortcutForm); protected: void paint(QPainter *pPainter, const QStyleOptionViewItem& option, const QModelIndex& index) const; QWidget *createEditor(QWidget *pParent, const QStyleOptionViewItem& option, const QModelIndex & index) const; void setEditorData(QWidget *pEditor, const QModelIndex &index) const; void setModelData(QWidget *pEditor, QAbstractItemModel *pModel, const QModelIndex& index) const; protected slots: void commitEditor(); private: qtractorShortcutForm *m_pShortcutForm; }; //------------------------------------------------------------------------- // qtractorShortcutForm class qtractorShortcutForm : public QDialog { Q_OBJECT public: // Constructor. qtractorShortcutForm(const QList& actions, QWidget *pParent = NULL); // Destructor. ~qtractorShortcutForm(); // Shortcut table widget accessor. QTableWidget *tableWidget() const; // Shortcut action finder & settler. bool commitEditor(qtractorShortcutTableItemEditor *pItemEditor); protected slots: void actionActivated(QTableWidgetItem *); void actionChanged(QTableWidgetItem *); void accept(); void reject(); private: // The Qt-designer UI struct... Ui::qtractorShortcutForm m_ui; QHash m_actions; QHash m_shortcuts; int m_iDirtyCount; }; #endif // __qtractorShortcutForm_h // end of qtractorShortcutForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMainForm.h0000644000175000001440000000012312223025330020674 xustar000000000000000027 mtime=1380723416.183262 26 atime=1381134670.95808 30 ctime=1381134671.088080114 qtractor-0.5.11/src/qtractorMainForm.h0000644000175000001440000003205112223025330020164 0ustar00rncbcusers00000000000000// qtractorMainForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMainForm_h #define __qtractorMainForm_h #include "ui_qtractorMainForm.h" // Forward declarations... class qtractorOptions; class qtractorSession; class qtractorSessionEvent; class qtractorSyncEvent; class qtractorTracks; class qtractorThumbView; class qtractorCommand; class qtractorCommandList; class qtractorInstrumentList; class qtractorFiles; class qtractorMessages; class qtractorConnections; class qtractorMixer; class qtractorMmcEvent; class qtractorCtlEvent; class qtractorMidiControl; class qtractorTimeSpinBox; class qtractorTempoSpinBox; class qtractorTempoCursor; class qtractorMidiEditorForm; class qtractorMidiEditor; class qtractorMidiControlObserver; class qtractorSubject; class qtractorNsmClient; class QLabel; class QComboBox; class QProgressBar; class QSocketNotifier; class QActionGroup; class QPalette; //---------------------------------------------------------------------------- // qtractorMainForm -- UI wrapper form. class qtractorMainForm : public QMainWindow { Q_OBJECT public: // Constructor. qtractorMainForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorMainForm(); static qtractorMainForm *getInstance(); void setup(qtractorOptions *pOptions); qtractorTracks *tracks() const; qtractorFiles *files() const; qtractorConnections *connections() const; qtractorMixer *mixer() const; qtractorThumbView *thumbView() const; QString sessionName(const QString& sFilename); void updateTransportTime(unsigned long iPlayHead); void appendMessages(const QString& s); void appendMessagesColor(const QString& s, const QString& c); void appendMessagesText(const QString& s); void appendMessagesError(const QString& s); void addEditorForm(qtractorMidiEditorForm *pEditorForm); void removeEditorForm(qtractorMidiEditorForm *pEditorForm); QMenu *editMenu() const { return m_ui.editMenu; } QMenu *trackMenu() const { return m_ui.trackMenu; } QMenu *trackCurveMenu() const { return m_ui.trackCurveMenu; } QMenu *trackCurveModeMenu() const { return m_ui.trackCurveModeMenu; } QProgressBar *progressBar() const { return m_pProgressBar; } void contextMenuEvent(QContextMenuEvent *pEvent); void dropEvent(QDropEvent *pDropEvent); int rolling() const; public slots: void fileNew(); void fileOpen(); void fileOpenRecent(); void fileSave(); void fileSaveAs(); void fileProperties(); void fileExit(); void editUndo(); void editRedo(); void editCut(); void editCopy(); void editPaste(); void editPasteRepeat(); void editDelete(); void editSelectModeClip(); void editSelectModeRange(); void editSelectModeRect(); void editSelectModeCurve(); void editSelectAll(); void editSelectNone(); void editSelectInvert(); void editSelectTrack(); void editSelectTrackRange(); void editSelectRange(); void editInsertRange(); void editInsertTrackRange(); void editRemoveRange(); void editRemoveTrackRange(); void editSplit(); void trackAdd(); void trackRemove(); void trackProperties(); void trackInputs(); void trackOutputs(); void trackStateRecord(bool bOn); void trackStateMute(bool bOn); void trackStateSolo(bool bOn); void trackStateMonitor(bool bOn); void trackNavigateFirst(); void trackNavigatePrev(); void trackNavigateNext(); void trackNavigateLast(); void trackNavigateNone(); void trackMoveTop(); void trackMoveUp(); void trackMoveDown(); void trackMoveBottom(); void trackHeightUp(); void trackHeightDown(); void trackHeightReset(); void trackAutoMonitor(bool bOn); void trackImportAudio(); void trackImportMidi(); void trackExportAudio(); void trackExportMidi(); void trackCurveSelect(bool On); void trackCurveSelect(QAction *pAction, bool bOn = true); void trackCurveMode(QAction *pAction); void trackCurveProcess(bool bOn); void trackCurveCapture(bool bOn); void trackCurveLocked(bool bOn); void trackCurveLogarithmic(bool bOn); void trackCurveColor(); void trackCurveClear(); void trackCurveProcessAll(bool bOn); void trackCurveCaptureAll(bool bOn); void trackCurveLockedAll(bool bOn); void trackCurveClearAll(); void clipNew(); void clipEdit(); void clipUnlink(); void clipSplit(); void clipMerge(); void clipNormalize(); void clipTempo(); void clipRangeSet(); void clipLoopSet(); void clipImport(); void clipExport(); void clipToolsQuantize(); void clipToolsTranspose(); void clipToolsNormalize(); void clipToolsRandomize(); void clipToolsResize(); void clipToolsRescale(); void clipToolsTimeshift(); void clipTakeSelect(QAction *pAction); void clipTakeFirst(); void clipTakePrev(); void clipTakeNext(); void clipTakeLast(); void clipTakeReset(); void clipTakeRange(); void viewMenubar(bool bOn); void viewStatusbar(bool bOn); void viewToolbarFile(bool bOn); void viewToolbarEdit(bool bOn); void viewToolbarTrack(bool bOn); void viewToolbarView(bool bOn); void viewToolbarOptions(bool bOn); void viewToolbarTransport(bool bOn); void viewToolbarTime(bool bOn); void viewToolbarThumb(bool bOn); void viewFiles(bool bOn); void viewMessages(bool bOn); void viewConnections(bool bOn); void viewMixer(bool bOn); void viewZoomIn(); void viewZoomOut(); void viewZoomReset(); void viewZoomHorizontal(); void viewZoomVertical(); void viewZoomAll(); void viewSnapZebra(bool bOn); void viewSnapGrid(bool bOn); void viewToolTips(bool bOn); void viewSnap(); void viewRefresh(); void viewInstruments(); void viewControllers(); void viewBuses(); void viewTempoMap(); void viewOptions(); void transportBackward(); void transportRewind(); void transportFastForward(); void transportForward(); void transportLoop(); void transportLoopSet(); void transportStop(); void transportPlay(); void transportRecord(); void transportPunch(); void transportPunchSet(); void transportMetro(); void transportFollow(); void transportAutoBackward(); void transportContinue(); void transportPanic(); void helpShortcuts(); void helpAbout(); void helpAboutQt(); void stabilizeForm(); void addAudioFile(const QString& sFilename, bool bAutoRemove = false); void addMidiFile(const QString& sFilename, bool bAutoRemove = false); void selectionNotifySlot(qtractorMidiEditor *pMidiEditor); void changeNotifySlot(qtractorMidiEditor *pMidiEditor); void updateNotifySlot(unsigned int flags); void dirtyNotifySlot(); protected slots: void timerSlot(); void peakNotify(); void alsaNotify(); void audioShutNotify(); void audioXrunNotify(); void audioPortNotify(); void audioBuffNotify(); void audioSessNotify(void *pvSessionArg); void audioSyncNotify(unsigned long iPlayHead); void midiMmcNotify(const qtractorMmcEvent& mmce); void midiCtlNotify(const qtractorCtlEvent& ctle); void midiSppNotify(int iSppCmd, unsigned short iSongPos); void midiClkNotify(float fTempo); void updateRecentFilesMenu(); void updateTrackMenu(); void updateCurveMenu(); void updateCurveModeMenu(); void updateClipMenu(); void updateTakeMenu(); void updateTakeSelectMenu(); void updateExportMenu(); void updateZoomMenu(); void updateSnapMenu(); void selectAudioFile(const QString& sFilename, int iTrackChannel, bool bSelect); void activateAudioFile(const QString& sFilename, int iTrackChannel = -1); void selectMidiFile(const QString& sFilename, int iTrackChannel, bool bSelect); void activateMidiFile(const QString& sFilename, int iTrackChannel = -1); void trackSelectionChanged(); void mixerSelectionChanged(); void transportTimeFormatChanged(int iDisplayFormat); void transportTimeChanged(unsigned long iPlayHead); void transportTimeFinished(); void transportTempoChanged(float fTempo, unsigned short iBeatsPerBar, unsigned short iBeatDivisor); void transportTempoFinished(); void snapPerBeatChanged(int iSnap); void contentsChanged(); void transportTempoContextMenu(const QPoint& pos); void handle_sigusr1(); void handle_sigterm(); void openNsmSession(); void saveNsmSession(); void showNsmSession(); void hideNsmSession(); protected: void closeEvent(QCloseEvent *pCloseEvent); void dragEnterEvent(QDragEnterEvent *pDragEnterEvent); void showEvent(QShowEvent *pShowEvent); void hideEvent(QHideEvent *pHideEvent); bool queryClose(); bool newSession(); bool openSession(); bool saveSession(bool bPrompt); bool editSession(); bool closeSession(); bool loadSessionFileEx( const QString& sFilename, bool bTemplate, bool bUpdate); bool loadSessionFile(const QString& sFilename); bool saveSessionFileEx( const QString& sFilename, bool bTemplate, bool bUpdate); bool saveSessionFile(const QString& sFilename); bool startSession(); bool checkRestartSession(); bool setPlaying(bool bPlaying); bool setRecording(bool bRecording); int setRolling(int iRolling); void setLocate(unsigned long iLocate); void setShuttle(float fShuttle); void setStep(int iStep); void setTrack(int scmd, int iTrack, bool bOn); void setSongPos(unsigned short iSongPos); void updateSessionPre(); void updateSessionPost(); void updateRecentFiles(const QString& sFilename); void updatePeakAutoRemove(); void updateMessagesFont(); void updateMessagesLimit(); void updateMessagesCapture(); void updateDisplayFormat(); void updatePluginPaths(); void updateTransportMode(); void updateMidiControlModes(); void updateAudioPlayer(); void updateMidiQueueTimer(); void updateMidiPlayer(); void updateMidiControl(); void updateAudioMetronome(); void updateMidiMetronome(); void updateContents(qtractorMidiEditor *pMidiEditor, bool bRefresh); void updateDirtyCount(bool bDirtyCount); void trackCurveSelectMenuAction(QMenu *pMenu, qtractorMidiControlObserver *pObserver, qtractorSubject *pCurrentSubject) const; bool trackCurveSelectMenuReset(QMenu *pMenu) const; bool trackCurveModeMenuReset(QMenu *pMenu) const; void saveNsmSessionEx(bool bSaveReply); private: // The Qt-designer UI struct... Ui::qtractorMainForm m_ui; // Instance variables... qtractorOptions *m_pOptions; qtractorSession *m_pSession; qtractorFiles *m_pFiles; qtractorMessages *m_pMessages; qtractorConnections *m_pConnections; qtractorMixer *m_pMixer; qtractorTracks *m_pTracks; QString m_sFilename; int m_iUntitled; int m_iDirtyCount; int m_iBackupCount; QSocketNotifier *m_pUsr1Notifier; QSocketNotifier *m_pTermNotifier; QActionGroup *m_pSelectModeActionGroup; qtractorTimeSpinBox *m_pTimeSpinBox; qtractorTempoSpinBox *m_pTempoSpinBox; QComboBox *m_pSnapPerBeatComboBox; QProgressBar *m_pProgressBar; qtractorThumbView *m_pThumbView; qtractorTempoCursor *m_pTempoCursor; qtractorMidiControl *m_pMidiControl; qtractorNsmClient *m_pNsmClient; QString m_sNsmFile; QString m_sNsmExt; bool m_bNsmDirty; unsigned long m_iPlayHead; int m_iPeakTimer; int m_iPlayTimer; int m_iIdleTimer; int m_iTransportUpdate; int m_iTransportRolling; bool m_bTransportPlaying; float m_fTransportShuttle; int m_iTransportStep; int m_iXrunCount; int m_iXrunSkip; int m_iXrunTimer; int m_iAudioRefreshTimer; int m_iMidiRefreshTimer; int m_iPlayerTimer; // Status bar item indexes enum { StatusName = 0, // Active session track caption. StatusMod = 1, // Current session modification state. StatusRec = 2, // Current session recording state. StatusMute = 3, // Current session muting state. StatusSolo = 4, // Current session soloing state. StatusLoop = 5, // Current session looping state. StatusTime = 6, // Current session length time. StatusRate = 7, // Current session sample rate. StatusItems = 8 // Number of status items. }; QLabel *m_statusItems[StatusItems]; // Palette status item indexes enum { PaletteNone = 0, // Default background color. PaletteRed = 1, // Current session recording state (red). PaletteYellow = 2, // Current session muting state (yellow). PaletteCyan = 3, // Current session soloing state (cyan). PaletteGreen = 4, // Current session looping state (green). PaletteItems = 5 // Number of palette items. }; QPalette *m_paletteItems[PaletteItems]; // View/Snap-to-beat actions (for shortcuts access) QList m_snapPerBeatActions; // Name says it all... QList m_editors; // Kind-of singleton reference. static qtractorMainForm *g_pMainForm; }; #endif // __qtractorMainForm_h // end of qtractorMainForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioEngine.h0000644000175000001440000000012312215372276021372 xustar000000000000000027 mtime=1379267774.934138 26 atime=1381134666.81608 30 ctime=1381134666.817080046 qtractor-0.5.11/src/qtractorAudioEngine.h0000644000175000001440000002666312215372276020676 0ustar00rncbcusers00000000000000// qtractorAudioEngine.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorAudioEngine_h #define __qtractorAudioEngine_h #include "qtractorAtomic.h" #include "qtractorEngine.h" #include #include // Forward declarations. class qtractorAudioBus; class qtractorAudioBuffer; class qtractorAudioMonitor; class qtractorAudioFile; class qtractorPluginList; class qtractorCurveList; //---------------------------------------------------------------------- // class qtractorAudioEngineProxy -- Audio engine event proxy object. // class qtractorAudioEngineProxy : public QObject { Q_OBJECT public: // Constructor. qtractorAudioEngineProxy(QObject *pParent = NULL) : QObject(pParent) {} // Event notifications. void notifyShutEvent() { emit shutEvent(); } void notifyXrunEvent() { emit xrunEvent(); } void notifyPortEvent() { emit portEvent(); } void notifyBuffEvent() { emit buffEvent(); } void notifySessEvent(void *pvSessionArg) { emit sessEvent(pvSessionArg); } void notifySyncEvent(unsigned long iPlayHead) { emit syncEvent(iPlayHead); } signals: // Event signals. void shutEvent(); void xrunEvent(); void portEvent(); void buffEvent(); void sessEvent(void *pvSessionArg); void syncEvent(unsigned long iPlayHead); }; //---------------------------------------------------------------------- // class qtractorAudioEngine -- JACK client instance (singleton). // class qtractorAudioEngine : public qtractorEngine { public: // Constructor. qtractorAudioEngine(qtractorSession *pSession); // Engine initialization. bool init(); // Special event notifier proxy object. const qtractorAudioEngineProxy *proxy() const; // Event notifications. void notifyShutEvent(); void notifyXrunEvent(); void notifyPortEvent(); void notifyBuffEvent(); void notifySessEvent(void *pvSessionArg); void notifySyncEvent(unsigned long iPlayHead); // JACK client descriptor accessor. jack_client_t *jackClient() const; // Process cycle executive. int process(unsigned int nframes); // Document element methods. bool loadElement(qtractorDocument *pDocument, QDomElement *pElement); bool saveElement(qtractorDocument *pDocument, QDomElement *pElement) const; // Session UUID accessors. void setSessionId(const QString& sSessionId); const QString& sessionId() const; // Internal sample-rate accessor. unsigned int sampleRate() const; // Buffer size accessor. unsigned int bufferSize() const; // Buffer offset accessor. unsigned int bufferOffset() const; // Audio (Master) bus defaults accessors. void setMasterAutoConnect(bool bMasterAutoConnect); bool isMasterAutoConnect() const; // Audio-export freewheeling (internal) state. void setFreewheel(bool bFreewheel); bool isFreewheel() const; // Audio-export active state. void setExporting(bool bExporting); bool isExporting() const; // Audio-export method. bool fileExport(const QString& sExportPath, unsigned long iExportStart = 0, unsigned long iExportEnd = 0, qtractorAudioBus *pExportBus = NULL); // Direct sync method (needed for export) void syncExport(unsigned long iFrameStart, unsigned long iFrameEnd); // Special track-immediate methods. void trackMute(qtractorTrack *pTrack, bool bMute); // Metronome switching. void setMetronome(bool bMetronome); bool isMetronome() const; // Metronome enabled accessors. void setMetroEnabled(bool bMetroEnabled); bool isMetroEnabled() const; // Metronome bus mode accessors. void setMetroBus(bool bMetroBus); bool isMetroBus() const; void resetMetroBus(); // Metronome bus defaults accessors. void setMetroAutoConnect(bool bMetroAutoConnect); bool isMetroAutoConnect() const; // Metronome bar audio sample. void setMetroBarFilename(const QString& sFilename); const QString& metroBarFilename() const; // Metronome bar audio sample gain. void setMetroBarGain(float fGain); float metroBarGain() const; // Metronome beat audio sample. void setMetroBeatFilename(const QString& sFilename); const QString& metroBeatFilename() const; // Metronome beat audio sample gain. void setMetroBeatGain(float fGain); float metroBeatGain() const; void resetMetro(); // Audition/pre-listening bus mode accessors. void setPlayerBus(bool bPlayerBus); bool isPlayerBus() const; void resetPlayerBus(); // Audition/pre-listening bus defaults accessors. void setPlayerAutoConnect(bool bPlayerAutoConnect); bool isPlayerAutoConnect() const; bool isPlayerOpen() const; bool openPlayer(const QString& sFilename); void closePlayer(); // Retrieve/restore all connections, on all audio buses; // return the effective number of connection attempts. int updateConnects(); // JACK Transport mode accessors. void setTransportMode(qtractorBus::BusMode transportMode); qtractorBus::BusMode transportMode() const; // Absolute number of frames elapsed since engine start. unsigned long jackFrame() const; // Reset all audio monitoring... void resetAllMonitors(); protected: // Concrete device (de)activation methods. bool activate(); bool start(); void stop(); void deactivate(); void clean(); // Metronome (de)activation methods. void createMetroBus(); bool openMetroBus(); void closeMetroBus(); void deleteMetroBus(); // Audition/pre-listening player (de)activation methods. void createPlayerBus(); bool openPlayerBus(); void closePlayerBus(); void deletePlayerBus(); private: // Special event notifier proxy object. qtractorAudioEngineProxy m_proxy; // Audio device instance variables. jack_client_t *m_pJackClient; // JACK Session UUID. QString m_sSessionId; // Initial sample-rate and buffer size. unsigned int m_iSampleRate; unsigned int m_iBufferSize; // Audio (Master) bus defaults. bool m_bMasterAutoConnect; // Partial buffer offset state; // careful for proper loop concatenation. unsigned int m_iBufferOffset; // Audio-export freewheeling (internal) state. bool m_bFreewheel; // Common audio buffer sync thread. qtractorAudioBufferThread *m_pSyncThread; // Audio-export (in)active state. volatile bool m_bExporting; qtractorAudioBus *m_pExportBus; qtractorAudioFile *m_pExportFile; unsigned long m_iExportStart; unsigned long m_iExportEnd; volatile bool m_bExportDone; // Audio metronome stuff. bool m_bMetronome; bool m_bMetroBus; qtractorAudioBus *m_pMetroBus; bool m_bMetroAutoConnect; qtractorAudioBuffer *m_pMetroBarBuff; qtractorAudioBuffer *m_pMetroBeatBuff; QString m_sMetroBarFilename; QString m_sMetroBeatFilename; float m_fMetroBarGain; float m_fMetroBeatGain; unsigned long m_iMetroBeatStart; unsigned int m_iMetroBeat; bool m_bMetroEnabled; // Audition/pre-listening player stuff. qtractorAtomic m_playerLock; bool m_bPlayerOpen; bool m_bPlayerBus; qtractorAudioBus *m_pPlayerBus; bool m_bPlayerAutoConnect; qtractorAudioBuffer *m_pPlayerBuff; unsigned long m_iPlayerFrame; // JACK Transport mode. qtractorBus::BusMode m_transportMode; }; //---------------------------------------------------------------------- // class qtractorAudioBus -- Managed JACK port set // class qtractorAudioBus : public qtractorBus { public: // Constructor. qtractorAudioBus(qtractorAudioEngine *pAudioEngine, const QString& sBusName, BusMode busMode, bool bMonitor = false, unsigned short iChannels = 2); // Destructor. ~qtractorAudioBus(); // Channel number property accessor. void setChannels(unsigned short iChannels); unsigned short channels() const; // Auto-connection predicate. void setAutoConnect(bool bAutoConnect); bool isAutoConnect() const; // Concrete activation methods. bool open(); void close(); // Auto-connect to physical ports. void autoConnect(); // Process cycle (preparator only). void process_prepare(unsigned int nframes); void process_monitor(unsigned int nframes); void process_commit(unsigned int nframes); // Bus-buffering methods. void buffer_prepare(unsigned int nframes, qtractorAudioBus *pInputBus = NULL); void buffer_commit(unsigned int nframes); float **buffer() const; // Frame buffer accessors. float **in() const; float **out() const; // Virtual I/O bus-monitor accessors. qtractorMonitor *monitor_in() const; qtractorMonitor *monitor_out() const; // Audio I/O bus-monitor accessors. qtractorAudioMonitor *audioMonitor_in() const; qtractorAudioMonitor *audioMonitor_out() const; // Plugin-chain accessors. qtractorPluginList *pluginList_in() const; qtractorPluginList *pluginList_out() const; // Automation curve list accessors. qtractorCurveList *curveList_in() const; qtractorCurveList *curveList_out() const; // Automation curve serializer accessors. qtractorCurveFile *curveFile_in() const; qtractorCurveFile *curveFile_out() const; // Audio I/O port latency accessors. unsigned int latency_in() const; unsigned int latency_out() const; // Retrieve/restore client:port connections; // return the effective number of connection attempts... int updateConnects(BusMode busMode, ConnectList& connects, bool bConnect = false) const; // Document element methods. bool loadElement(qtractorDocument *pDocument, QDomElement *pElement); bool saveElement(qtractorDocument *pDocument, QDomElement *pElement) const; protected: // Bus mode change event. void updateBusMode(); // Create plugin-list properly. qtractorPluginList *createPluginList(int iFlags) const; // Set plugin-list title name. void updatePluginListName( qtractorPluginList *pPluginList, int iFlags) const; // Set plugin-list buffers properly. void updatePluginList( qtractorPluginList *pPluginList, int iFlags); private: // Instance variables. unsigned short m_iChannels; bool m_bAutoConnect; // Specific monitor instances. qtractorAudioMonitor *m_pIAudioMonitor; qtractorAudioMonitor *m_pOAudioMonitor; // Plugin-chain instances. qtractorPluginList *m_pIPluginList; qtractorPluginList *m_pOPluginList; // Automation curve serializer instances. qtractorCurveFile *m_pICurveFile; qtractorCurveFile *m_pOCurveFile; // Specific JACK ports stuff. jack_port_t **m_ppIPorts; jack_port_t **m_ppOPorts; float **m_ppIBuffer; float **m_ppOBuffer; float **m_ppXBuffer; float **m_ppYBuffer; // Special under-work flag... // (r/w access should be atomic) bool m_bEnabled; // Buffer mix-down processor. void (*m_pfnBufferAdd)(float **, float **, unsigned int, unsigned short, unsigned short, unsigned int); }; #endif // __qtractorAudioEngine_h // end of qtractorAudioEngine.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorSpinBox.cpp0000644000175000001440000000012312166526620021117 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134667.96708 30 ctime=1381134667.967080064 qtractor-0.5.11/src/qtractorSpinBox.cpp0000644000175000001440000004060712166526620020415 0ustar00rncbcusers00000000000000// qtractorSpinBox.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorSpinBox.h" #include #include #include #include #include //---------------------------------------------------------------------------- // qtractorTimeSpinBox -- A time-scale formatted spin-box widget. // Constructor. qtractorTimeSpinBox::qtractorTimeSpinBox ( QWidget *pParent ) : QAbstractSpinBox(pParent) { m_pTimeScale = NULL; m_displayFormat = qtractorTimeScale::Frames; m_iValue = 0; m_iMinimumValue = 0; m_iMaximumValue = 0; m_iDeltaValue = 0; m_bDeltaValue = false; QAbstractSpinBox::setAccelerated(true); QObject::connect(this, SIGNAL(editingFinished()), SLOT(editingFinishedSlot())); QObject::connect(QAbstractSpinBox::lineEdit(), SIGNAL(textChanged(const QString&)), SLOT(valueChangedSlot(const QString&))); } // Destructor. qtractorTimeSpinBox::~qtractorTimeSpinBox (void) { } // Mark that we got actual value. void qtractorTimeSpinBox::showEvent ( QShowEvent */*pShowEvent*/ ) { QLineEdit *pLineEdit = QAbstractSpinBox::lineEdit(); bool bBlockSignals = pLineEdit->blockSignals(true); pLineEdit->setText(textFromValue(m_iValue)); QAbstractSpinBox::interpretText(); pLineEdit->blockSignals(bBlockSignals); } // Time-scale accessors. void qtractorTimeSpinBox::setTimeScale ( qtractorTimeScale *pTimeScale ) { m_pTimeScale = pTimeScale; setDisplayFormat(m_pTimeScale ? m_pTimeScale->displayFormat() : qtractorTimeScale::Frames); } qtractorTimeScale *qtractorTimeSpinBox::timeScale (void) const { return m_pTimeScale; } // Display-format accessors. void qtractorTimeSpinBox::setDisplayFormat ( qtractorTimeScale::DisplayFormat displayFormat ) { m_displayFormat = displayFormat; updateDisplayFormat(); } qtractorTimeScale::DisplayFormat qtractorTimeSpinBox::displayFormat (void) const { return m_displayFormat; } void qtractorTimeSpinBox::updateDisplayFormat (void) { setValue(m_iValue); } // Nominal value (in frames) accessors. void qtractorTimeSpinBox::setValue ( unsigned long iValue, bool bNotifyChange ) { QLineEdit *pLineEdit = QAbstractSpinBox::lineEdit(); int iCursorPos = pLineEdit->cursorPosition(); if (iValue < m_iMinimumValue) iValue = m_iMinimumValue; if (iValue > m_iMaximumValue && m_iMaximumValue > m_iMinimumValue) iValue = m_iMaximumValue; bool bValueChanged = (iValue != m_iValue); m_iValue = iValue; if (QAbstractSpinBox::isVisible()) { bool bBlockSignals = pLineEdit->blockSignals(true); pLineEdit->setText(textFromValue(iValue)); QAbstractSpinBox::interpretText(); if (bNotifyChange && bValueChanged) emit valueChanged(iValue); pLineEdit->blockSignals(bBlockSignals); } pLineEdit->setCursorPosition(iCursorPos); } unsigned long qtractorTimeSpinBox::value (void) const { return m_iValue; } // Minimum value (in frames) accessors. void qtractorTimeSpinBox::setMinimum ( unsigned long iMinimum ) { m_iMinimumValue = iMinimum; } unsigned long qtractorTimeSpinBox::minimum (void) const { return m_iMinimumValue; } // Maximum value (in frames) accessors. void qtractorTimeSpinBox::setMaximum ( unsigned long iMaximum ) { m_iMaximumValue = iMaximum; } unsigned long qtractorTimeSpinBox::maximum (void) const { return m_iMaximumValue; } // Differential value mode (BBT format only) accessor. void qtractorTimeSpinBox::setDeltaValue ( bool bDeltaValue, unsigned long iDeltaValue ) { m_bDeltaValue = bDeltaValue; m_iDeltaValue = iDeltaValue; } bool qtractorTimeSpinBox::isDeltaValue (void) const { return m_bDeltaValue; } unsigned long qtractorTimeSpinBox::deltaValue (void) const { return m_iDeltaValue; } // Inherited/override methods. QValidator::State qtractorTimeSpinBox::validate ( QString& sText, int& iPos ) const { #ifdef CONFIG_DEBUG_0 qDebug("qtractorTimeSpinBox[%p]::validate(\"%s\",%d)", this, sText.toUtf8().constData(), iPos); #endif if (iPos == 0) return QValidator::Acceptable; const QChar& ch = sText[iPos - 1]; switch (m_displayFormat) { case qtractorTimeScale::Time: if (ch == ':') return QValidator::Acceptable; // Fall thru. case qtractorTimeScale::BBT: if (ch == '.') return QValidator::Acceptable; // Fall thru. case qtractorTimeScale::Frames: default: if (ch.isDigit()) return QValidator::Acceptable; break; } return QValidator::Invalid; } void qtractorTimeSpinBox::fixup ( QString& sText ) const { #ifdef CONFIG_DEBUG_0 qDebug("qtractorTimeSpinBox[%p]::fixup(\"%s\")", this, sText.toUtf8().constData()); #endif sText = textFromValue(m_iValue); } void qtractorTimeSpinBox::stepBy ( int iSteps ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorTimeSpinBox[%p]::stepBy(%d)", this, iSteps); #endif QLineEdit *pLineEdit = QAbstractSpinBox::lineEdit(); int iCursorPos = pLineEdit->cursorPosition(); long iValue = long(value()); if (m_pTimeScale) { switch (m_displayFormat) { case qtractorTimeScale::BBT: { qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(iValue); unsigned long iFrame = pNode->frame; const QString& sText = pLineEdit->text(); int iPos = sText.section('.', 0, 0).length() + 1; if (iCursorPos < iPos) iFrame = pNode->frameFromBar(pNode->bar + 1); else if (iCursorPos < iPos + sText.section('.', 1, 1).length() + 1) iFrame = pNode->frameFromBeat(pNode->beat + 1); else iFrame = pNode->frameFromTick(pNode->tick + 1); iSteps *= int(iFrame - pNode->frame); break; } case qtractorTimeScale::Time: { const QString& sText = pLineEdit->text(); int iPos = sText.section(':', 0, 0).length() + 1; if (iCursorPos < iPos) iSteps *= int(3600 * m_pTimeScale->sampleRate()); else if (iCursorPos < iPos + sText.section(':', 1, 1).length() + 1) iSteps *= int(60 * m_pTimeScale->sampleRate()); else iSteps *= int(m_pTimeScale->sampleRate()); break; } case qtractorTimeScale::Frames: default: break; } } iValue += iSteps; if (iValue < 0) iValue = 0; setValue(iValue); pLineEdit->setCursorPosition(iCursorPos); } QAbstractSpinBox::StepEnabled qtractorTimeSpinBox::stepEnabled (void) const { StepEnabled flags = StepUpEnabled; if (value() > 0) flags |= StepDownEnabled; return flags; } // Value/text format converters. unsigned long qtractorTimeSpinBox::valueFromText (void) const { return valueFromText(QAbstractSpinBox::text()); } unsigned long qtractorTimeSpinBox::valueFromText ( const QString& sText ) const { if (m_pTimeScale == NULL) return sText.toULong(); return m_pTimeScale->frameFromTextEx( m_displayFormat, sText, m_bDeltaValue, m_iDeltaValue); } QString qtractorTimeSpinBox::textFromValue ( unsigned long iValue ) const { if (m_pTimeScale == NULL) return QString::number(iValue); if (m_bDeltaValue) { return m_pTimeScale->textFromFrameEx( m_displayFormat, m_iDeltaValue, true, iValue); } else { return m_pTimeScale->textFromFrameEx( m_displayFormat, iValue); } } // Local context menu handler. void qtractorTimeSpinBox::contextMenuEvent ( QContextMenuEvent *pContextMenuEvent ) { // QAbstractSpinBox::contextMenuEvent(pContextMenuEvent); if (m_pTimeScale == NULL) return; QMenu menu(this); QAction *pAction; pAction = menu.addAction(tr("&Frames")); pAction->setCheckable(true); pAction->setChecked(m_displayFormat == qtractorTimeScale::Frames); pAction->setData(int(qtractorTimeScale::Frames)); pAction = menu.addAction(tr("&Time")); pAction->setCheckable(true); pAction->setChecked(m_displayFormat == qtractorTimeScale::Time); pAction->setData(int(qtractorTimeScale::Time)); pAction = menu.addAction(tr("&BBT")); pAction->setCheckable(true); pAction->setChecked(m_displayFormat == qtractorTimeScale::BBT); pAction->setData(int(qtractorTimeScale::BBT)); pAction = menu.exec(pContextMenuEvent->globalPos()); if (pAction == NULL) return; const qtractorTimeScale::DisplayFormat displayFormat = qtractorTimeScale::DisplayFormat(pAction->data().toInt()); if (displayFormat != m_displayFormat) { setDisplayFormat(displayFormat); emit displayFormatChanged(int(displayFormat)); } } // Pseudo-fixup slot. void qtractorTimeSpinBox::editingFinishedSlot (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorTimeSpinBox[%p]::editingFinishedSlot()", this); #endif // Kind of final fixup. setValue(valueFromText()); } // Textual value change notification. void qtractorTimeSpinBox::valueChangedSlot ( const QString& sText ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorTimeSpinBox[%p]::valueChangedSlot(\"%s\")", this, sText.toUtf8().constData()); #endif // Forward this... emit valueChanged(sText); } //---------------------------------------------------------------------------- // qtractorTempoSpinBox -- A time-scale formatted spin-box widget. // Constructor. qtractorTempoSpinBox::qtractorTempoSpinBox ( QWidget *pParent ) : QAbstractSpinBox(pParent), m_fTempo(120.0f), m_iBeatsPerBar(4), m_iBeatDivisor(2), m_iValueChanged(0) { QAbstractSpinBox::setAccelerated(true); QObject::connect(this, SIGNAL(editingFinished()), SLOT(editingFinishedSlot())); QObject::connect(QAbstractSpinBox::lineEdit(), SIGNAL(textChanged(const QString&)), SLOT(valueChangedSlot(const QString&))); } // Destructor. qtractorTempoSpinBox::~qtractorTempoSpinBox (void) { } // Mark that we got actual value. void qtractorTempoSpinBox::showEvent ( QShowEvent */*pShowEvent*/ ) { QLineEdit *pLineEdit = QAbstractSpinBox::lineEdit(); bool bBlockSignals = pLineEdit->blockSignals(true); pLineEdit->setText(textFromValue(m_fTempo, m_iBeatsPerBar, m_iBeatDivisor)); pLineEdit->blockSignals(bBlockSignals); // QAbstractSpinBox::interpretText(); } // Nominal tempo value (BPM) accessors. void qtractorTempoSpinBox::setTempo ( float fTempo, bool bNotifyChange ) { if (updateValue(fTempo, m_iBeatsPerBar, m_iBeatDivisor, bNotifyChange)) updateText(); } float qtractorTempoSpinBox::tempo (void) const { return m_fTempo; } // Nominal time-signature numerator (beats/bar) accessors. void qtractorTempoSpinBox::setBeatsPerBar ( unsigned short iBeatsPerBar, bool bNotifyChange ) { if (updateValue(m_fTempo, iBeatsPerBar, m_iBeatDivisor, bNotifyChange)) updateText(); } unsigned short qtractorTempoSpinBox::beatsPerBar (void) const { return m_iBeatsPerBar; } // Nominal time-signature denominator (beat-divisor) accessors. void qtractorTempoSpinBox::setBeatDivisor ( unsigned short iBeatDivisor, bool bNotifyChange ) { if (updateValue(m_fTempo, m_iBeatsPerBar, iBeatDivisor, bNotifyChange)) updateText(); } unsigned short qtractorTempoSpinBox::beatDivisor (void) const { return m_iBeatDivisor; } // Common value setler. bool qtractorTempoSpinBox::updateValue ( float fTempo, unsigned short iBeatsPerBar, unsigned short iBeatDivisor, bool bNotifyChange ) { if (fTempo < 1.0f) fTempo = 1.0f; if (fTempo > 1000.0f) fTempo = 1000.0f; if (iBeatsPerBar < 2) iBeatsPerBar = 2; if (iBeatsPerBar > 128) iBeatsPerBar = 128; if (iBeatDivisor < 1) iBeatDivisor = 1; if (iBeatDivisor > 8) iBeatDivisor = 8; if (::fabs(m_fTempo - fTempo) > 0.05f) { m_fTempo = fTempo; ++m_iValueChanged; } if (m_iBeatsPerBar != iBeatsPerBar) { m_iBeatsPerBar = iBeatsPerBar; ++m_iValueChanged; } if (m_iBeatDivisor != iBeatDivisor) { m_iBeatDivisor = iBeatDivisor; ++m_iValueChanged; } int iValueChanged = m_iValueChanged; if (bNotifyChange && m_iValueChanged > 0) { emit valueChanged(m_fTempo, m_iBeatsPerBar, m_iBeatDivisor); m_iValueChanged = 0; } return (iValueChanged > 0); } void qtractorTempoSpinBox::updateText (void) { if (QAbstractSpinBox::isVisible()) { QLineEdit *pLineEdit = QAbstractSpinBox::lineEdit(); bool bBlockSignals = pLineEdit->blockSignals(true); int iCursorPos = pLineEdit->cursorPosition(); pLineEdit->setText(textFromValue( m_fTempo, m_iBeatsPerBar, m_iBeatDivisor)); // QAbstractSpinBox::interpretText(); pLineEdit->setCursorPosition(iCursorPos); pLineEdit->blockSignals(bBlockSignals); } } // Inherited/override methods. QValidator::State qtractorTempoSpinBox::validate ( QString& sText, int& iPos ) const { #ifdef CONFIG_DEBUG_0 qDebug("qtractorTempoSpinBox[%p]::validate(\"%s\",%d)", this, sText.toUtf8().constData(), iPos); #endif if (iPos == 0) return QValidator::Acceptable; const QChar& ch = sText[iPos - 1]; const QChar& decp = QLocale().decimalPoint(); if (ch == decp || ch == '/' || ch == ' ' || ch.isDigit()) return QValidator::Acceptable; else return QValidator::Invalid; } void qtractorTempoSpinBox::fixup ( QString& sText ) const { #ifdef CONFIG_DEBUG_0 qDebug("qtractorTempoSpinBox[%p]::fixup(\"%s\")", this, sText.toUtf8().constData()); #endif sText = textFromValue(m_fTempo, m_iBeatsPerBar, m_iBeatDivisor); } void qtractorTempoSpinBox::stepBy ( int iSteps ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorTempoSpinBox[%p]::stepBy(%d)", this, iSteps); #endif QLineEdit *pLineEdit = QAbstractSpinBox::lineEdit(); int iCursorPos = pLineEdit->cursorPosition(); const QString& sText = pLineEdit->text(); if (iCursorPos < sText.section(' ', 0, 0).length() + 1) { const QChar& decp = QLocale().decimalPoint(); if (iCursorPos > sText.section(decp, 0, 0).length()) setTempo(tempo() + 0.1f * float(iSteps)); else setTempo(tempo() + float(iSteps)); } else if (iCursorPos > sText.section('/', 0, 0).length()) setBeatDivisor(int(beatDivisor()) + iSteps); else setBeatsPerBar(int(beatsPerBar()) + iSteps); } QAbstractSpinBox::StepEnabled qtractorTempoSpinBox::stepEnabled (void) const { StepEnabled flags = StepNone; float fTempo = tempo(); unsigned short iBeatsPerBar = beatsPerBar(); unsigned short iBeatDivisor = beatDivisor(); if (fTempo > 1.0f && iBeatsPerBar > 2 && iBeatDivisor > 1) flags |= StepDownEnabled; if (fTempo < 1000.0f && iBeatsPerBar < 128 && iBeatDivisor < 8) flags |= StepUpEnabled; return flags; } // Value/text format converters. float qtractorTempoSpinBox::tempoFromText ( const QString& sText ) const { float fTempo = sText.section(' ', 0, 0).toFloat(); return (fTempo >= 1.0f ? fTempo : m_fTempo); } unsigned short qtractorTempoSpinBox::beatsPerBarFromText ( const QString& sText) const { unsigned short iBeatsPerBar = sText.section(' ', 1, 1).section('/', 0, 0).toUShort(); return (iBeatsPerBar >= 2 ? iBeatsPerBar : m_iBeatsPerBar); } unsigned short qtractorTempoSpinBox::beatDivisorFromText ( const QString& sText) const { unsigned short iBeatDivisor = 0; unsigned short i = sText.section(' ', 1, 1).section('/', 1, 1).toUShort(); while (i > 1) { ++iBeatDivisor; i >>= 1; } return (iBeatDivisor >= 1 ? iBeatDivisor : m_iBeatDivisor); } QString qtractorTempoSpinBox::textFromValue ( float fTempo, unsigned short iBeatsPerBar, unsigned short iBeatDivisor) const { return QString("%1 %2/%3") .arg(fTempo, 0, 'f', 1) .arg(iBeatsPerBar) .arg(1 << iBeatDivisor); } // Textual value change notification. void qtractorTempoSpinBox::valueChangedSlot ( const QString& sText ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorTempoSpinBox[%p]::valueChangedSlot(\"%s\")", this, sText.toUtf8().constData()); #endif // Kind of interim fixup. if (updateValue(tempoFromText(sText), beatsPerBarFromText(sText), beatDivisorFromText(sText), false)) { // Just forward this one... emit valueChanged(sText); } } // Final pseudo-fixup slot. void qtractorTempoSpinBox::editingFinishedSlot (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorTempoSpinBox[%p]::editingFinishedSlot()", this); #endif const QString& sText = QAbstractSpinBox::text(); // Kind of final fixup. if (updateValue(tempoFromText(sText), beatsPerBarFromText(sText), beatDivisorFromText(sText), true)) { // Rephrase text display... updateText(); } } // end of qtractorTimeSpinBox.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiSequence.cpp0000644000175000001440000000012312141244677022112 xustar000000000000000027 mtime=1367689663.484158 26 atime=1381134667.92608 30 ctime=1381134667.926080064 qtractor-0.5.11/src/qtractorMidiSequence.cpp0000644000175000001440000001454212141244677021407 0ustar00rncbcusers00000000000000// qtractorMidiSequence.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorMidiSequence.h" //---------------------------------------------------------------------- // class qtractorMidiSequence -- The generic MIDI event sequence buffer. // // Constructor. qtractorMidiSequence::qtractorMidiSequence ( const QString& sName, unsigned short iChannel, unsigned short iTicksPerBeat ) { m_sName = sName; m_iChannel = iChannel; m_iTicksPerBeat = iTicksPerBeat; m_iTimeOffset = 0; m_iTimeLength = 0; m_events.setAutoDelete(true); m_noteMax = 0; m_noteMin = 0; clear(); } // Destructor. qtractorMidiSequence::~qtractorMidiSequence (void) { clear(); } // Sequencer reset method. void qtractorMidiSequence::clear (void) { m_iBank = -1; m_iProg = -1; // m_noteMax = 0; // m_noteMin = 0; m_duration = 0; m_events.clear(); m_notes.clear(); } // Add event to a channel sequence, in time sort order. void qtractorMidiSequence::addEvent ( qtractorMidiEvent *pEvent ) { // Adjust to sequence offset... pEvent->adjustTime(m_iTimeOffset); // NOTE: Find previous note event and compute duration... if (pEvent->type() == qtractorMidiEvent::NOTEOFF) { unsigned char note = pEvent->note(); NoteMap::Iterator iter = m_notes.find(note); const NoteMap::Iterator& iter_end = m_notes.end(); NoteMap::Iterator iter_last; qtractorMidiEvent *pNoteEvent = NULL; for ( ; iter != iter_end && iter.key() == note; ++iter) { pNoteEvent = iter.value(); iter_last = iter; } if (pNoteEvent) { unsigned long iTime = pNoteEvent->time(); unsigned long iDuration = pEvent->time() - iTime; pNoteEvent->setDuration(iDuration); iDuration += iTime; if (m_duration < iDuration) m_duration = iDuration; m_notes.erase(iter_last); } // NOTEOFF: Won't own this any longer... delete pEvent; return; } else if (pEvent->type() == qtractorMidiEvent::NOTEON) { // NOTEON: Just add to lingering notes... m_notes.insert(pEvent->note(), pEvent); } else if (pEvent->type() == qtractorMidiEvent::SYSEX) { // SYSEX: add enough slack... unsigned long iTime = pEvent->time() + (m_iTicksPerBeat >> 3); if (m_duration < iTime) m_duration = iTime; } // Add it... insertEvent(pEvent); } // Insert event in correct time sort order. void qtractorMidiSequence::insertEvent ( qtractorMidiEvent *pEvent ) { // Find the proper position in time sequence... qtractorMidiEvent *pEventAfter = m_events.last(); while (pEventAfter && pEventAfter->time() > pEvent->time()) pEventAfter = pEventAfter->prev(); // Insert it... if (pEventAfter) m_events.insertAfter(pEvent, pEventAfter); else m_events.prepend(pEvent); unsigned long iTime = pEvent->time(); // NOTEON: Keep note stats and make it pending on a NOTEOFF... if (pEvent->type() == qtractorMidiEvent::NOTEON) { unsigned char note = pEvent->note(); if (m_noteMin > note || m_noteMin == 0) m_noteMin = note; if (m_noteMax < note || m_noteMax == 0) m_noteMax = note; iTime += pEvent->duration(); } if (m_duration < iTime) m_duration = iTime; } // Unlink event from a channel sequence. void qtractorMidiSequence::unlinkEvent ( qtractorMidiEvent *pEvent ) { m_events.unlink(pEvent); } // Remove event from a channel sequence. void qtractorMidiSequence::removeEvent ( qtractorMidiEvent *pEvent ) { m_events.remove(pEvent); } // Sequence closure method. void qtractorMidiSequence::close (void) { // Commit sequence length... if (m_duration < m_iTimeLength) m_duration = m_iTimeLength; else if (m_iTimeLength == 0) m_iTimeLength = m_duration; // Finish all pending notes... NoteMap::ConstIterator iter = m_notes.constBegin(); const NoteMap::ConstIterator& iter_end = m_notes.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorMidiEvent *pEvent = *iter; pEvent->setDuration(m_duration - pEvent->time()); } // Reset all pending notes. m_notes.clear(); } // Replace events from another sequence in given range. void qtractorMidiSequence::replaceEvents ( qtractorMidiSequence *pSeq, unsigned long iTimeOffset, unsigned long iTimeLength ) { // Sanitize range as default... if (iTimeOffset < 1 && iTimeLength < 1) { iTimeOffset = pSeq->timeOffset(); iTimeLength = pSeq->timeLength(); } // Set the given replacement range... unsigned short iTicksPerBeat = pSeq->ticksPerBeat(); unsigned long iTimeStart = timeq(iTimeOffset, iTicksPerBeat); unsigned long iTimeEnd = timeq(iTimeOffset + iTimeLength, iTicksPerBeat); // Remove existing events in the given range... qtractorMidiEvent *pEvent = m_events.first(); while (pEvent) { qtractorMidiEvent *pNextEvent = pEvent->next(); if (pEvent->time() >= iTimeStart && pEvent->time() < iTimeEnd) removeEvent(pEvent); pEvent = pNextEvent; } // Insert new (cloned and adjusted) ones... for (pEvent = pSeq->events().first(); pEvent; pEvent = pEvent->next()) { qtractorMidiEvent *pNewEvent = new qtractorMidiEvent(*pEvent); pNewEvent->setTime(timeq(iTimeOffset + pEvent->time(), iTicksPerBeat)); if (pEvent->type() == qtractorMidiEvent::NOTEON) { pNewEvent->setDuration(timeq(pEvent->duration(), iTicksPerBeat)); } insertEvent(pNewEvent); } // Done. } // Clopy all events from another sequence (raw-copy). void qtractorMidiSequence::copyEvents ( qtractorMidiSequence *pSeq ) { // Remove existing events. m_events.clear(); // Clone new ones... qtractorMidiEvent *pEvent = pSeq->events().first(); for (; pEvent; pEvent = pEvent->next()) m_events.append(new qtractorMidiEvent(*pEvent)); // Done. } // end of qtractorMidiSequence.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorLadspaPlugin.cpp0000644000175000001440000000012312073012112022077 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134666.35608 30 ctime=1381134666.356080039 qtractor-0.5.11/src/qtractorLadspaPlugin.cpp0000644000175000001440000003457312073012112021402 0ustar00rncbcusers00000000000000// qtractorLadspaPlugin.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #ifdef CONFIG_LADSPA #include "qtractorLadspaPlugin.h" #include //---------------------------------------------------------------------------- // qtractorLadspaPluginType -- LADSPA plugin type instance. // // Derived methods. bool qtractorLadspaPluginType::open (void) { // Do we have a descriptor already? if (m_pLadspaDescriptor == NULL) m_pLadspaDescriptor = ladspa_descriptor(file(), index()); if (m_pLadspaDescriptor == NULL) return false; #ifdef CONFIG_DEBUG qDebug("qtractorLadspaPluginType[%p]::open() filename=\"%s\" index=%lu", this, filename().toUtf8().constData(), index()); #endif // Retrieve plugin type names. m_sName = m_pLadspaDescriptor->Name; m_sLabel = m_pLadspaDescriptor->Label; // Retrieve plugin unique identifier. m_iUniqueID = m_pLadspaDescriptor->UniqueID; // Compute and cache port counts... m_iControlIns = 0; m_iControlOuts = 0; m_iAudioIns = 0; m_iAudioOuts = 0; m_iMidiIns = 0; m_iMidiOuts = 0; for (unsigned long i = 0; i < m_pLadspaDescriptor->PortCount; ++i) { const LADSPA_PortDescriptor portType = m_pLadspaDescriptor->PortDescriptors[i]; if (LADSPA_IS_PORT_INPUT(portType)) { if (LADSPA_IS_PORT_AUDIO(portType)) ++m_iAudioIns; else if (LADSPA_IS_PORT_CONTROL(portType)) ++m_iControlIns; } else if (LADSPA_IS_PORT_OUTPUT(portType)) { if (LADSPA_IS_PORT_AUDIO(portType)) ++m_iAudioOuts; else if (LADSPA_IS_PORT_CONTROL(portType)) ++m_iControlOuts; } } // Cache flags. m_bRealtime = LADSPA_IS_HARD_RT_CAPABLE(m_pLadspaDescriptor->Properties); // Done. return true; } void qtractorLadspaPluginType::close (void) { m_pLadspaDescriptor = NULL; } // Factory method (static) qtractorLadspaPluginType *qtractorLadspaPluginType::createType ( qtractorPluginFile *pFile, unsigned long iIndex ) { // Sanity check... if (pFile == NULL) return NULL; // Retrieve descriptor if any... const LADSPA_Descriptor *pLadspaDescriptor = ladspa_descriptor(pFile, iIndex); if (pLadspaDescriptor == NULL) return NULL; // Yep, most probably its a valid plugin descriptor... return new qtractorLadspaPluginType(pFile, iIndex, qtractorPluginType::Ladspa, pLadspaDescriptor); } // Descriptor method (static) const LADSPA_Descriptor *qtractorLadspaPluginType::ladspa_descriptor ( qtractorPluginFile *pFile, unsigned long iIndex ) { // Retrieve the descriptor function, if any... LADSPA_Descriptor_Function pfnLadspaDescriptor = (LADSPA_Descriptor_Function) pFile->resolve("ladspa_descriptor"); if (pfnLadspaDescriptor == NULL) return NULL; // Retrieve descriptor if any... return (*pfnLadspaDescriptor)(iIndex); } //---------------------------------------------------------------------------- // qtractorLadspaPlugin -- LADSPA plugin instance. // // Constructors. qtractorLadspaPlugin::qtractorLadspaPlugin ( qtractorPluginList *pList, qtractorLadspaPluginType *pLadspaType ) : qtractorPlugin(pList, pLadspaType), m_phInstances(NULL), m_piControlOuts(NULL), m_pfControlOuts(NULL), m_piAudioIns(NULL), m_piAudioOuts(NULL) { #ifdef CONFIG_DEBUG qDebug("qtractorLadspaPlugin[%p] filename=\"%s\" index=%lu typeHint=%d", this, type()->filename().toUtf8().constData(), type()->index(), int(type()->typeHint())); #endif // Get some structural data first... const LADSPA_Descriptor *pLadspaDescriptor = pLadspaType->ladspa_descriptor(); if (pLadspaDescriptor) { unsigned short iControlOuts = pLadspaType->controlOuts(); unsigned short iAudioIns = pLadspaType->audioIns(); unsigned short iAudioOuts = pLadspaType->audioOuts(); if (iAudioIns > 0) m_piAudioIns = new unsigned long [iAudioIns]; if (iAudioOuts > 0) m_piAudioOuts = new unsigned long [iAudioOuts]; if (iControlOuts > 0) { m_piControlOuts = new unsigned long [iControlOuts]; m_pfControlOuts = new float [iControlOuts]; } iControlOuts = iAudioIns = iAudioOuts = 0; for (unsigned long i = 0; i < pLadspaDescriptor->PortCount; ++i) { const LADSPA_PortDescriptor portType = pLadspaDescriptor->PortDescriptors[i]; if (LADSPA_IS_PORT_INPUT(portType)) { if (LADSPA_IS_PORT_AUDIO(portType)) m_piAudioIns[iAudioIns++] = i; else if (LADSPA_IS_PORT_CONTROL(portType)) addParam(new qtractorLadspaPluginParam(this, i)); } else if (LADSPA_IS_PORT_OUTPUT(portType)) { if (LADSPA_IS_PORT_AUDIO(portType)) m_piAudioOuts[iAudioOuts++] = i; else if (LADSPA_IS_PORT_CONTROL(portType)) { m_piControlOuts[iControlOuts] = i; m_pfControlOuts[iControlOuts] = 0.0f; ++iControlOuts; } } } // FIXME: instantiate each instance properly... qtractorLadspaPlugin::setChannels(channels()); } } // Destructor. qtractorLadspaPlugin::~qtractorLadspaPlugin (void) { // Cleanup all plugin instances... setChannels(0); // Free up all the rest... if (m_piAudioOuts) delete [] m_piAudioOuts; if (m_piAudioIns) delete [] m_piAudioIns; if (m_piControlOuts) delete [] m_piControlOuts; if (m_pfControlOuts) delete [] m_pfControlOuts; } // Channel/instance number accessors. void qtractorLadspaPlugin::setChannels ( unsigned short iChannels ) { // Check our type... qtractorPluginType *pType = type(); if (pType == NULL) return; // Estimate the (new) number of instances... unsigned short iOldInstances = instances(); unsigned short iInstances = pType->instances(iChannels, list()->isMidi()); // Now see if instance count changed anyhow... if (iInstances == iOldInstances) return; const LADSPA_Descriptor *pLadspaDescriptor = ladspa_descriptor(); if (pLadspaDescriptor == NULL) return; // Gotta go for a while... bool bActivated = isActivated(); setActivated(false); // Set new instance number... setInstances(iInstances); if (m_phInstances) { if (pLadspaDescriptor->cleanup) { for (unsigned short i = 0; i < iOldInstances; ++i) (*pLadspaDescriptor->cleanup)(m_phInstances[i]); } delete [] m_phInstances; m_phInstances = NULL; } // Bail out, if none are about to be created... if (iInstances < 1) { setActivated(bActivated); return; } #ifdef CONFIG_DEBUG qDebug("qtractorLadspaPlugin[%p]::setChannels(%u) instances=%u", this, iChannels, iInstances); #endif // We'll need output control (not dummy anymore) port indexes... unsigned short iControlOuts = pType->controlOuts(); // Allocate new instances... m_phInstances = new LADSPA_Handle [iInstances]; for (unsigned short i = 0; i < iInstances; ++i) { // Instantiate them properly first... LADSPA_Handle handle = (*pLadspaDescriptor->instantiate)(pLadspaDescriptor, sampleRate()); // Connect all existing input control ports... const qtractorPlugin::Params& params = qtractorPlugin::params(); qtractorPlugin::Params::ConstIterator param = params.constBegin(); const qtractorPlugin::Params::ConstIterator& param_end = params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); // Just in case the plugin decides // to set the port value at this time... float *pfValue = pParam->subject()->data(); float fValue = *pfValue; (*pLadspaDescriptor->connect_port)(handle, pParam->index(), pfValue); // Make new one the default and restore port value... pParam->setDefaultValue(*pfValue); *pfValue = fValue; } // Connect all existing output control ports... for (unsigned short j = 0; j < iControlOuts; ++j) { (*pLadspaDescriptor->connect_port)(handle, m_piControlOuts[j], &m_pfControlOuts[j]); } // This is it... m_phInstances[i] = handle; } // (Re)issue all configuration as needed... realizeConfigs(); realizeValues(); // But won't need it anymore. releaseConfigs(); releaseValues(); // (Re)activate instance if necessary... setActivated(bActivated); } // Specific accessors. const LADSPA_Descriptor *qtractorLadspaPlugin::ladspa_descriptor (void) const { qtractorLadspaPluginType *pLadspaType = static_cast (type()); return (pLadspaType ? pLadspaType->ladspa_descriptor() : NULL); } LADSPA_Handle qtractorLadspaPlugin::ladspa_handle ( unsigned short iInstance ) const { return (m_phInstances ? m_phInstances[iInstance] : NULL); } // Do the actual activation. void qtractorLadspaPlugin::activate (void) { const LADSPA_Descriptor *pLadspaDescriptor = ladspa_descriptor(); if (pLadspaDescriptor == NULL) return; if (m_phInstances && pLadspaDescriptor->activate) { for (unsigned short i = 0; i < instances(); ++i) (*pLadspaDescriptor->activate)(m_phInstances[i]); } } // Do the actual deactivation. void qtractorLadspaPlugin::deactivate (void) { const LADSPA_Descriptor *pLadspaDescriptor = ladspa_descriptor(); if (pLadspaDescriptor == NULL) return; if (m_phInstances && pLadspaDescriptor->deactivate) { for (unsigned short i = 0; i < instances(); ++i) (*pLadspaDescriptor->deactivate)(m_phInstances[i]); } } // The main plugin processing procedure. void qtractorLadspaPlugin::process ( float **ppIBuffer, float **ppOBuffer, unsigned int nframes ) { if (m_phInstances == NULL) return; const LADSPA_Descriptor *pLadspaDescriptor = ladspa_descriptor(); if (pLadspaDescriptor == NULL) return; // We'll cross channels over instances... const unsigned short iInstances = instances(); const unsigned short iChannels = channels(); const unsigned short iAudioIns = audioIns(); const unsigned short iAudioOuts = audioOuts(); unsigned short iIChannel = 0; unsigned short iOChannel = 0; unsigned short i, j; // For each plugin instance... for (i = 0; i < iInstances; ++i) { LADSPA_Handle handle = m_phInstances[i]; // For each instance audio input port... for (j = 0; j < iAudioIns; ++j) { (*pLadspaDescriptor->connect_port)(handle, m_piAudioIns[j], ppIBuffer[iIChannel]); if (++iIChannel >= iChannels) iIChannel = 0; } // For each instance audio output port... for (j = 0; j < iAudioOuts; ++j) { (*pLadspaDescriptor->connect_port)(handle, m_piAudioOuts[j], ppOBuffer[iOChannel]); if (++iOChannel >= iChannels) iOChannel = 0; } // Make it run... (*pLadspaDescriptor->run)(handle, nframes); // Wrap channels?... if (iIChannel < iChannels - 1) ++iIChannel; if (iOChannel < iChannels - 1) ++iOChannel; } } //---------------------------------------------------------------------------- // qtractorLadspaPluginParam -- LADSPA plugin control input port instance. // // Constructors. qtractorLadspaPluginParam::qtractorLadspaPluginParam ( qtractorLadspaPlugin *pLadspaPlugin, unsigned long iIndex ) : qtractorPluginParam(pLadspaPlugin, iIndex) { const LADSPA_Descriptor *pLadspaDescriptor = pLadspaPlugin->ladspa_descriptor(); const LADSPA_PortRangeHint *pPortRangeHint = &(pLadspaDescriptor->PortRangeHints[iIndex]); m_portHints = pPortRangeHint->HintDescriptor; // Set nominal parameter name... setName(pLadspaDescriptor->PortNames[iIndex]); // Initialize range values... float fMinValue = 0.0f; if (isBoundedBelow()) { fMinValue = pPortRangeHint->LowerBound; if (isSampleRate()) fMinValue *= float(pLadspaPlugin->sampleRate()); } setMinValue(fMinValue); float fMaxValue = 1.0f; if (isBoundedAbove()) { fMaxValue = pPortRangeHint->UpperBound; if (isSampleRate()) fMaxValue *= float(pLadspaPlugin->sampleRate()); } setMaxValue(fMaxValue); // Port default value... float fDefaultValue = value(); if (isDefaultValue()) { switch (m_portHints & LADSPA_HINT_DEFAULT_MASK) { case LADSPA_HINT_DEFAULT_MINIMUM: fDefaultValue = fMinValue; break; case LADSPA_HINT_DEFAULT_LOW: if (isLogarithmic()) { fDefaultValue = ::expf( ::logf(fMinValue) * 0.75f + ::logf(fMaxValue) * 0.25f); } else { fDefaultValue = (fMinValue * 0.75f + fMaxValue * 0.25f); } break; case LADSPA_HINT_DEFAULT_MIDDLE: if (isLogarithmic()) { fDefaultValue = ::sqrt(fMinValue * fMaxValue); } else { fDefaultValue = (fMinValue + fMaxValue) * 0.5f; } break; case LADSPA_HINT_DEFAULT_HIGH: if (isLogarithmic()) { fDefaultValue = ::expf( ::logf(fMinValue) * 0.25f + ::logf(fMaxValue) * 0.75f); } else { fDefaultValue = (fMinValue * 0.25f + fMaxValue * 0.75f); } break; case LADSPA_HINT_DEFAULT_MAXIMUM: fDefaultValue = fMaxValue; break; case LADSPA_HINT_DEFAULT_0: fDefaultValue = 0.0f; break; case LADSPA_HINT_DEFAULT_1: fDefaultValue = 1.0f; break; case LADSPA_HINT_DEFAULT_100: fDefaultValue = 100.0f; break; case LADSPA_HINT_DEFAULT_440: fDefaultValue = 440.0f; break; } } setDefaultValue(fDefaultValue); // Initialize port value... reset(); } // Destructor. qtractorLadspaPluginParam::~qtractorLadspaPluginParam (void) { } // Port range hints predicate methods. bool qtractorLadspaPluginParam::isBoundedBelow (void) const { return LADSPA_IS_HINT_BOUNDED_BELOW(m_portHints); } bool qtractorLadspaPluginParam::isBoundedAbove (void) const { return LADSPA_IS_HINT_BOUNDED_ABOVE(m_portHints); } bool qtractorLadspaPluginParam::isDefaultValue (void) const { return LADSPA_IS_HINT_HAS_DEFAULT(m_portHints); } bool qtractorLadspaPluginParam::isLogarithmic (void) const { return LADSPA_IS_HINT_LOGARITHMIC(m_portHints); } bool qtractorLadspaPluginParam::isSampleRate (void) const { return LADSPA_IS_HINT_SAMPLE_RATE(m_portHints); } bool qtractorLadspaPluginParam::isInteger (void) const { return LADSPA_IS_HINT_INTEGER(m_portHints); } bool qtractorLadspaPluginParam::isToggled (void) const { return LADSPA_IS_HINT_TOGGLED(m_portHints); } bool qtractorLadspaPluginParam::isDisplay (void) const { return false; } #endif // CONFIG_LADSPA // end of qtractorLadspaPlugin.cpp qtractor-0.5.11/src/PaxHeaders.10084/src.pro0000644000175000001440000000012312213640715016555 xustar000000000000000027 mtime=1378828749.720565 26 atime=1381134668.12208 30 ctime=1381134668.123080067 qtractor-0.5.11/src/src.pro0000644000175000001440000002020512213640715016043 0ustar00rncbcusers00000000000000# qtractor.pro # NAME = qtractor TARGET = $${NAME} TEMPLATE = app include(src.pri) #DEFINES += DEBUG HEADERS += config.h \ qtractorAbout.h \ qtractorAtomic.h \ qtractorAudioBuffer.h \ qtractorAudioClip.h \ qtractorAudioConnect.h \ qtractorAudioEngine.h \ qtractorAudioFile.h \ qtractorAudioListView.h \ qtractorAudioMadFile.h \ qtractorAudioMeter.h \ qtractorAudioMonitor.h \ qtractorAudioPeak.h \ qtractorAudioSndFile.h \ qtractorAudioVorbisFile.h \ qtractorClip.h \ qtractorClipCommand.h \ qtractorClipFadeFunctor.h \ qtractorClipSelect.h \ qtractorCommand.h \ qtractorConnect.h \ qtractorConnections.h \ qtractorCtlEvent.h \ qtractorCurve.h \ qtractorCurveCommand.h \ qtractorCurveFile.h \ qtractorCurveSelect.h \ qtractorDocument.h \ qtractorDssiPlugin.h \ qtractorEngine.h \ qtractorEngineCommand.h \ qtractorFifoBuffer.h \ qtractorFileList.h \ qtractorFileListView.h \ qtractorFiles.h \ qtractorInsertPlugin.h \ qtractorInstrument.h \ qtractorLadspaPlugin.h \ qtractorList.h \ qtractorLv2Plugin.h \ qtractorMessages.h \ qtractorMeter.h \ qtractorMidiBuffer.h \ qtractorMidiClip.h \ qtractorMidiConnect.h \ qtractorMidiControl.h \ qtractorMidiControlCommand.h \ qtractorMidiControlObserver.h \ qtractorMidiCursor.h \ qtractorMidiEditor.h \ qtractorMidiEditCommand.h \ qtractorMidiEditEvent.h \ qtractorMidiEditList.h \ qtractorMidiEditSelect.h \ qtractorMidiEditTime.h \ qtractorMidiEditView.h \ qtractorMidiEngine.h \ qtractorMidiEvent.h \ qtractorMidiEventList.h \ qtractorMidiFile.h \ qtractorMidiFileTempo.h \ qtractorMidiListView.h \ qtractorMidiMeter.h \ qtractorMidiMonitor.h \ qtractorMidiSequence.h \ qtractorMidiSysex.h \ qtractorMidiTimer.h \ qtractorMixer.h \ qtractorMmcEvent.h \ qtractorMonitor.h \ qtractorNsmClient.h \ qtractorObserver.h \ qtractorObserverWidget.h \ qtractorOptions.h \ qtractorPlugin.h \ qtractorPluginCommand.h \ qtractorPluginListView.h \ qtractorPropertyCommand.h \ qtractorRingBuffer.h \ qtractorRubberBand.h \ qtractorScrollView.h \ qtractorSession.h \ qtractorSessionCommand.h \ qtractorSessionCursor.h \ qtractorSessionDocument.h \ qtractorSpinBox.h \ qtractorThumbView.h \ qtractorTimeScale.h \ qtractorTimeScaleCommand.h \ qtractorTimeStretch.h \ qtractorTimeStretcher.h \ qtractorTrack.h \ qtractorTrackButton.h \ qtractorTrackCommand.h \ qtractorTrackList.h \ qtractorTrackTime.h \ qtractorTrackView.h \ qtractorTracks.h \ qtractorVstPlugin.h \ qtractorZipFile.h \ qtractorBusForm.h \ qtractorClipForm.h \ qtractorConnectForm.h \ qtractorEditRangeForm.h \ qtractorExportForm.h \ qtractorInstrumentForm.h \ qtractorMainForm.h \ qtractorMidiControlForm.h \ qtractorMidiControlObserverForm.h \ qtractorMidiEditorForm.h \ qtractorMidiSysexForm.h \ qtractorMidiToolsForm.h \ qtractorOptionsForm.h \ qtractorPasteRepeatForm.h \ qtractorPluginForm.h \ qtractorPluginSelectForm.h \ qtractorSessionForm.h \ qtractorShortcutForm.h \ qtractorTakeRangeForm.h \ qtractorTempoAdjustForm.h \ qtractorTimeScaleForm.h \ qtractorTrackForm.h SOURCES += \ qtractor.cpp \ qtractorAudioBuffer.cpp \ qtractorAudioClip.cpp \ qtractorAudioConnect.cpp \ qtractorAudioEngine.cpp \ qtractorAudioFile.cpp \ qtractorAudioListView.cpp \ qtractorAudioMadFile.cpp \ qtractorAudioMeter.cpp \ qtractorAudioMonitor.cpp \ qtractorAudioPeak.cpp \ qtractorAudioSndFile.cpp \ qtractorAudioVorbisFile.cpp \ qtractorClip.cpp \ qtractorClipCommand.cpp \ qtractorClipFadeFunctor.cpp \ qtractorClipSelect.cpp \ qtractorCommand.cpp \ qtractorConnect.cpp \ qtractorConnections.cpp \ qtractorDocument.cpp \ qtractorCurve.cpp \ qtractorCurveCommand.cpp \ qtractorCurveFile.cpp \ qtractorCurveSelect.cpp \ qtractorDssiPlugin.cpp \ qtractorEngine.cpp \ qtractorEngineCommand.cpp \ qtractorFileList.cpp \ qtractorFileListView.cpp \ qtractorFiles.cpp \ qtractorInsertPlugin.cpp \ qtractorInstrument.cpp \ qtractorLadspaPlugin.cpp \ qtractorLv2Plugin.cpp \ qtractorMessages.cpp \ qtractorMeter.cpp \ qtractorMidiBuffer.cpp \ qtractorMidiClip.cpp \ qtractorMidiConnect.cpp \ qtractorMidiControl.cpp \ qtractorMidiControlCommand.cpp \ qtractorMidiControlObserver.cpp \ qtractorMidiCursor.cpp \ qtractorMidiEditor.cpp \ qtractorMidiEditCommand.cpp \ qtractorMidiEditEvent.cpp \ qtractorMidiEditList.cpp \ qtractorMidiEditSelect.cpp \ qtractorMidiEditTime.cpp \ qtractorMidiEditView.cpp \ qtractorMidiEngine.cpp \ qtractorMidiEventList.cpp \ qtractorMidiFile.cpp \ qtractorMidiFileTempo.cpp \ qtractorMidiListView.cpp \ qtractorMidiMeter.cpp \ qtractorMidiMonitor.cpp \ qtractorMidiSequence.cpp \ qtractorMidiTimer.cpp \ qtractorMixer.cpp \ qtractorMmcEvent.cpp \ qtractorNsmClient.cpp \ qtractorObserver.cpp \ qtractorObserverWidget.cpp \ qtractorOptions.cpp \ qtractorPlugin.cpp \ qtractorPluginCommand.cpp \ qtractorPluginListView.cpp \ qtractorRubberBand.cpp \ qtractorScrollView.cpp \ qtractorSession.cpp \ qtractorSessionCommand.cpp \ qtractorSessionCursor.cpp \ qtractorSessionDocument.cpp \ qtractorSpinBox.cpp \ qtractorThumbView.cpp \ qtractorTimeScale.cpp \ qtractorTimeScaleCommand.cpp \ qtractorTimeStretch.cpp \ qtractorTimeStretcher.cpp \ qtractorTrack.cpp \ qtractorTrackButton.cpp \ qtractorTrackCommand.cpp \ qtractorTrackList.cpp \ qtractorTrackTime.cpp \ qtractorTrackView.cpp \ qtractorTracks.cpp \ qtractorVstPlugin.cpp \ qtractorZipFile.cpp \ qtractorBusForm.cpp \ qtractorClipForm.cpp \ qtractorConnectForm.cpp \ qtractorEditRangeForm.cpp \ qtractorExportForm.cpp \ qtractorInstrumentForm.cpp \ qtractorMainForm.cpp \ qtractorMidiControlForm.cpp \ qtractorMidiControlObserverForm.cpp \ qtractorMidiEditorForm.cpp \ qtractorMidiSysexForm.cpp \ qtractorMidiToolsForm.cpp \ qtractorOptionsForm.cpp \ qtractorPasteRepeatForm.cpp \ qtractorPluginForm.cpp \ qtractorPluginSelectForm.cpp \ qtractorSessionForm.cpp \ qtractorShortcutForm.cpp \ qtractorTakeRangeForm.cpp \ qtractorTempoAdjustForm.cpp \ qtractorTimeScaleForm.cpp \ qtractorTrackForm.cpp FORMS += \ qtractorBusForm.ui \ qtractorClipForm.ui \ qtractorConnectForm.ui \ qtractorEditRangeForm.ui \ qtractorExportForm.ui \ qtractorInstrumentForm.ui \ qtractorMainForm.ui \ qtractorMidiControlForm.ui \ qtractorMidiControlObserverForm.ui \ qtractorMidiEditorForm.ui \ qtractorMidiSysexForm.ui \ qtractorMidiToolsForm.ui \ qtractorOptionsForm.ui \ qtractorPasteRepeatForm.ui \ qtractorPluginForm.ui \ qtractorPluginSelectForm.ui \ qtractorSessionForm.ui \ qtractorShortcutForm.ui \ qtractorTakeRangeForm.ui \ qtractorTempoAdjustForm.ui \ qtractorTimeScaleForm.ui \ qtractorTrackForm.ui RESOURCES += \ qtractor.qrc TRANSLATIONS += \ translations/qtractor_cs.ts \ translations/qtractor_de.ts \ translations/qtractor_fr.ts \ translations/qtractor_it.ts \ translations/qtractor_ja.ts \ translations/qtractor_ru.ts unix { # variables OBJECTS_DIR = .obj MOC_DIR = .moc UI_DIR = .ui isEmpty(PREFIX) { PREFIX = /usr/local } BINDIR = $${PREFIX}/bin DATADIR = $${PREFIX}/share LOCALEDIR = $(localedir) DEFINES += DATADIR=\"$${DATADIR}\" !isEmpty(LOCALEDIR) { DEFINES += LOCALEDIR=\"$${LOCALEDIR}\" } # make install INSTALLS += target desktop icon \ icon_scalable mimeinfo mimetypes mimetypes_scalable target.path = $${BINDIR} desktop.path = $${DATADIR}/applications desktop.files += $${NAME}.desktop icon.path = $${DATADIR}/icons/hicolor/32x32/apps icon.files += images/$${NAME}.png icon_scalable.path = $${DATADIR}/icons/hicolor/scalable/apps icon_scalable.files += images/$${NAME}.svgz mimeinfo.path = $${DATADIR}/mime/packages mimeinfo.files += mimetypes/$${NAME}.xml mimetypes.path = $${DATADIR}/icons/hicolor/32x32/mimetypes mimetypes.files += \ mimetypes/application-x-$${NAME}-session.png \ mimetypes/application-x-$${NAME}-template.png \ mimetypes/application-x-$${NAME}-archive.png mimetypes_scalable.path = $${DATADIR}/icons/hicolor/scalable/mimetypes mimetypes_scalable.files += \ mimetypes/application-x-$${NAME}-session.svgz \ mimetypes/application-x-$${NAME}-template.svgz \ mimetypes/application-x-$${NAME}-archive.svgz } # XML/DOM support QT += xml # QT5 support !lessThan(QT_MAJOR_VERSION, 5) { QT += widgets } qtractor-0.5.11/src/PaxHeaders.10084/qtractorZipFile.h0000644000175000001440000000012312073012112020523 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134671.20108 30 ctime=1381134671.210080116 qtractor-0.5.11/src/qtractorZipFile.h0000644000175000001440000000502212073012112020011 0ustar00rncbcusers00000000000000// qtractorZipFile.h // /**************************************************************************** Copyright (C) 2010-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ /* Most of this code was originally borrowed, stirred, mangled * and finally adapted from the Qt 4.6 source code (LGPL). * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(ies). * All rights reserved. * Contact: Nokia Corporation (qt-info@nokia.com) */ #ifndef __qtractorZipFile_h #define __qtractorZipFile_h #include //---------------------------------------------------------------------------- // qtractorZipFile -- Custom ZIP file archive class. // class qtractorZipDevice; class qtractorZipFile { public: // Constructors. qtractorZipFile(const QString& sFilename, QIODevice::OpenMode mode = QIODevice::ReadOnly); explicit qtractorZipFile(QIODevice *pDdevice); // Destructor. ~qtractorZipFile(); enum Status { NoError = 0, FileOpenError, FileReadError, FileWriteError, FilePermissionsError, FileError }; Status status() const; bool isReadable() const; bool isWritable() const; bool exists() const; bool extractFile(const QString& sFilename); bool extractAll(); QString alias(const QString& sFilename, const QString& sPrefix = QString()) const; bool addFile(const QString& sFilename, const QString& sAlias = QString()); bool addDirectory(const QString& sDirectory); bool processAll(); void close(); unsigned int totalUncompressed() const; unsigned int totalCompressed() const; unsigned int totalProcessed() const; private: // Disable copy constructor. qtractorZipFile(const qtractorZipFile&); // Implementation device. qtractorZipDevice *m_pZip; }; #endif // __qtractorZipFile_h // end of qtractorZipFile.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorAbout.h0000644000175000001440000000012212070636464020255 xustar000000000000000026 mtime=1357069620.33615 26 atime=1381134671.08908 30 ctime=1381134671.089080114 qtractor-0.5.11/src/qtractorAbout.h0000644000175000001440000000270012070636464017544 0ustar00rncbcusers00000000000000// qtractorAbout.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorAbout_h #define __qtractorAbout_h #include "config.h" #define QTRACTOR_TITLE PACKAGE_NAME #define QTRACTOR_VERSION PACKAGE_VERSION #define QTRACTOR_SUBTITLE "An Audio/MIDI multi-track sequencer" #define QTRACTOR_WEBSITE "http://qtractor.sourceforge.net" #define QTRACTOR_COPYRIGHT "Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved." #define QTRACTOR_DOMAIN "rncbc.org" #endif // __qtractorAbout_h // end of qtractorAbout.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiControlObserverForm.cpp0000644000175000001440000000012212067456742024322 xustar000000000000000026 mtime=1356750306.99751 26 atime=1381134667.10708 30 ctime=1381134667.108080051 qtractor-0.5.11/src/qtractorMidiControlObserverForm.cpp0000644000175000001440000004720212067456742023617 0ustar00rncbcusers00000000000000// qtractorMidiControlObserverForm.cpp // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiControlObserverForm.h" #include "qtractorMidiControlObserver.h" #include "qtractorMidiControlCommand.h" #include "qtractorMidiEditor.h" #include "qtractorSession.h" #include "qtractorMainForm.h" #include "qtractorMidiEngine.h" #include "qtractorConnections.h" #include "qtractorCurve.h" #include "qtractorTracks.h" #include "qtractorTrackList.h" #include "qtractorCurveCommand.h" #include #include //---------------------------------------------------------------------------- // qtractorMidiControlObserverForm -- UI wrapper form. // Kind of singleton reference. qtractorMidiControlObserverForm * qtractorMidiControlObserverForm::g_pMidiObserverForm = NULL; // Constructor. qtractorMidiControlObserverForm::qtractorMidiControlObserverForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Make it auto-modeless dialog... QDialog::setAttribute(Qt::WA_DeleteOnClose); // Populate command list. const QIcon iconControlType(":/images/itemProperty.png"); // m_ui.ControlTypeComboBox->clear(); m_ui.ControlTypeComboBox->addItem(iconControlType, qtractorMidiControl::nameFromType(qtractorMidiEvent::NOTEON)); m_ui.ControlTypeComboBox->addItem(iconControlType, qtractorMidiControl::nameFromType(qtractorMidiEvent::NOTEOFF)); m_ui.ControlTypeComboBox->addItem(iconControlType, qtractorMidiControl::nameFromType(qtractorMidiEvent::KEYPRESS)); m_ui.ControlTypeComboBox->addItem(iconControlType, qtractorMidiControl::nameFromType(qtractorMidiEvent::CONTROLLER)); m_ui.ControlTypeComboBox->addItem(iconControlType, qtractorMidiControl::nameFromType(qtractorMidiEvent::PGMCHANGE)); m_ui.ControlTypeComboBox->addItem(iconControlType, qtractorMidiControl::nameFromType(qtractorMidiEvent::CHANPRESS)); m_ui.ControlTypeComboBox->addItem(iconControlType, qtractorMidiControl::nameFromType(qtractorMidiEvent::PITCHBEND)); // Start clean. m_iDirtyCount = 0; m_iDirtySetup = 0; // Populate param list. // activateControlType(m_ui.ControlTypeComboBox->currentText()); // Try to fix window geometry. adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.ControlTypeComboBox, SIGNAL(activated(const QString&)), SLOT(activateControlType(const QString&))); QObject::connect(m_ui.ChannelSpinBox, SIGNAL(valueChanged(int)), SLOT(change())); QObject::connect(m_ui.ParamComboBox, SIGNAL(activated(int)), SLOT(change())); QObject::connect(m_ui.LogarithmicCheckBox, SIGNAL(toggled(bool)), SLOT(change())); QObject::connect(m_ui.FeedbackCheckBox, SIGNAL(toggled(bool)), SLOT(change())); QObject::connect(m_ui.InvertCheckBox, SIGNAL(toggled(bool)), SLOT(change())); QObject::connect(m_ui.HookCheckBox, SIGNAL(toggled(bool)), SLOT(change())); QObject::connect(m_ui.InputsPushButton, SIGNAL(clicked()), SLOT(inputs())); QObject::connect(m_ui.OutputsPushButton, SIGNAL(clicked()), SLOT(outputs())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(clicked(QAbstractButton *)), SLOT(click(QAbstractButton *))); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); // Pseudo-singleton reference setup. g_pMidiObserverForm = this; } // Pseudo-singleton instance. qtractorMidiControlObserverForm * qtractorMidiControlObserverForm::getInstance (void) { return g_pMidiObserverForm; } // Pseudo-constructor. void qtractorMidiControlObserverForm::showInstance ( qtractorMidiControlObserver *pMidiObserver, QWidget *pParent, Qt::WindowFlags wflags ) { qtractorMidiControlObserverForm *pMidiObserverForm = qtractorMidiControlObserverForm::getInstance(); if (pMidiObserverForm) pMidiObserverForm->close(); pMidiObserverForm = new qtractorMidiControlObserverForm(pParent, wflags); pMidiObserverForm->setMidiObserver(pMidiObserver); pMidiObserverForm->show(); } // Observer accessors. void qtractorMidiControlObserverForm::setMidiObserver ( qtractorMidiControlObserver *pMidiObserver ) { m_pMidiObserver = pMidiObserver; if (m_pMidiObserver == NULL) return; if (m_pMidiObserver->subject() == NULL) return; ++m_iDirtySetup; QDialog::setWindowTitle( m_pMidiObserver->subject()->name() + " - " + tr("MIDI Controller")); const QString& sControlType = qtractorMidiControl::nameFromType(m_pMidiObserver->type()); m_ui.ControlTypeComboBox->setCurrentIndex( m_ui.ControlTypeComboBox->findText(sControlType)); activateControlType(sControlType); m_ui.ChannelSpinBox->setValue(m_pMidiObserver->channel() + 1); m_ui.ParamComboBox->setCurrentIndex(m_pMidiObserver->param()); m_ui.LogarithmicCheckBox->setChecked(m_pMidiObserver->isLogarithmic()); m_ui.FeedbackCheckBox->setChecked(m_pMidiObserver->isFeedback()); m_ui.InvertCheckBox->setChecked(m_pMidiObserver->isInvert()); m_ui.HookCheckBox->setChecked(m_pMidiObserver->isHook()); qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); QPushButton *pResetButton = m_ui.DialogButtonBox->button(QDialogButtonBox::Reset); if (pResetButton && pMidiControl) pResetButton->setEnabled( pMidiControl->isMidiObserverMapped(m_pMidiObserver)); --m_iDirtySetup; m_iDirtyCount = 0; stabilizeForm(); } qtractorMidiControlObserver *qtractorMidiControlObserverForm::midiObserver (void) const { return m_pMidiObserver; } // Pseudo-destructor. void qtractorMidiControlObserverForm::closeEvent ( QCloseEvent *pCloseEvent ) { // Pseudo-singleton reference setup. g_pMidiObserverForm = NULL; // Sure acceptance and probable destruction (cf. WA_DeleteOnClose). QDialog::closeEvent(pCloseEvent); } // Process incoming controller event. void qtractorMidiControlObserverForm::processEvent ( const qtractorCtlEvent& ctle ) { const QString& sControlType = qtractorMidiControl::nameFromType(ctle.type()); m_ui.ControlTypeComboBox->setCurrentIndex( m_ui.ControlTypeComboBox->findText(sControlType)); activateControlType(sControlType); m_ui.ChannelSpinBox->setValue(ctle.channel() + 1); m_ui.ParamComboBox->setCurrentIndex(ctle.param()); } // List view item activation. void qtractorMidiControlObserverForm::activateControlType ( const QString& sControlType ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiControlObserverForm::activateControlType(\"%s\")", sControlType.toUtf8().constData()); #endif qtractorMidiControl::ControlType ctype = qtractorMidiControl::typeFromName(sControlType); if (!ctype) return; const QIcon icon(":/images/itemControllers.png"); int iOldParam = m_ui.ParamComboBox->currentIndex(); m_ui.ParamComboBox->clear(); switch (ctype) { case qtractorMidiEvent::CHANPRESS: case qtractorMidiEvent::PITCHBEND: m_ui.ParamTextLabel->setEnabled(false); m_ui.ParamComboBox->setEnabled(false); break; case qtractorMidiEvent::NOTEON: case qtractorMidiEvent::NOTEOFF: case qtractorMidiEvent::CONTROLLER: case qtractorMidiEvent::KEYPRESS: case qtractorMidiEvent::PGMCHANGE: m_ui.ParamTextLabel->setEnabled(true); m_ui.ParamComboBox->setEnabled(true); for (unsigned short i = 0; i < 128; ++i) { QString sText; switch (ctype) { case qtractorMidiEvent::NOTEON: case qtractorMidiEvent::NOTEOFF: case qtractorMidiEvent::KEYPRESS: sText = QString("%1 (%2)") .arg(qtractorMidiEditor::defaultNoteName(i)).arg(i); break; case qtractorMidiEvent::CONTROLLER: sText = QString("%1 - %2") .arg(i).arg(qtractorMidiEditor::defaultControllerName(i)); break; default: sText = QString::number(i); break; } m_ui.ParamComboBox->addItem(icon, sText); } // Fall thru... default: break; } // Restore old parameter index, if convenient... if (iOldParam >= 0 && iOldParam < m_ui.ParamComboBox->count()) m_ui.ParamComboBox->setCurrentIndex(iOldParam); // This is enabled by as long there's a value. m_ui.LogarithmicCheckBox->setEnabled( m_pMidiObserver && !m_pMidiObserver->isToggled() && ctype != qtractorMidiEvent::PGMCHANGE); // Try make changes dirty. change(); } // Change settings (anything else slot). void qtractorMidiControlObserverForm::change (void) { if (m_iDirtySetup > 0) return; #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiControlObserverForm::change()"); #endif ++m_iDirtyCount; stabilizeForm(); } // Reset settings (action button slot). void qtractorMidiControlObserverForm::click ( QAbstractButton *pButton ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiControlObserverForm::click(%p)", pButton); #endif QDialogButtonBox::ButtonRole role = m_ui.DialogButtonBox->buttonRole(pButton); if ((role & QDialogButtonBox::ResetRole) == QDialogButtonBox::ResetRole) reset(); } // Accept settings (OK button slot). void qtractorMidiControlObserverForm::accept (void) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return; #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiControlObserverForm::accept()"); #endif // Get map settings... qtractorMidiControl::ControlType ctype = qtractorMidiControl::typeFromName( m_ui.ControlTypeComboBox->currentText()); unsigned short iChannel = m_ui.ChannelSpinBox->value(); if (iChannel > 0) --iChannel; unsigned short iParam = 0; if (m_ui.ParamComboBox->isEnabled()) iParam = m_ui.ParamComboBox->currentIndex(); bool bLogarithmic = false; if (m_ui.LogarithmicCheckBox->isEnabled()) bLogarithmic = m_ui.LogarithmicCheckBox->isChecked(); bool bFeedback = false; if (m_ui.FeedbackCheckBox->isEnabled()) bFeedback = m_ui.FeedbackCheckBox->isChecked(); bool bInvert = false; if (m_ui.InvertCheckBox->isEnabled()) bInvert = m_ui.InvertCheckBox->isChecked(); bool bHook = false; if (m_ui.HookCheckBox->isEnabled()) bHook = m_ui.HookCheckBox->isChecked(); // Check whether already mapped... qtractorMidiControlObserver *pMidiObserver = pMidiControl->findMidiObserver(ctype, iChannel, iParam); if (pMidiObserver && pMidiObserver != m_pMidiObserver) { if (QMessageBox::warning(this, QDialog::windowTitle(), tr("MIDI controller is already assigned.\n\n" "Do you want to replace the mapping?"), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; } // Map the damn control.... pMidiControl->unmapMidiObserver(m_pMidiObserver); m_pMidiObserver->setType(ctype); m_pMidiObserver->setChannel(iChannel); m_pMidiObserver->setParam(iParam); m_pMidiObserver->setLogarithmic(bLogarithmic); m_pMidiObserver->setFeedback(bFeedback); m_pMidiObserver->setInvert(bInvert); m_pMidiObserver->setHook(bHook); #if 0 pMidiControl->mapMidiObserver(m_pMidiObserver); #else qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) pSession->execute(new qtractorMidiControlObserverMapCommand(m_pMidiObserver)); #endif // Aint't dirty no more... m_iDirtyCount = 0; // Just go with dialog acceptance... QDialog::accept(); QDialog::close(); } // Reject settings (Cancel button slot). void qtractorMidiControlObserverForm::reject (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiControlObserverForm::reject()"); #endif // Check if there's any pending changes... if (m_iDirtyCount > 0) { switch (QMessageBox::warning(this, QDialog::windowTitle(), tr("Some settings have been changed.\n\n" "Do you want to apply the changes?"), QMessageBox::Apply | QMessageBox::Discard | QMessageBox::Cancel)) { case QMessageBox::Discard: break; case QMessageBox::Apply: accept(); default: return; } } // Just go with dialog rejection... QDialog::reject(); QDialog::close(); } // Reset settings (Reset button slot). void qtractorMidiControlObserverForm::reset (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiControlObserverForm::reset()"); #endif #if 0 qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl) pMidiControl->unmapMidiObserver(m_pMidiObserver); #else qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) pSession->execute(new qtractorMidiControlObserverUnmapCommand(m_pMidiObserver)); #endif // Bail out... QDialog::accept(); QDialog::close(); } // Show control inputs (Custom button slot). void qtractorMidiControlObserverForm::inputs (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiControlObserverForm::inputs()"); #endif qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorMidiEngine *pMidiEngine = pSession->midiEngine(); if (pMidiEngine == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm && pMainForm->connections() && pMidiEngine->controlBus_in()) { (pMainForm->connections())->showBus( pMidiEngine->controlBus_in(), qtractorBus::Input); } } // Show control outputs (Custom button slot). void qtractorMidiControlObserverForm::outputs (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiControlObserverForm::outputs()"); #endif qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorMidiEngine *pMidiEngine = pSession->midiEngine(); if (pMidiEngine == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm && pMainForm->connections() && pMidiEngine->controlBus_out()) { (pMainForm->connections())->showBus( pMidiEngine->controlBus_out(), qtractorBus::Output); } } // Update control widget state. void qtractorMidiControlObserverForm::stabilizeForm(void) { qtractorMidiEngine *pMidiEngine = NULL; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) pMidiEngine = pSession->midiEngine(); if (pMidiEngine) { bool bFeedback = m_ui.FeedbackCheckBox->isChecked(); m_ui.InputsPushButton->setEnabled( pMidiEngine->controlBus_in() != NULL); m_ui.OutputsPushButton->setEnabled( bFeedback && pMidiEngine->controlBus_out() != NULL); } else { m_ui.InputsPushButton->setEnabled(false); m_ui.OutputsPushButton->setEnabled(false); } } // MIDI controller/observer attachment (context menu) activator. // Q_DECLARE_METATYPE(qtractorMidiControlObserver *); QAction *qtractorMidiControlObserverForm::addMidiControlAction ( QWidget *pParent, QWidget *pWidget, qtractorMidiControlObserver *pMidiObserver ) { QAction *pAction = new QAction( QIcon(":/images/itemControllers.png"), tr("&MIDI Controller..."), pWidget); pAction->setData( qVariantFromValue (pMidiObserver)); QObject::connect( pAction, SIGNAL(triggered(bool)), pParent, SLOT(midiControlActionSlot())); pWidget->addAction(pAction); pWidget->setContextMenuPolicy(Qt::CustomContextMenu); QObject::connect( pWidget, SIGNAL(customContextMenuRequested(const QPoint&)), pParent, SLOT(midiControlMenuSlot(const QPoint&))); return pAction; } void qtractorMidiControlObserverForm::midiControlAction ( QWidget *pParent, QAction *pAction ) { if (pAction == NULL) return; qtractorMidiControlObserver *pMidiObserver = pAction->data().value (); if (pMidiObserver) qtractorMidiControlObserverForm::showInstance(pMidiObserver, pParent); } void qtractorMidiControlObserverForm::midiControlMenu ( QWidget *pWidget, const QPoint& pos ) { if (pWidget == NULL) return; QAction *pMidiControlAction = NULL; qtractorMidiControlObserver *pMidiObserver = NULL; QListIterator iter(pWidget->actions()); while (iter.hasNext()) { QAction *pAction = iter.next(); pMidiObserver = pAction->data().value (); if (pMidiObserver) { pMidiControlAction = pAction; break; } } if (pMidiControlAction == NULL) return; if (pMidiObserver == NULL) return; QMenu menu(pWidget); menu.addAction(pMidiControlAction); qtractorMidiControlObserverForm::addMidiControlMenu(&menu, pMidiObserver); menu.exec(pWidget->mapToGlobal(pos)); } // Add esquisite automation menu actions... void qtractorMidiControlObserverForm::addMidiControlMenu ( QMenu *pMenu, qtractorMidiControlObserver *pMidiObserver ) { qtractorCurveList *pCurveList = pMidiObserver->curveList(); if (pCurveList == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorTrack *pTrack = pSession->findTrack(pCurveList); if (pTrack == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks == NULL) return; qtractorCurve *pCurve = NULL; qtractorSubject *pSubject = pMidiObserver->subject(); if (pSubject) pCurve = pSubject->curve(); if (pCurve && pCurveList->currentCurve() != pCurve) { pCurveList->setCurrentCurve(pCurve); pTracks->updateTrackView(); } pTracks->trackList()->setCurrentTrack(pTrack); QAction *pAction; pMenu->addSeparator(); pAction = pMenu->addAction(tr("&Automation")); pAction->setCheckable(true); pAction->setChecked(pCurve && pCurve == pCurveList->currentCurve()); pAction->setData(qVariantFromValue(pMidiObserver)); QObject::connect( pAction, SIGNAL(triggered(bool)), pMainForm, SLOT(trackCurveSelect(bool))); pMenu->addSeparator(); QMenu *pTrackCurveModeMenu = pMainForm->trackCurveModeMenu(); pTrackCurveModeMenu->setEnabled(pCurve != NULL); pMenu->addMenu(pTrackCurveModeMenu); pAction = pMenu->addAction(tr("&Lock")); pAction->setCheckable(true); pAction->setChecked(pCurve && pCurve->isLocked()); pAction->setEnabled(pCurve != NULL); QObject::connect( pAction, SIGNAL(triggered(bool)), pMainForm, SLOT(trackCurveLocked(bool))); pMenu->addSeparator(); QIcon iconProcess; iconProcess.addPixmap( QPixmap(":/images/trackCurveProcess.png"), QIcon::Normal, QIcon::On); iconProcess.addPixmap( QPixmap(":/images/trackCurveEnabled.png"), QIcon::Normal, QIcon::Off); iconProcess.addPixmap( QPixmap(":/images/trackCurveNone.png"), QIcon::Disabled, QIcon::Off); pAction = pMenu->addAction(iconProcess, tr("&Play")); pAction->setCheckable(true); pAction->setChecked(pCurve && pCurve->isProcess()); pAction->setEnabled(pCurve != NULL); QObject::connect( pAction, SIGNAL(triggered(bool)), pMainForm, SLOT(trackCurveProcess(bool))); QIcon iconCapture; iconCapture.addPixmap( QPixmap(":/images/trackCurveCapture.png"), QIcon::Normal, QIcon::On); iconCapture.addPixmap( QPixmap(":/images/trackCurveEnabled.png"), QIcon::Normal, QIcon::Off); iconProcess.addPixmap( QPixmap(":/images/trackCurveNone.png"), QIcon::Disabled, QIcon::Off); pAction = pMenu->addAction(iconCapture, tr("&Record")); pAction->setCheckable(true); pAction->setChecked(pCurve && pCurve->isCapture()); pAction->setEnabled(pCurve != NULL); QObject::connect( pAction, SIGNAL(triggered(bool)), pMainForm, SLOT(trackCurveCapture(bool))); pMenu->addSeparator(); pAction = pMenu->addAction(tr("&Clear")); pAction->setEnabled(pCurve != NULL); QObject::connect( pAction, SIGNAL(triggered(bool)), pMainForm, SLOT(trackCurveClear())); } // end of qtractorMidiControlObserverForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditTime.cpp0000644000175000001440000000012312204260560022033 xustar000000000000000027 mtime=1376870768.049744 26 atime=1381134666.48708 30 ctime=1381134666.487080041 qtractor-0.5.11/src/qtractorMidiEditTime.cpp0000644000175000001440000005535212204260560021334 0ustar00rncbcusers00000000000000// qtractorMidiEditTime.cpp // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorMidiEditTime.h" #include "qtractorMidiEditor.h" #include "qtractorMidiEditView.h" #include "qtractorOptions.h" #include "qtractorSessionCommand.h" #include "qtractorTimeScaleCommand.h" #include "qtractorMainForm.h" #include "qtractorTimeScaleForm.h" #include #include #include #include #include #include #include //---------------------------------------------------------------------------- // qtractorMidiEditTime -- MIDI sequence time scale widget. // Constructor. qtractorMidiEditTime::qtractorMidiEditTime ( qtractorMidiEditor *pEditor, QWidget *pParent ) : qtractorScrollView(pParent) { m_pEditor = pEditor; m_dragState = DragNone; m_dragCursor = DragNone; m_pDragMarker = NULL; qtractorScrollView::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); qtractorScrollView::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); qtractorScrollView::setFrameStyle(QFrame::Panel | QFrame::Raised); qtractorScrollView::setFocusPolicy(Qt::NoFocus); // qtractorScrollView::viewport()->setFocusPolicy(Qt::ClickFocus); // qtractorScrollView::viewport()->setFocusProxy(this); // qtractorScrollView::viewport()->setAcceptDrops(true); // qtractorScrollView::setDragAutoScroll(false); qtractorScrollView::setMouseTracking(true); const QFont& font = qtractorScrollView::font(); qtractorScrollView::setFont(QFont(font.family(), font.pointSize() - 2)); // QObject::connect(this, SIGNAL(contentsMoving(int,int)), // this, SLOT(updatePixmap(int,int))); // Trap for help/tool-tips events. qtractorScrollView::viewport()->installEventFilter(this); } // (Re)create the complete view pixmap. void qtractorMidiEditTime::updatePixmap ( int cx, int /*cy*/) { QWidget *pViewport = qtractorScrollView::viewport(); int w = pViewport->width(); int h = pViewport->height(); if (w < 1 || h < 1) return; const QPalette& pal = qtractorScrollView::palette(); m_pixmap = QPixmap(w, h); m_pixmap.fill(pal.window().color()); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorTimeScale *pTimeScale = m_pEditor->timeScale(); if (pTimeScale == NULL) return; QPainter p(&m_pixmap); p.initFrom(this); // // Draw the time scale... // const QFontMetrics& fm = p.fontMetrics(); int x, y1, y2 = h - 1; // Account for the editing offset: int dx = cx + pTimeScale->pixelFromFrame(m_pEditor->offset()); qtractorTimeScale::Cursor cursor(pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekPixel(dx); unsigned short iPixelsPerBeat = pNode->pixelsPerBeat(); unsigned int iBeat = pNode->beatFromPixel(dx); if (iBeat > 0) pNode = cursor.seekBeat(--iBeat); x = pNode->pixelFromBeat(iBeat) - dx; while (x < w) { bool bBeatIsBar = pNode->beatIsBar(iBeat); if (bBeatIsBar) { y1 = 0; p.setPen(pal.windowText().color()); p.drawText(x + 2, fm.ascent(), QString::number(pNode->barFromBeat(iBeat) + 1)); if (iBeat == pNode->beat) { iPixelsPerBeat = pNode->pixelsPerBeat(); p.setPen(pal.base().color().value() < 0x7f ? pal.light().color() : pal.dark().color()); p.drawText(x + 16, fm.ascent(), QString("%1 %2/%3") .arg(pNode->tempo, 0, 'g', 3) .arg(pNode->beatsPerBar) .arg(1 << pNode->beatDivisor)); } } else { y1 = (y2 >> 1); } if (bBeatIsBar || iPixelsPerBeat > 8) { p.setPen(pal.mid().color()); p.drawLine(x, y1, x, y2); p.setPen(pal.light().color()); p.drawLine(x + 1, y1, x + 1, y2); } pNode = cursor.seekBeat(++iBeat); x = pNode->pixelFromBeat(iBeat) - dx; } // Draw location markers, if any... qtractorTimeScale::Marker *pMarker = pTimeScale->markers().seekPixel(dx); while (pMarker) { x = pTimeScale->pixelFromFrame(pMarker->frame) - dx + 4; if (x > w) break; p.setPen(pMarker->color); p.drawText(x, y2, pMarker->text); pMarker = pMarker->next(); } // Draw loop boundaries, if applicable... if (pSession->isLooping()) { QPolygon polyg(3); // h -= 4; int d = (h >> 2) + 1; p.setPen(Qt::darkCyan); p.setBrush(Qt::cyan); x = pTimeScale->pixelFromFrame(pSession->loopStart()) - dx; if (x >= 0 && x < w) { polyg.putPoints(0, 3, x + d, h - d, x, h, x, h - d); p.drawPolygon(polyg); } x = pTimeScale->pixelFromFrame(pSession->loopEnd()) - dx; if (x >= 0 && x < w) { polyg.putPoints(0, 3, x, h - d, x, h, x - d, h - d); p.drawPolygon(polyg); } } // Draw punch in/out boundaries, if applicable... if (pSession->isPunching()) { QPolygon polyg(3); // h -= 4; int d = (h >> 2) + 1; p.setPen(Qt::darkMagenta); p.setBrush(Qt::magenta); x = pTimeScale->pixelFromFrame(pSession->punchIn()) - dx; if (x >= 0 && x < w) { polyg.putPoints(0, 3, x + d, h - d, x, h, x, h - d); p.drawPolygon(polyg); } x = pTimeScale->pixelFromFrame(pSession->punchOut()) - dx; if (x >= 0 && x < w) { polyg.putPoints(0, 3, x, h - d, x, h, x - d, h - d); p.drawPolygon(polyg); } } } // Rectangular contents update. void qtractorMidiEditTime::updateContents ( const QRect& rect ) { updatePixmap( qtractorScrollView::contentsX(), qtractorScrollView::contentsY()); qtractorScrollView::updateContents(rect); } // Overall contents update. void qtractorMidiEditTime::updateContents (void) { updatePixmap( qtractorScrollView::contentsX(), qtractorScrollView::contentsY()); qtractorScrollView::updateContents(); } // Resize event handler. void qtractorMidiEditTime::resizeEvent ( QResizeEvent *pResizeEvent ) { qtractorScrollView::resizeEvent(pResizeEvent); updateContents(); } // Draw the time scale. void qtractorMidiEditTime::drawContents ( QPainter *pPainter, const QRect& rect ) { pPainter->drawPixmap(rect, m_pixmap, rect); // Draw special play/edit-head/tail headers... int cx = qtractorScrollView::contentsX(); int h = qtractorScrollView::height() - 4; int d = (h >> 2); int x = m_pEditor->editHeadX() - cx; if (x >= rect.left() - d && x <= rect.right() + d) { QPolygon polyg(3); polyg.putPoints(0, 3, x, h - d, x, h, x + d, h - d); pPainter->setPen(Qt::blue); pPainter->setBrush(Qt::blue); pPainter->drawPolygon(polyg); } x = m_pEditor->editTailX() - cx; if (x >= rect.left() - d && x <= rect.right() + d) { QPolygon polyg(3); polyg.putPoints(0, 3, x - d, h - d, x, h, x, h - d); pPainter->setPen(Qt::blue); pPainter->setBrush(Qt::blue); pPainter->drawPolygon(polyg); } x = m_pEditor->playHeadX() - cx; if (x >= rect.left() - d && x <= rect.right() + d) { QPolygon polyg(3); polyg.putPoints(0, 3, x - d, h - d, x, h, x + d, h - d); pPainter->setPen(Qt::red); pPainter->setBrush(Qt::red); pPainter->drawPolygon(polyg); } } // To have timeline in h-sync with main view. void qtractorMidiEditTime::contentsXMovingSlot ( int cx, int /*cy*/ ) { if (qtractorScrollView::contentsX() != cx) qtractorScrollView::setContentsPos(cx, qtractorScrollView::contentsY()); } // Check if some position header is to be dragged... bool qtractorMidiEditTime::dragHeadStart ( const QPoint& pos ) { // Try to catch mouse clicks over the // play/edit-head/tail cursors... int h = qtractorScrollView::height(); // - 4; int d = (h >> 1); QRect rect(0, h - d, d << 1, d); // Check play-head header... rect.moveLeft(m_pEditor->playHeadX() - d); if (rect.contains(pos)) { m_dragCursor = DragPlayHead; return true; } // Check loop and punch points... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; qtractorTimeScale *pTimeScale = m_pEditor->timeScale(); if (pTimeScale == NULL) return false; int dx = pTimeScale->pixelFromFrame(m_pEditor->offset()) + d; // Loop points... if (pSession->isLooping()) { // Check loop-start header... rect.moveLeft(pTimeScale->pixelFromFrame(pSession->loopStart()) - dx); if (rect.contains(pos)) { m_dragCursor = DragLoopStart; return true; } // Check loop-end header... rect.moveLeft(pTimeScale->pixelFromFrame(pSession->loopEnd()) - dx); if (rect.contains(pos)) { m_dragCursor = DragLoopEnd; return true; } } // Punch in/out points... if (pSession->isPunching()) { // Check punch-in header... rect.moveLeft(pTimeScale->pixelFromFrame(pSession->punchIn()) - dx); if (rect.contains(pos)) { m_dragCursor = DragPunchIn; return true; } // Check punch-out header... rect.moveLeft(pTimeScale->pixelFromFrame(pSession->punchOut()) - dx); if (rect.contains(pos)) { m_dragCursor = DragPunchOut; return true; } } // Check location marker headers... qtractorTimeScale::Marker *pMarker = pTimeScale->markers().seekPixel(pos.x() + dx); if (pMarker) { unsigned long iFrame = pMarker->frame; rect.moveLeft(pTimeScale->pixelFromFrame(iFrame) - dx); if (rect.contains(pos)) { m_dragCursor = DragMarker; m_pDragMarker = pSession->timeScale()->markers().seekFrame(iFrame); return true; } } // Check edit-head header... rect.moveLeft(m_pEditor->editHeadX() - d); if (rect.contains(pos)) { m_dragCursor = DragEditHead; return true; } // Check edit-tail header... rect.moveLeft(m_pEditor->editTailX() - d); if (rect.contains(pos)) { m_dragCursor = DragEditTail; return true; } // Reset cursor if any persist around. if (m_dragCursor != DragNone) { qtractorScrollView::unsetCursor(); m_dragCursor = DragNone; } // Nothing. return false; } // Handle item selection/dragging -- mouse button press. void qtractorMidiEditTime::mousePressEvent ( QMouseEvent *pMouseEvent ) { // Force null state. m_dragState = DragNone; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Which mouse state? bool bModifier = (pMouseEvent->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)); // Make sure we'll reset selection... if (!bModifier) m_pEditor->selectAll(m_pEditor->editView(), false); // Direct snap positioning... const QPoint& pos = viewportToContents(pMouseEvent->pos()); qtractorTimeScale *pTimeScale = m_pEditor->timeScale(); unsigned long iFrame = pTimeScale->frameSnap(m_pEditor->offset() + pTimeScale->frameFromPixel(pos.x() > 0 ? pos.x() : 0)); // We'll need options somehow... qtractorOptions *pOptions = qtractorOptions::getInstance(); switch (pMouseEvent->button()) { case Qt::LeftButton: // Remember what and where we'll be dragging/selecting... m_dragState = DragStart; m_posDrag = pos; // Try to catch mouse clicks over the cursor heads... if (dragHeadStart(m_posDrag)) { m_dragState = m_dragCursor; qtractorScrollView::setCursor(QCursor(Qt::SizeHorCursor)); } else if (!bModifier) { // Edit-head positioning... m_pEditor->setEditHead(iFrame); // Logical contents changed, just for visual feedback... m_pEditor->selectionChangeNotify(); } break; case Qt::MidButton: if (pOptions && pOptions->bMidButtonModifier) bModifier = !bModifier; // Reverse mid-button role... if (bModifier) { // Play-head positioning... m_pEditor->setPlayHead(iFrame); pSession->setPlayHead(m_pEditor->playHead()); } else { // Edit-head/tail (merged) positioning... m_pEditor->setEditHead(iFrame); m_pEditor->setEditTail(iFrame); } // Logical contents changed, just for visual feedback... m_pEditor->selectionChangeNotify(); break; case Qt::RightButton: // Edit-tail positioning... m_pEditor->setEditTail(iFrame); // Logical contents changed, just for visual feedback... m_pEditor->selectionChangeNotify(); // Fall thru... default: break; } // qtractorScrollView::mousePressEvent(pMouseEvent); } // Handle item selection/dragging -- mouse pointer move. void qtractorMidiEditTime::mouseMoveEvent ( QMouseEvent *pMouseEvent ) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; // Are we already moving/dragging something? const QPoint& pos = viewportToContents(pMouseEvent->pos()); qtractorTimeScale *pTimeScale = m_pEditor->timeScale(); unsigned long iFrame = pTimeScale->frameSnap(m_pEditor->offset() + pTimeScale->frameFromPixel(pos.x() > 0 ? pos.x() : 0)); int y = m_pEditor->editView()->contentsY(); switch (m_dragState) { case DragNone: // Try to catch mouse over the cursor heads... if (dragHeadStart(pos)) qtractorScrollView::setCursor(QCursor(Qt::PointingHandCursor)); break; case DragSelect: // Rubber-band selection... m_rectDrag.setRight(pos.x()); m_pEditor->editView()->ensureVisible(pos.x(), y, 16, 0); m_pEditor->selectRect(m_pEditor->editView(), m_rectDrag, pMouseEvent->modifiers() & Qt::ControlModifier, false); // Edit-tail positioning... m_pEditor->setEditTail(iFrame); showToolTip(m_rectDrag.normalized()); break; case DragPlayHead: // Play-head positioning... m_pEditor->editView()->ensureVisible(pos.x(), y, 16, 0); m_pEditor->setPlayHead(iFrame); // Let the change get some immediate visual feedback... pMainForm->updateTransportTime(iFrame); showToolTip(iFrame); break; case DragEditHead: case DragPunchIn: case DragLoopStart: // Edit-head positioning... m_pEditor->editView()->ensureVisible(pos.x(), y, 16, 0); m_pEditor->setEditHead(iFrame); showToolTip(iFrame); break; case DragEditTail: case DragPunchOut: case DragLoopEnd: // Edit-head positioning... m_pEditor->editView()->ensureVisible(pos.x(), y, 16, 0); m_pEditor->setEditTail(iFrame); showToolTip(iFrame); break; case DragMarker: // Marker positioning... m_pEditor->editView()->ensureVisible(pos.x(), y, 16, 0); showToolTip(iFrame); break; case DragStart: // Rubber-band starting... if ((m_posDrag - pos).manhattanLength() > QApplication::startDragDistance()) { // We'll start dragging alright... int h = m_pEditor->editView()->contentsHeight(); m_rectDrag.setTop(0); m_rectDrag.setLeft(m_posDrag.x()); m_rectDrag.setRight(pos.x()); m_rectDrag.setBottom(h); m_dragState = m_dragCursor = DragSelect; qtractorScrollView::setCursor(QCursor(Qt::SizeHorCursor)); } // Fall thru... default: break; } // qtractorScrollView::mouseMoveEvent(pMouseEvent); } // Handle item selection/dragging -- mouse button release. void qtractorMidiEditTime::mouseReleaseEvent ( QMouseEvent *pMouseEvent ) { // qtractorScrollView::mouseReleaseEvent(pMouseEvent); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Which mouse state? const bool bModifier = (pMouseEvent->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)); // Direct snap positioning... const QPoint& pos = viewportToContents(pMouseEvent->pos()); qtractorTimeScale *pTimeScale = m_pEditor->timeScale(); unsigned long iFrame = pTimeScale->frameSnap(m_pEditor->offset() + pTimeScale->frameFromPixel(pos.x() > 0 ? pos.x() : 0)); switch (m_dragState) { case DragSelect: // Do the final range selection... m_pEditor->selectRect(m_pEditor->editView(), m_rectDrag, pMouseEvent->modifiers() & Qt::ControlModifier, true); // Edit-tail positioning... m_pEditor->setEditTail(iFrame); // Not quite a selection change, // but for visual feedback... m_pEditor->selectionChangeNotify(); break; case DragPlayHead: // Play-head positioning commit... m_pEditor->setPlayHead(iFrame); pSession->setPlayHead(m_pEditor->playHead()); // Fall thru... case DragEditHead: case DragEditTail: // Not quite a selection change, // but for visual feedback... m_pEditor->selectionChangeNotify(); break; case DragLoopStart: // New loop-start boundary... if (pSession->editHead() < pSession->loopEnd()) { // Yep, new loop-start point... m_pEditor->commands()->exec( new qtractorSessionLoopCommand(pSession, pSession->editHead(), pSession->loopEnd())); } break; case DragLoopEnd: // New loop-end boundary... if (pSession->loopStart() < pSession->editTail()) { // Yep, new loop-end point... m_pEditor->commands()->exec( new qtractorSessionLoopCommand(pSession, pSession->loopStart(), pSession->editTail())); } break; case DragPunchIn: // New punch-in boundary... if (pSession->editHead() < pSession->punchOut()) { // Yep, new punch-in point... m_pEditor->commands()->exec( new qtractorSessionPunchCommand(pSession, pSession->editHead(), pSession->punchOut())); } break; case DragPunchOut: // New punch-out boundary... if (pSession->punchIn() < pSession->editTail()) { // Yep, new punch-out point... m_pEditor->commands()->exec( new qtractorSessionPunchCommand(pSession, pSession->punchIn(), pSession->editTail())); } break; case DragMarker: // Marker positioning commit... if (m_pDragMarker) { // Yep, new marker location... pSession->execute( new qtractorTimeScaleMoveMarkerCommand( pSession->timeScale(), m_pDragMarker, iFrame)); } break; case DragStart: // Left-button indirect positioning... if (bModifier) { // Play-head positioning... m_pEditor->setPlayHead(iFrame); // Immediately commited... pSession->setPlayHead(iFrame); // Not quite a selection, rather just // for immediate visual feedback... m_pEditor->selectionChangeNotify(); } // Fall thru... case DragNone: default: break; } // Clean up. resetDragState(); } // Tempo-map dialog accessor. void qtractorMidiEditTime::mouseDoubleClickEvent ( QMouseEvent *pMouseEvent ) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; // Direct snap positioning... const QPoint& pos = viewportToContents(pMouseEvent->pos()); qtractorTimeScale *pTimeScale = m_pEditor->timeScale(); unsigned long iFrame = pTimeScale->frameSnap(m_pEditor->offset() + pTimeScale->frameFromPixel(pos.x() > 0 ? pos.x() : 0)); // Show tempo map dialog. qtractorTimeScaleForm form(pMainForm); form.setFrame(iFrame); form.exec(); } // Keyboard event handler. void qtractorMidiEditTime::keyPressEvent ( QKeyEvent *pKeyEvent ) { if (pKeyEvent->key() == Qt::Key_Escape) { // Restore uncommitted play-head position?... if (m_dragState == DragPlayHead) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) m_pEditor->setPlayHead(pSession->playHead()); } resetDragState(); } if (!m_pEditor->keyPress(this, pKeyEvent->key(), pKeyEvent->modifiers())) qtractorScrollView::keyPressEvent(pKeyEvent); } // Reset drag/select state. void qtractorMidiEditTime::resetDragState (void) { // Cancel any dragging/cursor out there... if (m_dragState == DragSelect) qtractorScrollView::updateContents(); if (m_dragCursor != DragNone) qtractorScrollView::unsetCursor(); // Also get rid of any meta-breadcrumbs... m_pEditor->resetDragState(this); // Force null state. m_dragState = DragNone; m_dragCursor = DragNone; m_pDragMarker = NULL; // HACK: give focus to track-view... m_pEditor->editView()->setFocus(); } // Context menu event handler (dummy). void qtractorMidiEditTime::contextMenuEvent ( QContextMenuEvent */*pContextMenuEvent*/ ) { } // Trap for help/tool-tip events. bool qtractorMidiEditTime::eventFilter ( QObject *pObject, QEvent *pEvent ) { QWidget *pViewport = qtractorScrollView::viewport(); if (static_cast (pObject) == pViewport) { if (pEvent->type() == QEvent::ToolTip && m_dragCursor != DragNone && m_pEditor->isToolTips()) { QHelpEvent *pHelpEvent = static_cast (pEvent); if (pHelpEvent) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { unsigned long iFrame = 0; switch (m_dragCursor) { case DragMarker: if (m_pDragMarker) iFrame = m_pDragMarker->frame; break; case DragPlayHead: iFrame = pSession->playHead(); break; case DragEditHead: iFrame = pSession->editHead(); break; case DragEditTail: iFrame = pSession->editTail(); break; case DragLoopStart: iFrame = pSession->loopStart(); break; case DragLoopEnd: iFrame = pSession->loopEnd(); break; case DragPunchIn: iFrame = pSession->punchIn(); break; case DragPunchOut: iFrame = pSession->punchOut(); break; default: break; } showToolTip(iFrame); } } } else if (pEvent->type() == QEvent::Leave && m_dragState != DragNone) { qtractorScrollView::unsetCursor(); return true; } } // Not handled here. return qtractorScrollView::eventFilter(pObject, pEvent); } // Show dragging tooltip... void qtractorMidiEditTime::showToolTip ( unsigned long iFrame ) const { if (!m_pEditor->isToolTips()) return; qtractorTimeScale *pTimeScale = m_pEditor->timeScale(); if (pTimeScale == NULL) return; QString sToolTip; switch (m_dragCursor) { case DragMarker: if (m_pDragMarker) sToolTip += m_pDragMarker->text; break; case DragPlayHead: sToolTip += tr("Play-head"); break; case DragEditHead: sToolTip += tr("Edit-head"); break; case DragEditTail: sToolTip += tr("Edit-tail"); break; case DragLoopStart: sToolTip += tr("Loop-start"); break; case DragLoopEnd: sToolTip += tr("Loop-end"); break; case DragPunchIn: sToolTip += tr("Punch-in"); break; case DragPunchOut: sToolTip += tr("Punch-out"); break; default: break; } if (!sToolTip.isEmpty()) sToolTip += '\n'; sToolTip += pTimeScale->textFromFrame(iFrame); QToolTip::showText(QCursor::pos(), sToolTip, qtractorScrollView::viewport()); } void qtractorMidiEditTime::showToolTip ( const QRect& rect ) const { if (!m_pEditor->isToolTips()) return; qtractorTimeScale *pTimeScale = m_pEditor->timeScale(); if (pTimeScale == NULL) return; unsigned long iFrameStart = pTimeScale->frameSnap( pTimeScale->frameFromPixel(rect.left())); unsigned long iFrameEnd = pTimeScale->frameSnap( iFrameStart + pTimeScale->frameFromPixel(rect.width())); QToolTip::showText(QCursor::pos(), tr("Start:\t%1\nEnd:\t%2\nLength:\t%3") .arg(pTimeScale->textFromFrame(iFrameStart)) .arg(pTimeScale->textFromFrame(iFrameEnd)) .arg(pTimeScale->textFromFrame(iFrameStart, true, iFrameEnd - iFrameStart)), qtractorScrollView::viewport()); } // end of qtractorMidiEditTime.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTimeScaleCommand.h0000644000175000001440000000012212165037037022344 xustar000000000000000027 mtime=1372864031.847614 26 atime=1381134668.98808 29 ctime=1381134668.98808008 qtractor-0.5.11/src/qtractorTimeScaleCommand.h0000644000175000001440000001727412165037037021647 0ustar00rncbcusers00000000000000// qtractorTimeScaleCommand.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorTimeScaleCommand_h #define __qtractorTimeScaleCommand_h #include "qtractorCommand.h" #include "qtractorTimeScale.h" // Forward declarations. class qtractorClipCommand; class qtractorClip; //---------------------------------------------------------------------- // class qtractorTimeScaleNodeCommand - declaration. // class qtractorTimeScaleNodeCommand : public qtractorCommand { public: // Constructor. qtractorTimeScaleNodeCommand(const QString& sName, qtractorTimeScale *pTimeScale, unsigned long iFrame = 0, float fTempo = 120.0f, unsigned short iBeatType = 2, unsigned short iBeatsPerBar = 4, unsigned short iBeatDivisor = 2); // Destructor. virtual ~qtractorTimeScaleNodeCommand(); // Time-scale accessor. qtractorTimeScale *timeScale() const { return m_pTimeScale; } // Node properties accessors. unsigned long frame() const { return m_iFrame; } float tempo() const { return m_fTempo; } unsigned short beatType() const { return m_iBeatType; } unsigned short beatsPerBar() const { return m_iBeatsPerBar; } unsigned short beatDivisor() const { return m_iBeatDivisor; } protected: // Executive commands. bool addNode(); bool updateNode(); bool removeNode(); // Make it automatic clip time-stretching command (static). qtractorClipCommand *createClipCommand(const QString& sName, qtractorTimeScale::Node *pNode, float fOldTempo, float fNewTempo); private: // Instance variables. qtractorTimeScale *m_pTimeScale; unsigned long m_iFrame; float m_fTempo; unsigned short m_iBeatType; unsigned short m_iBeatsPerBar; unsigned short m_iBeatDivisor; qtractorClipCommand *m_pClipCommand; bool m_bAutoTimeStretch; }; //---------------------------------------------------------------------- // class qtractorTimeScaleAddNodeCommand - declaration. // class qtractorTimeScaleAddNodeCommand : public qtractorTimeScaleNodeCommand { public: // Constructor. qtractorTimeScaleAddNodeCommand( qtractorTimeScale *pTimeScale, unsigned long iFrame, float fTempo = 120.0f, unsigned short iBeatType = 2, unsigned short iBeatsPerBar = 4, unsigned short iBeatDivisor = 2); // Time-scale command methods. bool redo(); bool undo(); }; //---------------------------------------------------------------------- // class qtractorTimeScaleUpdateNodeCommand - declaration. // class qtractorTimeScaleUpdateNodeCommand : public qtractorTimeScaleNodeCommand { public: // Constructor. qtractorTimeScaleUpdateNodeCommand(qtractorTimeScale *pTimeScale, unsigned long iFrame, float fTempo, unsigned short iBeatType, unsigned short iBeatsPerBar, unsigned short iBeatDivisor); // Time-scale command methods. bool redo(); bool undo(); }; //---------------------------------------------------------------------- // class qtractorTimeScaleRemoveNodeCommand - declaration. // class qtractorTimeScaleRemoveNodeCommand : public qtractorTimeScaleNodeCommand { public: // Constructor. qtractorTimeScaleRemoveNodeCommand(qtractorTimeScale *pTimeScale, qtractorTimeScale::Node *pNode); // Time-scale command methods. bool redo(); bool undo(); }; //---------------------------------------------------------------------- // class qtractorTimeScaleMoveNodeCommand - declaration. // class qtractorTimeScaleMoveNodeCommand : public qtractorTimeScaleNodeCommand { public: // Constructor. qtractorTimeScaleMoveNodeCommand(qtractorTimeScale *pTimeScale, qtractorTimeScale::Node *pNode, unsigned long iFrame); // Time-scale command methods. bool redo(); bool undo(); private: // The new location argument. unsigned long m_iNewFrame; // Replaced node salvage. bool m_bOldNode; unsigned long m_iOldFrame; float m_fOldTempo; unsigned short m_iOldBeatType; unsigned short m_iOldBeatsPerBar; unsigned short m_iOldBeatDivisor; }; //---------------------------------------------------------------------- // class qtractorTimeScaleMarkerCommand - declaration. // class qtractorTimeScaleMarkerCommand : public qtractorCommand { public: // Constructor. qtractorTimeScaleMarkerCommand(const QString& sName, qtractorTimeScale *pTimeScale, unsigned long iFrame = 0, const QString& sText = QString(), const QColor& rgbColor = Qt::darkGray); // Time-scale accessor. qtractorTimeScale *timeScale() const { return m_pTimeScale; } // Marker properties accessors. unsigned long frame() const { return m_iFrame; } const QString& text() const { return m_sText; } const QColor& color() const { return m_rgbColor; } protected: // Executive commands. bool addMarker(); bool updateMarker(); bool removeMarker(); private: // Instance variables. qtractorTimeScale *m_pTimeScale; unsigned long m_iFrame; QString m_sText; QColor m_rgbColor; }; //---------------------------------------------------------------------- // class qtractorTimeScaleAddMarkerCommand - declaration. // class qtractorTimeScaleAddMarkerCommand : public qtractorTimeScaleMarkerCommand { public: // Constructor. qtractorTimeScaleAddMarkerCommand( qtractorTimeScale *pTimeScale, unsigned long iFrame, const QString& sText, const QColor& rgbColor = Qt::darkGray); // Time-scale command methods. bool redo(); bool undo(); }; //---------------------------------------------------------------------- // class qtractorTimeScaleUpdateNodeCommand - declaration. // class qtractorTimeScaleUpdateMarkerCommand : public qtractorTimeScaleMarkerCommand { public: // Constructor. qtractorTimeScaleUpdateMarkerCommand( qtractorTimeScale *pTimeScale, unsigned long iFrame, const QString& sText, const QColor& rgbColor = Qt::darkGray); // Time-scale command methods. bool redo(); bool undo(); }; //---------------------------------------------------------------------- // class qtractorTimeScaleRemoveMarkerCommand - declaration. // class qtractorTimeScaleRemoveMarkerCommand : public qtractorTimeScaleMarkerCommand { public: // Constructor. qtractorTimeScaleRemoveMarkerCommand( qtractorTimeScale *pTimeScale, qtractorTimeScale::Marker *pMarker); // Time-scale command methods. bool redo(); bool undo(); }; //---------------------------------------------------------------------- // class qtractorTimeScaleMoveMarkerCommand - declaration. // class qtractorTimeScaleMoveMarkerCommand : public qtractorTimeScaleMarkerCommand { public: // Constructor. qtractorTimeScaleMoveMarkerCommand(qtractorTimeScale *pTimeScale, qtractorTimeScale::Marker *pMarker, unsigned long iFrame); // Time-scale command methods. bool redo(); bool undo(); private: // The new location argument. unsigned long m_iNewFrame; // Replaced marker salvage. bool m_bOldMarker; unsigned long m_iOldFrame; QString m_sOldText; QColor m_rgbOldColor; }; #endif // __qtractorTimeScaleCommand_h // end of qtractorTimeScaleCommand.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiMeter.cpp0000644000175000001440000000012311514076275021416 xustar000000000000000027 mtime=1295023293.370359 26 atime=1381134670.36708 30 ctime=1381134670.367080102 qtractor-0.5.11/src/qtractorMidiMeter.cpp0000644000175000001440000002613511514076275020714 0ustar00rncbcusers00000000000000// qtractorMidiMeter.cpp // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiMeter.h" #include "qtractorMidiMonitor.h" #include "qtractorObserverWidget.h" #include #include #include #include #include #include // The decay rates (magic goes here :). // - value decay rate (faster) #define QTRACTOR_MIDI_METER_DECAY_RATE1 (1.0f - 1E-5f) // - peak decay rate (slower) #define QTRACTOR_MIDI_METER_DECAY_RATE2 (1.0f - 1E-6f) // Number of cycles the peak stays on hold before fall-off. #define QTRACTOR_MIDI_METER_PEAK_FALLOFF 16 // Number of cycles the MIDI LED stays on before going off. #define QTRACTOR_MIDI_METER_HOLD_LEDON 4 // MIDI On/Off LED pixmap resource. int qtractorMidiMeter::g_iLedRefCount = 0; QPixmap *qtractorMidiMeter::g_pLedPixmap[qtractorMidiMeter::LedCount]; // MIDI meter color arrays. QColor qtractorMidiMeter::g_defaultColors[qtractorMidiMeter::ColorCount] = { QColor(160,220, 20), // ColorPeak QColor(160,160, 40), // ColorOver QColor( 20, 40, 20), // ColorBack QColor( 80, 80, 80) // ColorFore }; QColor qtractorMidiMeter::g_currentColors[qtractorMidiMeter::ColorCount] = { g_defaultColors[ColorPeak], g_defaultColors[ColorOver], g_defaultColors[ColorBack], g_defaultColors[ColorFore] }; //---------------------------------------------------------------------------- // qtractorMidiMeterScale -- Meter bridge scale widget. // Constructor. qtractorMidiMeterScale::qtractorMidiMeterScale ( qtractorMidiMeter *pMidiMeter, QWidget *pParent ) : qtractorMeterScale(pMidiMeter, pParent) { pMidiMeter->boxLayout()->addWidget(this); } // Actual scale drawing method. void qtractorMidiMeterScale::paintScale ( QPainter *pPainter ) { qtractorMidiMeter *pMidiMeter = static_cast (meter()); if (pMidiMeter == NULL) return; int h = QWidget::height() - 4; int d = (h / 5); int n = 100; while (h > 0) { drawLineLabel(pPainter, h, QString::number(n)); h -= d; n -= 20; } } //---------------------------------------------------------------------------- // qtractorMidiMeterValue -- Meter bridge value widget. // Constructor. qtractorMidiMeterValue::qtractorMidiMeterValue ( qtractorMidiMeter *pMidiMeter, QWidget *pParent ) : QWidget(pParent), m_pMidiMeter(pMidiMeter) { // Avoid intensively annoying repaints... QWidget::setAttribute(Qt::WA_StaticContents); QWidget::setAttribute(Qt::WA_OpaquePaintEvent); m_iValue = 0; m_fValueDecay = QTRACTOR_MIDI_METER_DECAY_RATE1; m_iPeak = 0; m_iPeakHold = 0; m_fPeakDecay = QTRACTOR_MIDI_METER_DECAY_RATE2; QWidget::setFixedWidth(14); QWidget::setBackgroundRole(QPalette::NoRole); pMidiMeter->boxLayout()->addWidget(this); } // Default destructor. qtractorMidiMeterValue::~qtractorMidiMeterValue (void) { } // Reset peak holder. void qtractorMidiMeterValue::peakReset (void) { m_iPeak = 0; } // Value refreshment. void qtractorMidiMeterValue::refresh (void) { qtractorMidiMonitor *pMidiMonitor = m_pMidiMeter->midiMonitor(); if (pMidiMonitor == NULL) return; float fValue = pMidiMonitor->value(); if (fValue < 0.001f && m_iPeak < 1) return; int iValue = int(fValue * float(QWidget::height())); if (iValue < m_iValue) { iValue = int(m_fValueDecay * float(m_iValue)); m_fValueDecay *= m_fValueDecay; } else { m_fValueDecay = QTRACTOR_MIDI_METER_DECAY_RATE1; } int iPeak = m_iPeak; if (iPeak < iValue) { iPeak = iValue; m_iPeakHold = 0; m_fPeakDecay = QTRACTOR_MIDI_METER_DECAY_RATE2; } else if (++m_iPeakHold > m_pMidiMeter->peakFalloff()) { iPeak = int(m_fPeakDecay * float(iPeak)); if (iPeak < iValue) { iPeak = iValue; } else { m_fPeakDecay *= m_fPeakDecay; } } if (iValue == m_iValue && iPeak == m_iPeak) return; m_iValue = iValue; m_iPeak = iPeak; update(); } // Paint event handler. void qtractorMidiMeterValue::paintEvent ( QPaintEvent * ) { QPainter painter(this); int w = QWidget::width(); int h = QWidget::height(); if (isEnabled()) { painter.fillRect(0, 0, w, h, m_pMidiMeter->color(qtractorMidiMeter::ColorBack)); } else { painter.fillRect(0, 0, w, h, Qt::gray); } #ifdef CONFIG_GRADIENT painter.drawPixmap(0, h - m_iValue, m_pMidiMeter->pixmap(), 0, h - m_iValue, w, m_iValue); #else painter.fillRect(0, h - m_iValue, w, m_iValue, m_pMidiMeter->color(qtractorMidiMeter::ColorOver)); #endif painter.setPen(m_pMidiMeter->color(qtractorMidiMeter::ColorPeak)); painter.drawLine(0, h - m_iPeak, w, h - m_iPeak); } // Resize event handler. void qtractorMidiMeterValue::resizeEvent ( QResizeEvent *pResizeEvent ) { m_iPeak = 0; QWidget::resizeEvent(pResizeEvent); // QWidget::repaint(); } //---------------------------------------------------------------------- // class qtractorMidiMeter::GainSpinBoxInterface -- Observer interface. // // Local converter interface. class qtractorMidiMeter::GainSpinBoxInterface : public qtractorObserverSpinBox::Interface { public: // Constructor. GainSpinBoxInterface ( qtractorObserverSpinBox *pSpinBox ) : qtractorObserverSpinBox::Interface(pSpinBox) {} // Formerly Pure virtuals. float scaleFromValue ( float fValue ) const { return 100.0f * fValue; } float valueFromScale ( float fScale ) const { return 0.01f * fScale; } }; //---------------------------------------------------------------------- // class qtractorMidiMeter::GainSliderInterface -- Observer interface. // // Local converter interface. class qtractorMidiMeter::GainSliderInterface : public qtractorObserverSlider::Interface { public: // Constructor. GainSliderInterface ( qtractorObserverSlider *pSlider ) : qtractorObserverSlider::Interface(pSlider) {} // Formerly Pure virtuals. float scaleFromValue ( float fValue ) const { return 10000.0f * fValue; } float valueFromScale ( float fScale ) const { return 0.0001f * fScale; } }; //---------------------------------------------------------------------------- // qtractorMidiMeter -- Audio meter bridge slot widget. // Constructor. qtractorMidiMeter::qtractorMidiMeter ( qtractorMidiMonitor *pMidiMonitor, QWidget *pParent ) : qtractorMeter(pParent) { if (++g_iLedRefCount == 1) { g_pLedPixmap[LedOff] = new QPixmap(":/images/trackMidiOff.png"); g_pLedPixmap[LedOn] = new QPixmap(":/images/trackMidiOn.png"); } m_pMidiMonitor = pMidiMonitor; m_iMidiCount = 0; #ifdef CONFIG_GRADIENT m_pPixmap = new QPixmap(); #endif topLayout()->addStretch(); m_pMidiLabel = new QLabel(/*topWidget()*/); m_pMidiLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); m_pMidiLabel->setPixmap(*g_pLedPixmap[LedOff]); topLayout()->addWidget(m_pMidiLabel); gainSlider()->setInterface(new GainSliderInterface(gainSlider())); gainSpinBox()->setInterface(new GainSpinBoxInterface(gainSpinBox())); gainSpinBox()->setMinimum(0.0f); gainSpinBox()->setMaximum(100.0f); gainSpinBox()->setToolTip(tr("Volume (%)")); gainSpinBox()->setSuffix(tr(" %")); m_pMidiScale = new qtractorMidiMeterScale(this/*, boxWidget()*/); m_pMidiValue = new qtractorMidiMeterValue(this/*, boxWidget()*/); setPeakFalloff(QTRACTOR_MIDI_METER_PEAK_FALLOFF); reset(); updatePanning(); updateGain(); } // Default destructor. qtractorMidiMeter::~qtractorMidiMeter (void) { #ifdef CONFIG_GRADIENT delete m_pPixmap; #endif // No need to delete child widgets, Qt does it all for us delete m_pMidiValue; delete m_pMidiScale; delete m_pMidiLabel; if (--g_iLedRefCount == 0) { delete g_pLedPixmap[LedOff]; delete g_pLedPixmap[LedOn]; } } // MIDI monitor reset void qtractorMidiMeter::reset (void) { if (m_pMidiMonitor == NULL) return; setPanningSubject(m_pMidiMonitor->panningSubject()); setGainSubject(m_pMidiMonitor->gainSubject()); } // Reset peak holder. void qtractorMidiMeter::peakReset (void) { m_pMidiValue->peakReset(); m_iMidiCount = 0; } #ifdef CONFIG_GRADIENT // Gradient pixmap accessor. const QPixmap& qtractorMidiMeter::pixmap (void) const { return *m_pPixmap; } void qtractorMidiMeter::updatePixmap (void) { int w = boxWidget()->width(); int h = boxWidget()->height(); QLinearGradient grad(0, 0, 0, h); grad.setColorAt(0.0f, color(ColorPeak)); grad.setColorAt(0.4f, color(ColorOver)); *m_pPixmap = QPixmap(w, h); QPainter(m_pPixmap).fillRect(0, 0, w, h, grad); } #endif // Slot refreshment. void qtractorMidiMeter::refresh (void) { m_pMidiValue->refresh(); // Take care of the MIDI LED status... bool bMidiOn = (m_pMidiMonitor->count() > 0); if (bMidiOn) { if (m_iMidiCount == 0) m_pMidiLabel->setPixmap(*g_pLedPixmap[LedOn]); m_iMidiCount = QTRACTOR_MIDI_METER_HOLD_LEDON; } else if (m_iMidiCount > 0) { if (--m_iMidiCount == 0) m_pMidiLabel->setPixmap(*g_pLedPixmap[LedOff]); } } // Resize event handler. void qtractorMidiMeter::resizeEvent ( QResizeEvent * ) { // HACK: make so that the MIDI gain slider (volume) // aligns its top at the Audio 0 dB gain level... int iFixedHeight = int(0.15f * float(boxWidget()->height())) - 4; if (iFixedHeight < 16) iFixedHeight = 16; topWidget()->setFixedHeight(iFixedHeight); #ifdef CONFIG_GRADIENT updatePixmap(); #endif } // Virtual monitor accessor. void qtractorMidiMeter::setMonitor ( qtractorMonitor *pMonitor ) { setMidiMonitor(static_cast (pMonitor)); } qtractorMonitor *qtractorMidiMeter::monitor (void) const { return midiMonitor(); } // MIDI monitor accessor. void qtractorMidiMeter::setMidiMonitor ( qtractorMidiMonitor *pMidiMonitor ) { m_pMidiMonitor = pMidiMonitor; reset(); } qtractorMidiMonitor *qtractorMidiMeter::midiMonitor (void) const { return m_pMidiMonitor; } // Common resource accessor. void qtractorMidiMeter::setColor ( int iIndex, const QColor& color ) { g_currentColors[iIndex] = color; } const QColor& qtractorMidiMeter::color ( int iIndex ) { return g_currentColors[iIndex]; } const QColor& qtractorMidiMeter::defaultColor ( int iIndex ) { return g_defaultColors[iIndex]; } // Pan-slider value change method. void qtractorMidiMeter::updatePanning (void) { // setPanning(m_pMidiMonitor->panning()); panSlider()->setToolTip( tr("Pan: %1").arg(panning(), 0, 'g', 2)); } // Gain-slider value change method. void qtractorMidiMeter::updateGain (void) { // setGain(m_pMidiMonitor->gain()); gainSlider()->setToolTip( tr("Volume: %1%").arg(gainSpinBox()->value(), 0, 'g', 3)); } // end of qtractorMidiMeter.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiFile.cpp0000644000175000001440000000012312147444575021226 xustar000000000000000027 mtime=1369327997.991776 26 atime=1381134666.49308 30 ctime=1381134666.493080041 qtractor-0.5.11/src/qtractorMidiFile.cpp0000644000175000001440000007213512147444575020525 0ustar00rncbcusers00000000000000// qtractorMidiFile.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiFile.h" #include "qtractorTimeScale.h" #include #include #include // Symbolic header markers. #define SMF_MTHD "MThd" #define SMF_MTRK "MTrk" //---------------------------------------------------------------------- // class qtractorMidiFile -- A SMF (Standard MIDI File) class. // // Constructor. qtractorMidiFile::qtractorMidiFile (void) { // SMF instance variables. m_iMode = None; m_pFile = NULL; m_iOffset = 0; // Header informational data. m_iFormat = 0; m_iTracks = 0; m_iTicksPerBeat = 0; m_pTrackInfo = NULL; // Special tempo/time-signature map. m_pTempoMap = NULL; } // Destructor. qtractorMidiFile::~qtractorMidiFile (void) { close(); } // Open file method. bool qtractorMidiFile::open ( const QString& sFilename, int iMode ) { close(); if (iMode == None) iMode = Read; QByteArray aFilename = sFilename.toUtf8(); m_pFile = ::fopen(aFilename.constData(), iMode == Write ? "w+b" : "rb"); if (m_pFile == NULL) return false; m_sFilename = sFilename; m_iMode = iMode; m_iOffset = 0; // Bail out of here, if in write mode... if (m_iMode == Write) return true; // First word must identify the file as a SMF; // must be literal "MThd" char header[5]; readData((unsigned char *) &header[0], 4); header[4] = (char) 0; if (::strcmp(header, SMF_MTHD)) { close(); return false; } // Second word should be the total header chunk length... int iMThdLength = readInt(4); if (iMThdLength < 6) { close(); return false; } // Read header data... m_iFormat = (unsigned short) readInt(2); m_iTracks = (unsigned short) readInt(2); m_iTicksPerBeat = (unsigned short) readInt(2); // Should skip any extra bytes... while (iMThdLength > 6) { if (::fgetc(m_pFile) < 0) { close(); return false; } ++m_iOffset; --iMThdLength; } // Allocate the track map. m_pTrackInfo = new TrackInfo [m_iTracks]; for (int iTrack = 0; iTrack < m_iTracks; ++iTrack) { // Must be a track header "MTrk"... readData((unsigned char *) &header[0], 4); header[4] = (char) 0; if (::strcmp(header, SMF_MTRK)) { close(); return false; } // Check track chunk length... int iMTrkLength = readInt(4); if (iMTrkLength < 0) { close(); return false; } // Set this one track info. m_pTrackInfo[iTrack].length = iMTrkLength; m_pTrackInfo[iTrack].offset = m_iOffset; // Set next track offset... m_iOffset += iMTrkLength; // Advance to next one... if (::fseek(m_pFile, m_iOffset, SEEK_SET)) { close(); return false; } } // Special tempo/time-signature map. m_pTempoMap = new qtractorMidiFileTempo(this); // We're in business... return true; } // Close file method. void qtractorMidiFile::close (void) { if (m_pFile) { ::fclose(m_pFile); m_pFile = NULL; } if (m_pTrackInfo) { delete [] m_pTrackInfo; m_pTrackInfo = NULL; } if (m_pTempoMap) { delete m_pTempoMap; m_pTempoMap = NULL; } } // Sequence/track/channel readers. bool qtractorMidiFile::readTracks ( qtractorMidiSequence **ppSeqs, unsigned short iSeqs, unsigned short iTrackChannel ) { if (m_pFile == NULL) return false; if (m_pTempoMap == NULL) return false; if (m_iMode != Read) return false; // So, how many tracks are we reading in a row?... unsigned short iSeqTracks = (iSeqs > 1 ? m_iTracks : 1); // Go fetch them... for (unsigned short iSeqTrack = 0; iSeqTrack < iSeqTracks; ++iSeqTrack) { // If under a format 0 file, we'll filter for one single channel. if (iSeqTracks > 1) iTrackChannel = iSeqTrack; unsigned short iTrack = (m_iFormat == 1 ? iTrackChannel : 0); if (iTrack >= m_iTracks) return false; unsigned short iChannelFilter = iTrackChannel; if (m_iFormat == 1 || iSeqs > 1) iChannelFilter = 0xf0; // Locate the desired track stuff... unsigned long iTrackStart = m_pTrackInfo[iTrack].offset; if (iTrackStart != m_iOffset) { if (::fseek(m_pFile, iTrackStart, SEEK_SET)) return false; m_iOffset = iTrackStart; } // Now we're going into business... unsigned long iTrackTime = 0; unsigned long iTrackEnd = m_iOffset + m_pTrackInfo[iTrack].length; unsigned int iLastStatus = 0; // While this track lasts... while (m_iOffset < iTrackEnd) { // Read delta timestamp... iTrackTime += readInt(); // Read probable status byte... unsigned int iStatus = readInt(1); // Maybe a running status byte? if ((iStatus & 0x80) == 0) { // Go back one byte... ::ungetc(iStatus, m_pFile); --m_iOffset; iStatus = iLastStatus; } else { iLastStatus = iStatus; } unsigned short iChannel = (iStatus & 0x0f); qtractorMidiEvent::EventType type = qtractorMidiEvent::EventType(iStatus & 0xf0); if (iStatus == qtractorMidiEvent::META) type = qtractorMidiEvent::META; // Make proper sequence reference... unsigned short iSeq = 0; if (iSeqs > 1) iSeq = (m_iFormat == 0 ? iChannel : iTrack); qtractorMidiSequence *pSeq = ppSeqs[iSeq]; // Event time converted to sequence resolution... unsigned long iTime = pSeq->timeq(iTrackTime, m_iTicksPerBeat); // Check for sequence time length, if any... if (pSeq->timeLength() > 0 && iTime >= pSeq->timeOffset() + pSeq->timeLength()) break; // Check whether it won't be channel filtered... bool bChannelEvent = (iTime >= pSeq->timeOffset() && ((iChannelFilter & 0xf0) || (iChannelFilter == iChannel))); qtractorMidiEvent *pEvent; unsigned char *data, data1, data2; unsigned int len, meta, bank; switch (type) { case qtractorMidiEvent::NOTEOFF: case qtractorMidiEvent::NOTEON: data1 = readInt(1); data2 = readInt(1); // Check if its channel filtered... if (bChannelEvent) { if (data2 == 0 && type == qtractorMidiEvent::NOTEON) type = qtractorMidiEvent::NOTEOFF; pEvent = new qtractorMidiEvent(iTime, type, data1, data2); pSeq->addEvent(pEvent); pSeq->setChannel(iChannel); } break; case qtractorMidiEvent::CONTROLLER: data1 = readInt(1); data2 = readInt(1); // Check if its channel filtered... if (bChannelEvent) { // Create the new event... pEvent = new qtractorMidiEvent(iTime, type, data1, data2); pSeq->addEvent(pEvent); pSeq->setChannel(iChannel); // Set the primordial bank patch... switch (data1) { case 0x00: // Bank MSB... bank = (pSeq->bank() < 0 ? 0 : (pSeq->bank() & 0x007f)); pSeq->setBank(bank | (data2 << 7)); break; case 0x20: // Bank LSB... bank = (pSeq->bank() < 0 ? 0 : (pSeq->bank() & 0x3f80)); pSeq->setBank(bank | data2); break; default: break; } } break; case qtractorMidiEvent::KEYPRESS: case qtractorMidiEvent::PITCHBEND: data1 = readInt(1); data2 = readInt(1); // Check if its channel filtered... if (bChannelEvent) { // Create the new event... pEvent = new qtractorMidiEvent(iTime, type, data1, data2); pSeq->addEvent(pEvent); pSeq->setChannel(iChannel); } break; case qtractorMidiEvent::PGMCHANGE: data1 = 0; data2 = readInt(1); // Check if its channel filtered... if (bChannelEvent) { // Create the new event... pEvent = new qtractorMidiEvent(iTime, type, data1, data2); pSeq->addEvent(pEvent); pSeq->setChannel(iChannel); // Set the primordial program patch... if (pSeq->prog() < 0) pSeq->setProg(data2); } break; case qtractorMidiEvent::CHANPRESS: data1 = 0; data2 = readInt(1); // Check if its channel filtered... if (bChannelEvent) { // Create the new event... pEvent = new qtractorMidiEvent(iTime, type, data1, data2); pSeq->addEvent(pEvent); pSeq->setChannel(iChannel); } break; case qtractorMidiEvent::SYSEX: len = readInt(); if ((int) len < 1) { m_iOffset = iTrackEnd; // Force EoT! break; } data = new unsigned char [1 + len]; data[0] = (unsigned char) type; // Skip 0xf0 head. if (readData(&data[1], len) < (int) len) { delete [] data; return false; } // Check if its channel filtered... if (bChannelEvent) { pEvent = new qtractorMidiEvent(iTime, type); pEvent->setSysex(data, 1 + len); pSeq->addEvent(pEvent); pSeq->setChannel(iChannel); } delete [] data; break; case qtractorMidiEvent::META: meta = qtractorMidiEvent::MetaType(readInt(1)); // Get the meta data... len = readInt(); if ((int) len < 1) { // m_iOffset = iTrackEnd; // Force EoT! break; } if (meta == qtractorMidiEvent::TEMPO) { m_pTempoMap->addNodeTempo(iTime, qtractorTimeScale::uroundf( 60000000.0f / float(readInt(len)))); } else { data = new unsigned char [len + 1]; if (readData(data, len) < (int) len) { delete [] data; return false; } data[len] = (unsigned char) 0; // Now, we'll deal only with some... switch (meta) { case qtractorMidiEvent::TRACKNAME: pSeq->setName(QString((const char *) data).simplified()); break; case qtractorMidiEvent::TIME: // Beats per bar is the numerator of time signature... if ((unsigned short) data[0] > 0) { m_pTempoMap->addNodeTime(iTime, (unsigned short) data[0], (unsigned short) data[1]); } break; case qtractorMidiEvent::MARKER: m_pTempoMap->addMarker(iTime, QString((const char *) data).simplified()); break; default: // Ignore all others... break; } delete [] data; } // Fall thru... default: break; } } } // FIXME: Commit the sequence(s) length... for (unsigned short iSeq = 0; iSeq < iSeqs; ++iSeq) ppSeqs[iSeq]->close(); #ifdef CONFIG_DEBUG_0 for (unsigned short iSeq = 0; iSeq < iSeqs; ++iSeq) { qtractorMidiSequence *pSeq = ppSeqs[iSeq]; qDebug("qtractorMidiFile::readTrack([%u]%p,%u,%u)" " name=\"%s\" events=%d duration=%lu", iSeq, pSeq, iSeqs, iTrackChannel, pSeq->name().toUtf8().constData(), pSeq->events().count(), pSeq->duration()); } #endif return true; } bool qtractorMidiFile::readTrack ( qtractorMidiSequence *pSeq, unsigned short iTrackChannel ) { return readTracks(&pSeq, 1, iTrackChannel); } // Header writer. bool qtractorMidiFile::writeHeader ( unsigned short iFormat, unsigned short iTracks, unsigned short iTicksPerBeat ) { if (m_pFile == NULL) return false; if (m_pTempoMap) return false; if (m_iMode != Write) return false; // SMF format 0 sanitization... if (iFormat == 0) iTracks = 1; #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiFile::writeHeader(%u,%u,%u)", iFormat, iTracks, iTicksPerBeat); #endif // First word must identify the file as a SMF; // must be literal "MThd" writeData((unsigned char *) SMF_MTHD, 4); // Second word should be the total header chunk length... writeInt(6, 4); // Write header data (6 bytes)... writeInt(m_iFormat = iFormat, 2); writeInt(m_iTracks = iTracks, 2); writeInt(m_iTicksPerBeat = iTicksPerBeat, 2); // Special tempo/time-signature map. m_pTempoMap = new qtractorMidiFileTempo(this); // Assume all is fine. return true; } // Sequence/track writers. bool qtractorMidiFile::writeTracks ( qtractorMidiSequence **ppSeqs, unsigned short iSeqs ) { if (m_pFile == NULL) return false; if (m_pTempoMap == NULL) return false; if (m_iMode != Write) return false; #ifdef CONFIG_DEBUG_0 if (ppSeqs == NULL) qDebug("qtractorMidiFile::writeTrack(NULL,%u)", iSeqs); for (unsigned short iSeq = 0; ppSeqs && iSeq < iSeqs; ++iSeq) { qtractorMidiSequence *pSeq = ppSeqs[iSeq]; qDebug("qtractorMidiFile::writeTrack([%u]%p,%u)" " name=\"%s\" events=%d duration=%lu", iSeq, pSeq, iSeqs, pSeq->name().toUtf8().constData(), pSeq->events().count(), pSeq->duration()); } #endif // So, how many tracks are we reading in a row?... unsigned short iTracks = (iSeqs > 1 ? m_iTracks : 1); // Go fetch them... for (unsigned short iTrack = 0; iTrack < iTracks; ++iTrack) { // Make proper initial sequence reference... unsigned short iSeq = 0; if (iSeqs > 1 && m_iFormat == 1) iSeq = iTrack; // Which is just good for track labeling... qtractorMidiSequence *pSeq = NULL; if (ppSeqs) pSeq = ppSeqs[iSeq]; // Must be a track header "MTrk"... writeData((unsigned char *) SMF_MTRK, 4); // Write a dummy track length (we'll overwrite it later)... unsigned long iMTrkOffset = m_iOffset; writeInt(0, 4); // Track name... QString sTrackName = (pSeq ? pSeq->name() : QFileInfo(m_sFilename).baseName()); if (!sTrackName.isEmpty()) { writeInt(0); // delta-time=0 writeInt(qtractorMidiEvent::META, 1); writeInt(qtractorMidiEvent::TRACKNAME, 1); writeInt(sTrackName.length()); QByteArray aTrackName = sTrackName.toUtf8(); writeData((unsigned char *) aTrackName.constData(), aTrackName.length()); } // Tempo/time-signature map and location markers... qtractorMidiFileTempo::Node *pNode = m_pTempoMap->nodes().first(); qtractorMidiFileTempo::Marker *pMarker = m_pTempoMap->markers().first(); // Tempo/time-signature map (track 0) // - applicable to SMF format 1 files... if (pSeq == NULL) { unsigned long iNodeTime = 0; while (pNode) { while (pMarker && pMarker->tick < pNode->tick) { writeMarker(pMarker, iNodeTime); iNodeTime = pMarker->tick; pMarker = pMarker->next(); } writeNode(pNode, iNodeTime); iNodeTime = pNode->tick; pNode = pNode->next(); } while (pMarker) { writeMarker(pMarker, iNodeTime); iNodeTime = pMarker->tick; pMarker = pMarker->next(); } } // Now's time for proper events being written down... // if (pSeq) { // Provisional data structures for sequence merging... struct EventItem { EventItem(qtractorMidiSequence *pSeq) : seq(pSeq), event(pSeq->events().first()) { notesOff.setAutoDelete(true); } qtractorMidiSequence *seq; qtractorMidiEvent *event; qtractorList notesOff; }; EventItem *pItem; unsigned short iItem; unsigned short iItems = (m_iFormat == 0 ? iSeqs : 1); // Prolog... EventItem **ppItems = new EventItem * [iItems]; for (iItem = 0; iItem < iItems; ++iItem) { iSeq = (m_iFormat == 0 ? iItem : iTrack); ppItems[iItem] = new EventItem(ppSeqs[iSeq]); } // Write the whole sequence out... unsigned int iChannel; unsigned int iStatus; unsigned int iLastStatus = 0; unsigned long iLastTime = 0; unsigned long iTime; unsigned long iTimeOff; unsigned char *data; unsigned int len; EventItem *pEventItem; EventItem *pNoteOffItem; qtractorMidiEvent *pEvent; qtractorMidiEvent *pNoteFirst; qtractorMidiEvent *pNoteAfter; qtractorMidiEvent *pNoteOff; unsigned long iEventTime = 0; // Track/channel bank-select... if (pSeq->bank() >= 0) { iChannel = pSeq->channel(); iStatus = (qtractorMidiEvent::CONTROLLER | iChannel) & 0xff; writeInt(0); // delta-time=0 writeInt(iStatus, 1); writeInt(0x00, 1); // Bank MSB. writeInt((pSeq->bank() & 0x3f80) >> 7, 1); writeInt(0); // delta-time=0 writeInt(iStatus, 1); writeInt(0x20, 1); // Bank LSB. writeInt((pSeq->bank() & 0x007f), 1); } // Track/channel program change... if (pSeq->prog() >= 0) { iChannel = pSeq->channel(); iStatus = (qtractorMidiEvent::PGMCHANGE | iChannel) & 0xff; writeInt(0); // delta-time=0 writeInt(iStatus, 1); writeInt((pSeq->prog() & 0x007f), 1); } // Lets-a go, down to event merge loop... // for (;;) { // Find which will be next event to write out, // keeping account onto sequence merging... pSeq = NULL; pEvent = NULL; pEventItem = NULL; for (iItem = 0; iItem < iItems; ++iItem) { pItem = ppItems[iItem]; if (pItem->event && (pEventItem == NULL || iEventTime >= (pItem->event)->time())) { iEventTime = (pItem->event)->time(); pEventItem = pItem; } } // So we'll have another event ready? if (pEventItem) { pSeq = pEventItem->seq; pEvent = pEventItem->event; pEventItem->event = pEvent->next(); if (pEventItem->event) iEventTime = (pEventItem->event)->time(); } // Maybe we reached the (partial) end... if (pEvent == NULL) break; // Event (absolute) time converted to file resolution... iTime = pSeq->timep(pEvent->time(), m_iTicksPerBeat); // Check for pending note-offs... for (;;) { // Get any a note-off event pending... iTimeOff = iTime; pNoteOff = NULL; pNoteOffItem = NULL; for (iItem = 0; iItem < iItems; ++iItem) { pItem = ppItems[iItem]; pNoteFirst = pItem->notesOff.first(); if (pNoteFirst && iTimeOff >= pNoteFirst->time()) { iTimeOff = pNoteFirst->time(); pNoteOff = pNoteFirst; pNoteOffItem = pItem; } } // Was there any? if (pNoteOff == NULL) break; // - Delta time... writeInt(iTimeOff > iLastTime ? iTimeOff - iLastTime : 0); iLastTime = iTimeOff; // - Status byte... iChannel = (pNoteOffItem->seq)->channel(); iStatus = (pNoteOff->type() | iChannel) & 0xff; // - Running status... if (iStatus != iLastStatus) { writeInt(iStatus, 1); iLastStatus = iStatus; } // - Data bytes... writeInt(pNoteOff->note(), 1); writeInt(pNoteOff->velocity(), 1); // Remove from note-off list and continue... pNoteOffItem->notesOff.remove(pNoteOff); } // Tempo/time-signature map (interleaved) // - applicable to SMF format 0 files... if (iSeqs > 1 && iTrack == 0) { while (pNode && iTime >= pNode->tick) { while (pMarker && pMarker->tick < pNode->tick) { writeMarker(pMarker, iLastTime); iLastTime = pMarker->tick; pMarker = pMarker->next(); } writeNode(pNode, iLastTime); iLastTime = pNode->tick; iLastStatus = 0; pNode = pNode->next(); } while (pMarker && iTime >= pMarker->tick) { writeMarker(pMarker, iLastTime); iLastTime = pMarker->tick; iLastStatus = 0; pMarker = pMarker->next(); } } // OK. Let's get back to actual event... // - Delta time... writeInt(iTime > iLastTime ? iTime - iLastTime : 0); iLastTime = iTime; // - Status byte... iChannel = pSeq->channel(); iStatus = (pEvent->type() | iChannel) & 0xff; // - Running status? if (iStatus != iLastStatus) { writeInt(iStatus, 1); iLastStatus = iStatus; } // - Data bytes... switch (pEvent->type()) { case qtractorMidiEvent::NOTEON: writeInt(pEvent->note(), 1); writeInt(pEvent->velocity(), 1); iTimeOff = (pEvent->time() + pEvent->duration()); pNoteOff = new qtractorMidiEvent( pSeq->timep(iTimeOff, m_iTicksPerBeat), qtractorMidiEvent::NOTEOFF, pEvent->note()); // Find the proper position in notes-off list ... pNoteAfter = pEventItem->notesOff.last(); while (pNoteAfter && pNoteAfter->time() > pNoteOff->time()) pNoteAfter = pNoteAfter->prev(); if (pNoteAfter) pEventItem->notesOff.insertAfter(pNoteOff, pNoteAfter); else pEventItem->notesOff.prepend(pNoteOff); break; case qtractorMidiEvent::CONTROLLER: writeInt(pEvent->controller(), 1); writeInt(pEvent->value(), 1); break; case qtractorMidiEvent::KEYPRESS: case qtractorMidiEvent::PITCHBEND: writeInt(pEvent->note(), 1); writeInt(pEvent->velocity(), 1); break; case qtractorMidiEvent::PGMCHANGE: case qtractorMidiEvent::CHANPRESS: writeInt(pEvent->value(), 1); break; case qtractorMidiEvent::SYSEX: if (pEvent->sysex() && pEvent->sysex_len() > 1) { data = pEvent->sysex() + 1; // Skip 0xf0 head. len = pEvent->sysex_len() - 1; writeInt(len); writeData(data, len); } // Fall thru... default: break; } } // Merge all remaining note-offs... for (iItem = 0; iItem < iItems; ++iItem) { pItem = ppItems[iItem]; pItem->event = pItem->notesOff.first(); } iTimeOff = 0; for (;;) { // Find which note-off will be next to write out, // always accounting for sequence merging... pNoteOff = NULL; pNoteOffItem = NULL; for (iItem = 0; iItem < iItems; ++iItem) { pItem = ppItems[iItem]; if (pItem->event && (pNoteOffItem == NULL || iTimeOff >= (pItem->event)->time())) { iTimeOff = (pItem->event)->time(); pNoteOffItem = pItem; } } // So we'll have another event ready? if (pNoteOffItem) { pNoteOff = pNoteOffItem->event; pNoteOffItem->event = pNoteOff->next(); if (pNoteOffItem->event) iTimeOff = (pNoteOffItem->event)->time(); } // Maybe we reached the (whole) end... if (pNoteOff == NULL) break; // - Delta time... iTime = pNoteOff->time(); writeInt(iTime > iLastTime ? iTime - iLastTime : 0); iLastTime = iTime; // - Status byte... iChannel = (pNoteOffItem->seq)->channel(); iStatus = (pNoteOff->type() | iChannel) & 0xff; // - Running status... if (iStatus != iLastStatus) { writeInt(iStatus, 1); iLastStatus = iStatus; } // - Data bytes... writeInt(pNoteOff->note(), 1); writeInt(pNoteOff->velocity(), 1); // Done with this note-off... } // Epilog... for (iItem = 0; iItem < iItems; ++iItem) delete ppItems[iItem]; delete [] ppItems; } // End-of-track marker. writeInt(0); // delta-time=0 writeInt(qtractorMidiEvent::META, 1); writeInt(qtractorMidiEvent::EOT, 1); writeInt(0); // length=0; // Time to overwrite the actual track length... if (::fseek(m_pFile, iMTrkOffset, SEEK_SET)) return false; // Do it... writeInt(m_iOffset - (iMTrkOffset + 4), 4); m_iOffset -= 4; // Restore file position to end-of-file... if (::fseek(m_pFile, m_iOffset, SEEK_SET)) return false; } // Success. return true; } bool qtractorMidiFile::writeTrack ( qtractorMidiSequence *pSeq ) { return writeTracks((pSeq ? &pSeq : NULL), 1); } // Integer read method. int qtractorMidiFile::readInt ( unsigned short n ) { int c, val = 0; if (n > 0) { // Fixed length (n bytes) integer read. for (int i = 0; i < n; ++i) { val <<= 8; c = ::fgetc(m_pFile); if (c < 0) return -1; val |= c; ++m_iOffset; } } else { // Variable length integer read. do { c = ::fgetc(m_pFile); if (c < 0) return -1; val <<= 7; val |= (c & 0x7f); ++m_iOffset; } while ((c & 0x80) == 0x80); } return val; } // Raw data read method. int qtractorMidiFile::readData ( unsigned char *pData, unsigned short n ) { int nread = ::fread(pData, sizeof(unsigned char), n, m_pFile); if (nread > 0) m_iOffset += nread; return nread; } // Integer write method. int qtractorMidiFile::writeInt ( int val, unsigned short n ) { int c; if (n > 0) { // Fixed length (n bytes) integer write. for (int i = (n - 1) * 8; i >= 0; i -= 8) { c = (val & (0xff << i)) >> i; if (::fputc(c & 0xff, m_pFile) < 0) return -1; ++m_iOffset; } } else { // Variable length integer write. n = 0; c = val & 0x7f; while (val >>= 7) { c <<= 8; c |= (val & 0x7f) | 0x80; } while (true) { if (::fputc(c & 0xff, m_pFile) < 0) return -1; ++n; if ((c & 0x80) == 0) break; c >>= 8; } m_iOffset += n; } return n; } // Raw data write method. int qtractorMidiFile::writeData ( unsigned char *pData, unsigned short n ) { int nwrite = ::fwrite(pData, sizeof(unsigned char), n, m_pFile); if (nwrite > 0) m_iOffset += nwrite; return nwrite; } // Write tempo-time-signature node. void qtractorMidiFile::writeNode ( qtractorMidiFileTempo::Node *pNode, unsigned long iLastTime ) { unsigned long iDeltaTime = (pNode->tick > iLastTime ? pNode->tick - iLastTime : 0); qtractorMidiFileTempo::Node *pPrev = pNode->prev(); if (pPrev == NULL || (pPrev->tempo != pNode->tempo)) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiFile::writeNode(%lu) time=%lu TEMPO (%g)", iLastTime, iDeltaTime, pNode->tempo); #endif // Tempo change... writeInt(iDeltaTime); writeInt(qtractorMidiEvent::META, 1); writeInt(qtractorMidiEvent::TEMPO, 1); writeInt(3); writeInt(qtractorTimeScale::uroundf(60000000.0f / pNode->tempo), 3); iDeltaTime = 0; } if (pPrev == NULL || pPrev->beatsPerBar != pNode->beatsPerBar || pPrev->beatDivisor != pNode->beatDivisor) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiFile::writeNode(%lu) time=%lu TIME (%u/%u)", iLastTime, iDeltaTime, pNode->beatsPerBar, 1 << pNode->beatDivisor); #endif // Time signature change... writeInt(iDeltaTime); writeInt(qtractorMidiEvent::META, 1); writeInt(qtractorMidiEvent::TIME, 1); writeInt(4); writeInt(pNode->beatsPerBar, 1); // Numerator. writeInt(pNode->beatDivisor, 1); // Denominator. writeInt(32, 1); // MIDI clocks per metronome click. writeInt(4, 1); // 32nd notes per quarter. // iDeltaTime = 0; } } // Write location marker. void qtractorMidiFile::writeMarker ( qtractorMidiFileTempo::Marker *pMarker, unsigned long iLastTime ) { unsigned long iDeltaTime = (pMarker->tick > iLastTime ? pMarker->tick - iLastTime : 0); #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiFile::writeMarker(%lu) time=%lu (\"%s\")", iLastTime, iDeltaTime, pMarker->text.toUft8().constData()); #endif writeInt(iDeltaTime); writeInt(qtractorMidiEvent::META, 1); writeInt(qtractorMidiEvent::MARKER, 1); writeInt(pMarker->text.length()); const QByteArray aMarker = pMarker->text.toUtf8(); writeData((unsigned char *) aMarker.constData(), aMarker.length()); } // Create filename revision (name says it all). QString qtractorMidiFile::createFilePathRevision ( const QString& sFilename, int iRevision ) { QFileInfo fi(sFilename); QDir adir(fi.absoluteDir()); QRegExp rxRevision("(.+)\\-(\\d+)$"); QString sBasename = fi.baseName(); if (rxRevision.exactMatch(sBasename)) { sBasename = rxRevision.cap(1); iRevision = rxRevision.cap(2).toInt(); } sBasename += "-%1." + fi.completeSuffix(); if (iRevision < 1) ++iRevision; fi.setFile(adir, sBasename.arg(iRevision)); while (fi.exists()) fi.setFile(adir, sBasename.arg(++iRevision)); #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiFile::createFilePathRevision(\"%s\")", fi.absoluteFilePath().toUtf8().constData()); #endif return fi.absoluteFilePath(); } // All-in-one SMF file writer/creator method. bool qtractorMidiFile::saveCopyFile ( const QString& sNewFilename, const QString& sOldFilename, unsigned short iTrackChannel, unsigned short iFormat, qtractorMidiSequence *pSeq, qtractorTimeScale *pTimeScale, unsigned long iTimeOffset ) { qtractorMidiFile file; qtractorTimeScale ts; unsigned short iTracks; unsigned short iSeq, iSeqs = 0; qtractorMidiSequence **ppSeqs = NULL; const QString sTrackName = QObject::tr("Track %1"); if (pSeq == NULL) return false; if (pTimeScale) ts.copy(*pTimeScale); // Open and load the whole source file... if (file.open(sOldFilename)) { ts.setTicksPerBeat(file.ticksPerBeat()); iFormat = file.format(); iSeqs = (iFormat == 1 ? file.tracks() : 16); ppSeqs = new qtractorMidiSequence * [iSeqs]; for (iSeq = 0; iSeq < iSeqs; ++iSeq) { ppSeqs[iSeq] = new qtractorMidiSequence( sTrackName.arg(iSeq + 1), iSeq, ts.ticksPerBeat()); } if (file.readTracks(ppSeqs, iSeqs) && file.tempoMap()) file.tempoMap()->intoTimeScale(&ts, iTimeOffset); file.close(); } // Open and save the whole target file... if (!file.open(sNewFilename, qtractorMidiFile::Write)) return false; if (ppSeqs == NULL) iSeqs = (iFormat == 0 ? 1 : 2); // Write SMF header... iTracks = (iFormat == 0 ? 1 : iSeqs); if (!file.writeHeader(iFormat, iTracks, ts.ticksPerBeat())) { file.close(); return false; } // Set (initial) tempo/time-signature node. if (file.tempoMap()) file.tempoMap()->fromTimeScale(&ts, iTimeOffset); // Write SMF tracks(s)... if (ppSeqs) { // Replace the target track-channel events... ppSeqs[iTrackChannel]->replaceEvents(pSeq); // Write the whole new tracks... file.writeTracks(ppSeqs, iSeqs); } else { // Most probabley this is a brand new file... if (iFormat == 1) file.writeTrack(NULL); file.writeTrack(pSeq); } file.close(); // Free locally allocated track/sequence array. if (ppSeqs) { for (iSeq = 0; iSeq < iSeqs; ++iSeq) delete ppSeqs[iSeq]; delete [] ppSeqs; } return true; } // end of qtractorMidiFile.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiMonitor.h0000644000175000001440000000012311632156165021434 xustar000000000000000027 mtime=1315495029.097474 26 atime=1381134668.06808 30 ctime=1381134668.068080066 qtractor-0.5.11/src/qtractorMidiMonitor.h0000644000175000001440000000521111632156165020722 0ustar00rncbcusers00000000000000// qtractorMidiMonitor.h // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiMonitor_h #define __qtractorMidiMonitor_h #include "qtractorMonitor.h" #include "qtractorMidiEvent.h" // Forwrad decalarations. class qtractorTimeScale; //---------------------------------------------------------------------------- // qtractorMidiMonitor -- MIDI monitor bridge value processor. class qtractorMidiMonitor : public qtractorMonitor { public: // Constructor. qtractorMidiMonitor(float fGain = 1.0f, float fPanning = 0.0f); // Destructor. ~qtractorMidiMonitor(); // Monitor enqueue methods. void enqueue(qtractorMidiEvent::EventType type, unsigned char val, unsigned long tick = 0); // Monitor dequeue methods. float value(); int count(); // Clear monitor. void clear(); // Reset monitor. void reset(); // Singleton time base reset. static void resetTime(qtractorTimeScale *pTimeScale, unsigned long iFrame); // Singleton time base split (scheduled tempo change) static void splitTime(qtractorTimeScale *pTimeScale, unsigned long iFrame, unsigned long iTime); protected: // Singleton time base slot. static unsigned int timeSlot(unsigned long iTime) { return g_iTimeSlot[g_iTimeSplit >= iTime ? 0 : 1]; } // Update monitor (nothing really done here). void update(); private: // Queue iten struct. struct QueueItem { unsigned char value; unsigned char count; }; // Instance variables. QueueItem *m_pQueue; unsigned int m_iQueueIndex; unsigned long m_iFrameStart; unsigned long m_iTimeStart; QueueItem m_item; // Singleton variables. static unsigned int g_iFrameSlot; static unsigned int g_iTimeSlot[2]; static unsigned long g_iTimeSplit; }; #endif // __qtractorMidiMonitor_h // end of qtractorMidiMonitor.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioVorbisFile.h0000644000175000001440000000012311563576072022236 xustar000000000000000027 mtime=1305410618.253123 26 atime=1381134666.49408 30 ctime=1381134666.494080041 qtractor-0.5.11/src/qtractorAudioVorbisFile.h0000644000175000001440000000617011563576072021531 0ustar00rncbcusers00000000000000// qtractorAudioVorbisFile.h // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorAudioVorbisFile_h #define __qtractorAudioVorbisFile_h #include "qtractorAudioFile.h" #ifdef CONFIG_LIBVORBIS // libvorbis API. #include #include #endif //---------------------------------------------------------------------- // class qtractorAudioVorbisFile -- Buffered audio file declaration. // class qtractorAudioVorbisFile : public qtractorAudioFile { public: // Constructor. qtractorAudioVorbisFile(unsigned short iChannels = 0, unsigned int iSampleRate = 0, unsigned int iBufferSize = 0); // Destructor. virtual ~qtractorAudioVorbisFile(); // Virtual method mockups. bool open (const QString& sFilename, int iMode = Read); int read (float **ppFrames, unsigned int iFrames); int write (float **ppFrames, unsigned int iFrames); bool seek (unsigned long iOffset); void close (); // Virtual accessor mockups. int mode() const; unsigned short channels() const; unsigned long frames() const; // Specialty methods. unsigned int sampleRate() const; protected: // Flush encoder buffers. void flush(bool fEos = false); private: int m_iMode; // open mode (Read only). FILE *m_pFile; // fopen file descriptor. unsigned short m_iChannels; // estimated channel count. unsigned int m_iSampleRate; // estimated sample rate; unsigned long m_iFrames; // estimated encoded frames; #ifdef CONFIG_LIBVORBIS // Common codec variable. vorbis_info *m_ovinfo; // libvorbisfile info struct. // Encoder specific variables. vorbis_comment m_ovcomment; // struct that stores all the user comments. vorbis_dsp_state m_ovdsp; // central working state for the encoder. vorbis_block m_ovblock; // local working space for the encoder. ogg_stream_state m_ovstate; // physical pages, logical stream of packets. // Decoder specific variables. OggVorbis_File m_ovfile; // libsvorbisfile descriptor. int m_ovsect; // libvorbisfile current section. #endif // CONFIG_LIBVORBIS unsigned int m_iBufferSize; // estimated buffer size. }; #endif // __qtractorAudioVorbisFile_h // end of qtractorAudioVorbisFile.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorConnections.cpp0000644000175000001440000000012311507411052022005 xustar000000000000000027 mtime=1293816362.933232 26 atime=1381134671.09608 30 ctime=1381134671.097080114 qtractor-0.5.11/src/qtractorConnections.cpp0000644000175000001440000001742511507411052021305 0ustar00rncbcusers00000000000000// qtractorConnections.cpp // /**************************************************************************** Copyright (C) 2005-2010, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorConnections.h" #include "qtractorSession.h" #include "qtractorOptions.h" #include "qtractorAudioEngine.h" #include "qtractorMidiEngine.h" #include "qtractorMainForm.h" #include "qtractorConnectForm.h" #include #include #include //------------------------------------------------------------------------- // qtractorConnections - Connections dockable window. // // Constructor. qtractorConnections::qtractorConnections ( QWidget *pParent, Qt::WindowFlags wflags ) : QWidget(pParent, wflags) { // Surely a name is crucial (e.g.for storing geometry settings) QWidget::setObjectName("qtractorConnections"); // Create main inner widget. m_pConnectForm = new qtractorConnectForm(this); // Set proper tab widget icons... QTabWidget *pTabWidget = m_pConnectForm->connectTabWidget(); pTabWidget->setTabIcon(0, QIcon(":/images/trackAudio.png")); pTabWidget->setTabIcon(1, QIcon(":/images/trackMidi.png")); // Prepare the layout stuff. QHBoxLayout *pLayout = new QHBoxLayout(); pLayout->setMargin(0); pLayout->setSpacing(0); pLayout->addWidget(m_pConnectForm); QWidget::setLayout(pLayout); // Some specialties to this kind of dock window... QWidget::setMinimumWidth(480); QWidget::setMinimumHeight(240); // Finally set the default caption and tooltip. const QString& sCaption = tr("Connections") + " - " QTRACTOR_TITLE; QWidget::setWindowTitle(sCaption); QWidget::setWindowIcon(QIcon(":/images/viewConnections.png")); QWidget::setToolTip(sCaption); // Get previously saved splitter sizes, // (with fair default...) qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { QList sizes; sizes.append(180); sizes.append(60); sizes.append(180); pOptions->loadSplitterSizes( m_pConnectForm->audioConnectSplitter(), sizes); pOptions->loadSplitterSizes( m_pConnectForm->midiConnectSplitter(), sizes); } } // Destructor. qtractorConnections::~qtractorConnections (void) { qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { // Get previously saved splitter sizes... pOptions->saveSplitterSizes( m_pConnectForm->audioConnectSplitter()); pOptions->saveSplitterSizes( m_pConnectForm->midiConnectSplitter()); } // No need to delete child widgets, Qt does it all for us. delete m_pConnectForm; } // Notify the main application widget that we're emerging. void qtractorConnections::showEvent ( QShowEvent *pShowEvent ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnections::showEvent()"); #endif qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeForm(); QWidget::showEvent(pShowEvent); } // Notify the main application widget that we're closing. void qtractorConnections::hideEvent ( QHideEvent *pHideEvent ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnections::hideEvent()"); #endif QWidget::hideEvent(pHideEvent); qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeForm(); } // Just about to notify main-window that we're closing. void qtractorConnections::closeEvent ( QCloseEvent * /*pCloseEvent*/ ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnections::closeEvent()"); #endif QWidget::hide(); qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeForm(); } // Connect form accessor. qtractorConnectForm *qtractorConnections::connectForm (void) const { return m_pConnectForm; } // Main bus mode switching. void qtractorConnections::showBus ( qtractorBus *pBus, qtractorBus::BusMode busMode ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; const QString sSuffix = ".*"; switch (pBus->busType()) { case qtractorTrack::Audio: { // Show exclusive Audio engine connections... qtractorAudioBus *pAudioBus = static_cast (pBus); if (pAudioBus) { m_pConnectForm->audioClear(); m_pConnectForm->connectTabWidget()->setCurrentIndex(0); if (busMode & qtractorBus::Input) { m_pConnectForm->audioOClientsComboBox()->setCurrentIndex(0); m_pConnectForm->audioIClientsComboBox()->setCurrentIndex( m_pConnectForm->audioIClientsComboBox()->findText( pSession->audioEngine()->clientName())); m_pConnectForm->audioIListView()->setPortName( pAudioBus->busName() + sSuffix); } else { m_pConnectForm->audioIClientsComboBox()->setCurrentIndex(0); m_pConnectForm->audioOClientsComboBox()->setCurrentIndex( m_pConnectForm->audioOClientsComboBox()->findText( pSession->audioEngine()->clientName())); m_pConnectForm->audioOListView()->setPortName( pAudioBus->busName() + sSuffix); } m_pConnectForm->audioRefresh(); } break; } case qtractorTrack::Midi: { // Show exclusive MIDI engine connections... qtractorMidiBus *pMidiBus = static_cast (pBus); if (pMidiBus) { m_pConnectForm->midiClear(); m_pConnectForm->connectTabWidget()->setCurrentIndex(1); if (busMode & qtractorBus::Input) { m_pConnectForm->midiOClientsComboBox()->setCurrentIndex(0); m_pConnectForm->midiIClientsComboBox()->setCurrentIndex( m_pConnectForm->midiIClientsComboBox()->findText( QString::number(pSession->midiEngine()->alsaClient()) + ':'+ pSession->midiEngine()->clientName())); m_pConnectForm->midiIListView()->setPortName( QString::number(pMidiBus->alsaPort()) + ':' + pMidiBus->busName() + sSuffix); } else { m_pConnectForm->midiIClientsComboBox()->setCurrentIndex(0); m_pConnectForm->midiOClientsComboBox()->setCurrentIndex( m_pConnectForm->midiOClientsComboBox()->findText( QString::number(pSession->midiEngine()->alsaClient()) + ':' + pSession->midiEngine()->clientName())); m_pConnectForm->midiOListView()->setPortName( QString::number(pMidiBus->alsaPort()) + ':' + pMidiBus->busName() + sSuffix); } m_pConnectForm->midiRefresh(); } break; } default: break; } // Make it stand out, sure... show(); raise(); activateWindow(); } // Complete connections refreshment. void qtractorConnections::refresh (void) { m_pConnectForm->audioRefresh(); m_pConnectForm->midiRefresh(); } // Complete connections recycle. void qtractorConnections::clear (void) { m_pConnectForm->audioClear(); m_pConnectForm->midiClear(); } // Conditional connections recycle. void qtractorConnections::reset (void) { m_pConnectForm->audioReset(); m_pConnectForm->midiReset(); } // Keyboard event handler. void qtractorConnections::keyPressEvent ( QKeyEvent *pKeyEvent ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnections::keyPressEvent(%d)", pKeyEvent->key()); #endif int iKey = pKeyEvent->key(); switch (iKey) { case Qt::Key_Escape: close(); break; default: QWidget::keyPressEvent(pKeyEvent); break; } } // end of qtractorConnections.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiControlForm.ui0000644000175000001440000000012212067456742022445 xustar000000000000000026 mtime=1356750306.99751 26 atime=1381134666.49508 30 ctime=1381134666.496080041 qtractor-0.5.11/src/qtractorMidiControlForm.ui0000644000175000001440000003101612067456742021736 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorMidiControlForm 0 0 538 377 Controllers - Qtractor :/images/itemControllers.png Controller files false true false true Files Path Import controller files &Import... :/images/formOpen.png Alt+I Remove controller file &Remove :/images/formRemove.png Alt+R Move controller file up on list order &Up :/images/formMoveUp.png Alt+U Move controller file down on list order &Down :/images/formMoveDown.png Alt+D &Type Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft ControlTypeComboBox &Channel Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft ChannelComboBox &Parameter Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft ParamComboBox Trac&k Offset Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft TrackSpinBox C&ommand Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft CommandComboBox Qt::Horizontal 20 8 MIDI Event type MIDI Channel MIDI Controller (parameter) MIDI parameter (track offset) + Track offset 0 Command action Command feedback &Feedback Map/update controller command &Map :/images/formAccept.png Alt+M 0 160 Controller map false true false true true Type Channel Parameter Track Command Feedback Unmap/remove controller command U&nmap :/images/formReject.png Alt+N Qt::Vertical 20 8 Reload/apply all controller files Relo&ad :/images/formRefresh.png Alt+A Export to controller file E&xport... :/images/formSave.png Alt+X Close this dialog Close FilesListView ImportPushButton RemovePushButton MoveUpPushButton MoveDownPushButton ControlTypeComboBox ChannelComboBox ParamComboBox TrackCheckBox TrackSpinBox CommandComboBox FeedbackCheckBox MapPushButton ControlMapListView UnmapPushButton ReloadPushButton ExportPushButton ClosePushButton qtractor-0.5.11/src/PaxHeaders.10084/qtractorConnectForm.h0000644000175000001440000000012311354101152021402 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134666.35508 30 ctime=1381134666.356080039 qtractor-0.5.11/src/qtractorConnectForm.h0000644000175000001440000000675411354101152020705 0ustar00rncbcusers00000000000000// qtractorConnectForm.h // /**************************************************************************** Copyright (C) 2005-2010, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorConnectForm_h #define __qtractorConnectForm_h #include "ui_qtractorConnectForm.h" #include "qtractorAudioConnect.h" #include "qtractorMidiConnect.h" // Forward declarations... class qtractorSession; class qtractorOptions; //---------------------------------------------------------------------------- // qtractorConnectForm -- UI wrapper form. class qtractorConnectForm : public QWidget { Q_OBJECT public: // Constructor. qtractorConnectForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorConnectForm(); QTabWidget *connectTabWidget() const { return m_ui.ConnectTabWidget; } QSplitter *audioConnectSplitter() const { return m_ui.AudioConnectSplitter; } QSplitter *midiConnectSplitter() const { return m_ui.AudioConnectSplitter; } QComboBox *audioOClientsComboBox() const { return m_ui.AudioOClientsComboBox; } QComboBox *audioIClientsComboBox() const { return m_ui.AudioIClientsComboBox; } qtractorClientListView *audioOListView() const { return m_ui.AudioOListView; } qtractorClientListView *audioIListView() const { return m_ui.AudioIListView; } QComboBox *midiOClientsComboBox() const { return m_ui.MidiOClientsComboBox; } QComboBox *midiIClientsComboBox() const { return m_ui.MidiIClientsComboBox; } qtractorClientListView *midiOListView() const { return m_ui.MidiOListView; } qtractorClientListView *midiIListView() const { return m_ui.MidiIListView; } public slots: void audioRefresh() { audioUpdate(false); } void audioClear() { audioUpdate(true); } void midiRefresh() { midiUpdate(false); } void midiClear() { midiUpdate(true); } void audioReset(); void midiReset(); protected slots: void audioIClientChanged(); void audioOClientChanged(); void audioConnectSelected(); void audioDisconnectSelected(); void audioDisconnectAll(); void audioConnectChanged(); void audioStabilize(); void midiIClientChanged(); void midiOClientChanged(); void midiConnectSelected(); void midiDisconnectSelected(); void midiDisconnectAll(); void midiConnectChanged(); void midiStabilize(); signals: void connectChanged(); protected: void updateClientsComboBox(QComboBox *pComboBox, qtractorClientListView *pClientListView, const QIcon& icon); void audioUpdate(bool bClear); void midiUpdate(bool bClear); private: // The Qt-designer UI struct... Ui::qtractorConnectForm m_ui; // Instance variables... qtractorAudioConnect *m_pAudioConnect; qtractorMidiConnect *m_pMidiConnect; }; #endif // __qtractorConnectForm_h // end of qtractorConnectForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiControlForm.h0000644000175000001440000000012312073012112022230 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134666.76108 30 ctime=1381134666.761080045 qtractor-0.5.11/src/qtractorMidiControlForm.h0000644000175000001440000000471412073012112021525 0ustar00rncbcusers00000000000000// qtractorMidiControlForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiControlForm_h #define __qtractorMidiControlForm_h #include "ui_qtractorMidiControlForm.h" #include "qtractorMidiControl.h" //---------------------------------------------------------------------------- // qtractorMidiControlForm -- UI wrapper form. class qtractorMidiControlForm : public QDialog { Q_OBJECT public: // Constructor. qtractorMidiControlForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorMidiControlForm(); protected slots: void reject(); void importSlot(); void removeSlot(); void moveUpSlot(); void moveDownSlot(); void mapSlot(); void unmapSlot(); void reloadSlot(); void exportSlot(); void typeChangedSlot(); void keyChangedSlot(); void valueChangedSlot(); void stabilizeForm(); protected: void stabilizeTypeChange(); void stabilizeKeyChange(); void stabilizeValueChange(); void refreshFiles(); void refreshControlMap(); unsigned short channelFromText(const QString& sText) const; QString textFromChannel(unsigned short iChannel) const; unsigned short paramFromText( qtractorMidiControl::ControlType ctype, const QString& sText) const; QString textFromParam( qtractorMidiControl::ControlType ctype, unsigned short iParam) const; private: // The Qt-designer UI struct... Ui::qtractorMidiControlForm m_ui; // Instance variables... int m_iDirtyCount; int m_iDirtyMap; int m_iUpdating; }; #endif // __qtractorMidiControlForm_h // end of qtractorMidiControlForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiFileTempo.cpp0000644000175000001440000000012212051431527022215 xustar000000000000000027 mtime=1353069399.429821 26 atime=1381134670.83908 29 ctime=1381134670.83908011 qtractor-0.5.11/src/qtractorMidiFileTempo.cpp0000644000175000001440000001705612051431527021516 0ustar00rncbcusers00000000000000// qtractorMidiFileTempo.cpp // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorMidiFileTempo.h" #include "qtractorMidiFile.h" #include "qtractorTimeScale.h" //---------------------------------------------------------------------- // class qtractorMidiFileTempo -- MIDI tempo/time-signature map class. // // (Re)initializer method. void qtractorMidiFileTempo::clear (void) { m_nodes.setAutoDelete(true); m_markers.setAutoDelete(true); // Clear/reset tempo-map and location markers... m_nodes.clear(); m_markers.clear(); // There must always be one node, always. addNode(0); } // Update node coefficient divisor factors. void qtractorMidiFileTempo::Node::update ( qtractorMidiFile *pMidiFile ) { ticksPerBeat = pMidiFile->ticksPerBeat(); if (beatDivisor > 2) { ticksPerBeat >>= (beatDivisor - 2); } else if (beatDivisor < 2) { ticksPerBeat <<= (2 - beatDivisor); } } // Update tempo-map node position metrics. void qtractorMidiFileTempo::Node::reset ( qtractorMidiFileTempo::Node *pNode ) { if (bar > pNode->bar) tick = pNode->tickFromBar(bar); else bar = pNode->barFromTick(tick); } // Tempo-map node seeker (by tick). qtractorMidiFileTempo::Node *qtractorMidiFileTempo::seekNode ( unsigned long iTick ) const { Node *pNode = m_nodes.first(); // Seek tick forward... while (pNode && pNode->next() && iTick >= (pNode->next())->tick) pNode = pNode->next(); return pNode; } // Node list specifics. qtractorMidiFileTempo::Node *qtractorMidiFileTempo::addNode ( unsigned long iTick, float fTempo, unsigned short iBeatsPerBar, unsigned short iBeatDivisor ) { Node *pNode = 0; // Seek for the nearest preceding node... Node *pPrev = seekNode(iTick); // Snap to nearest bar... if (pPrev) { iTick = pPrev->tickSnapToBar(iTick); pPrev = seekNode(iTick); } // Either update existing node or add new one... Node *pNext = (pPrev ? pPrev->next() : 0); if (pPrev && pPrev->tick == iTick) { // Update exact matching node... pNode = pPrev; pNode->tempo = fTempo; pNode->beatsPerBar = iBeatsPerBar; pNode->beatDivisor = iBeatDivisor; } else if (pPrev && pPrev->tempo == fTempo && pPrev->beatsPerBar == iBeatsPerBar && pPrev->beatDivisor == iBeatDivisor) { // No need for a new node... return pPrev; } else if (pNext && pNext->tempo == fTempo && pNext->beatsPerBar == iBeatsPerBar && pNext->beatDivisor == iBeatDivisor) { // Update next exact matching node... pNode = pNext; pNode->tick = iTick; pNode->bar = 0; } else { // Add/insert a new node... pNode = new Node(iTick, fTempo, iBeatsPerBar, iBeatDivisor); if (pPrev) m_nodes.insertAfter(pNode, pPrev); else m_nodes.append(pNode); } // Update coefficients and positioning thereafter... updateNode(pNode); return pNode; } void qtractorMidiFileTempo::updateNode ( qtractorMidiFileTempo::Node *pNode ) { // Update coefficients... pNode->update(m_pMidiFile); // Update positioning on all nodes thereafter... Node *pPrev = pNode->prev(); while (pNode) { if (pPrev) pNode->reset(pPrev); pPrev = pNode; pNode = pNode->next(); } } void qtractorMidiFileTempo::removeNode ( qtractorMidiFileTempo::Node *pNode ) { // Don't ever remove the very first node... Node *pPrev = pNode->prev(); if (pPrev == 0) return; // Update positioning on all nodes thereafter... Node *pNext = pNode->next(); while (pNext) { if (pPrev) pNext->reset(pPrev); pPrev = pNext; pNext = pNext->next(); } // Actually remove/unlink the node... m_nodes.remove(pNode); } // Location marker seeker (by tick). qtractorMidiFileTempo::Marker *qtractorMidiFileTempo::seekMarker ( unsigned long iTick ) const { Marker *pMarker = m_markers.first(); // Seek tick forward... while (pMarker && pMarker->next() && iTick >= (pMarker->next())->tick) pMarker = pMarker->next(); return pMarker; } // Marker list specifics. qtractorMidiFileTempo::Marker *qtractorMidiFileTempo::addMarker ( unsigned long iTick, const QString& sText ) { Marker *pMarker = 0; // Snap to nearest bar... Node *pNodePrev = seekNode(iTick); if (pNodePrev) iTick = pNodePrev->tickSnapToBar(iTick); // Seek for the nearest preceding node... Marker *pMarkerPrev = seekMarker(iTick); // Either update existing marker or add new one... if (pMarkerPrev && pMarkerPrev->tick == iTick) { // Update exact matching node... pMarker = pMarkerPrev; pMarker->text = sText; } else { // Add/insert a new marker... pMarker = new Marker(iTick, sText); if (pMarkerPrev) m_markers.insertAfter(pMarker, pMarkerPrev); else m_markers.append(pMarker); } return pMarker; } void qtractorMidiFileTempo::removeMarker ( qtractorMidiFileTempo::Marker *pMarker ) { // Actually remove/unlink the marker m_markers.remove(pMarker); } // Time-scale sync methods. void qtractorMidiFileTempo::fromTimeScale ( qtractorTimeScale *pTimeScale, unsigned long iTimeOffset ) { if (pTimeScale == NULL) return; const unsigned short p = pTimeScale->ticksPerBeat(); const unsigned short q = m_pMidiFile->ticksPerBeat(); if (q < 1) return; // Copy tempo-map nodes... m_nodes.clear(); qtractorTimeScale::Cursor cursor(pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekTick(iTimeOffset); while (pNode) { unsigned long iTime = uint64_t(pNode->tick) * p / q; iTime = (iTime > iTimeOffset ? iTime - iTimeOffset : 0); addNode(iTime, pNode->tempo, pNode->beatsPerBar, pNode->beatDivisor); pNode = pNode->next(); } // Copy location markers... m_markers.clear(); qtractorTimeScale::Marker *pMarker = pTimeScale->markers().seekTick(iTimeOffset); while (pMarker) { unsigned long iTick = pTimeScale->tickFromFrame(pMarker->frame); unsigned long iTime = uint64_t(iTick) * p / q; iTime = (iTime > iTimeOffset ? iTime - iTimeOffset : 0); addMarker(iTime, pMarker->text); pMarker = pMarker->next(); } } void qtractorMidiFileTempo::intoTimeScale ( qtractorTimeScale *pTimeScale, unsigned long iTimeOffset ) { if (pTimeScale == NULL) return; const unsigned short p = m_pMidiFile->ticksPerBeat(); const unsigned short q = pTimeScale->ticksPerBeat(); if (q < 1) return; pTimeScale->reset(); // Copy tempo-map nodes... qtractorMidiFileTempo::Node *pNode = m_nodes.first(); while (pNode) { unsigned long iTime = uint64_t(pNode->tick) * p / q; pTimeScale->addNode( pTimeScale->frameFromTick(iTime + iTimeOffset), pNode->tempo, 2, pNode->beatsPerBar, pNode->beatDivisor); pNode = pNode->next(); } // Copy location markers... qtractorMidiFileTempo::Marker *pMarker = m_markers.first(); while (pMarker) { unsigned long iTime = uint64_t(pMarker->tick) * p / q; pTimeScale->addMarker( pTimeScale->frameFromTick(iTime + iTimeOffset), pMarker->text); pMarker = pMarker->next(); } } // end of qtractorMidiFileTempo.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTrackForm.h0000644000175000001440000000012312141244677021074 xustar000000000000000027 mtime=1367689663.484158 26 atime=1381134668.17508 30 ctime=1381134668.175080067 qtractor-0.5.11/src/qtractorTrackForm.h0000644000175000001440000001004612141244677020364 0ustar00rncbcusers00000000000000// qtractorTrackForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorTrackForm_h #define __qtractorTrackForm_h #include "ui_qtractorTrackForm.h" #include "qtractorTrack.h" #include // Forward declarations... class qtractorMidiBus; class qtractorMidiManager; class qtractorCommand; //---------------------------------------------------------------------------- // qtractorTrackForm -- UI wrapper form. class qtractorTrackForm : public QDialog { Q_OBJECT public: // Constructor. qtractorTrackForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorTrackForm(); void setTrack(qtractorTrack *pTrack); qtractorTrack *track() const; const qtractorTrack::Properties& properties() const; qtractorTrack::TrackType trackType() const; void setMidiProgram(int iBank, int iProg); protected slots: void accept(); void reject(); void stabilizeForm(); void changed(); void pluginListChanged(); void trackTypeChanged(); void inputBusNameChanged(const QString& sBusName); void outputBusNameChanged(const QString& sBusName); void busNameClicked(); void channelChanged(int iChannel); void instrumentChanged(const QString& sInstrumentName); void bankSelMethodChanged(int iBankSelMethod); void bankChanged(); void progChanged(); void foregroundColorChanged(const QString& sText); void backgroundColorChanged(const QString& sText); void selectForegroundColor(); void selectBackgroundColor(); void addPlugin(); void removePlugin(); void moveUpPlugin(); void moveDownPlugin(); protected: qtractorMidiBus *midiBus() const; int midiBank() const; int midiProg() const; void updateInstruments(); void updateInstrumentsAdd( const QIcon& icon, qtractorMidiManager *pMidiManager); void updateTrackType(qtractorTrack::TrackType trackType); void updateChannel(int iChannel, int iBankSelMethod, int iBank, int iProg); void updateBanks(const QString& sInstrumentName, int iBankSelMethod, int iBank, int iProg); void updatePrograms(const QString& sInstrumentName, int iBank, int iProg); bool updateBanksAdd(const QIcon& icon, qtractorMidiManager *pMidiManager, const QString& sInstrumentName, int iBank, int& iBankIndex); bool updateProgramsAdd(const QIcon& icon, qtractorMidiManager *pMidiManager, const QString& sInstrumentName, int iBank, int iProg, int& iProgIndex); void updateColorItem(QComboBox *pComboBox, const QColor& color); void updateColorText(QComboBox *pComboBox, const QColor& color); QColor colorItem(QComboBox *pComboBox); private: // The Qt-designer UI struct... Ui::qtractorTrackForm m_ui; // Instance variables... qtractorTrack *m_pTrack; qtractorTrack::Properties m_props; qtractorMidiBus *m_pMidiBus; QMap m_banks; QMap m_progs; int m_iDirtySetup; int m_iDirtyCount; int m_iDirtyPatch; qtractorMidiBus *m_pOldMidiBus; int m_iOldChannel; QString m_sOldInstrumentName; int m_iOldBankSelMethod; int m_iOldBank; int m_iOldProg; // Keep last acceptable command. qtractorCommand *m_pLastCommand; // MIDI bank/program observer. class MidiProgramObserver; MidiProgramObserver *m_pMidiProgramObserver; }; #endif // __qtractorTrackForm_h // end of qtractorTrackForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorConnectForm.cpp0000644000175000001440000000012211354101152021734 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134667.05008 29 ctime=1381134667.05008005 qtractor-0.5.11/src/qtractorConnectForm.cpp0000644000175000001440000002464611354101152021240 0ustar00rncbcusers00000000000000// qtractorConnectForm.cpp // /**************************************************************************** Copyright (C) 2005-2010, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorConnectForm.h" #include "qtractorAbout.h" #include "qtractorOptions.h" #include "qtractorSession.h" #include "qtractorAudioEngine.h" #include "qtractorMidiEngine.h" #include //---------------------------------------------------------------------------- // qtractorConnectForm -- UI wrapper form. // Constructor. qtractorConnectForm::qtractorConnectForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QWidget(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); m_pAudioConnect = new qtractorAudioConnect( m_ui.AudioOListView, m_ui.AudioIListView, m_ui.AudioConnectorView); m_pAudioConnect->setBezierLines(true); m_pMidiConnect = new qtractorMidiConnect( m_ui.MidiOListView, m_ui.MidiIListView, m_ui.MidiConnectorView); m_pMidiConnect->setBezierLines(true); // UI signal/slot connections... QObject::connect(m_ui.AudioIClientsComboBox, SIGNAL(activated(int)), SLOT(audioIClientChanged())); QObject::connect(m_ui.AudioOClientsComboBox, SIGNAL(activated(int)), SLOT(audioOClientChanged())); QObject::connect(m_ui.AudioConnectPushButton, SIGNAL(clicked()), SLOT(audioConnectSelected())); QObject::connect(m_ui.AudioDisconnectPushButton, SIGNAL(clicked()), SLOT(audioDisconnectSelected())); QObject::connect(m_ui.AudioDisconnectAllPushButton, SIGNAL(clicked()), SLOT(audioDisconnectAll())); QObject::connect(m_ui.AudioRefreshPushButton, SIGNAL(clicked()), SLOT(audioRefresh())); QObject::connect(m_ui.MidiIClientsComboBox, SIGNAL(activated(int)), SLOT(midiIClientChanged())); QObject::connect(m_ui.MidiOClientsComboBox, SIGNAL(activated(int)), SLOT(midiOClientChanged())); QObject::connect(m_ui.MidiConnectPushButton, SIGNAL(clicked()), SLOT(midiConnectSelected())); QObject::connect(m_ui.MidiDisconnectPushButton, SIGNAL(clicked()), SLOT(midiDisconnectSelected())); QObject::connect(m_ui.MidiDisconnectAllPushButton, SIGNAL(clicked()), SLOT(midiDisconnectAll())); QObject::connect(m_ui.MidiRefreshPushButton, SIGNAL(clicked()), SLOT(midiRefresh())); // Connect it to some UI feedback slots. QObject::connect(m_ui.AudioOListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(audioStabilize())); QObject::connect(m_ui.AudioIListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(audioStabilize())); QObject::connect(m_ui.MidiOListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(midiStabilize())); QObject::connect(m_ui.MidiIListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(midiStabilize())); QObject::connect(m_pAudioConnect, SIGNAL(connectChanged()), SLOT(audioConnectChanged())); QObject::connect(m_pMidiConnect, SIGNAL(connectChanged()), SLOT(midiConnectChanged())); } // Destructor. qtractorConnectForm::~qtractorConnectForm (void) { delete m_pAudioConnect; delete m_pMidiConnect; } // Audio client name change slots. void qtractorConnectForm::audioIClientChanged (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::audioIClientChanged()"); #endif // Reset any port name pattern... m_ui.AudioIListView->setPortName(QString::null); audioRefresh(); } void qtractorConnectForm::audioOClientChanged (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::audioOClientChanged()"); #endif // Reset any port name pattern... m_ui.AudioOListView->setPortName(QString::null); audioRefresh(); } // Connect current selected ports. void qtractorConnectForm::audioConnectSelected (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::audioConnectSelected()"); #endif m_pAudioConnect->connectSelected(); } // Disconnect current selected ports. void qtractorConnectForm::audioDisconnectSelected (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::audioDisconnectSelected()"); #endif m_pAudioConnect->disconnectSelected(); } // Disconnect all connected ports. void qtractorConnectForm::audioDisconnectAll (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::audioDisconnectAll()"); #endif m_pAudioConnect->disconnectAll(); } // Refresh complete form by notifying the parent form. void qtractorConnectForm::audioUpdate ( bool bClear ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::audioUpdate(%d)", int(bClear)); #endif m_ui.AudioOListView->setClientName( m_ui.AudioOClientsComboBox->currentIndex() > 0 && !bClear ? m_ui.AudioOClientsComboBox->currentText() : QString::null); m_ui.AudioIListView->setClientName( m_ui.AudioIClientsComboBox->currentIndex() > 0 && !bClear ? m_ui.AudioIClientsComboBox->currentText() : QString::null); m_pAudioConnect->updateContents(bClear); updateClientsComboBox(m_ui.AudioOClientsComboBox, m_ui.AudioOListView, m_pAudioConnect->icon(qtractorAudioConnect::ClientOut)); updateClientsComboBox(m_ui.AudioIClientsComboBox, m_ui.AudioIListView, m_pAudioConnect->icon(qtractorAudioConnect::ClientIn)); audioStabilize(); } // Refresh complete form conditionally. void qtractorConnectForm::audioReset (void) { audioUpdate( m_ui.AudioOClientsComboBox->currentIndex() > 0 || m_ui.AudioIClientsComboBox->currentIndex() > 0); } // A helper connection change slot. void qtractorConnectForm::audioConnectChanged (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::audioConectChanged()"); #endif audioStabilize(); emit connectChanged(); } // A helper stabilization slot. void qtractorConnectForm::audioStabilize (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::audioStabilize()"); #endif m_ui.AudioConnectPushButton->setEnabled( m_pAudioConnect->canConnectSelected()); m_ui.AudioDisconnectPushButton->setEnabled( m_pAudioConnect->canDisconnectSelected()); m_ui.AudioDisconnectAllPushButton->setEnabled( m_pAudioConnect->canDisconnectAll()); } // MIDI client name change slots. void qtractorConnectForm::midiIClientChanged (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::midiIClientChanged()"); #endif // Reset any port name pattern... m_ui.MidiIListView->setPortName(QString::null); midiRefresh(); } void qtractorConnectForm::midiOClientChanged (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::midiOClientChanged()"); #endif // Reset any port name pattern... m_ui.MidiOListView->setPortName(QString::null); midiRefresh(); } // Connect current selected ports. void qtractorConnectForm::midiConnectSelected (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::midiConnectSelected()"); #endif m_pMidiConnect->connectSelected(); } // Disconnect current selected ports. void qtractorConnectForm::midiDisconnectSelected (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::midiDisconnectSelected()"); #endif m_pMidiConnect->disconnectSelected(); } // Disconnect all connected ports. void qtractorConnectForm::midiDisconnectAll (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::midiDisconnectAll()"); #endif m_pMidiConnect->disconnectAll(); } // Refresh complete form by notifying the parent form. void qtractorConnectForm::midiUpdate ( bool bClear ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::midiUpdate(%d)", int(bClear)); #endif m_ui.MidiOListView->setClientName( m_ui.MidiOClientsComboBox->currentIndex() > 0 && !bClear ? m_ui.MidiOClientsComboBox->currentText() : QString::null); m_ui.MidiIListView->setClientName( m_ui.MidiIClientsComboBox->currentIndex() > 0 && !bClear ? m_ui.MidiIClientsComboBox->currentText() : QString::null); m_pMidiConnect->updateContents(bClear); updateClientsComboBox(m_ui.MidiOClientsComboBox, m_ui.MidiOListView, m_pMidiConnect->icon(qtractorMidiConnect::ClientOut)); updateClientsComboBox(m_ui.MidiIClientsComboBox, m_ui.MidiIListView, m_pMidiConnect->icon(qtractorMidiConnect::ClientIn)); midiStabilize(); } // Refresh complete form conditionally. void qtractorConnectForm::midiReset (void) { midiUpdate( m_ui.MidiOClientsComboBox->currentIndex() > 0 || m_ui.MidiIClientsComboBox->currentIndex() > 0); } // A helper connection change slot. void qtractorConnectForm::midiConnectChanged (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::midiConectChanged()"); #endif midiStabilize(); emit connectChanged(); } // A helper stabilization slot. void qtractorConnectForm::midiStabilize (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorConnectForm::midiStabilize()"); #endif m_ui.MidiConnectPushButton->setEnabled( m_pMidiConnect->canConnectSelected()); m_ui.MidiDisconnectPushButton->setEnabled( m_pMidiConnect->canDisconnectSelected()); m_ui.MidiDisconnectAllPushButton->setEnabled( m_pMidiConnect->canDisconnectAll()); } // Refresh given combo-box with client names. void qtractorConnectForm::updateClientsComboBox ( QComboBox *pComboBox, qtractorClientListView *pClientListView, const QIcon& icon ) { // Refresh client names combo box contents... pComboBox->clear(); pComboBox->addItem(tr("(All)")); const QStringList& clientNames = pClientListView->clientNames(); QStringListIterator iter(clientNames); while (iter.hasNext()) pComboBox->addItem(icon, iter.next()); // Update current item/selection... const QString& sClientName = pClientListView->clientName(); if (sClientName.isEmpty()) { pComboBox->setCurrentIndex(0); } else { // Select and expand all else... pComboBox->setCurrentIndex(pComboBox->findText(sClientName)); // Select and expand all else... qtractorClientListItem *pClientItem = pClientListView->findClientItem(sClientName); if (pClientItem) pClientListView->setCurrentItem(pClientItem); pClientListView->setOpenAll(true); } } // end of qtractorConnectForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTrackForm.ui0000644000175000001440000000012312156361710021254 xustar000000000000000027 mtime=1371136968.140159 26 atime=1381134668.08608 30 ctime=1381134668.086080066 qtractor-0.5.11/src/qtractorTrackForm.ui0000644000175000001440000005302512156361710020550 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorTrackForm 0 0 374 372 Qt::StrongFocus Track - Qtractor :/images/trackProperties.png 0 Track &Name: TrackNameTextEdit 320 0 32767 48 Track name description 4 0 Type 4 8 Audio track type &Audio Alt+A MIDI track type &MIDI Alt+M Input / Output 4 8 3 0 0 0 80 0 Input bus name 3 0 0 0 80 0 Output bus name 22 22 24 24 Qt::TabFocus Manage buses ... MIDI / Instrument 8 4 &Program: ProgComboBox &Bank: BankComboBox Bank &Select Method: BankSelMethodComboBox &Omni MIDI Omni: Capture All Channels Alt+O &Channel: ChannelSpinBox 48 24 MIDI Channel (1-16) 1 16 MIDI Patch: Instrument 7 0 0 0 MIDI Patch: Bank Select Method MIDI Patch: Bank true MIDI Patch: Program true View / Colors 4 8 &Foreground: ForegroundColorComboBox 64 0 Foreground color true 22 22 24 24 Qt::TabFocus Select custom track foreground color :/images/formColor.png ... Qt::Horizontal QSizePolicy::Expanding 8 8 Bac&kground: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter BackgroundColorComboBox 64 0 Background color true 22 22 24 24 Qt::TabFocus Select custom track background color :/images/formColor.png ... Plugins Qt::WheelFocus Track plugins 90 28 Add plugin &Add... :/images/formCreate.png Alt+A Qt::ToolButtonTextBesideIcon 90 28 Remove plugin &Remove :/images/formRemove.png Alt+R Qt::ToolButtonTextBesideIcon Qt::Vertical 8 8 90 28 Move plugin up &Up :/images/formMoveUp.png Alt+U Qt::ToolButtonTextBesideIcon 90 28 Move plugin down &Down :/images/formMoveDown.png Alt+D Qt::ToolButtonTextBesideIcon Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qtractorPluginListView QListWidget
qtractorPluginListView.h
TrackNameTextEdit AudioRadioButton MidiRadioButton InputBusNameComboBox OutputBusNameComboBox BusNameToolButton OmniCheckBox ChannelSpinBox InstrumentComboBox BankSelMethodComboBox BankComboBox ProgComboBox ForegroundColorComboBox ForegroundColorToolButton BackgroundColorComboBox BackgroundColorToolButton PluginListView AddPluginToolButton RemovePluginToolButton MoveUpPluginToolButton MoveDownPluginToolButton DialogButtonBox
qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioMeter.h0000644000175000001440000000012311514076275021242 xustar000000000000000027 mtime=1295023293.370359 26 atime=1381134667.40808 30 ctime=1381134667.408080055 qtractor-0.5.11/src/qtractorAudioMeter.h0000644000175000001440000001053211514076275020532 0ustar00rncbcusers00000000000000// qtractorAudioMeter.h // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorAudioMeter_h #define __qtractorAudioMeter_h #include "qtractorMeter.h" // Forward declarations. class qtractorAudioMeter; class qtractorAudioMeterValue; class qtractorAudioMonitor; class QResizeEvent; class QPaintEvent; //---------------------------------------------------------------------------- // qtractorAudioMeterScale -- Audio meter bridge scale widget. class qtractorAudioMeterScale : public qtractorMeterScale { Q_OBJECT public: // Constructor. qtractorAudioMeterScale(qtractorAudioMeter *pAudioMeter, QWidget *pParent = 0); protected: // Actual scale drawing method. void paintScale(QPainter *p); }; //---------------------------------------------------------------------------- // qtractorAudioMeterValue -- Audio meter bridge value widget. class qtractorAudioMeterValue : public QWidget { Q_OBJECT public: // Constructor. qtractorAudioMeterValue(qtractorAudioMeter *pAudioMeter, unsigned short iChannel, QWidget *pParent = 0); // Default destructor. ~qtractorAudioMeterValue(); // Reset peak holder. void peakReset(); // Value refreshment. void refresh(); protected: // Specific event handlers. void paintEvent(QPaintEvent *); void resizeEvent(QResizeEvent *); private: // Local instance variables. qtractorAudioMeter *m_pAudioMeter; unsigned short m_iChannel; // Running variables. int m_iValue; float m_fValueDecay; int m_iPeak; int m_iPeakHold; float m_fPeakDecay; int m_iPeakColor; }; //---------------------------------------------------------------------------- // qtractorAudioMeter -- Audio meter bridge slot widget. class qtractorAudioMeter : public qtractorMeter { Q_OBJECT public: // Constructor. qtractorAudioMeter(qtractorAudioMonitor *pAudioMonitor, QWidget *pParent = 0); // Default destructor. ~qtractorAudioMeter(); // Virtual monitor accessor. void setMonitor(qtractorMonitor *pMonitor); qtractorMonitor *monitor() const; // Audio monitor accessor. void setAudioMonitor(qtractorAudioMonitor *pAudioMonitor); qtractorAudioMonitor *audioMonitor() const; // Local slider update methods. void updatePanning(); void updateGain(); // Monitor reset. void reset(); // Slot refreshment. void refresh(); // Reset peak holder. void peakReset(); // IEC scale accessors. int iec_scale(float dB) const; int iec_level(int iIndex) const; #ifdef CONFIG_GRADIENT const QPixmap& pixmap() const; void updatePixmap(); #endif // Color/level indexes. enum { ColorOver = 0, Color0dB = 1, Color3dB = 2, Color6dB = 3, Color10dB = 4, LevelCount = 5, ColorBack = 5, ColorFore = 6, ColorCount = 7 }; // Common resource accessors. static void setColor(int iIndex, const QColor& color); static const QColor& color(int iIndex); static const QColor& defaultColor(int iIndex); protected: // Specific event handlers. void resizeEvent(QResizeEvent *); private: // Local forward declarations. class GainSliderInterface; class GainSpinBoxInterface; // Local instance variables. qtractorAudioMonitor *m_pAudioMonitor; unsigned short m_iChannels; qtractorAudioMeterScale *m_pAudioScale; qtractorAudioMeterValue **m_ppAudioValues; float m_fScale; int m_levels[LevelCount]; #ifdef CONFIG_GRADIENT QPixmap *m_pPixmap; #endif static QColor g_defaultColors[ColorCount]; static QColor g_currentColors[ColorCount]; }; #endif // __qtractorAudioMeter_h // end of qtractorAudioMeter.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorTakeRangeForm.cpp0000644000175000001440000000012312166134117022216 xustar000000000000000027 mtime=1373157455.942698 26 atime=1381134671.08908 30 ctime=1381134671.090080114 qtractor-0.5.11/src/qtractorTakeRangeForm.cpp0000644000175000001440000001701412166134117021510 0ustar00rncbcusers00000000000000// qtractorTakeRangeForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorTakeRangeForm.h" #include "qtractorAbout.h" #include "qtractorSession.h" #include "qtractorClip.h" #include #include //---------------------------------------------------------------------------- // qtractorTakeRangeForm -- UI wrapper form. // Constructor. qtractorTakeRangeForm::qtractorTakeRangeForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::ApplicationModal); // Initialize dirty control state. m_pTimeScale = NULL; m_pClip = NULL; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { m_pTimeScale = new qtractorTimeScale(*pSession->timeScale()); m_ui.TakeStartSpinBox->setTimeScale(m_pTimeScale); m_ui.TakeEndSpinBox->setTimeScale(m_pTimeScale); // Set proper time scales display format... m_ui.FormatComboBox->setCurrentIndex( int(m_pTimeScale->displayFormat())); } // Try to restore old window positioning. adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.SelectionRangeRadioButton, SIGNAL(toggled(bool)), SLOT(rangeChanged())); QObject::connect(m_ui.LoopRangeRadioButton, SIGNAL(toggled(bool)), SLOT(rangeChanged())); QObject::connect(m_ui.PunchRangeRadioButton, SIGNAL(toggled(bool)), SLOT(rangeChanged())); QObject::connect(m_ui.EditRangeRadioButton, SIGNAL(toggled(bool)), SLOT(rangeChanged())); QObject::connect(m_ui.CustomRangeRadioButton, SIGNAL(toggled(bool)), SLOT(rangeChanged())); QObject::connect(m_ui.TakeStartSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(valueChanged())); QObject::connect(m_ui.TakeStartSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.TakeEndSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(valueChanged())); QObject::connect(m_ui.TakeEndSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.FormatComboBox, SIGNAL(activated(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); // Done. stabilizeForm(); } // Destructor. qtractorTakeRangeForm::~qtractorTakeRangeForm (void) { // Don't forget to get rid of local time-scale instance... if (m_pTimeScale) delete m_pTimeScale; } // Setup accessors. void qtractorTakeRangeForm::setClip ( qtractorClip *pClip ) { m_pClip = pClip; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { // Populate range options... if (m_pClip && m_pClip->isClipSelected()) m_ui.SelectionRangeRadioButton->setChecked(true); else if (pSession->isLooping()) m_ui.LoopRangeRadioButton->setChecked(true); else if (pSession->isPunching()) m_ui.PunchRangeRadioButton->setChecked(true); else if (pSession->editHead() < pSession->editTail()) m_ui.EditRangeRadioButton->setChecked(true); else m_ui.CustomRangeRadioButton->setChecked(true); // Populate range values... rangeChanged(); } } qtractorClip *qtractorTakeRangeForm::clip (void) const { return m_pClip; } // Retrieve the current take-range, if the case arises. unsigned long qtractorTakeRangeForm::takeStart (void) const { return m_ui.TakeStartSpinBox->value(); } unsigned long qtractorTakeRangeForm::takeEnd (void) const { return m_ui.TakeEndSpinBox->value(); } int qtractorTakeRangeForm::currentTake (void) const { return m_ui.CurrentTakeListBox->currentRow(); } // Display format has changed. void qtractorTakeRangeForm::rangeChanged (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; if (m_ui.SelectionRangeRadioButton->isChecked() && m_pClip) { m_ui.TakeStartSpinBox->setValue(m_pClip->clipSelectStart(), false); m_ui.TakeEndSpinBox->setValue(m_pClip->clipSelectEnd(), false); } else if (m_ui.LoopRangeRadioButton->isChecked()) { m_ui.TakeStartSpinBox->setValue(pSession->loopStart(), false); m_ui.TakeEndSpinBox->setValue(pSession->loopEnd(), false); } else if (m_ui.PunchRangeRadioButton->isChecked()) { m_ui.TakeStartSpinBox->setValue(pSession->punchIn(), false); m_ui.TakeEndSpinBox->setValue(pSession->punchOut(), false); } else if (m_ui.EditRangeRadioButton->isChecked()) { m_ui.TakeStartSpinBox->setValue(pSession->editHead(), false); m_ui.TakeEndSpinBox->setValue(pSession->editTail(), false); } updateCurrentTake(); stabilizeForm(); } // Range values have changed. void qtractorTakeRangeForm::valueChanged (void) { m_ui.CustomRangeRadioButton->setChecked(true); updateCurrentTake(); stabilizeForm(); } // Display format has changed. void qtractorTakeRangeForm::formatChanged ( int iDisplayFormat ) { bool bBlockSignals = m_ui.FormatComboBox->blockSignals(true); m_ui.FormatComboBox->setCurrentIndex(iDisplayFormat); qtractorTimeScale::DisplayFormat displayFormat = qtractorTimeScale::DisplayFormat(iDisplayFormat); m_ui.TakeStartSpinBox->setDisplayFormat(displayFormat); m_ui.TakeEndSpinBox->setDisplayFormat(displayFormat); if (m_pTimeScale) m_pTimeScale->setDisplayFormat(displayFormat); m_ui.FormatComboBox->blockSignals(bBlockSignals); stabilizeForm(); } // Populate current take list. void qtractorTakeRangeForm::updateCurrentTake (void) { int iCurrentTake = m_ui.CurrentTakeListBox->currentRow(); m_ui.CurrentTakeListBox->clear(); if (m_pClip) { int iTakeCount = qtractorClip::TakeInfo( m_pClip->clipStart(), m_pClip->clipOffset(), m_pClip->clipLength(), m_ui.TakeStartSpinBox->value(), m_ui.TakeEndSpinBox->value()).takeCount(); for (int iTake = 0; iTake < iTakeCount; ++iTake) m_ui.CurrentTakeListBox->addItem(tr("Take %1").arg(iTake + 1)); if (iCurrentTake < 0) iCurrentTake = 0; else if (iCurrentTake > iTakeCount - 1) iCurrentTake = iTakeCount - 1; } m_ui.CurrentTakeListBox->setCurrentRow(iCurrentTake); } // Stabilize current form state. void qtractorTakeRangeForm::stabilizeForm (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; m_ui.SelectionRangeRadioButton->setEnabled( m_pClip && m_pClip->isClipSelected()); m_ui.LoopRangeRadioButton->setEnabled(pSession->isLooping()); m_ui.PunchRangeRadioButton->setEnabled(pSession->isPunching()); m_ui.EditRangeRadioButton->setEnabled( pSession->editHead() < pSession->editTail()); m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled( m_ui.TakeStartSpinBox->value() < m_ui.TakeEndSpinBox->value()); } // end of qtractorTakeRangeForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorDocument.h0000644000175000001440000000012312075300321020743 xustar000000000000000027 mtime=1358266577.503765 26 atime=1381134669.66808 30 ctime=1381134669.668080091 qtractor-0.5.11/src/qtractorDocument.h0000644000175000001440000000707112075300321020237 0ustar00rncbcusers00000000000000// qtractorDocument.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorDocument_h #define __qtractorDocument_h #include // Forward declartions. class QDomDocument; class QDomElement; class qtractorZipFile; //------------------------------------------------------------------------- // qtractorDocument -- Document file import/export abstract class. // class qtractorDocument { public: // Document flags. enum Flags { Default = 0, Template = 1, Archive = 2, Temporary = 4 }; // Constructor. qtractorDocument(QDomDocument *pDocument, const QString& sTagName = QString(), Flags = Default); // Default destructor. virtual ~qtractorDocument(); // Accessors. QDomDocument *document() const; const QString& name() const; // Regular text element factory method. void saveTextElement (const QString& sTagName, const QString& sText, QDomElement *pElement); // Document flags property. void setFlags(Flags flags); Flags flags() const; bool isTemplate() const; bool isArchive() const; bool isTemporary() const; // Archive filename filter. QString addFile (const QString& sFilename) const; // External storage simple methods. bool load (const QString& sFilename, Flags flags = Default); bool save (const QString& sFilename, Flags flags = Default); // External storage element pure virtual methods. virtual bool loadElement (QDomElement *pElement) = 0; virtual bool saveElement (QDomElement *pElement) = 0; // Helper methods. static bool boolFromText (const QString& sText); static QString textFromBool (bool bBool); // Filename extensions (suffix) accessors. static void setDefaultExt (const QString& sDefaultExt); static void setTemplateExt (const QString& sTemplateExt); static void setArchiveExt (const QString& sArchiveExt); static const QString& defaultExt(); static const QString& templateExt(); static const QString& archiveExt(); // Extracted archive paths simple management. static const QStringList& extractedArchives(); static void clearExtractedArchives(bool bRemove = false); // Extra-ordinary archive files management. static QString addArchiveFile(const QString& sFilename); private: // Instance variables. QDomDocument *m_pDocument; QString m_sTagName; Flags m_flags; // Base document name (derived from filename). QString m_sName; // Archive stuff. qtractorZipFile *m_pZipFile; // Filename extensions (file suffixes). static QString g_sDefaultExt; static QString g_sTemplateExt; static QString g_sArchiveExt; // Extracted archive paths. static QStringList g_extractedArchives; // Extra-ordinary archive files. static qtractorDocument *g_pArchive; }; #endif // __qtractorDocument_h // end of qtractorDocument.h qtractor-0.5.11/src/PaxHeaders.10084/qtractor.desktop.in0000644000175000001440000000012312102155164021077 xustar000000000000000027 mtime=1359534708.011491 26 atime=1381134670.93108 30 ctime=1381134670.931080111 qtractor-0.5.11/src/qtractor.desktop.in0000644000175000001440000000065212102155164020371 0ustar00rncbcusers00000000000000[Desktop Entry] Name=@PACKAGE_NAME@ Version=1.0 GenericName=Multi-track Sequencer Comment=Qtractor is an Audio/MIDI multi-track sequencer application Exec=@ac_prefix@/bin/qtractor Icon=qtractor Categories=Audio;AudioVideo;Midi;Sequencer;X-Multitrack;X-Alsa;X-Jack;Qt; MimeType=application/x-qtractor-session;application/x-qtractor-template;application/x-qtractor-archive; Terminal=false Type=Application X-SuSE-translate=true qtractor-0.5.11/src/PaxHeaders.10084/mimetypes0000644000175000001440000000013212224470516017205 xustar000000000000000030 mtime=1381134670.768080109 30 atime=1381134670.704080108 30 ctime=1381134670.768080109 qtractor-0.5.11/src/mimetypes/0000755000175000001440000000000012224470516016551 5ustar00rncbcusers00000000000000qtractor-0.5.11/src/mimetypes/PaxHeaders.10084/application-x-qtractor-archive.png0000644000175000001440000000012312163333061026007 xustar000000000000000027 mtime=1372436017.184798 26 atime=1381134670.72608 30 ctime=1381134670.726080108 qtractor-0.5.11/src/mimetypes/application-x-qtractor-archive.png0000644000175000001440000000427012163333061025301 0ustar00rncbcusers00000000000000‰PNG  IHDR szzôIDATXí–IŒÕÇェê®^¦gëž{¼¯,`ŽÀ ‰‚Š $CN‘%B‚‚BHN¸D9Eá)J$NQÀl‰³b0ÆÆ8ØŒí±ÁãÏ´gíé®®ª·äÐÃcƒ£¼Cªžêû½ïÿý¿÷ ¬o|û¾pÕêõýÝån)UÖ–:{܆«¯ÍF¸Ù N ¯½´[t´e„Ê™ ¾òH’H¾¾÷•ÉÝ»vŽrË[ø"i6oN?ÙÑ–÷ó¹BR‹fÝÄèk6\ƒï¼wh?×ö+_!ãÔ:!„+µDšÆÁxèÃ¥ËÖ<ñ—?ýñÏ@ü?øA¶}Ùʵ•®ÊRª£g˜žš!nL3=Y%ßÖ…KkxÒº(—:PŒ1¬»úúMåJß“£§—=ûÜ ¿¢+(u–Íæ­·¹®r¨×¦­NSþýÚ‹„*¡¿+àÄ©Wmþ2¥ŽnáûR §µ8çüLÖ­\½N=òËÇ~.¤ ŸyæÙÇ€Ú()Éd2"Ÿ/Ð^*‰Úl!+W­à ›®ed¬ŠŠîr…¸"“É"„©ÖbxxØ-_¾B=þÛÇRÊ/=õÔßL}nçFŒN1:g±ªcçÕ±1ö¼ô2ÃÃ#AnN² âá€J¥åçÜž×ö¹çvþ‹;_±6ÓÉ÷îÿñ¯o¾yëw¯(ÖZ„€Þ%ý;¼fœ²æª Ã­Ó ¢U; (÷ôrË—¾Êu›·ær”Ú»d©½ƒÊ’bõ›ïxë­7Ÿ’Ï`¥³³›JïV­XΆk6a›ÏŽããà ä EV­Ýˆ !%bnŸ‚JÏ’v L\@\,A#ªf|’T3==Cgå‚cDËŸ€Ph ¢ãf kRÙ6áµ­G[a.RmQ.ØáÏ ­ÒÑÑNÆW¾ÏeàÂ)q³:Àø™èÂzi6#ŒŽÁÆÏcâüy¢FcŒKKÇu”LîÊB·(@+¸ÆhM’Ääó„ ( òÙùŠ_`°*G½6Ãà‰SLœŸ¤Yo`´Á9pN’$š8i¬þúÛ6-^öc ZÎZfggÅøÄ$Óµ:BÊ‹‚;çðý ú8ÍÚ0(åÄà0FÜjf8¤”8'@(p”|Oô]ÀµNoæd0š4M;?N˜Íà«–çs(/@*Ï;wš½ÏýŽ“Ç^§Ré¦i/R <ß'“Í `]ë*NS¦ Îïù8kñ<¿e¥=s‚î¥k9²'GÎ’É•iïõùÖ½wrèà ²¹<! ¥.ÚÚ»y¿1V¨-`ìœþiË‚Z£Ó˜B!DxÍ$ÁY‹’G^¥˜ÏÒÝY¤#§¹ñÖ{¸ú¦»ùðØË8ÎíwÞÎXu’FÔ!]wÏ2jµY1:61rè½Á—È@K‚4M‘R’& ~%N ÙÀ'ã{¤i‚çù´÷ldpà0o¼ù{l2ƒ_XBßø*ìãøÉX·$eÍÚÕ8‘Cù!Q‰o¿Ãá#§vGoÅÖÌ[PÊV#‰³ø ªÕq 5:+)õFÌK»žbüüžïaÒ&GÞ~‘ÎÎ2¹RÔYÙ÷客H`àøivïÙ÷Ásøx8ù€1jÒ$ie H°ÖÅšu• Ù¬O7QžO>_dt䵩Â0s–¨6Jux)%n¸‹Êú»9óÆ,o¼3|èèñá‡c—¼Œ¬5¤sBê”$މ› ÎŽm«Ðn :MÈKtttà‹a¾ˆ§<”’()Ñi“r¥‹m_þÙì]¤iJ¢½¡û÷¹ìmh­:MHÓ)i’b­¡»«‹l6G££!I†O¡½èQ ºÉäòAO)”’X›æBŒÑ8ç¡$¬2ÀìåܼJµ\` g††)—»)æ³Xë8{ö gO죿§Éñ„\! WÌãI57(=NmjŒ0» kÎY±0Þ§‘ц8Ž]7I⦛‘Õij—÷÷YcŒž™µIY¥<;ÓpöüdÓ6u`‰gkug§ëÆNÕ´© [>i_ÝùW[o4ì\}ÙÏœ ¥JJ)¤TH©””’l6„b=KW„%„tuvpÃ-÷0²b ÊóPÊC)ÏWxž”­É¨T*QÈçCŸlf>àøÀÑi©ÔÞB¡è„”Ö÷<¬µ$iLì£P("H) ÙlˆR!•SR!•B)…”­ÙûÊn„ ûòîžZ˜u±ÈDXºËÿw €ë6ß<ôî;oÍOÅÿ&èj£û@òIEND®B`‚qtractor-0.5.11/src/mimetypes/PaxHeaders.10084/application-x-qtractor-template.svgz0000644000175000001440000000012312163333061026406 xustar000000000000000027 mtime=1372436017.184798 26 atime=1381134670.70408 30 ctime=1381134670.726080108 qtractor-0.5.11/src/mimetypes/application-x-qtractor-template.svgz0000644000175000001440000002272112163333061025701 0ustar00rncbcusers00000000000000‹í]Ûr#Ç‘}×WôR/R,ЬʺS3³±–Â?8áKì3†ÀÌÐ& .ˆ¹éë÷œ¬Ð q!9À+Ù!¢ÑÝU•yòœ¬Bõ«ÿúruÙ|šÌn/¦×¯OlkNšÉõùt|qýþõÉ?ÿñÇa>inç£ëñèrz=y}r==ù¯7?¼úá°ùu6Í'ãæóÅüCóçëßžn&ÍOæó›³ÓÓÏŸ?·ÝÁv:{ús3¾ùá‡W·ŸÞÿÐ4 Ú½¾=Ÿ¿>é.¸ù8»ÔÇç§“ËÉÕäz~{j[{z²:ý|uú9[¿ø49Ÿ^]M¯oõÊëÛ{'ÏÆï–g³7ŸždK)§FNE†8cxûõz>ú2\¿}Üt©cNñÝê̇uö妨Úý¶ß:̃ÿ//Xho§gç“w¸rÒ^Oæ§¿ýã·å—CÓŽçãÞmÖ_kwmH®GW“Û›Ñùäötq\¯_óø|1žx}â¤~ü0¹xÿa¾úüébòùÓ/¯OL ­mðM³øöbüúæŸò¢wgÚêë“›Ùäv2ûT[]tálÙ¼i}n}3+Å=eñ¬gãé9;ÿúäç³Ñù|:Î'W7—ðÇMý~òæÕòTž7fyƒ¦¹½‡Ï\Ng¯O~|§ÿœÔ/ÞNgãÉlñUÔÖ¾š¢Ïó¯°Jwxúö_“óù|z9™®ù8Ötß¼ŸÁ`›Ž¼O6}±|vvoÙÐÆoo?ŒÆÓϯOäî—Ÿ/®ñŰ«èï]ݰ=Ÿ—g`„–f“ºÃ·¦Ÿù$¯OÞ.o'wo÷ûtzÅ1J.…»ßÃl¼×ƒó¯wÃ51ç-_òÊmß]¾\\]ü>o0ÙùÇÙ P2¼}ÌVŽØœ¾yu5™Æ£ùhe„Å‘àáA@‡³¿ýöÇ7¯ÎÏÏþg:ûw=ÿð›ÑÛéGçÏÏ‘W£ù›‹+ŒCÿ?áã¯NW_ðœù×›Éêõ&pè 8>¿ºàE§Ÿ_\^þ™÷Önó^óË ÿ>íú†¿–Ý=]<N¼»]=? GýÍ+ Îd4ûÓl4¾€qÝâIëß8 –Á4ŸÞ¬ú®#øÒ¬ßο^Nê7C £³þó‹ê¼úÌö.™¾{w;™sÔø0[[ oÅlhÅj+§ëOø[„²Ã¡ì±E›o´E({lQ"ÿÝßÊ·Ú•²ÝÞØ'ŒX+.HñVkoö˜~“Q¾ÙA¾Ø×' oyŸ¯8L\~þ"i)mŽÑøÕY8êBjCIåd‡½YÝY ÂهلæÇ ±8ï}wðŸ×sP“È­g¢ýëõ?—ð½:ëHB·(àÞh>»øò“i£›‹µÃW‡LÅÉe7°à&„ìVcm·‹¹Åÿc^3µ¡1ôŽÉ¥ âcY3S m–àmÚe'ØñAvbð~;9›Š÷kÚì¢õ¥ÚéÝÅå|2[vôõ ÏÌ=·¸w¤Ëã¶M=.r÷úQuóáÅ5Z¸™‚< kƒxºÛ¿ýék¬ß¸d"øÝäO£··£ë?\~œ­B™éã%z÷öïš¡`Ç›çkq6þmòéB[C‡|ëź”OÖtýþh4UsL~eŸÿ¢ö¼{Eï+o¤ÛŸF—'x&Óðß¡mL³ëOüÕïÎõ®ÇÙòÀÿ}yóaÔuù—ÓéøÑ÷ãE½ãúyØÑÌÙû·?©ý|ïŒ lïÛT{Û„¥1¯n¦·óI¿w²«{ÓpÐ9ûpq}×Fwz¼x’óE#ö^–í£O‹ÞíWoqt«3õQu“¡•ÒµòW…îû÷¯Þ»ËøëÝûŽ¿ln©ÞIÅî±î½6VFBÃ<Úõ––]v®f©Æw‘åiPàì¡À·®$oË$èžã¡HàJNÿ›‘¶)/ ÀKìñ‘­¸c#ÚØ‡³ÏèVZG‚\ÌçÖ¸Ô£ŠÊÅ\«snåUÊÅŠom eÕ4¹Xv­· sq ?î‰Å‡q1ŠÊgäb;ì^nÄu;‰sm²Þ•5;Åœ‹)¯ÛIœo5;í$¡ä‡ØIœ1³“m£— ¤X˜ÉädÄÄ ¹µÜm`h¥DÙIí7<»¹MœáË=Zp“.Þ$ÎvI@´"Oh¥…àÿÎmj®õ%б!ìn÷ ªP㬄 n üctyw$´Æf¬Qz7c‰-ÄÖ;é•—ˆÍ"Ñ›•¿Ã 2NõÎö 9ïpƒÿð&õJ|âõnˆôœ|—ÃëíE¼…&¬Ñ-šÅ¤ƒx1»¹uœ¥'Ì6޳[{¿¢Q«È±<Ö¥ìqgÿÎys~·9ÄZA\oôæ 1ãÎfóžê’#Öí )â[Œ]ði x­­)¹ÛZSqm!ö"ÀËH E· x}4^{Hàe= ¶í€7yÀ dÒ!€×î^»x㻈lõmI´²ÇSÓ»Cx@+ín µ{€VÆ’¬=páS9AABïA2‚äZIѬ3‚,m6ÆÉºcJp­v2 õ3`iÈ pš\ç™ÈJÿ d”¶x—¬þ%ʰ9ÅØ:gó];y$åõjŸ­î~ÇNdY!…¼ËNò°jßA™ \EŽuK†éLŠVžb§*j!׫¢.Ÿg{ÇŸhÓˆfýJÈîn?õoõ€†É‚d—:3ù€'JRžb&`<ÀÜß,Ùå6{'ø¶䈸f¥ ãr‰a§•ìÃÌ!­$-ˆ8ÌÂJV ”}|RÐY è…¬[)!—zøÒÝ™ˆˆx·wä üº51Ä]Sp¦ME:èøÙú8Ak™§Åœ5±…ïhßÔ­îD¤ckí14´J²¤'ùaÈ$9ÐHÏ\X“+%Rú>ÒH'ïbÃ}F»!OÆû¶|#µ²‡À¤Q²A¾™ZH1»Û)’Þ¹<Í£©… éìoÍ5½‡ïÓ£oš4I{!1Òškb˜¶ûõ„IÓ=‹k›‘8W¾éL”ø¤l–`Ñë8pÈsñkvbQ ô:¬§Zº$ãvÚÉ™‡ Új'XDŒMe]E‰àF.„;dDÄC;¯O¹ÒzÙ!¥ìö§ç°Tò$2@Ç.Râr'± ›Yç˲NV™Ls´æŽ?•þ߯u|•Mçn¤,ó”„Ið$¬tŒ–~»•vÔ–JFÚëG.ß2ˆ¯W.6Q4xS¯ˆÄë½k#DîÊ,-A ·Æ÷WÝ/-9›Æ8,‡lÌi¿¬è6›·ÛîSo d'f”8gÔ×Íý9£ÝžYï=crøö#¯µù"HÞ§ÌõïÊÙ¢û­tsEaïLÜãæŠ2Sº©¸CÎs½Û39îÞé¸ïî¸å‹ö9nyÒ’‡;n4‡]îpÇe‘÷ÐŽ X&Ç&½0Ç¥þ=¶ãFkë¸v_{ǵáðŽkÓs9®Ý—Ô¾»ãÊ—ìs\yÒÒ’‡;îÞå{ÏḒï¸RžËq÷®áû\övDÇuḎëöå±çp\Wï¸þ¹ÄYô/MœE|qýqÅYô/PœÅpxqÃs‰³^š8‹áøâ,†#‹³øÅY<‚8‹Ï&Îâ‹gñ;ˆ³tdq–^¢8KGgéÙÄYzqâ,q–,ÎòKgùâ,?›8+/Nœ•ï ÎÊ‘ÅYy‰â¬^œ%ó\â,™—&Î’9¾8Kæ¸â,™(Î’=¼8ãÂ×gr\ûÒÄÙê÷àGt\{\q–äг$Gø™°<—8KòÒÄY’㋳äŽ+Îú?Á~9Žë/Î’{.q–ÜKgÉ_œ%\q–ü gÉ^œ%ÿ\â,…—&ÎR8¾8Ká¸â,…(ÎR8¼8+åØŽ»uSœ½ë˜¾û–8掻Kó$×}Ü–8{0}÷E§?¾x&÷Ý»šé»»¯=@ma¿ûÚ'Uç¾{—1=‡ûÊÁ+ Þ¸c µ­î»wiÈww_w¡¶ß}ý“¤ÚãÜwïšçp_p¹†{[®muß½ D¾»û†ï°‹Z9ú.Zhãå‰6têŽh;å&Éo^ÝŒæêU¸àª‰¡Ítõ4ð¦1ÙÛÆ |1m)Ü q9·¹kÜÀ4çøÎ4¦59•ÁPBi³Í&áèйк$5Cî>$i0´¥õI¢k†Ò nàpN²Üñ0zÇŸŠ:ÛüŠÆwKñqP\Sö>7.Jk‹õv,.¶=tè¬õNÜ ðw`ýiœsm ¡Ø­/¶Diœ¤Ö$±…Oç%ÆŒk ¾N¹ôŸø¼aϰÎ͵$t}t±QBàA[$†‚gqÝÈÁÒ ¿w#0ßô³>ð·€ÿ/tU ¾9H-GBXiƒ÷)¥EDs 9>λEät?ÚÅ ^žýhFü÷~èïSĆ˜c=>ûx99›|š\OÇã_nç³é¿'½]‰ù±î£~Fƒä$HÓ‹ãü ÚùèæìíÇù¼ì_Ó‹ë³+8ÕlqT?\^à?g~qlùûáÅñèöÃh6}=»ž^O~©~xöqvùÓ«Ý»ŸêMλÈìö† Ë­û®Žp‹ÙèZnÚ»ø÷˜µ¿{—è{Æä}Å/wèSû´Ë>¶5ÑdȽôËøâöæ²{íï †[„$Ä‚À»ä}@H|8ÅìJhDà›ðqg{A$ÙZF ÛÊ]TxÎ8ð1Ñj,Áц® Ã>n Îî·ƒák†—#†ÂðbÈðåЫx åpbÃ0 †ûó/oRB, ClÅH΃amÀâÄèÐ3œ&aÉò$x¬5Ñbûh>éÁXL ìúK.Œã¬Í0e\ëœháY3à =/Þö"håûËý5×|üv"·îûöÑ./ÁƸ›@ý'?›ï£ñ-¾ocäm)݉8 —›Fá¦Üã­â€¿B¥‡¤;aàÜrƒõ¾]µK÷7èþù®¡ûfuwÍzXÓP£þ¼)Ì$<.7"?:}¡·K£cvÀ¡X|óN€ÂMn™n'xîß’œß Þ[¶^dâÉz‡¶ £ø{èÍ&Kÿè#ÿý6¶7_ï±kÝÃ`6¶Œä»¤¸´Ý)è®%¡A& `yà‘‘§Ÿ¹'¼+º—z*)6À=!0J jS“Û›»všˆÏ>|m¹c¡Í¼`²²ÇmLâ1ï׆Ò‡à­DM\p_Ü,à˜áfe9–FLiù[hp‚Ì?€ žS†9xLºŒ-ì€ä@PORX @$'é=¬ÑAn¢dA!lb»ßpNnÎsö zJÎôDð\yúÂr§•}!Jº¢[=iÓ $à›ÁÑ?&RÝW_|¿2Ì{——o«YYåÞ•$jyÝ–.Qï–?‚_|ZÈD:´Ì³Ü²XY‰,털ÞN_[»ÁY vcJËpB΄søœ.Â'#ذ²N€â}‚_Á“‘‘…{!Äw)‡À…cAÀ‰…UAÀ’/i`áš× àèt0·"nï1žp(z¹÷R4‹ƒBHpóƒˆPîêÆ‡—ZpðPvP{$G®mr#ä­pmPy£œ Ì›[è0‚ÞïÃJR²bfÊÜÐK‰A„¸>ÄZÂ…°9¨<¸R0žüÄ*5%‘A¿²'@—ZúT‘»zrû¬k<Å :OÀm‹Ü Ô¸Y-n׈›±´” l&# E! R£!5³QùI-‚\(Ùbk#%ÐHÒÀFšŸØ˜ŒJq›*›Ó#ÿ ¼*´.Jhß`¤¸^ƒ=‡Ö±€&0: ýòüÈ-JÐc™œ #ʽÆ-OJ¹ðlÈAàЃ5á ˜É;n‚¬“«C¯¦7ɇ:¤ vÜŸðUé]r‰‹(B‹X É…ô "˜xSòºÈ!ÇÝ)­JvÍh?,Q›>Òo`þd…nÃÉ,ñxES‹Ý€=!‘ÃŒÄ@h¸Y,ýƨ¬†1ó"XGÖS$¡wÅÛPLPªJÐdœ‹Iuäð߈dÂk õ¥ðÚÐXáHy«'á¡ð8|­î§ðäØÜD™{_(•…×P±ÒÖ.+õNx@„Ž?Ï…Ó€«Ðh–â™Æ"öG†cpwL ž¬ž‘­ 5XÏòÉFžƒ`ÂÉOž‘ªá`?ŽRT£#ùQwý®{uYXPGÐ ="·ð>v FcÌi8"ó9Þ«…ãERuÄDôt ŠeÄŒCÉÇCXø¨ª9 ‹[C"×¹ÖB&×8Á˜™:3·êàèVLÆ+nt*^¹¿UjFd𑋨Íl––öclRAÿt€ÓàX¬BP¨Hù„^ÂM`üXPè. tT" ÍP·£áJê p‡†GRá8pˆˆ*“”Â3&ƒ'O°r£9ˆ£Æ à‡PC«’Ì7>¨q…¢2HH“Ó¸IÑõKãý1FX‡ÆÃ¯,kè1.Ý8#íä(ò é§TÒzIÇ :ˆ øa–ÃL× D2ÙH VHƒ`AB•áÆÏ"À«+gÑDu$¾i *TÙ":,`ãšß›+\Ù…¡îÙ s’ØÐ/³S˜ÈB/b€2wjD1= ×ç2âbÿ¥ëeŒJlï”1 µ»a;Ù ¿Wù•Û=;¦Mîð¢öŸÄ â _ÜÀ‚±MÙ~ÀÞqÇ$+`@l„O4&6ØBˆ÷DHØŽØ“]¬i94æß‚‘LŸÃ`, "èc SFnì LP+@¶˜ ÎHš'‘}14‰)©8ÕN@õ|1^Ã$çøžõÍ!`K’Bv[âf€* ¾0'a¬ÏšØA²õ)[X K¸YX.Šà U–û &h¦‰pùŒ–„¬ë¢9‰e «Š(3ˆžÀ°ÔÀàÀA …¦‚I"KÒÄŠƒ|«ÒEÖÜ¡:€ 0-ë¨ñWÐßEP×ÏáðEb1sX®R œÓ0þœ¯<5Yæ–Õp÷l'ôrÑø`™r÷ |2}-Wf\!\ÔÀC%0Ä{VGèLüQóAæ 4 '²1í)|‘¤+ÌÚK ›Óä ­²2ëÓ0±"Viaë%«ÒDV€—Ñ™ š½C"„íUÿF¡~qŒ€80 ·íë(ðpìA±ƒ&o-{é•ÇJÌH'yVÌ–Þ„;’r};Xä£ÃÍÒ¸ýÛÄzV©™)%Ò †X ,÷®Áà@“‹fà†d‘-ÕQÕßXúbOŠLø n¢-ƒúò9T­Š ¤É›‚¢T¢ 棃‰$Û– ÅVŽ‚X š¥LÁh4ÛdÍèhŸÏ@Tñ¶“ êD‹æ%”OS–Ác6Úw%^·W©Éáé¡,”lƒŸƒbdæDË«º[n$µÀ¡¬ã]å4Túê|NžÒº+3îÄ Î”Ñh¯”c˜D:+Nñ>6Î1­Âw=Ë@txd2"¦Ö6pGtŠˆ¤žÚO*eåί¬Z!dA¶q?Cx§ËávdŒjOâ…ÆðüÅ’¤Ú×÷“Âú“|¥ %&Õ)¥†i¤Z_ÈkÈæ‡ qAk¾àŸôòDj WÐl,Jê&`Û¹ªCx¾¨{êÑpkøI"I2¾éʸÅor«¬KJ)^-—h¤ÖÔpâØï` iÃΨGf ôîã–õKÚÀ‡!K€7»ÂLè•áøN(áPæ<S s(šd cfŽâ )}ݳ…¤Ñ²«úÎ'<Æ1á—~´æ¸¨Oø&B&ä;+÷(ïH>@¦Ié@T )ÑœiTyCQÿ@¦`Ÿ¼¢‹£7P’¶¬%PóýŒ(z¤K˱‚ ?ãîV2ÎÂm)[Ý>]q¢8â9ƒèdíRŒ&ÝôñàvF*>%-)0%0˜“¤&<ÃSj´JTÇÅså™ÐjNjUoaÅ3F ‡¢R LɉÃ9áÇm ÙøK¨:À““áþh‰U=²ÿÂ4‰å&GõL–spHŒ+Ÿ‚“šô˜m˜”;ÐCÞdæÌ…<ÎP(Áv9xQÌ«I•höŠ*ŠÄ‹E ൯| Ÿ¹Uu!ƒ‹845ƒ.d¶È’‚Rì`·d¤*2V8‚­ŽnV%š`ÿèÉ!| 9R†ì¦/26˜Ú-P«~ÃÙ׬<±HdúÆÃUJº?7’†Ú1E\ô'£`q «£‰ÈÐÒpQéò ùÆ:ÖbT-œ ´²Æp:æYg¶8ó#±Êÿ¬„]ó¨fЍóNŠA°æCâ½¢¸AÔY¦Ö@‹z™‡DTƒYDAÖæ0¾•Þ”¢ò–‘b‘I»²ÕëÊ€K­%!é¥ )^Y},d¡h%r²¶é’_ͮ؄Í,hÑRnp;J«#õ±ñ|_$ÜZèï0¯i4.PÁóšl4Hø¨|ã8G…AèŽ謃a™€E•g®O]¨“uàFâhihm\–¹}'€^¡œ%q¿»Iç¶a@NÉTu6Žsz‰„ÆR5Pjg«Eˆ©]9PYX!DAÐ{Š¡JdŒt9€O‚^] h^Q?P1Œ¦#0°ÔLì—£<®’“ •œ`è‘‹ c Hà½Ju•U–‘¾ã»â §Ô‡,æ—*ìø¢ £‹4´1ÚGÀ“>pà›!ªXNG”sàD*ûm¡þRU@ j94µ~$| ¬W̶³J oa©à¬³$‚'+ħ zɪÆ8_³P¹'N¡£U–#‰ÆÓm°ø¬M7ׯU†(-=XÈÝ-ùtÃ{oŽ›O9œðÏT3)«®YˆUXO²çééÆ@G޹Vi *AœÀw™4ø°%×êDƒxMgH8µÁY<Í¿àup´“ªFÕŒf9#hXtÆÐ Áƒ…noáBá"FAމPÔŒf ¿Žålæ-efÆ/k‰ŠRéëÒZ1E^¡¼f9‰žMmjkQ¹Ô±TËòQí?ß–¬ÄI´JIËÂÕ€ø§ò_?ÔäR0ê w¶RaZT5hV_ažóþY…)û Ÿ4ÜCZ'ä‹«Ö2!u0Ä5c4I±ÞpË\–ùB“ʇ!*9u("Ñ2@Q]ÉL?[ùH ¼®†F¥–Z2VÔr¾¬Vü ìÀ, Zc˜tøf 8`þܨ„Ë܆§':¶–I8 ®¥ÐÌŠ&k"`ê舅pá@ƒ(åZžÑXÑ8?²¦ïZ-~0iÃÕü@ŸVH2ËãœÅͺ0ƒ•™/EC¿Œ!F®Š‘ÙÓ¹e3€39 DzÍErLMÎ:+˜»ì#âak|®²£Ó¢¹hdŠ+"gI»ª1˜Q¬Õ%¬Þ&¦W­FÀyEõ"e¡–”0„]‘fTéi8m ×ykS¨ù‘Ú…4‹T¬Ñâ°R«âˆ@L©Hˆå³­ý"*´Ÿ<§tˆúLˆLs|¥Ojøª:à[¯YVä\» ¢iðÎê'Õ¤NÓr¾=° ßMá'Nœ* 84‹Œ4+çr ³6óß$E™¡KQj9ˆ/CÇ¡"š­Ž*7*½R ­V’3¨w7ÍïXKôEÖp¢búõk “WT *pƒÒøÈ¥ <æÀ,åšýÞütÈÕ*#2 àSŽsa¬ Ág¸J'¡yF¢/§šûij­ØdªsèH«ž2´šÖ•çûÈgøfNgo+s—ìžrK±Ÿî­¨Å¹3èp+þ Ü’fVq¼jA£|'ª6ZE‚餙4‰† N éZM]TëUäcx*ŠÚ '±ÎM`àlœjd7….™îÂô åçë‘ç’S*•9u§ÎüÈœ‰aýÜj)­4|“¥&còaÒ¬Av[’Û¦W×(¹¾ï¯ÌY®Í­…õ'ƒ—ï-çØ;Û{ßÌLW"ÃYÈ–°ºbÆ÷²ŽÌêÑòè—úN)¤°Þ;p,rU£ô¶ª¿?µm‰Ž+$ºñ»OÃÄ9Öà»IƒÓ¬Olë9×{ýž…ÜùÿÁ –kVæ›ÿ¥» O:Á—@ºf#kzÐ$€| ¾ªÕÈ $,n–Èú-òb^À£,s©uqˤÌêžÇ×—äLœê:›×}’q$¾:ù’• –W,å t:<˜Ó@FÓ¡מ^ªdÃÐÕ™j$÷koà¶u¶,p2’þ¬XÀ 9\Ç™oq•lzŠ”K…ÌDòÑ=œJ NÕ©PJ¹Y°É”XÞ§¤Êœk}ß2Îï`ü@L•mÔ^³´–ùè‹.Vú ¹+›|A Réâ¶ú×:4$,z7è:Îgšñ±–Èx»úܰS¡B6Öëì&»‰Š ÉÙ’R­ À32—M7 EµdZ­’Ö Cuu… )›–qlvuäáǺ:ž4Ü]=3›~¼ß[>Sn ¹·k±"ËSÁð¥vÀujXËadЯK$å%{ÖÊ “{dY[ë‘(] ÊEÕ-”úE-—$Ã[ÇN Ñ”%‘” ðC"j©‡Õj‚”ÄŽÊÇ”s/ (LSÖ)bh»„t¡*‹.µœÉ¨®*¯ˆ Y:<çE—¡ÀYMJ¹p\?Èæ~à¾i­ß¾so­U sN¥lÁFë¶:A"ß"êe§+ Z­Q'‚èÌsá{Qq„ô*êdµ~ä¬)0†æùáëë–cª„ ¸»eLͽU­Ë1…4‹ O õŠjg®Ž”Áœb¾ˆB”ófºøµPV+<¬«¢³J& "«Ñ…•]B,Ö¹èÑq‰6K’Z¶æLþ䂤2ƒÂkiÁA8Η-[¦Ò¢kÇ+–°œ¢K’ž•¸„…Ð{¤>â:ënIë¶ô©XtͳÝ‘GY¶òý—ñˆÌÄ\¶ nfõ‡ƒ8³JàÔ…ÎÖ9ËDyiu͆ÖÕ↌•bV°Qœ ¢3ÞâU×Þ%Võ—9ü! Uàst ‰äà@R'!ê9Ë-µÄØPzANTm€Mºî)Üñ§–$-`^ãn‚{ J\ÖU­,M+n€<ä] ˆJD—sd]ïT{iê†%ìOÙ´¦"ØtˆG]I Êr–}ðÙ’„˜:§h)¹v%ûúë ËzDtN½°²g8ÏvT#Ú‡ °ÁC1n#5\e͹Qkü¾(Mç6AT:ZVí¸€$‚7U†yä£Yxrœ pº,Åh‘¶³?×!xJùîN:}çSlê…‹ï)Ey!ÕE¦ÔaâB>Næ.…[вX`mÌvqQQõ¬WqEXð:olëUÓšÀµ$È–ì›ÅWZ½C‹¡ç2Â:r=Bé™r¨ÑÛØ  …Šãª:]¦V´v—½ A±6ÁÉ}"#â,¯†qF7&\QÏàr¢blÂüæøh±Í„þÞ/å–5 r1€p¼W’à$þÔ)¯•$X Í\²V¸Tß“Yuî½jX+\DTz/¿;FEb#Ô?Án²5/“33iÀøð\Y'ú S]ލPø+¾zÈÕ¹|N3vj'5 9¥RWOgÕ-®îäBhÎÙÕýÃEŒƒÈíÖ„XX¡æj¹ÒC²þ؈K¸;o…kâ©cuýº„ìW8‡§å¢`OTj‰Àéï—G§zÐ{sn0×ê!ç"X·éN^XÝzÑ*§b@Üdy`qê1Í÷ÞVºoÐ|4‡4³½ªÀ%ú$¤ŠE¬V˜TšÙZ<£Vã’ƒX_·ÉŸ…QŽèŒ3‰má¢&—tžçÄ D˜ÂÒ„1–?Öp\?‹øàVN¢ ø¦M YÊ‚€r¡Â_ÁÔã¢JÁ"Ãs‘ ²°© ·wxÓ%NÖ‹Î^dôÇŒ¶Xê ~´Ü-|™|a.ëj•ãŠËþ»ì÷È.¿9аB¾mÖô×qàô—:ÁÏE'¢¿0Öê¾þʃèuôZB,pê‡ TÂS0ršÍ}Qmp¾ö¨f,'(¡ªr—]Yõ?½ýôþÍÿº_U> qtractor-0.5.11/src/mimetypes/PaxHeaders.10084/application-x-qtractor-template.png0000644000175000001440000000012312163333061026201 xustar000000000000000027 mtime=1372436017.184798 26 atime=1381134670.70408 30 ctime=1381134670.704080108 qtractor-0.5.11/src/mimetypes/application-x-qtractor-template.png0000644000175000001440000000332412163333061025472 0ustar00rncbcusers00000000000000‰PNG  IHDR szzô›IDATXí—[lT׆¿µ÷™ËñŒÇc_!$ŠA¢%‘(m¥@#$$hE¤–4Rž£4”JT µÚšª•ªF}jšÐÛC E•R‘K•&†%‚Áv ¶1¶ñ…±g|æìKf0‡8bI[gÖÑ9gýû_ÿZ{p—½°ïémO>¹:ÛØ¨¼³€€R,kÞƒ÷h­å/‡^›>ôê«c¬À‚»o?ÑÝÝýÇUíí kŒAäžI<ÿý}CκßýùO‡~D_€µ®¹!›íÊ55aŒA>çND„|KKË÷öíûí\áæš=ú  ´b€õÎyg­xçœ_Ö9ß³~½>ðÓ—~¢´9òs Pïµü†äÖU*,W~×òî{¯FGFüšµkõ/_~ùG{öìù5ÿ"nk _Wϯ¤@Db` ßyãF8ðÜîÝ»UDpoÉBåüÅ:˜šž3_ò€ß¼y³YX@…òØÔbµ{U?!4—Î}@6ÒÚ’#Ÿ¯ný&¿²ƒÁ ’•!vìÚÁØøÅÒ<ˆò«: P˜•ëc“×Î|:yгçß.ÔÕ@l J bdé9!‚(Å\1âÍýɉq‚D€‰Ë|üÑÛ´´¶’ɵqñb‰»®ÐÖš“Ø*ú. rì­þÙ70ú›[ÃIíÄ1q¹ŒR ª‚«hÀ/P`%“Í2ví3nN_' pÎS*Œ36Ò(Å—ßA×úíŒ õS*ÎòŸSŸ¹pid?ð鲇‘[Ôˆ:^réIhâ˜L&G>Ÿ'yÂL–@h­ÐJaLD{[+Û¶o'ÚE—‰Œ:yâäÕº§¡sNâ8&Žc”Z¤äbB¹\føÊEò¹$©VR ’ÉÖh­p.&l+åì-Z ‚W@ ˜­ÀÇ&&ŽË(¥ïaD sµÿ4«;òL߈ ³)2Y´Ò•qÂ[”™¦05A˜êÆ9‡s^>Ç_3CE>Š"QJ9ï}õåÊòI‡ˆ t@¡h¹1U$Ž(+ÜœE)Î!Já W8þÆ_y꙽’N'•wÖÝ€RJ+¥DD¡µÖ:Ðh$A@$ÐZÓÒ’aÓ×wÒ¹öQ‚ `á¹ ÐJ+Œ54åÉdBÂ0$•S÷p©¯oFiýïl&ë•RN•®§µBi…VºB³R„ !étˆR ¥”×Z£•ªvÊŠ~Œ1¼÷Î;ˆHúø›Çï>j øMÀ*ÀqMÛ´ièÌ©S SñÿL¨i¸¨ZñuIEND®B`‚qtractor-0.5.11/src/mimetypes/PaxHeaders.10084/application-x-qtractor-session.svgz0000644000175000001440000000012312163333061026256 xustar000000000000000027 mtime=1372436017.184798 26 atime=1381134670.76608 30 ctime=1381134670.768080109 qtractor-0.5.11/src/mimetypes/application-x-qtractor-session.svgz0000644000175000001440000002271612163333061025555 0ustar00rncbcusers00000000000000‹í]Ûr#Ç‘}×WôR/R,ЬʺS3³±–Â?8áKì3†ghs.ˆ¹éë÷œ¬Ð q!9À+Ù!¢ÑÝU•yòœ¬Bõ«ÿúòáªù4™Ý^N¯_ŸØÖœ4“ëóéøòúÝë“þãÃ|ÒÜÎG×ãÑÕôzòúäzzò_o~xõÃaóël2šOÆÍçËùûæÏ×ÿ¾=ÝLšŸÞÏç7g§§Ÿ?n/»ƒítöîôçf8|óïn?½û¡i´{}{6>}Ò]póqv¥'ŽÏO'W““ëùí©míéÉêôóÕéçlýòÓä|úáÃôúV¯¼¾ý±wòl|±<›½ùìô$[J95r*2ÄÃÛ¯×óÑ—áú¥èã¦KÅsŠïVg>쬳/W0ÅÖÎè·ýÖaþüyÁâ@{;ý8;Ÿ\àÊI{=™Ÿþöß–_M;ž{·YX­Ýµ!¹}˜ÜÞŒÎ'·§‹ãzýš?ðÀçËñüýë'õãûÉå»÷óÕçO—“Ϙ~y}bÚÐHhmƒošÅ·—ã×'0‡ø”½;ÓV_ŸÜÌ&·“Ù§Úê¢ gËæMësë›Y)®è)‹g=OÏÙù×'ÿ;ŸÎçÓÙðvrË‹Z´ôûÉ›WË3yÚ˜äõMs3z—¹šÎ^Ÿüx¡ÿœÔ/ÞNgãÉlñUÔÖ¾š¢Ë—ó¯0Jwxúö_“óù|z5™®ù4Ötß¼›Á^›Ž¼O6}±|tvoÙÐÆoo߯ÓϯOäî—Ÿ/¯ñŰªèï]ݰ<Ÿ—g`€–f“ºÃ·ï§Ÿù$¯O.FW·“»·û}:ýÀ!J.…»ßÃl¼×ƒó¯wû²á‰»¯6£ûêÃèËå‡Ëß'ã §œœÍ#ëÑ×Élå„Íé›W&óÑx4­,°8<ÜÈpö·ßþøæÕùùÙÿLgÿ®§ñ~3z;ý â¼ñù¢ñÃhþæò‡aÿŸðïW§«/xÎüëÍdu‹z¸¾FóFŸ¸äE§Ÿ_^]ý™÷Önó^—ó« ÿ>íú†¿–Ý=]<N\Ü®žŽŸ„CþæÐf2šýi6_Â8‹nñ¤õoœËHšOoV}×`Æ|éNV‡oç_¯&õ›¡ÆÐÙFÿùEu.}f{—L/.n'sŽfk+áñ­˜ ­Xmåtý a‹PvØ"”=¶¨Hó¶e-Jä¿û[ùV[¸R¶ÛÂû„kÅ)ÞÊcâÍÓo2Ê7;Èûú$#Ù-ïó‚‰ËÏ_-¥Í1¿: G]Hm(©œì0°7«;+98{?›€Ìü¸a ç½ëþóúrZòyõïL²½þç»Wgýè–ÜÍg—_~2m”bs±v`øïêãi8¹ì|À„ýÏj¬í¶q1·øÌk²6´1†þÃÑ ¹´A|,kf*¡Í¼M»ì;>ÈN Þïb'gSñ~`M›]´¾T;]\^Í'³eG_ŸðÌÜs‹{Gº$nÛÔ3á"q¯U7^^£…›é(ñôzXÄÓÝþíOX3`ýÆ%Á“?>‚5®ÿpõq¶ d¦Whèâíß5CÁŽ7ï/Ï×âlüÛäÓ¥¶†ùÖ‹u)Ÿ¬èúýÑhªæ˜üÊ>ÿEíy÷ŠÞWÞH?¶?®>NðL¦á¿CÛ˜fןø«ßë]³åÿûêæý¨ëò¯¦Óñ£ïÇ‹zÇõó°ã˜³woRúùÞ+ØÞ·©ö¶ Kc~¸™Þ^Î'ýÞÉ®îMo@@çìÃåõ]ÝéñâIÎØ{ýY¶>-x·_½ÅÑ­ÎÔGÕMn„VJ×Ê_ºïß¿Bzï.ã¯wï;þ²¹¥zK$»Çº÷ÚXu ýòh×[Xvعš¥jßE–§A³„ߺ’¼-{ {އ"+9ý?lFئ¼4$/±ÇG´âŽhcÎ> [i vp1Ÿ[ãR**s¬Î¹•W)+¾µ%”UÓäbÙµÞ‚ÌÅ5ü¸'ÆÅ(*Ÿ‘‹í°x¹5×í$εÉzWÖìp.¦¼n'q¾5Öì´“„’b'qÆÌN¶^2ba&““6äÖ:p·M •e'µßð8ìæ6q†/÷hÁMºx“8Û%ÑŠ<¡•€ÿ;·©¹Ö—(Ɔ°»Ý'¨~@³64ºE€òÑÕݑЛA°FéÝŒõµ[ï ¤W^ 4‹DoV^|dœêír.pƒÿð&õJ|âõnˆôœ|—ÃëíE¼…&¬Ñ-šÅ¤ƒx1»¹uœ¥'Ì6޳[{¿¢QKȱ<Ö¥ìqgá¼9¿Ûb­ ®7zs‹qg³yOuÉëö…ñ-Æ.ø´¼ÖÆÖ”Ü‹m­©¸6„{‘Gàe$ТÛ¼>š‡¯=$ð²ÛvÀ›<`2éÀkw¯Ý¼ñ""[}[A­ìñÔt‘bh¥Ý ´vÐÊX’µ.|*'(Hè=¨SF\+)šuF¥ÍÆ8YwL ®µâÃNF´~, 9N“ë<Y©àa€ŒÒï’Õ¿¤8ö1§[çl¾k'0/¤¼^íó¡ÁÝïØ‰,+¤wÙIVí;(s‚a€«È±nÉ0IÑÊSìT@E-äñzUÔ%ðólïømѬ¿ãO ÙÝíñ§þ­¾ÐÁ0YìRg&ðDIÊSÌŒ˜û;‚%»Ü¦bï¤ßƒ׬”¡b\.1ì´’}ƒ9¤•¤±‡YXÉ „²O : Ľu+%äR_º;ïöŽ\_·&†¸k*Îô ©ˆC"[¿'h-󴘳&¶°ñí›Z Õˆƒtl­±=0¦‘†ÖAI–´3â$? ™$çÉã’ `r¥DJßGiããä]l¸Ïh7$ãÉxbß–o¤Rö˜4J6È7S )fw;EÒ…{ÀÓ<šZؘÁþÖ\Ó{ø~1=ú¦I“´#­¹&† i»_Oؘ4ݳ¸f±‰så›ÎD‰OÊa ½Žs÷<¿f'µ@¯Ãz: ¥K2n§œy¨ }¡v‚EÄØTÖU”näB¸CVAD<´óú”+­—RÊnz;AE O"tì"%.x»°™u¾,ëd•É4GkîøSIàÿýZÇWÙtîFzñÀ2ßAI˜ï@ÂJW Áhùà·[iGm©d¤½~ÔéÚ-ƒø qåb3U@“7õŠH¼Þ»6B䮌ÀÒ”pk|åÐýÒ’³éaŒãÀrÈÆŒ‘öË i€n³y»í0õJv²aFé€sF}ÝÜŸ3 Ùí™ÕøÞ3F!‡oŸ1ò÷X›/‚ä}Ê|Qÿ®œ-ºßJ7WöÎÄ=n®è 3E¡›Š;äœ1×»=“ãîŽûîŽ[°èaŸã–'-yx°ãFsØåq\yí¸€õgrÜhÒ s\êßc;n´ö¸Žk÷å±çp\ï¸6=—ãÚ}Ií»;®`qÉ>Ç•'--y¸ãî]¾÷Ž+éðŽ+å¹wï¾ïî¸ËeoGt\Žë¸n_{ÇuåðŽëŸKœEÿÒÄYôÇgÑWœEÿÅY ‡g1<—8‹á¥‰³Ž/Îb8²8‹/QœÅ#ˆ³ølâ,¾8q¿ƒ8KGgé%гtq–žMœ¥'ÎòwgùÈâ,¿Dq– Îò³‰³òâÄYùâ¬Yœ•—(ÎÊáÅY2Ï%Î’yiâ,™ã‹³dŽ+Î’yâ,ÙË3.|}&ǵ/Mœ­~~DǵÇgI^ 8Kr„Ÿ Ës‰³$/Mœ%9¾8Kî¸â¬ÿì—ã¸îðâ,¹çgɽ4q–üñÅYòÇgÉ¿@q–üáÅYòÏ%ÎRxiâ,…㋳Ž+ÎRxâ,…˳RŽí¸[7ÅÙ»Žé»o‰cà¸û·Ä1OrÝÇm‰³wÓ÷w_têàîëùã‹grß½«™¾»ûÚÔö»¯}Ruáqî»wÓs¸¯¼Âà;¶PÛê¾{—†|w÷ujûÝ×?Iª=Î}÷® y÷õ—k¸ç±åÚV÷Ý»@ä»»oø»h¡•£ï¢…6^žhC§îˆ¶Sn’üæÕÍhþ¾^… >41´™®žÞ´"&{Û˜/¦-…›4.ç6—`˜æߙƴ&§2J(m¶Ù$:Z’¤fÈ݇$ †¶´>ItÍPZÁ ÎâÏcÂI–û¢ CïøSQg›_ÑXàn)>ŠkcÊÞçÆEim±Þ’ÅŶ ‡µÞ‰þÌ ?s®-!;ð¡õÅ–(“Ôš$¶ðé¼Ä˜q­Á×)—þŸ7ì™ãÖ¹¹–ä‚î¢.¶1J¥´ˆhŽ!ÇÇy·ˆœîG»Ä«³͈ÿþÂý½qŠØs¬Çg¯&g“O“ëéxüËí|6ý÷¤·+1?ÖMÔÏhœizqœ?A;Ýœ½ý8Ÿ÷ýkzy}öN5[ÕW—øÏ™_[þ~xq`<º}?šÍF_Ï®§×“_ªž}œ]ýôãjwÆî§z“ó.2»½aÃr+„ž°«#Üb6º–›ö.~ÀÇ=fmàïÞ%úž1y_ñËúÆÔ>í²mM4r/ý2¾¼½¹êžCû{'ˆ‚á! 1 ð.yN1»ø&|ÜÙ^I¶–QÂß¶r‚sF|DL´Kp´¡…ëð›‚s„ûí`øšaÁ刄¡p'¼2|9´ð*Ã_9œØ0Ì‚á>ÇüË›” Ã[1’ó`BÅ0à†81:ô § ‚GØD²< kMô‡Ø>šOz0“{‡~Ç’ ãÅ8ëc3L×:'BxÖ̰BOÅ‹·½ZùþrÍ5ß§‰»ðë¾oíòlL» Ôò³ù>ßâû6FîЖÒ€CÀÐq¹iônÊÝ9Þ*ø+TzHºÎ-7XïÛU»tƒîŸïºoVw׬‡5 5êÏ›ÂLRÁãrƒ‘!ò¡Óz+°4:fŠÅ711ïx!üÑäPà†‘é&0p‚çþ-ÉùÝà½eëE&ž`! wh 2Š¿‡ÞÑl²ô>òßoó`{óåñ»ÖØ= ¶a³±a;1ÀØAA¾ËA € IÑ‚îZdÂöyºñ™{»¢{©§’bÜ£´ 15¹ ¹y¸k§‰øìSÁ×–;ÚLÀ &+{pÜÆ$>ó~m¸!}ÞúAÔDPÁ÷ÅÍŽnV–ciÄ”–¿…'Èüø×ðá9ex‘ƒÇ¡ËØÂHõ$%€µAr¢‘ÐÃ*ä&JÂ&¶¸û ÷çäæ 9gß §ä q@OÿÀ•÷ /,wZÙ¢¡¤{!ºÕ“6Ý@n°ýsa"Õ}õÅw+üsyùªš•Uî]éA¢–×m éâõnù#øÅÇ¡5€L¤CË<Ëý!‹••ÈÒNˆëíôµµœÕ`7V¡´ 'äL8‡Ïià"|2‚ +ëh!.Ð'ø<Y¸ÇBÌqgx\8œXXœ!ù"®Y€p ÎNçs+âùã ‡¢—{/E³8(„ä7?ˆ5á®nŒpx©eµGòwäÚ&7BÞ ×•7ʉÁÀ¼¹uA‘щ#ˆàý1¬$%k f¦üÈ ½”dðgAˆ€PëC< %\›ƒÊƒ+5ƒàÉO¬RSô+{Ò t¡¥O¹«'·@ÀºÆSœ€ ó܆±È Bý€›Õâvx°k@K¹Àf2ÂP 5R3•ŸØÒ)È…’í ¶6R ‰„ lÔ©ù‰É ·©²Ù©1=òOÒÁ«R@;ࢄF€ñ FŠë5Øsh h£ÃÐ/ÏÜ2 =–ɹ0¢ÜkÜò„ ” φä>=Xž‚™¼ã¦!È:¹Ú9Dñjz“|¨C bÇý_•Þ%—ˆ°ˆ"´ˆ…Q‘\HŸ ‚‰7%¯‹rÜѪ¤a׌öõ¹á#ýæOVè6Ü(ÌW45à±Ø Ø#9ÌH €†›ÅÒo¼Êj¸3<+Òud=EzW|° Åd ¥ªMÆ °8TGÿH&¼úP_ê¯ Ž”·z Ãw:áNàx OŽÍM”¹÷…RYx +mí²Rï„'D¨áøóLP0 ¸ f‰ ži,ò1ad8wÇ”àÉê™Ù Rƒõ !Ÿlä9&œìñä© öã(E5:’åq×ïºW—…u½Ð#r ïc—`4Æœ†#2Ÿã½Z8^$UGLDO§ XF,àQÀè1”|<„…ªÚ‘Ãà°¸8$rk-dr P€Œ™©¡3q«ŽnÅ4`ܸÒèF§â•û[¥fD‰°ˆÚÌfii_0Ʀ¡ ôOG! (0 ŽÅŠ …ú”Oè%Ü6À€…îÂaÐÀAG%Ò‘Ð u;®4¡Bwhy$Ž£gÁˆ¨Ò8I9!<`B0(pò+70š£8j¼~5°*É|ãW(*ƒ„48›ä1Y¿4ŽÑc$€E qh<üʰ†Cà‚Ð3Ò.AŽ"¯ÞxJ%­—pÌ ƒ˜€a9Ìt âA$“”`…4$TnüÌ!¼º¢qMTG⛢B•-¢Ãb6®ù½ù€+»0Ô=[aNúev sùQè%€B PæNH"¦'áú\F\ì¿Ô`½ŒQ‰í2†¡v÷1lç1ä÷*¿r»gÇ´ÉžCÔþá“Tä‹C06¢)ûÒØ›ã!î˜$p ˆð‰FÃÄ; Bñž Û{²‹5 "‡Æ<à[ ’ésŒE!A} dÊÈC JcÈ6ÄIó$²/†&1%§¢Ú h‚¢ž/Æk˜ä¿Â³ ¾y#lI@RÈnKÜÌp@%Ôæd ŒõY;H¶>e !a 7 ËEC|¡Êr_ÁmÂ4.ŸÑ’ð±‘õ"c€c]4'±,aUe†'ib·üÙ’1hÀ*J%£æD>aô‘\" “ƒê¸ˆŒêè“èãl@ºq'´ZÆIe8ô8²tF³ì Øf:rÉበº„€ÅàÕÔ&F˜M˜X³ðI·©|`‚Î`8¢$Š¿1AFN†jXÚÎ| }Cðæºá>CM-H#l1ÐÔh¡Ðï²êu–õ8ÀÌ€®Ä ! †ÿ" Øp^–["¥Õ;Ò‘ˆàˆtÃq@úOEaá™ÃE«§xfÄ% àÅØ†êÅjA1"EØ†É „–ÎѶ€8ˆ¡ÐôB0I¤q`Iš¸@qoUºÁš;T¦e5¾à ú[௪àú9¾H,fÎËU*sÆŸó•§&˲.àží„>P.ú,Sâ>O¦¯åÊŒ+„‹x¨†xÏê©€?j>È|ƒfáD6¦=…/’Ô!b…Y›c‰as𼑡UVf}&VÄ* l½dUšÈ ð2:D³wH$ƒ°½êÂ(Ô/·¦1á¶}Å^Ž=(vÐä e/½râX‰é$ÏŠÙÒ›pGR£o‹|4p¸¢Y·£ÿq›XÏ*53¥DºBÁ«Á€åÞ5hrÑ ÜÀ,²¥:ªúK_ì @B‘ ÁM´eP_¢ ‡ª¢U‘4ySP”J”ÁœcÔ`0‘dÛ2¡ØÊQKAá@³´‚)f›¬íóˆ*ÞvrAh1À¼$€òiÊ2xÌFû®ÄËãö*"9<À"”…‚mðásPŒÌœh`yUwˤ8”uÜ «‚†J_ÂÉS:@weÆÄ™2í•r “HgÅ)ÞÇÆ9¦Uø®gHƒLFÄôÏÚîˆîA‘ÔSûI¥¬Üù•U+„,È6îgït9ÜŽLƒQíI¼Ðž¿X²“Tûà>`2BøC’¯´¡Ä¤:¥Ãp"”@ë y Ùü²$.hÍü“^žHmá š €EIÝl;WuÏuOÝ#n ?I$ICÆ7ýQ™·øMn•uI)Å«å²4КZNû¬!mØõȬÞ=pܲ~Iø0d ðfW˜ ½  ÿÀ %ÊœÇaÊ"aE“¬bÌÌQ|!E¢¯£{¶4ZV`U?Ãùdà‘Ǹ#&üöÀÜõ ßAÈ„|gå>åÉÈ4)ˆJA"%š3*o(êÈì“WtqôJ²Â–•  c¾ß‚ñEtiY"ã#VägÜÀJÆY¸-e«Û§+NG<"g £]ŠÑ¤’>ÜÎHŧ¤%¦sR˜Ô„g¸sJV‰ê¸xŽ¢<ZÍI­*ð-¬xÆôP”@ª)9q"'ü¸­a"{ Uxr2Ü-±ªGö_˜&у ¼Ã䨞ÉRa‰q¥ñSpR“³ “rzț̼€Ù Ç %Ø./Šy5 ²Í^QE‘x±¨¼ö•Ï@á3·ª.äap炦fÐ…ÌYRPŠlâ–ŒTEƪG°ÕÑͪDì=9„$GJÃÝô…@ÆS»j`Õo8ûš•'‰Lßx8¢*@I÷ç&à@ÒP;¦ˆK€þd”,Nau4Zî/*]¾` ßXÇZŒê¯€³bá‚VÖ8NÇ<ëÌg~$VùŸ•°kÕLuÞI1(‚Ö|H¼W7ˆ:ËÔšhQ/óˆj0‹(ÈÚÆ·Ò›RTÞ22@,2iW¶z@p©µ$$=£”$Å+«…,­DNÖ6]ò«Ùµ›°™¥-ZÊ nCiu„¢>6žï‹„ûq@ ýæ!fÂ*x^“ ¿•oçá¨0Ý1u0,°¨òÌò© u²ÜH- ­Ë2·ïÐ+”³$îb7éÜ6l€€ÈÁ)™*¢ÎÆqN/‘ÐXªJíl•¢1µ+* +„(z/C1T‰Œ‘.ðàIЫ Í+ê*†Ñb–š‰ýr”ÇUrr"¡’ =r±"ão  ¼W©N ²Ê2ÒÂw|W<£Bá”úżàR…_dt1€†6F;ð˜`Ò|3DËIãˆrœHe¿-Ô_Š£ hA-‡&£Ö„/õŠÀvV)á-,õ£œ•c–Dðd…øD YÕçk*÷Ä)t´ÊÒ`$Ñb:@  Ÿ•£éæúµêÁ¥¥ ¹»%ŸnxïÍqó)‡þ™j&eÕÕ" ± ëIö<=ÝãÈ Ð1×* T%ˆø.“¶äZýÀh°â¯é §–"8‹§ù¼.€`RÕ¨šÑ,g ‹Îz!x°Ðí-|@(\Ä(èÀñ ñŠšÑ,á×±œÍ¼¢¥ÌÌøeÍ QQ*]b]Z+¦È+”×,'ѳ©Mm-Š#—:–jY>ªýçÛ’•#‰V)iY¸ÿTþ+⇚\ F]áÎV*L‹ª& Íê+Ìs¾¡À?«0cŸá“†{Hë„|qÕZ ¤†£fŒ&)Ön™Ë20_hRù0D%§®E$Z(ª‹"™ég`+)×ÕШÔRKÆÊ€ZΗՊŸ˜¥Ak “ß ,‚ÀŸ•°b™Ûâô„@ÇÖ2 §ÁµšYÑdML±.h¥\Ë3+:§àãGÖô]«Å&m¸š¨× Ifyœ³¸Yfp¢2ó¥hè—1DÃÈU@12{:0·Ì`ÆãBp&$H¯±¹HŽ©ÉYgs—aDº‡S Ä©:J)W" 6™Ëû”Ô@™s­ï;CFÂùà⌈I£²Úk–Ö2}ÑåÂJŸ!7ce“/Hc¡S*BüÑ6PÿZ‡†„Eï]ÇùàL3>ÖoWŸv*TÈÆzÝDb7Q$y£"[Rª5x&Pæªé@¡¨–L«UÒZaè ®®!eÓ2ŽÍ®Ž<üXWÇ“†»«gfÓ×ã{ËgêÑMa!÷Öc-Vdy*¾Ô¸N k9Œ¬ºâu‰²| dÏZ9ar,kk=e «A¹h£º…R¿È¡å’dxKàØi!š²$’R~HDC-õ°ZM’ØQù˜rî……iÊ:E m—.TeÑ墖3ÕUåQ!K‡ç¼è28«I)ŽëÙ<ÂÜ7­µâÛwî­µ dΩ”-ØhÝV'Hä[D½ìteA«õ1ê„Cy.|/*Ž^E¬Öœ#ƧJ~Án$þ;ð|kSJUÀ€i*üj˜â]\ï'R롆W²O’Å…¨F'º"9–Ò2—òëT4¸Ž.VáGºVg¬.‰©3¬—yÌíÃNjΡy€¢;ò(ËöQ¾ÿ2ž‘™˜Ë¶ÁͬþpÐgV œº°ÂÙ:g™(/­®ùÀкZÜñRÌ "Š AtÆ;@¼êÚ»ÄÊ¢þ2‡?d!°ê|Ž4‘HêÄ#D=g¹¥–J/ȉª ¢I×=…;þÔ’¤ÌküÂMp¯¡B‰Ëºª•¥iÅ ‡Ü k`Q‰ˆãâ²cŽ¬ë½“j/Mݰ„ý‰#›¶ÓTƒñ¨+)!@9Cβ>[’ÀÀ€Sç-%îd_]a¹@ˆÎ©Vö çÙŽjDûp6x(#Æm¤†«¬9W@#jߥéܦ£3ˆJG˪D°ó¦Ê0|# OŽsN—¥-Òvöç:O)ßÝI§ï|ŠM½pñ=¥(/¤ºÈ”:L\ÈÇÉÜÅ bKQ ¬Ù..*ªžõ*® ^ç­‘m½jZ¸VÀ‚Ù’}³øJ«wh1ô\FCG¡G(=S5úa›A"¡Pq\U§ËÔŠÖî²$(Ö&8¹OdDœåÕð/ÎèÆ„+0ê\NTì‘M˜ÁÍ"¶™Ðßû¥Ü²&A.Ž÷J\‚ÄŸ:åµ’k¡™+@Ö ÷ê{ò"«Î½W kE‚‹ˆJïåwǨHl„ú'ØM¶æerf&Íž+ëDaªËñ ÅW¹:—ÏiÆNí¤f!§Têê鬺ÅÂÕ\Í9»£º¢¸ˆqp ¹¢Ýš +Ô|@-WzHÖ;‚q w§ñ­pMþé éltÆ‚HɊùò×SR¼ôâ¯'ÿô‡FXÇð–þEzW[ûÆß76·øF±ÆE)¤ÿÕýú­5¿zé¿}þ'kM]:“i«ÉÕb´~ßw"„¤¶¾¡þéýßüeqztã«}íG@qÝ€±Ö:k¬°ÖÚ÷ŸL‹±Öm¹ûÃêÐs?ü®T^òèÑW~äW;«juBqÇO!ÊŸêqeàœt>°Y=ÿãç<õÔ¾ŸµëXZ`8ÜÊ1TX ¿¿Þë½îÞûîãСï}eÏžÏýd5oíâVT6·Vµx‘&'Æ…+:¸;vˆÃ‡?ãy^xäÈÑï¥uˆò•¹c­¥ñ"Òd2éÞºrFf&ikkwâàÁoCàÆ_>òÊaÀ¬ À•óî*+.‹+3ÐÜÜJ—Ÿr'þuššš×nÛ‡v>,¿üÌ·¾?08üîÙ³g~³¾ÌÕÜÍÕ¸©¥•G?ö)ØþÉTŠ\mƒÌÕÖÑܾYÜó‘íŸ={æE ü¿j ¼x¹2éL–ní@…1/PAsK{-ÆWëÔ€‹ Z‡ˆb713‚5‘+ÚáÕlC[až›ÜÒs†¿†Êw©JìäÆú.pér'Åâ ­­Mܵõ£ÄÌ­š¥Ú]æÎXœ1‹Öv¨•}À9‡m¡8yñKœ¿ô6ÓE¦fºzz9wêÛ6‰GžÝÿ¥Ý«XgÑFc+s–XMsqÙ%¸ˆühSÄãqbžÄƒÑÂMLåð;¶6='üº€/~þ“¢*€1­5ÖÞ !kBˆ…¸r4,Á̆g5A±€4Q ­›˜œ$?5ºóг{¿ðç—OT)µ­Ñ:BGÑ™˜Z¹ X®—R©ˆÑ8ÃØ­[Œß¾M±PÀã¢ÐÆÁ,J†û€&!„«  u„Öz!K kbq’É ¨³ùiz{n0~{‚Òl£M¥q‘„¡& [>ûøîû«kÀΕ Bëcô2ˆ¥O«sßS˜£”¤PŒèé¤P°Ö"pH)qN€PàÈùžh[¡!q•»×Ëô©Ô|&”Ã9‹‚‘[79ùêOñtíîgã†V´ñ|Ÿx"Ž‹á¤"®crjÆ+‹ñêÎ`tDéŠßˆ+ÀÍCH©¾‰s‚Æ [é<÷:W»ˆ§š¨mõù¾'¸|é?H‰T‡™\5µô½]ÏW0¶œ1×s̈²ãà çyôt¾I6 ±>K]JóЮ'¹wç^Þ½öºyì‰Ç P,®±eùüŒºüïÞž2P.AEH)—û@¹MBJImK½]W8uægØp?ÓNÛX?*ÙF÷õ÷¸»=âC[·àD å')‹âÂù‹\é¼q ¸ZÝŠí‚¥X *Æ“ f ÿ8öÆnàù&*ÑyþïÔ×7‘ʵÐõÎ,wµ½GSCVDFÐÕ}“ã'N¿ÖÕ{ësÍÉ2c,:ÒDaˆ”ráEãîtÀ˜6¤ÓY†‡nŸ"™L㜥˜ft° )%÷<¸‡æm{ê{‡Ba†S/_í<\[­-'ªø€X¤… ˆÊþ!$•ÍQWW‡/ $ÓY<å¡”DI‰ŽJ457°ûŸ!‘ØCE„Úë¿pîtßû+tE!Rª* GaÈàÍNj³ÙX#ñTšX,ާJI¬ I¦’£qÎCIX Ä™ÕÜ| ”ª*BÏóèc ç4˜ Ieb¤²i<©*/¬J‘Ÿ!™Ø„µç¬X³-7Ú ‚A©dƒ dÃ0´AØ0(Ù( lP*Y¥<;]pööDÉ–tÌBÏægš5v2¯íô¬°£ƒ×훯ÿÎÎ ¶¢/»fW,¥PRJ!¥B•ÊSx¾çùx~ ¥$ õu<øè“ mÞò<”òPÊÇóžç#e¹3ÊårdÒ)’IŸD2_ »ëê”Têd&“uBJë)…T %RJT%–R’L¦ˆ'’(%R9%+s+Ç`´æä?#‰7ŽÿíÆÒ¬WÛøæ€F`ûÂ÷·x`ûÃýo]<;ßÿ¸ŒŽàxŸIEND®B`‚qtractor-0.5.11/src/mimetypes/PaxHeaders.10084/qtractor.xml0000644000175000001440000000012312002232403021624 xustar000000000000000027 mtime=1342780675.268562 26 atime=1381134670.76808 30 ctime=1381134670.768080109 qtractor-0.5.11/src/mimetypes/qtractor.xml0000644000175000001440000000126012002232403021112 0ustar00rncbcusers00000000000000 Qtractor session Qtractor template Qtractor archive qtractor-0.5.11/src/mimetypes/PaxHeaders.10084/application-x-qtractor-archive.svgz0000644000175000001440000000012312163333061026214 xustar000000000000000027 mtime=1372436017.184798 26 atime=1381134670.72608 30 ctime=1381134670.766080109 qtractor-0.5.11/src/mimetypes/application-x-qtractor-archive.svgz0000644000175000001440000006606212163333061025515 0ustar00rncbcusers00000000000000‹ì½ks#É‘%ú]¿·ôEmÈŠ÷£¤Òšº{$³›µÑÌîýÖÆ.²º¸b‘µ$«úõ÷™$‘ ¾R=cE&óáqüwˆ?ý_?_Ì~>»¾9¿º|ÿFWêÍììòÃÕéùåOïßü÷ýu‘ÞÌnnO.OO.®.ÏÞ¿¹¼zó?þü»?ý?‹Åì»ë³“Û³ÓÙ/ç·Ÿfÿzù›'_Îføt{ûåÝÛ·¿üòKu^¬®®zûÍl±øóï~÷§›ŸúÝl6Ãs/oÞ¿SŸySœ^ýxV}¸úüö/üé_/.¾ÞÜ^ŸÜ^]¿ÕªRo߬¯;é¸îïÿëoÿëüì—³ëùõöì’vóÖn^~úauý—¯×ò~§Þž]œ}>»¼½y«+Ý<ýÃúôüèóŸÏð´Ï¸±\yyóûÆÉ×§Wg³~±r’Î9¿Uæ­1 œ±¸ùíòöä×Åæ¥hš¶KRê-þ¶>óng½ûõ=°÷eä¯Í§£×¿àÿW,T7W_¯?œ}Ä•gÕåÙíÛïÿëûÕª:½=mÜfÙéÏݰ„Ë“Ïg7_N>œÝ¼]—ë7Ì~9?½ýôþ5å×Ogç?}º]ÿþ3zùÛ«_ß¿Q•Ÿ_éþ2[þõüôý4‡q1-ßî<õý›/×g7g×?—§._áÝêñªr©r³ëœm–S–ßúîôê_þý›ÿ »üÃ\œ\øs¨ð¤¾ùóŸVgò´S¾ ¯ŸÍ¾œü“¹¸º~ÿæ÷åoÊ~¼º>=»^þ)Èÿ6þt…W>¿ý R¾úñÿœ}¸½½º8»>¹ä×hUÿå§k´WÛñ¯ç§gmX}:_oõ Ö¿Þ|Â(ûåý³ýÇ_Î/ñ‡EÝU:¤Ëë3–½—Óêè¡U;ëÃ7Ÿ®~á§¼óñäâælûvÿ¼ºúŒ÷¨œöÁøí¿~ø•/±ó~k=\¿®Yìû0\¸°{þöùä×óÏçÿ<;]÷Îú‰_¯¯%‹‹“ßήז8{ûç?}>»=9=¹=Y·Âòˆw°!Àûÿüþ¯þÓ‡ïþ÷Õõ?ÊiüÿròãÕW´"Î;ýðCòóÉíŸÏ?£‡8öÿ_ùŸÞ®ÿÀsnûr¶¾E¹ ì_†t+ ž~ø|΋Þþýöüââ_yoymÞëüöâŒ?¿­ß ?­^÷íò+pêÙÇ›õ×ñ7ã`þ çìäúo×'§çhœåkñ¤Í¿Xã5‡ÓíÕ—õ»ËˆÆüqÙ#b/·¿]œ•¿,d ½û½’ÿýQÕvýN7.¹úøñæì–¦ÎÙûÿ§¨–§hyÊÛÍ/¼G[øÜÑ>÷´E›ÛÂçž¶Èÿõ?åж°9ïo §ôz¬2֛촹o£8ÕÓômr°üªß¿Iðx«ûü†^…Õï¿À£ÉU A¹õY8j}¬|ŽùMG;µ¾³0„wŸ®ÏÀh~ßÒËó~ªþ÷åù-¸ÉW8׿ÓÓþÇå¯ð{}ÖÁ Ý €{'·×ç¿þAUÁd²ÖsÅÿÖ¿.è‹£Mv®A ”÷É}#µ¿mlHþ?¤ÒÚW!øæÇ±AR®¼q!o4SöU2ÞéØÕNhÇ;µïQÚÉꘛƒ)'´Ë¥>ž_Üž]¯^Î g¦†YìYzò*6špé¼7Š™/Î/ñ„/WàÅW—‹ò@|ÝÍþíÛ,±Q{Œàg;ùzss~rùíÅ×ëõ€gúz}üñïâ¡ÐŽ_>Øg§ßŸý|.Oà ¹Êmcz³9@7ï‡ÆÒgßñÿ]ÚsûŠÆŸœ2ͱýóÉÅ×3|“šñ¿…ž©Y×ø©ù:—]Ÿ³çƒÿrñåÓIýʽ¸º:½÷ýxQã¸ü¾¨‰æõO?þA,è›3Ö4°ÚmSy´_5æç/W7ç·gÍ·3]¯wõåLÝû7ç—Ûm´õÆË/ù°|ˆÞyŸÕóñNËî¶«qt¯15QµÍŒð”\?å?ºwï_ ½q—Óß¶ï{úkû“Ê-áTtOëîÕz7¢QâÈ!ßלMî1g÷Ñ:õaûqkãºÕš½ °:›z¢Köc]H1®Bßy7€WëP©œc[b*¶òÞ‡ÆÈ#ðr$Ђí^ÔÝ€W ¼Œ‡¡mkà°™4ðê.àÕ=À>x«Ã’xJ¥Æ1x‡§TÝ@«{€Öœš¨õÀOá½u¢­L j“$S%¥¬Ù4Lãm¥óŒhýXêSœF[[&¼RÆÿù9Ö®¦U1hóvÊ ¢òx3*j#øyÒ[öÄ6 x¬Û²§ïn{ì©y«#&8»X7“óø¢hòCš 0w[‚%ÙTŬ·Ü«²‚­” blÊÁw¶’¾ƒ²•Lb³l%m ”]xРÓ@Ð ³ÙJ¾ÔÁ–¶3ã]oÉØu¥‚]©ÓRC:~DÒn NÐZêacN«P¡·´o¬€V[#Ò±ÒJ7À˜´ÐJ2ÇÎgÒÝɤ4`#9|C´~ L6ç@é{ÏFjýœÔņ›Œ¶ÅŸžéóÔÂäO¢öæ`ja²ê~N6ñ£½Ã×Ü›ZèáÁþ6LÓ9Ø~V ú&N“´#n˜&º n»OhušöQL3ëǹ¶M«‚ ò Ã,zç<îynÜF;1¨zí7Ý[:Ge;Ûɪ» Ú'ÚNh£tÌ›*ÊÜÈz¿EVAD´ófÊ•­—,\J·==F;AEÀOÂÔì"F– <ˆ]èÄ8_2›d•Î4­¶ì)Gðÿf¬ã7Óvn+½¸c˜oPf¼³ a¹ ·œwû[©#¶”Ü^sÔIõ–Âøòamb× ª€&kj‘x½³U€È]7CKP•rÍÊ¡ÝÐ’ÕñnŒc`9¤CBO»U„ÔC·é´¿íH½’½iÉ( ˜3jêæfÎÈ'Û“Õ8vÆÈ'xÆÈí<`#_Éû|Qó®Ìí>¥ÎùÞLÜýrEƒdŠ|Š2gÌz·G2ÜÞtÜÑ 7PôÐg¸ùA%w6Ü †-wÄpäÚpëd¸AÅ'f¸Ô¿cnÐz\ÃÕ}~ì1 Wûá WÇÇ2\ÝçÔŽn¸f€â’>Ã5*-¹»áö–ï=†áš8¼ášüX†Û[ÃwtÃ]•½h¸Ök¸¶Ï=†áÚ<¼áºÇgÁ=5qÜøâ,¸qÅYpOPœ?¼8 þ±ÄYðOMœ?¾8 ~dqž¢8 #ˆ³ðhâ,<9qŽ ÎâÈâ,>EqGgñÑÄY|râ,Aœ¥‘ÅYzŠâ, ÎÒ£‰³üäÄY>‚8Ë#‹³üÅY^œEõXâ,ª§&΢_œE5®8‹ê г¨‡g,|}$ÃÕOMœ­çƒh¸z\qÍgÑŒ0MØ<–8‹æ©‰³hÆgÑŽ+ΚS°ŸŽáÚáÅY´%΢}jâ,ºñÅYt㊳螠8‹nxqÝc‰³èŸš8‹~|qý¸â,ú'(΢^œå<¶áî]§·ŽéèK⨠·Iõ ӽߒ8½LÇ7_¼Ôàæë8ùâ‘Ì··šéèæ«ˆ-ô›¯~Ptá~æÛ[Æôæk08eÇj{Í··4äèækjýæë$Õîg¾½5!a¾np¹†{Ž-×öšooÈÑÍ×a-¨Eܰ™¬^ó¿­™¬l¶øjʬâR¶³f}0}O³ŽåŽwxZ1ñ“wŸÏOÿçÀâïl¹ó_åÝï=Ìíü}ïå½¾mA©=³ƒÇËdM^¬ p½òùÕÅÅÙ<ùäâ—“ßn:VxÜE„d­^¨.@íö:mé¾ßq€qù”lNÛ#,e­rÚa)ùМˆªeÝ«”Us6ô½ÇXP?,|׋‹žYéû©{8åEèN\y{iÓsI–e¹fKl¬%–+øûíÙÒ!W¡Ò܆¨Ò\Èîþf¥Xt¬Õä£ɬbX¤žÿ…ÿµv™†¿ê¾{Zô¬ñ/ßýË÷ÿò]ëÝMŠÝ&©¾FùÞ¾o[H«Ï˜ÎU|êõ_ßúo÷®õîÁÔLqïÝ{;4}—¾OíížTO»§Þ^õñßùö•àr²©ûî©÷îÝCó©AOˆáÑ'æJe«¶V± ®òÎè-¿ÎÝXÁAÈòÜÐÇtÇlû:ü$Ÿœžl¯×J;-+û¾ÙPì§c8¹oÿòí÷߆!,mÿž]ôn±ÆÌÆŽšëæ6ì±lIà}vÍÍVûðôÜ\ñWÎý‚SM~pBêÃbs ÀMBjLLÉ ÉGµÒŒykØrMŒ°)÷@/ÀOCs€sÐjœéÓ½·çhŽ[ûÃÂí·A©>ÎØ%””ït¿øž>ùWÅÿöPßé‚r}ïþÝ_ð_ëÒ©²OFçÍCßÍÅû~Ûzóh꺈½wO‹ž£Žá×8?:=ž“Ô ŠNŸ9Øbƒö[ =ÆÊ[cšëô”áUð‘t×=Ü´]ô¬û/ü_+Ûí4(íûÌu¯Ë¹·Aõ¼â wº¿ìù¾û°­ÍeÃæOq3`!Uþ‡…é°Ó»KkïÝ{Áù{û}ü®ýîÙšž»»…éÁÏ”þ’ö/aþ2bywiÂanwïWëiÿûGð1q8ëÝ 4¨\sã2ÍsCóÜ"OxîAL'ü°èXp2˜ÜçrLV÷öuÝ«0÷{ÙÔþÖ Rv\»Ï%½þ‡Ç´2ÜoÁÏÆU6&»Nß ¨ëÊÁB·–æK¦Š>mZ(duÌ›D<ábRãâ{›§Ö?,öïwéaûð²ÃYö™§‰¾ë‡C㻼ç#q„á Ok®ºñ¹²Ü«ak‘ÑXåœ7ãÁ»gÞÛ l=ëÝ`P.ê¾0ÌdP÷#ð¡Š+yoZ”¯ð¿eQ*87oùPïxîA6¥M§5IhS&™¾TÀdS)»mRÍ0ö"Ôæi÷6%§~XìßëÒ_9žRoîd2¥Aè˜ÏÁ)îN³üG¡gv¾°&«Í&óºòQ›-͸ó£×jÓ>«²¶z ï3 Ö„w¶›”¥øðpÍð.O"¿x#-x—d›@—*Ïš~R¶{æýQOw£^“å»Ô›› jÔsÆÙ9›÷ëä ƒT À¼PY¹MÌs–õyñ"÷ÊÜ PãrÝv>ˆgSl¡Üñ\7âåÞ¢ƒC/‡ ñÆ`x[ˆ§+e¡ÿ6ë¥v;'Ýìºk\V‹ž-»l&°;ØïQ.„´þG_y àÎs{$½ w8¨c6[Õ˜ ÂÂÙmÀ3ð½[`Ç]põa`ç€ÈèÚWv‘ÆÓ³VõÖÄLú´Û” ÜóÛpmî€ÔÆïvϼ?äÙn~—c_’á ÈË“ª=äÕ;ϵuÍY@ÅceՖĈ¶JÁ¨í½Ñ5wÚª1ˆˆ©šÛÝÛê¤pÖnW9 j6õÖÅL6øPÛš¤6á«8ž·UW¾uÞý-u“·fĈ·½\-þÛÞ obÎ×a\F®¶Œ+®´ÍÛ;e»*¸¼U¸‘`sÚýáÊv橬#ªðÌ>‡<ÁÕpû‘êr±³ªÎß×É?žþxöáNÅçý eb/hÉÿ&Ðz°‰Ù= elÞ,Æã¾¼­ u ÇÒ¹sßætÉá9Vo1ÑZcó|•+«õfêTx¾ÞbùÊÀÓ.Ë?Ômšn–ïÇLÅ[ß[:Yà=‹Óý]1-'BZ3 5¨™î4ëì˜&å|Ï›LjtPã„"u—àE†ðzc&ý0Ñ ÛS¢ÆŒ^85E/†Åµ,á°´½âB;°©±€ l-v[Î}øƒlJ÷…H&›زm³ÂB×¶ã)´YáŒ-t"›©Sâ^So²u²ÂW’芕Hv`Tí ;ùØ—–!è\y†9‚¡M²}•áSžà0{"y‚ÞLÁˆÕi’+˜œèËÈtMc‘|AŸ:cЧj§œÁ†ö4r €YƒÓé’7è³³ À^‹ èXY¢VãEŠ ˜2ï/Mô• »-2 ÇkO2à0{*2 cZA‘#B—È€©pûeÈ€'Xd@ž^ôð¿IhiODtÅ`EŒÈ0ÕoL: è€®XÈR ô.Â}°˜’¤/O tîsPôÀØÓ`Þ=!ÛIfhOFtVäU0&Œ]05^Š2询 Aô=rÒÚÛSÑý™=æÄ¨¢&R6©„ºf¨Ó‹J3êVꆦåa^œHPýIƒ1g€ÖÕC}@7‰„Ã í©ˆ„Nk«+ˆF\¢£®!š’ð/D$¤;Ôõ×ð"aª%zAwFnK5ѨœLê‰&0i„¢úVZ˜ñ–t.ašÿÒäA׺"Æ3©" ú|é$ 2±§" zeÁÈ‹MÐõB$AW4CÁ±åÀ”0˜èÚ–¥Ö…]sâ…¯YƒDº6Õ ½4ºÖµ¸WŽº6{¼ ºfûk=Æ.wÓfT/ƒ±u$6 c;ò⑽¹¨‰±fhO$|Û5‰E‚·cF˺ìEÚ•ë·,=ºmʼnܿ÷Ø9?`Yyô§ïê9yÉÃìíé Ygpv‰g£njQ#Ú4íóå`ÚPíø«Àøþ©²huO Ù:W´ZcÛèe‚n“"xIøv— ,®nF¸ÞHí„r‡ÙÞB¹®DÓãÆŸÍ2‰Òp½©v-ùøG@·3›°í@³{BØÖ]öØ`pÇ€·4ã¾$€[øþõ‰äÜcg¨j 7 ÕWs}» Ƚv)!nšúr®«Zh…n=F5› íÕ@[¼c Î-Ôˆ3C×u©/âôÁ2 0³GI6ôzÔ ê4¿'uºM±z  KÓ4ø—t«wK©>J±ˆL–žpî•à\ï¼xÝ?ûdŒ›Âq/ázëĉn‰› ÆÇ²ºóËÜ|8ùröw½8û€ËO.~9ùífm^¸îï>]Ÿ}|ÿæ÷;}6mióæÚ$kîi‘s UC2¡L9\ýÂi†Á[=‡®¨rÐγ1&vw4ݳûiûN©»ª²Al?™JÖÓ~n°öÛÓ|®Š*ìm½;M«k›~×D±›­lsÜÝl÷õ®C7ÛŽ“ß³ñs;wØØPzh£#Î÷´^zäÖëñt[ÎpDS+»´w6–SOáZŒmwçúöù×l>¥+«U|€sÃ9ˆ—pº¿ÙÛ/´\º;Ài勎:>¾¹ÇöOߌ鷴áœÁ  N+cKnÞô6¸e€›¶n~8ßðbÀM‚=ÍöØ>¡Üv£9û±m#:>¶ùÇv OÛTÿøÎ ÊÝv×ÃÙOÝ–«ì<º=¶Lx‚è&«vt7[xl§°³6Iû2&í+ž4G9>º…Çö OÝî LÃp® Ý싦áh"¡µíž$¸õëÒp4ŸÐÞjÏY–Æ£9†ö¶{2ØvU˜WØ‹mÏS”Æ£)„glwФñ‘ÝÁ3–¤ñ‘}ÂÓÁµ~EšŽ˜M¸g{‚4M<d»ƒMìž±Mìž²/`*e“AÀ–¥ Z[î™âZ>–7ho´g kùX¡½åžªÝ»Œ÷ᨖ^ªK´¶ÜSD5Ý`ËjPZʣŬsƧæõŸ²­œW:ÌNW!+»ÕŒIW΄԰56d@Ë7ð—í˜L}ƒk²£–›ãâ¡£ã¹Ï=dõÈ©Ÿ+BØÚ ÃÇMkc˵œ¹¶A3¸ š3HÚ›î‘sÌÞU “ÛMt••Æÿm6žç¹~«ñ¢â¹fïÚ›–Éê‘«Ð"VÛ~«Û:mmrƒ-µí‡½AÕƒóIÙHÓ!†Æ¿õ`JÚz¹Šð™[˜g+¬Û²?窬­Þ²¿ä*›½V›-éuå#ø…Üþt¯ýéGÎ?»Tù쀯åL±ÂÄSg,ÚõZ¡4ë`ÏÑÒú²¡ñoý á“™/¼ªR4vÇmŠQmŽd*]PfÛ£Î~Ka8[ik‡‡@8ÛÓŽì@@e”u¡A@ ûÛ´¾Ý“Ö8¼õõS?=¨ÖxÅÔO?ráÒ3¦~æ‘Çó¦~æ±5Çs¤~fÐ2¦WMýÌ#KgLýÌ äõR?ûØêã R?ÿCc›¢öVTxèl Ñ‹ÎDï›?Ô²Ž–hÅþ¼7i›ù¹Ji½m€cvËøàHœÝ6>ë+ Š8ÂÔVÛ‹€=ŸÚÚ*‚¿4<Å>l9smƒƒ;²¤H_ãM5PûSj}Ìùx“ªŸC­@O 2sVõ3¬ƒêS¸Ç›Uý¼*¡zÛmª…z8ÂoZõ‹@¸©ê€;ÚÌêçUÕÛlSMÔƒáíh3«ŸCUTºqfõ3¬‹ê¦SeT«>í1ºãͬ~ŽúÔô4Þ#K†'†o}­õ4çV?€ë‰¦O“«÷ð·žèù˜^ý„ \ϘæWßáŽ8Ãú9êÓ€;Ú$ëg¦O{ðíh³¬Ÿ£>í°Çò ÏBŸö4ÖçY?G}ÚƒnG›hýlôiA·¾f›² ðÖ×xSv¡‰o}­5eºð­'4Í·~¾M3®oÓœë{ Û4ëzŸ©Ý ݦìB{õ[wЪç^¿ÀüBêm¾)ð‘Aí.·D{M9†}W’¨Ýn 8eöT‰ô¶Ü”g8éŽ7Åúe ݰóª_œZí®G›OýÌôjÃMù†C`nÊ8Üåœ;ýUkï`=Úìég¦[û ïñóOX·šî¥¿ñæSæa#³Úç†*ýòtkî3¸ãÍ‘~fºÕö¶Ü#‡˜ž6¡ëEºãÍŽ~H7à„è—¨[ûîqÄóʧG¿<ÝÚ sG›ý,tk/Ê 8)ú%êÖ^”;Ú¼èg£[Cß:AVo¿¥=;=ÚÊ7p‚­]¥²Ž ,“vs§±2À¾pÝEt/ÛûŒpȺº—f„±§éT´/ÝûÆóQ]Êó²Âžýh¼£ú‘çm‡=|ZY†÷Ò ±¯éŽêIžµvl=ä(/ͻ録Zå…awbWY¾òÒŒ0÷à!«W^¸Â%›žA=äÆ/Íc;ÔCV¶¼tSÌ‹ÜgŠ“kÞŽ·†ž=¬n¼É¡¦«h‚ ÑIÀUW.¸cF;¡ÁçÍvâ¼ ÛMf+­|ÞÚ ê*Ƕ¶W^Îmn?ƒ£Iñ\?ü ÙÁÿн¨€Õ.0sHnE­Ãf«mXüuèvr=ûË¢ì“h'Í€ßZŠ=F@ 1jíbÐÛ ÙkTqð¼R°ýM8ó;¬ ­öik¸r”œ¶7¢ ç6mSPãÔ»ùz 3Ë÷ž}wõùËÕÍùíÙöóWÀ;ÄÆMÎ/Ñj¿úzýá æðåÓù‡?.ï¾>võåìúä–/u~Ùò2–ÏÑõýíäëÍÍùÉå·_¯·_ªù7¼WÞzôê^ã7·§ßŸý|.ýÃ&ó-ïð#nW?ý?>~¼9»Ý~n9j“׫Oݾßéoûžp%7¸G›{»Ýæõ-6¿x_G¬ýêç³ë®f/èû¶Xî (âswšßi“‘‡eùUe­ñÛà È¶Óü©rÚ5w.ÌV9™ÜƒlüQ±#íÂC;ve ìh¤Ÿv4’ªwÅ}r4ôsA½…mw¿7j4\ÞËE£­t÷˜¨álc¹°#¢ž5ðé)¢†³[h62jàyf 5Fâx’{äx{zöñæÏúrrû©\„û< ¾JN9çNUãÉ陚c$U9C²ç,lž»kÎÕìþ¦fªRITƒÏU‚À‹8º°ÖWÖGg üݘ8_è\9;£¾À ,ÎRU°!â$ }s±(îê9ûó8j]àžÈ!&çÒÌB»é¬žG‹uÆZ¼¬vÖØ¹×|k¼ÏÌZ vﳞ;_¹¬s03k ç¢Ñ™_çL ×*ü9¦Üüâ3¾™…ÒŒ>ʼ¶¶¡ Pˆ’ÔÙŸñ-ª‘• òϺn[/(…&T¹†¼®”ñóX9åsm*ï\Œq9i+ìëìÒ˜k@B'^¼û½:áä/K¤x‡×ÎFûB9~ýõâìÝÙÏg—W§§¼¹½¾úÇ.”ÿÕ¿.~9?½ýôŽ ’¢qÊ,þeï~üz{Û<ö®Î/ß}†E]/Ê/çøç[[¾^8=¹ùtr}}òۻ˫˳?;|÷õú⿯ùZ´ú1Òkø¬ò½ònܼu9?ÿôé¶yƒsl•¢]UÒ`t.´§5«ãÙ˜¼¯q«U4›)ïÔÕ>ºRA%î‚úÇÓó›/õwÈûn "O?¥©¤1œÎy †Ÿ³ÙÏŒmÂÆ­n "“4·¿Õ£Ã8xÆ8p`#ŽQÆ m¡5k°9l`ã*ãÃÍ$Ñ}³EÆå¦DÇ• >Á–}«â1ü”‚lj33¯l²2àœŠcaYo”IÐýÞWÁ(¸N 6rî3<†ˆš'Ábµ .ãŸÇG9²Šžo‡÷9eŽeµ ³EL¸^\†¾5qXáM3N7FÐÚöun³ýÓxf?ºMÛ×÷6yãuˆžûÝ–ÿ¥G³}<|íë€_É­`˜KŠëq°2¼õ87ªh!qkX»ª9o¶«¼Ò&ï¸úo¶ºÙ¬v»Y‡m§t [ÃÌÄŒÏu4ðO„N—i­ÀÒ`ép(d7EÄÈð°BØ£J>à ÝçÀñŽ[PGëºÁ›»×g½ä««_éx’G ½=8kHn½ƒjkéß»Àÿ³`ýå×û[ìÆÃv0XûöÆFÛŒgø»äMpÁictGn`ëkð„ì!Í<"üôÌ+ /òx¥bŽaÜ3FS„8K•ðÍs|õÇï.füç¥Ï«$ìÁ2^îˆyßcñ6*`.QI“áÁ î‹›yÃHÁ›†<3*WÚ$Nøðo¦3^<&X‘…ÅdC“Ñ™/`’'¨G“=X @$'(Óz´JÀ r_ ¡#Ÿá+ÙäpŽFÌ1¥äfxSr†0§%‚àÊèƒYÞqˆúw†è^Kj»ñ¸A;8ºÇÂD§lm‹?­æ'Ȥ°Ó*;W:¨Õu{†tvõÖ-‡ôò×…V€L¸CM?«˜‚×f­­ä% ß¶HlL.ó5ÖCi5œà3a.Ź °É6,¬ …qá¸#9¼3€Šl«Ó•fó¸pÈ0bð5Ð p¾Hs ÓÌ@¸™f†H¹4§oŸ¿G håΙ,^¤¹$ˆ0Ôà)’ŒpX©eµ‡ó·äÚ*Í y+LT^ 'óÆ5 ÈщÆ ²ó ·$)Ib¢ËÂ@ˆA6" TàúÜp[¯ã;ñ~væÑ ŽüD 5%‘Á{%G:‘ÐòUÁã> ¯ÉÎÅ :OÀm8ѧîœÛÍŒ›AcÍÙRÖó1 ÃЄAjÌHÍt~’Ñ–V@Îç¤ç¡ÒhA$iàC­4?±1*™9 A'+éà<V=ž.Jh(7COk3ßœ5Q€&0:týê|< çã‹É¹Ð£Ññœà…riæ`ð‘s ÐCkÂ2@0£ãþö^'•vöÁ8iz/] bÇ  à«Ð»h#c ¶ˆF£#!¹à>A#oJ^Øå¸;¢IÃWSòš¨ íeh7hþ¨ Í& Yâó²¸|_íá ‰ìf8 @œ=„œ‚Ê‚¯p †x °ô¬£HÂÛeçõŒbÒƒ„RU‚&ã´8Tzÿ8^}È#VëgÚ°§œ–“ðQøükq'p|…#ÇÆ‡Á]Pžâ“a5T¬lk›„zsÊ$ B†ƒ»ãàµÄYá±DG7ø™hxšÄïÈêéù¸í8„\Ô!KÔKãd‡/OpUðph?öRF‡ó£<®ß›‘5n.=è -"U°>¾cN†#<Ÿå½*^ UÌôÑ((–1ð)`ôèJ~†… ¢ÚáÃ`°¸8$|­4dr '4f¢†NtÄ•8'æGVîD›9Рœp-ÔŒÈà£6ñ±li—ÑÇjÆ‚T-…0 @Íp, `šú”ÏÐJ€øDMtÉ4vƒ ¼¨ 4$<†º.4¡t‚w˜òH*,{Æ‚£JÆILÃ3& :FÑÊ34še±×xìjÈ`E’¹™‹j\!¨ 2c–7Isb8¼~žY'5€Æ~æ`Wš€µpèë Í8Áíä(ò2é£T’xIÇôÒ‰ø¡X•hă@&(Á2iZP¥T╆ðj³Œ³ ‚’͉#f—t‹ØØÙ?gŸqe= á ÐáFˆ í2Y9ù‘i%€BtLF–DÊþ³ºª¹Œ±¡™ËÜ cb»ÆPÔî.øý<¦E~¯ýk b p¯Jzï¿€M¢SqŸ9†ÐØ‘ß9ÜØ›å!ô<ì¼0À&f2L´×s"„!Þ!ÑvÄždCqƒð¡!Aä“`Úz}‘IA=™2ü8k†33Bc m&ˆ3¢øIx_tM¤KÊVDµ5  ‚z.+'Ã$%ø5< ê›7€ÍH Ù­‰› ¨€ºLŸl OâØA²å++´Ð!ª”e(‚/Yî ˜à™hš“Ox’ágÃëŽöuŸÄ°„E”8Ú$W:°ÚÃ]€¸Z5ÇIa8´8²¼Œx ´'`›îÈF˹ÿx% X\^Mm¢ ½ k2<ÁÒm*çé Ž+Å#ÐHT ÄÐvºhø[è6€’ü¯ÅP“¤¶8ФÑ|¦ÝaÈŠÕiÆãhŒáBÌ0„ÁÃðo&°1–ÀËpK ¢ÔrG#]±4§A Ì2}¸‘è)¾ã’ ð¢ôŒêEK@1ÀEè-¢ÇsØjÐàÀAt…¸‚I$KÇŠ+ÒŬáR zœnYz ß [‚Íù€f¶éÃa‹Äbú°\¡8gÆñg]á©QÓ‡0¬† ðfžÐÊE;à‡%ÊAÜÇóËèÿ(âàD’ÜZ LÓ‹°w)ƒ?Š?H ›A¼p$“7…-’ÔaÄzmö%ºÍŠó†‡Y™äkèX1VÙ†Og ^^VFc€ˆ÷ö‘d•DÔÿ„Q¨_œƒFÀ8œÓ6¼©)ðpì@±½8o Z¾¥N 1#äY!iZîHÊA>â9ºëp¤â¥q;Ú_¢Õ0JMOiM!£‹¥Á€åÎÎÐ9ÐäF<p]²ô–b¨bo }ñM‚Lø f"Oõå! r¨*¶*<8o Š\ˆ2˜s2T ÙÖt(ºpŒ%/p ^ZÀŒF¼MŽçóˆ*N×rAŒhÙÁ¼Äƒò‰ËRøÌ™¼»/‡Û‹Täð4¡l(!ø ~|ò‚‘‰‰†W+fk©%é7è*‹AC¥/Æáä( »ÇQgÂhä­„c¨H:k¬à}˜YK· Ûu É Ã'“Ñý3¶;âõ ˆHê©ýL¡¬I …ƒ~Á ‚¶KŠðN“ÃíÈ48ª‰—a‘78#ÙI,ïêÓŸød͆ÚC’³âp"4ž­oÈkÈæ q^b¾àŸ´òHj So,Šb&`Û©¨CX¾óÌTô.è Z›Ì•ã›ö(Ì!3ص×%¥4NZ.)## ´¦„€#û¾ƒ5D}tÖ@ëž[Ÿj'màÇ%Àšm¦'tB€¼aÿ{&”p(1C—EÂì³8YŘè£0þu¤­ãõt&iÔŒÀŠ~†ñ™¹ƒ túhñ¬È Eøa%­§ ™ïŒÜ{¢¼%ù™&¥QÉp¤DsºQá Yìž‚ïä],­’,óÉBP<…±ÿäx€¢‡»Ô ‘ñ òwÜÀJƉ¯ç@Õ™šŽ¾×ÈŒ$ÃØ.Y‰ÓõQ>f§LÁ§(!ºæ(0)£¤–A÷‰áâ;²ðLh5kJTÁ2¦â ô”€«AS2qè~ãUdOà/¾èGNXÛÏ!B.Æ„` žzá*±L†s0Hô+?zkŠÓ£·¡S®A~“ž0ëò˜¡‚m“wF0¯8AF¢ùVTQ$^ j¯]ás Pø<'eò0˜ˆµ^\3èBâRŠí5Z®¤•ŽÁVz7‰hÿàÈ!œ'9ïæ(“”öª¼¨»aö5 OÌ&Ð}ã㈪%^HjÇp ПŒ€ÅVMá¡Í,¡«Líoð7šó3’è¯%€3ba½DÖØVúê ÄT¥˜ ‘›Œ‘á}Jj Ì‰ï[EFÂü¡ñÆ D§QØFyk†Ö?}ùÊ™‘>EnÆÈf¤”ç0/t ãmõ/qhHX¼Ý¼~q~8ÝŒ %DÆÛ•ïF;e*d¥d7áØU‰N‰È61–˜,(s1«;@ ¨„LK«ÄÀР¦.ar[G»©Ãß×Ôñ¥~»zæúêëåéNùL9Ú6,ÌN=Ö²"ËQÁ¸Hj¨a5»‘1B›”HÀË{Jö$‘:÷À°¶Ä#!QæR Ê¢bBý¸¶ÄŒ%ɰϾ“@4eI ¥âB‰ƒIB=ŒV¤L¨©|ˆ)5†…iL’"†¶‹p¢²hrA™ÕEåe#B–ϼèj(0«I)çǵƒÆ´ä~;°ÕZáÍÂN­•'sŽ9ïÁFm÷A$ß"ê%+•‰Ö‡ o$ó mkx„ô*H²Z~eVŒ] ù»±#ñï§á†±0M_ S¼›9ëýŒ)ñPÅ+'Éb!ª’D·e!’e(-±”_RÑà:R¬Â_ÙéÑRS2²d.¹ÏõÝû<ݽ¾nÕ§B¸€»{úTíTµ®úÒÀh bð¶^í áQÇ‘˜S(}ÂyS¢Ì›Iñk¦¬ž{FxW îb`Xã¤D(.ìb°Î¢GËm†$%lÍLN¹ ©L ðZ°„sæÏf’ (¥v¼` Ã)Rjå,®úM–¶°\¾!×w‹·¥M…,94ÇP°#÷²ÙßËìÞ“‹U$h÷@d&¤¼¯s£?ì4ÏÌ*S +¸.V2lY¹F—®µ%¸‡.c¤˜,Œ(&@½‘Œ·‡x•Ú»ÈÈ¢ÌÌáD«à³wà ‰äà@¦$!ê™å6%Ä8£ô‚œ(Ú.štÝQ¸ËÚ;Ì‚æeüÂLp¯…@‰MRÕÊдàÈCšáÕÀ‚΂µg­Ú™§·Ÿ¦¶”°?°gã~šŠÁÆA‡ñ(•” Ì3ìƒß5I ç€0ªä5%‡]N®Ì®Ð,Ð#¢3õÂÈžbžmÔFÔw'@`ƒC5bØGjXeÍ\Qbü. M·Ìo•騵cI;ŸæàB`àÉ2`¥,EI¶nÖ!8JùúN’¾s1ÌÊ…Ë¿SŠòBª‹dèR‘…|Læ.;…Ûda±ÀÚôò¢,êY®bE˜w’·†·u¢i•g­€ Ò9¹ÙòO½Ã}Ãd ÇÐÈCèJOå¡zßïc3p$*–UuR¦–%v—œƒbl‚É}"#7;[wÿòŒºOXQÎ`9QÖ#7aºs¼7‹Ø×„ng¦Ü*&A.;! – qªSÚI0štsé/$vòTtOôàâ› åÆÄá1"­Pÿ€v3{ý293æŒÏÊ:#3L¥ßS¡p_9dK.ŸiÆZíÄÙRN‰Ô•Óu ™Õ,„fÎnTStw14)ê½13BÍ/Ô²ÒÃ$™ìÄîZãkÚxêX©_7>¹õ&âðµ, æÒ1—•yƒ«#ËÓ•¤äÞÌ ¦=d.‚q›úäåõ­—Oe*Äͬ,O³ÓœÏwî4ÔP¦öG£äÔ'Cª˜–“H3]‚gÔj,9,aD[1n¿Œ3‰mfQ“R±ï˜˜aA„Ê M(¥9Yò~ãÃÈzQ™BRy YÊ€€p¡ÌY0¥b܈RÐðð,RV¥pÛ‚Ú–j}&ëd/’ö2ù‚£-äRÁ¯½„»ñ,§Ìîj•qÅ¥·ätSv°üf n…|Û×­>Êì0·2óBü,:12ÃX¢û2Ë褊 z-b,0õC*…ðŒL³)²/ª ækGmÆ|w‚âóP¡hŸjïʨÿº)«ª\^Â-]]/>|½þùäöë5Þk‰½ËwOÚÅÕZnem†^"x S™Ú€îIá[™ÿÍ$^>[8þ¨¤„YfB0¸Ã2r%9L^ÏÖ\{M²ºÐ FªO + |¹V¦)àöÁ•ß… söiü®µaѦ¬¾Õ¨“ä_4x,m`Ý'S¼¨ó šï‹Ñ¤¨™ÿÃpg®ßK)2.ä¸ô ádʬ°Ìò°xX‚?çQ_ÜöÏ,wby¸Ô¥)™" È9]ËÖG.8; h(ÓE>Ì–×â—Õ¹‹å}‡V×Ë„{ ¼3ë¼”]¦ù‚|$åF™¹Ã/ü:Λ/•ß©Ôå9uÁãp̲1 Ø[Ê Ni³©nÔ¤U™ à«JZ5sf—|”„•‰¿Lœ©˜0k“]Ñ’Æ<¦°*- Zöeò• ó®8bä„í5‹:ywrzõãÙâÇ‹³ËÓóËŸŸ¯Na㟿^Üž¹ømmê­Xv§Â‡OO:køî:äzxíÎ}ÓûÖe„²ÀÍiX h çI=¼ƒÕÓ˜yF—þñœê+=†dS¬Óÿe²(˼X3"µÔ\dé{Oꪶr N±,Ÿ¯î0«Ïæ(0¬Ïv’1C™¯ÌD"v™EuÅ„ÅdD™R¸.CŠC69™CTq#ߌè5ЊÛúØá®=ÀT0¤“'Fº c âÈ—^¿ù“Z4pŒ[àb]½9ɰÆÙ¦€ˆ‚´“#IK)ÖÖT•#{œÀhb\oE6׌EÀ[Jùd‚e ±zÍòMËm ¤2o8­t<¼VºÌm7eöð<)ªàÊF$nèÔ2çË‘¿³ÔD¹$h½ Z9Ö7rž7ÔtLòfÃ~¸—ƒÁœ§Sl8‘éÉæì¹”qÑ5ç$‘L –hb|^Á!ÃJèò%J&òµ£“éd„®çøµÓ†Õ›‚°Áè2Ÿ’L ^¡Mqw‚¬¥È+qݕ٠[‹Ã³å4‡Î+Ó=¬)e9>”™‰ç[mÝ×¶NyuÖݲÚ`—u’]ÔÉæZrÂL<Ý(ú‹‰M‰×qÿÊ1 °}ð®À_*+ý4-ÕeÀ`„*r2GS©Mv,9ž/åx-m]™Å'WÆèW,ü¬>‹–ì”8ú”1š‡´T¸"UĤvV”!$gR“)¡U\Ö?Ÿ H)ÒFRŠ«-î:—õ~Ú¥àË´[¹eS7Èù2'žCªE‘’bHHJT,ký`Ü¥‰Œ—™û²µ ’/â§‚G-T$•JX‚\¹`– ®ƒUè,’Ä-G‘•ø°f¶†­`Yý*ü‰ÒQè<½ ʪa˜û+GeËU¬h.³¯1²E¨W¿õ(ÏR m•4«8ƒÔ)ÊÆê©2¦-Õ4§å¥ÂJÊëÌd}ÄŠß“÷™-Ÿ^X_h¶z¼\)¯TLÃÐ#,–ï4û·™w¬BQæs~Š–:ZÇ‚TΡ6l@Ðs±Ny•yG¬µ†©Ô¶  [Ún+PhcáÁN±qߨ­t¹@}EdКSJÉÈ çöSF}¡š*ÈK¦TͲÊT½ðm ¡é„fä³ ¿ u—{ÌäüZ0$caÀ³út_œ·²Zn`]bŸàRmS÷»¬@“¬¬Õ³´ÅEmŒL‚ÖÆ¾¨­}£Qï@Û©ƒq»!ÅôAÜé‹÷õI¦~svz¬‰wCKph*žDßÀÞKýz=4#£Ò6ƶÍ,Ê—±­%╈C³¥ àÀö^ 3 "„‹hv­ GQ¨K>“OYè ÓñÇz–™$„a@¾Ptˆ–´¶¹¸ÌĨ%síu¬~Ä*ëM)gF '™ýÍEC‘H ̳’ŠÑúâT&å[#ä/RŽÍ¥R8…ØpñZTË—Y™\ÏJÓ1²ÒFæ9r“¥e±±àKì ‚Ë $®÷@æÊ"2I«‚ϱP‡áH¼dYZÅ¢jxà²QòâœíR$g]ùq¥Ã¾cx¸T¥/ALî'D®DßʺO+ •VçDŒaL;|³ÍC„bpJPïc–+ýu.1Ʋ—<=¨0‘åoõC² ‘á"#œø°µÀ§w/vV¯ßG¶'_Ýu|®G(ž͵ŸK嬙à,F¨nS{Pj·á¢%F1/žTVi=$Ö^Öwðä¾E.€t¡n µK2E_ˆB}L‚ C²YGm —,é^K|iðÍCuˆ!“#”suh²¾µäXãÝ'î^MÙ#‡Äã–K%ÜXŸºh޶աÆÃW1Myúbï^ªñéEKÌz!Ë,ø’à”§äeÙî—ˤzà•D Yv›“$ö ’á´º¼ð;VÇ 9®#ÆB¶ñqݨ›­(‹\@îIè= ƒZ° ÿ®-Oßׯ¶>²:ý¢$«Ë/‹µ¨zž M©a•÷oïVXJÖìz܇µ®Õ ³ÓºÜê-‡¸.¶¶¤ÿu¨ž‹G™ÍI^bIAf£6lËØ² é¶0p|Ý:í¯\§)¢,V~×|°É%4ŸH626ËP’AÔŒîoÿ,#_ Ã¹\V['vŸ\`­6;XÁQ߆2ƒÙÉJ‡%¿S/ÍT”‡üXR M+á„K0m/ß/樈šF²XÓ iVÏœP¡îpѱ€çà× µ9ÏV‘A’W“ìX!&2e#`$ d€éæÄUp4T·ã?‡÷ƒÖ.ÚrÀ£ùAÛT Ë1#kÔÈê™\Û••5ÛÌ\'sÙ•²Ôõ’Ó4ÜØvGJTx­W®²é)aá±Ìàmĵ,×ù«×r$¯AãØ*ºö#«lè¢-›ª6aõè®qÃ1oraÏß$ÏÁíÙØâö6Œ»Ó5¾vß[´8¾E‹ç[4\ßb×÷-zœ_»ï;¬Õ÷`JÌùå…kicº¾h8µ%j®Zdξ‘šÇEâꬻ‡ -y»:tZ¼ ¸KhŒúéÌ&­qmº¢ñ9•Âq¥â% ïâҮ͢ái6»”SÂËꙜl­K^¿‰ô²#¢Úù¦#+>¿ö¶Î¥¥«¹ðOròj‚J׌‘ÂÚ›²Š~Sõ" ๬íD¯_ÜX°œ”L“Mû§<ß1Ø–Ö]+B.]íá8GQ„qKÆ)KøÒ¡W{Ál¸êV— ~ѶšÓh^0t&p^4MŠpR„úÆØÆ¿VŠöÇe„õ«R„~°Ò™Æ¼þuë®!×1ñF9;å'Iø0K=¼X¦_¦&µ;‚#”)Ü{ézà Z:¬¨ä¤ 'Mø#ó-Ñ÷ #ã~—þjÂ0X…LŠ­m¼Ô„má£&M8% ‡°ÛcÔˤ¼h[fr4_˜ÛêeÖ¢0—ÂÑ»iÂö#›Š0í B¿«ý½äàn§7Å`Ãßùw·ãíîáìv}݆ lªÀ Ø"»`‹þ{n0·¥¬Öò/K‰èn…hÓÚ]í·+ýº”ߎðkz¾vÙ7†ê ƒÕÆdß•Œ²IIÚ( ÝÕ|»’odÅ×y;?îs- Û´@A»Ôk*½µÐk˜Åa2¯Eåù="¯EãUâ…Ãk_ú%^>ríKn«}Y±oîœË2Ð…× Tnõᆾۖw~[Ý¥iw„]ì”uiGÕå ;¶+0é›jηˆ¹¶ñûܤ\ÂÐk-ElS°-Õž›NlWǵȸn·+â6Œ Õ‘¢àªhAÓÚ®*Oîβ¯ÊsW¬µÙPoyG¼ùíæï!ÝÊ­ÉüªÛö§òŽ0ÛO襁-!G–à°²Òxx9KŸ^ƒuñî»Ýð_éµèï^ÔéÛl%ðZòw-é»I®í$장^ƒ}µÍÅ^é5Ø—pnë5Û­×ìŽ^³ûõZØ–k¶W®ù1äZ¨t%)­»&òÅ e›á™Éµ¼‹þqýã=Ñ?¶Ëµ¸–kf¥ÖìÊ*ìcªµtTµ¯Li¨5‡¯×~Ç©i{Lµ†çu®äÓj4ªÖ\K.®%×’‰»§bK ³Í,ÜnÎLŠ·'èýû¶AáûgëjiîAsµ\^ë% ¶8PÁ Z6·Î¯] ¶,e˜n0Á–lf­×ì½õÚ¿7}öÚ\&¹6”Ž¿. ¤‘nȧ#x6ÓVj²’kIKÍeU¯š^3-$í‰é5½+Øò®`Ë÷ʯÅqÝOÏo¾\œüöîü’#a t6¾K½%]Š-_E¶-©oFjãØµTg2¥ä²¡æÒŽšÛ°Ä§{ÕÜPðžTò­MÍ\b¹«æÜUsÉ´é¨âÎäc.M–”m‹~¬¸xrRmÙ»Jçsw•ŽsO\܃ÇËζÚ -w²s¶GìÙ]±g»Ä^ØÑz¶OëùQ´^r#9>Û6h%ý’—jKû¥ß£¦êîV_¹+ýÒó‘~ÜVyX7دm<®l]äv­ã¤'%8 X;Ý’'^+Áøš”`É!:Û2µq­Ó¤'%xW#ÍíáŠQ• óÇœwGàëZ61«I NJð ûÊ]‘Ú×ëR‚¹=ºtxC{Ý*¹k%˜õ¤'%ø@“m^ŒªýQ×aÁó| m\)Ál'%8)Á!Áºs˜ÛëQ‚¹=Î4@·M7Z)Áì&%8)Á;i{¸¢×¢ŸôѼp%çTÙ#>';$Ã0Îmš'|ÚÌâ«\ˆ)ï¸Ä¨(]ŠØ>÷—­ ›¶yèÆzžç²HnÉø„ÅÀz³»Ñ…;гÁϹsЮÌ8·¶ìAo€Ó2èæËíPÀ…#µ3Öˆ'¨7€/Œ˜ûz£uz‚ƒ õJeôF†/‚ÆÍª®M]íM¯Ð‹¥@M/ÔxÈm‘ –(™ !OÜn×g”¼›‚}ò|÷¢ÆïF¨®OM"{[X¡ánÒhC+s>xåì©c–ÂRXœ0¯´Ò\KY z)ãSS¬\ÌB%Ã{Ë* ¼wúö¥y䮳úEËmgË›ÌËû²ujg!ãÇFܱ&3Üï[É@ó^¥"ÑÁ¬Sá%õú¼߬ıhŽâ².G²)–m¥ëF‚ ÐJ§Â<¸á8º„YK[šÌÎÐa» ˆmtŸ§hñ-ë±ÑB}®‚ P>s‹s.‚𰹦3à `²±´¤M @!Øé³*tLE“3 Ä‚‹@³¼œ5hγåéÅhˆ¥O×±ô^ Ngyö¼¾Ä3–ceõ•Ñ›Q&Ù¹L²]Œ’[“×e±)ádVꛡú¢}Cmtt‚S‰/ëÕÍ_†|.Ë@Õ#ƒf‚±h—ÕÀí죌|«“¨2´xÖ¼OÄ+v^¬›þ0©|6Â?[¶á¨à[%Šå¹LÇ|‰‚µgùÏVÌƤ‹ŽÎôº±HCoêuY0òäjãµéa.4ƒo¨ s6 ,ü å=OOâ+ A”U¿žGÀ¢µK-†ƒ7HÙ‹ º ¦gÏ÷‰žËàŽx^žyz3àX’w¦Þ‚žT‹4—«ù µÅÊ»ï;¨Ð¹ˆ$gS½^†Ëíðõe•®‚Ée|°J—¸"¦¦K,æP<‚Ë%" `ÖäW8B0ÌÈÍ}ü¨A@‘·3V`*ÃÝ`oÖªXèK°B5p‰«Cqé„X"ødh<Ùštj6L!j…f9ã[¤*ÈÀYò'°/}“9–Ç4á+Ó0 pr©¼ÓìßfÞU1é€î5„Òœ€€ßñ('nÀ "ƒvH`3@žAG—¶ i½´]»‰>+7—òFÔö™[²Ëž¾"ƒÇCwchרvTFU"Ÿ/MKL…$K€kh•–ÒÐ}Ž.@»Ì%ìx~¨ûºÜc&çëÒ³à‘0äY}zqô]6B—¡P%8\AEf¦~êþŸ³÷“¬Ñ±²ÉEm”z¶2úEmõv8hOCñ—lwù ÌÂdxUZE"_Y.g 80…(p°"˜ÄecÄ"‚Ê`iŒ•óYv¦²º3wÓ2Øâ–#nv :[«ò h€N–*®†Ü‚ã˜ÄN2þPœ,†¦p ˜RY¨ Í'lXJÀ>eI8¯#…R‚°Þ¡/‘P /A‰ÑM”u-ìÅ./(‡¿3‚I€ãÊ|/!ãBåŒaÊK‡*P=×BÑGÿàʲà®I€Î4±ä¶3¸ CP3¦»€¨€fQ*L¤ÉÈÇ8ÑAò_DÏêPŽVüµÐ°F!0¶xîzpអ_%Ú)K§'ÜÎ#¼ÄÙ¢8Lè"#ÁMU/'¿}¸éD)ëÜ¡©™\‰-#R *`K^Ž~×S«ÆˆOª“+$ï¼ê˯4´ÿ—±<`!L\IíqjIN ¶â”qÁQ>ñsàÚ©$9x§àS·ŠÁÞÂ0D©„ï"fÞ‚¡›KQvªUë¤1uŠG1*a—¤Œ)hV`X¤Š®+©<Þ2ý™? ˆ@1y<žª\C Õm\Y?XtªQ.ÒKgmrm¦Ü¨¼LÉ2E]N+¯r㲡eFò¬e¼¯uÈ(Æ ¹&žË!˜«-ñœ`³)ê‹íÌ&ÇÚʃ|iK™¦sÌ"3Úå(hg0¸:7ë€ßå«b€dË…+j•¤têŸ5'LKyŒ§â ²t–!Ï÷Qi ,®¹9Ï Kè„·pšáéÒèT0Í „ðpD ¡ OÖ_úÝŠ|¯Mq±²E ŒH e²ƒÁþ½eëžþÐJïÖ í² tüšuŒJ™šXÖ㤶Ö €/”P Œ¤ ƒ)Mgññ Dý¥H>ë#«ß÷`…$¸ „c £,X㌠K°HB‚6 Zd á„‹d‡¹‰èq +—Ðæ9 ë¤tó¾Þ«TÞ\§•€Hã uèRQ_롌ØX7Pô"Tð´$k,>HŒ c!ç¥rARUd„’Z5-GèHJ<Ñ(~¢bQÕ*º+I¿œËôyxÈ^–JyÍ…NøÇ¼Ì E³ÐC&o] ×V>›¼NÐ Pô:ˆ« Š-*dòúAŽ#j'y6ºòµADÜ¡È;£U)÷‘Æ, — n;gçJpH¥è×+٨׶õh_ê3½Rn`&%Ü6rs]5‘X'ûØDcünÓ&}ȪWŒµïmº)­4¥•7­´vV‡ò;À@øæî£â&”Ö}qh´ë}‘îÑSBiJ( •PZ¹Þ\½ÿ‘Y¶líºþ¦¶ÌxD{$M¿ä™¤à–U¥@1`äH±¼V±G`¼¨p¸ùzIHËxŒ z¶.«ªƒÆ¤£%-¢ùéPh-½ïd©.ôxº žaÔ”„ þ-ál ©0y©Í,®]b©žÌèX»®ºôˆ÷5=…Qj¸ô¹Œ¦\Kñ9RMÜ—ˆn:Aà@ÎíÈÐày¤Ùó:K/ªUar{IŸàµm3ˆÑˆ£8à”¨D!@%€ÞÅEÊm騕åÌG7‹o//X´X¾Æ¬ÙXò"ò8y®øjm5åEyp¡F|•ÙòÑ%A òV˜–D•Ë×)|î£ð譼ܱIQ „B¶ȃ¹šÒGKøa]YR%¯“¸4pAB=ó¥˜:€óS‘ 1ô›’é(ÍÉo2ü»Çí†_:m\ggÔ}ˆG 3…윛@²Šnb ¨g£+‚Æ¤Š¬ :Y™#^¨À!¤¹êbžÉ °=±e©Ö›¯nAæa/â®ÜaVŸ]˜2D¥ê!f3_ÍBì™\§´‡Œ/!õ³R‹MÛ嶸ï>LÞœå4J_˜ûôE‚¥Gæ ½ Œ¸ÔZ®£øÇ ”¤É‚Î1nR@m‚—ۓᎳMåt9’t qÌêmД•$éIqš%CMV’jp*è’dZï‹f’ˆ d³|ÓrÛ0I ɾE+&À°*‰#fKŠš+r ¯Ä]mþ?da# ±) ŠJJBr^&}Ux ðs¶ÌW±JÉôÚ’’“ £B„! Áj2‘öm+x6Fì\•`=ÌÜ[&LkJ“ʶÎOk_Ö)gô¢Ô¥*@ßwLK\q3¤aÓ­£«Ð½ež·äMJTj…¹ÅÚräœV p¯ÜÊ«ß܈rLOïÜÆÀ@=†ej]Áô¸³:¸†iç6Ó*¦Ó*¦÷_ÅtÛ¤^õ:¦²C®cÚ²B´’é´’éáV:ØJ¦‰¸ÝÝÂ.dzÜ'¸”iË´ßi1Óiââx‹™¶0ªW¹œivc.gÚ²2Õ´ é4yñ!f:Ö‚¦û¥×3= îüÀM[æTOkšN+Ù ¸¦i×ZI¯nUÓìÆ\Õ´KNëšN«Ù<ØhÇZ×t¿.䲦Ç_Ø´«¦¥M']8ÞÒ¦-Ë­¼ÊÅM³sqÓN]8-o:éÂ;›©kyÓýº«›Wr}Ó®mç§N']x …åEûþ{¯uÓìÇ\ã´eùªi•ÓIn´c­rº_r‘Ó‡¯ÕòÐeN[×Uš:táX NK.!fÌ¥N[Â=Ób§“.|ˆ™>p±Ó^]èØ”h¢öÊУÎHeèn$eª *ClRq±³±ôë® jØÊжJî©4t* =ÔLÍP¥¡ppœ}–M{ièÑw¹o©Ô›JC'©7bihW ð5•††±Jc¤4twG­©4t’z1ÓÁ‹aú¤žT†·F·:©2tÊYÚca¯+ƪ€‘Êж¸ÍT:e4Ú8x=L¯,,•¡G|Jièn}* tሥ¡)ÀWUÇ*‘ÒÐÝÌþT:釘éàÅ0}ºP*Cý1¡T†vÌçš*C']8@ehG’ùõU†ÆÑ*`XÚV„;U†NºðP£¼¦WJeèÃwû}heèn^aª dሕ¡éÂWUšÆZIF*C;dáT:ÉÂ{˜éh+ɸ*‹ªjϺczBÉvÌçšò…“. _ض¼É«Í¦QW’Ù] qÊNºðp£m%ÏÅË“Ýõ†’/<ª.”taÇŒÁ)]8éÂáÓ…]+Œ¾¦tau%™Ý¤ì”.œtáÌ4¶’Ì^](ù£֑J¾°'›3éÂI`ayXyµùÂ<îJ2ÂpJNÂðÁV;ÚR2{…¡$ º°š$ ;æN ÃIŸ0Ü­×z Ã<êR2KŒN ÃIÞÃLÇZJF+îÆ£Ý³Ëàqƒ¤eŸÁ®bÒi=™i=™í4¸¤{Í+ÊXtÀ°+ÊtM%œ–”G¾ü%e`§ƒ-)CG—ˆì{v<²ßà´ãà$û޼ã`çÂ׳° eÔ…eÚð™––™¤ßC u¬¥eöK¿²ëà#¬.ãûªù¦¼à”<ÀÆdçÁ®]L^[Å(àeÔfÚ*¦šÑ)5x°Ùê±Ö˜Ù¯Ë3ÇÕ‰eÿÁ©ntÒ‰GÞ°Åä^cå(€fÔ…fÜT;:éÄ u¬¥föëIJ áqS„e¾}â&8éÄlLv"læW[A xuřвdÆTB:éÄÃÍv¬5göëIJáq£§e?–èéTF:éÄ1w$lÁí×XHj•uåÛ²ÒðTJ:éćêXkÏhë« M¸»?oÙ–ðJIÛÂ+S)éTJú`£’­ ·‹_w)©qoNØšŸjI§ZÒC 5 VKj1Þ}ŒzÏö„ºÎ£mP8Õ’NÚïÈ[¶˜Üë¬%5cÕДM [Úyª%´ß ÕŽµ¾Ì~íWö)lLé;ÚN…]Ó§ZÒ)G8@-i»Vyµµ¤v¬Z™²[akqøTK:å5Û±–™Ù¯ëý ÕÑGÛ±p*&„â‘÷,ìÜÍþ5“Ú±ŠhÊ®…-“-¦bÒI(>ÄPG[of¯P,6ê Ž¶ua_¡ß$'¡x€Éæ…Ór¤Mxq£ËÈö…-Å2S1é$7ÛÁKgz…bÙÀð¸áÓ²…aWBq*&tâ›vmWñªŠIÝX‹Ó”m §uI'8¡î_œ¦i¬mNQ÷´«âò·…©Ê:bt —16õM‹÷ÛóF:Ùoþ¸Ï9þ®ç‹e(`€ B•„TE˜kvkµÒt\€Z+ÇŽGƒPBh-Ù†>ÐU°´b Ö[èCƒOT ÆÏoÕ ý0¯µÁ‡Â.¢20áÕ‘€Ñl‹ A˜` }®7G‰­œ7„ýÕ‘‹™æˆA|,oI8y¢£…À,röë#«K žás_œDeöER*+/fÀ“Ëã§C±i ¼”_Œn“‡Àk$X,Û@[ñbhŒäuM”å6 ›ÞÂVÞ €Ë ß)ú3[Åh¡­›ceÑ22^ðw­-ðÆ Î¬¯‰ÖÍåíÐbÿÜàR‚ Þðw€nCî1­XjÅ ”˜1[ÎbÕdÍj²¥ŠFéÉUШ°¾”èÔ|ìbåÎåɱá‚Û7àgãéä¢KÏí!NyèåU !iji ž@ÔY^¬óË?ÜËRß-•0TX”¶!WåÇf‰ŽÆ+q¿—I•°óÆSÖwX4nÑ€êÕ-ÖwXß ÕÎýóðÖñPΩ5ËW<(ÏÚÎvǘ \K®9=¼`Ñ #Rºq¨níÔ4y›+œ–îxyîÒ«†õ-›/þجüqØòÇaÙÉiÃäëÇ.V<€Fup+›H«oŵtô½dàÓ—Š+¨àDy0px| k“~¬~¿ _¤R[¶]„ñÇÒvr"5³þ}}¥âøƒCï_¾yjy¨]Ÿ»{mã¡å™%Æ §ÕOÜySñÀåqütŽ&îQ]w[ ëæ[Êeë5ˆTcL.­¦a4qÙuk£‰!ZâT8®³2n«û–4nÝUÛ7`ÿ7¿k8«‡o½yžZ=¹ â3AƒC¹»f;(pŒyôà™Æ÷¡I¨·-!­û²Ñž+rK¨²vUù­iaÇâŽ!Ð’šOßfôqÛ6´zcùàV;Èz’»ØÁ5Ž?‚„Øo¿¾þ_yND]üíý›ÀøŽ@ôZÌ/ç§·ŸÞ¿©[Û­ÓçŸÎÎú„“—m¹Ñ’l¨ê ¶PgötT6ÕͳümaÀe”•Níhƒñ[Ù ÈJ{ÔÄE=çw'Ь¯À¦žÛLs#[«MÚÆ”K¦À0+'2:!•'cbøÙ¥°ŠÁé‹ÈPÙ–t½±1×â’Ôî+—Bg3)‚Ûf°{:&4×Gè rM– <£“ ⛄ ‚Ôò럇.„ Cæëå÷õW<œ$!)Z¯yDþ-ã,Wò³_Æ3qµEâBnœÚr­å®Ü¥T}^ ZâÖ44»püÍØôœ&ýî¤Ã´q•qèî¹¥R ©äãÙïý Qn—l .LÙ'ˆýåù7d_L@NUJ»kþy±sÁÒB^w¨+ýcËÁes?$3Ô.ôS£|§Ñ¨+ôX|Àyg× À `"Ãç9 Œ‚ºÌ9_75c¯Ô³RHS+F“¤ìŒX_´Y,ÈàZë%‰åÝ:ÍNuh¢1Îë[`(Õ§‹%`¤c¼0^U1…Aµ &¨"ëqWÖXŒÑJaM=>«‚‘ ˜`ÊFÆ*è¦'YÃàf™ðýaÕ}úŸE–ŽÁÎJ™º¤±¼õ*<ÆG˜},圷’Ë€Ø!½`i QQ ÖA,ê#«ß÷˜Ïpm›G¬qF…%‚%ÉØÁèȘ./ÌÂ9k’„…r‚x•¬zœo¦€…s@?#áiÍxAã¾Þ3žÉ7ô€my¼dk¼!T®ÜΣëW ›¥ä#ź¢g¤zVÅRbñAbLà59/‰UGô¥zÅHÔÄÑ´¡w+JNM>Q±†»\…ו‚"¸}Sô>«,h€è+ÀâNÜÑYÆÍ+`uf°¼bq˜‹báÚ–˜/<ª@0@‰€DQRšJƒ"B ‚úÌÔ-H]LŒf Ñ•¯ "JöŸ=b´*•ÅÒ˜ÿ{ײÛ6 ¥|-I]zéÇôÒ[~gg)K†é4Š«Z¨yvôàîÎÌîPaÒª¨‘{Ç€ÀêBàMö\Æ­LÍ‚‡`;)%WÌâ#)µ#[Šåÿû¾ÜÓÔaKú`RUqÒZÉRô™6bíñqa&¯‘ʼnbánú,²x6^BM–†b¥ ÒEÒDöõQUbiÈb¬dÛk­Q‡èµIzsäh[XÍ™ù¦rt†J è¼s r¶c0ީш.ÉRŠ×Óy ’h<×£K IÅÕ§ÍNªJH½5®Ø7{ÎK麾:Ò&¨LfGï‚òAæˆ7[§@Î =jø2)ÒThÃḂÌ&EâºÔM:[TU>!‘÷°w³xŸ‘ÌA/2c©8õ…›{®˜¡5—Z<‘ TCO†úšÔ{!Æ’¸¦§ÕT§®Á¦j¹Ý¶žÛXRhöÖFrOóq% ¢¨ ÁqEf»áéyŒ—d$5ÕD·Bóf7àJ´k‘\‚MWh„x›*™0gPX8p¦ÿ›*Űšã¤;;œ(2#ÔJUê]ŒX¢è;Èõo¬ ÈX—õƒÀ$Cø.d/X©WgÊ—Š(UQC5V€ª,Í58q:Wr(ù2·äæž°³ÉYÙ˜Ö tÑU7œ.!Ù"2³×¨iš-FóÄ’5*QjÙÚ¯êÉo®ê›W#m!JŠ¥…Š@tƒžD#JfEµ"Ž¡„a!ªÕ½(Ree. ”?VL©«fhm[oÞ+V@³‹‚Lfk¬D¡7$d0T­Ú§^6k,*Ö°ýH€Ü³boÙ}IîKn«Ky›ÍtBE(äYä{y}Ä*£Ñ¾<Ù/žBí­™gŒWMdu|_LE±Ôd] YT‰øúeû[‰.ÓìÁq|+&%sçHîΑQJ µºêxpé7“ÿ9G™p¦cФI2‰»zOP4NHt‘:)ͱ¾xv¦@0™œIG˜H¨ìØG«À O§eŸåLà×%6Žè€tFrÊLìÜ,m'™ÌñÜ;@J½±!m˜ R•“$13®8'®YÑæßäŠW/\ÞL™–¹ÌŠìlúxíÝíÑúüà Ïík§ÇŒgÌxˆ«6ã¹ÝñÂSžÉaÊÓKõ1çsžGƒ;jÎsqñ̃Z~ÿà³ø·/N¸àp§^8ü鸚qøæ%U¯ŒÃé8ÜIõÇ îÍV¢¿ˆÃk9¼ŠïÃs=KÊY»¾ÏÖÃC$ÞG÷ü´¯‹Å›íaûhâÛ)ã@ãÆ†·w›[>OQžꞆ¬î¡÷Eqz §±a`ñX|óÝ×Ebï67ðöAâĈwâÍ=Ÿ½·!$çc°ö!dçâõïË'‚Äs­2½É'(Þ×.6ËS°¹SB4hþt\ÍÐ|óé†fŒ†ugI2d~4¸Ó°^âÿ`÷¤3"ì,XÅz€–ugKõÀâÅŸŽ¬¥eÝe¯‹ÆGiYwfú?ÞáX-ëûÀ¼Î…¾wzmäz–•ëTGßzò.n®SêØ^‘Ã1Z×éTFóz@òü„æ5~þúþõ7o&Âtæqtractor-0.5.11/src/PaxHeaders.10084/qtractorTakeRangeForm.h0000644000175000001440000000012312166134117021663 xustar000000000000000027 mtime=1373157455.942698 26 atime=1381134668.01608 30 ctime=1381134668.016080065 qtractor-0.5.11/src/qtractorTakeRangeForm.h0000644000175000001440000000402312166134117021151 0ustar00rncbcusers00000000000000// qtractorTakeRangeForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorTakeRangeForm_h #define __qtractorTakeRangeForm_h #include "ui_qtractorTakeRangeForm.h" // Forward declarations. class qtractorTimeScale; class qtractorClip; //---------------------------------------------------------------------------- // qtractorTakeRangeForm -- UI wrapper form. class qtractorTakeRangeForm : public QDialog { Q_OBJECT public: // Constructor. qtractorTakeRangeForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorTakeRangeForm(); // Setup accessors. void setClip(qtractorClip *pClip); qtractorClip *clip() const; // Result accessors. unsigned long takeStart() const; unsigned long takeEnd() const; int currentTake() const; protected slots: void rangeChanged(); void formatChanged(int); void valueChanged(); void updateCurrentTake(); void stabilizeForm(); private: // The Qt-designer UI struct... Ui::qtractorTakeRangeForm m_ui; // Instance variables... qtractorTimeScale *m_pTimeScale; qtractorClip *m_pClip; }; #endif // __qtractorTakeRangeForm_h // end of qtractorTakeRangeForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorCurveSelect.cpp0000644000175000001440000000012312223511102021740 xustar000000000000000027 mtime=1380880962.062114 26 atime=1381134666.56708 30 ctime=1381134666.567080042 qtractor-0.5.11/src/qtractorCurveSelect.cpp0000644000175000001440000000752712223511102021242 0ustar00rncbcusers00000000000000// qtractorCurveSelect.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorCurveSelect.h" //------------------------------------------------------------------------- // qtractorCurveSelect -- MIDI event selection capsule. // Constructor. qtractorCurveSelect::qtractorCurveSelect (void) { m_pCurve = NULL; m_pAnchorNode = NULL; } // Default destructor. qtractorCurveSelect::~qtractorCurveSelect (void) { clear(); } // Event selection item lookup. qtractorCurveSelect::Item *qtractorCurveSelect::findItem ( qtractorCurve::Node *pNode ) { // Check if this very event already exists... return m_items.value(pNode, NULL); } // Item insertion method. void qtractorCurveSelect::addItem ( qtractorCurve::Node *pNode, const QRect& rectNode ) { m_items.insert(pNode, new Item(rectNode)); m_rect = m_rect.united(rectNode); if (m_pAnchorNode == NULL || m_pAnchorNode->frame > pNode->frame) m_pAnchorNode = pNode; } // Item removal method. void qtractorCurveSelect::removeItem ( qtractorCurve::Node *pNode ) { ItemList::Iterator iter = m_items.find(pNode); if (iter != m_items.end()) { delete iter.value(); m_items.erase(iter); commit(); } } // Item selection method. void qtractorCurveSelect::selectItem ( qtractorCurve *pCurve, qtractorCurve::Node *pNode, const QRect& rectNode, bool bSelect, bool bToggle ) { Item *pItem = findItem(pNode); if (pItem) { unsigned int flags = pItem->flags; if ( (!bSelect && (flags & 2) == 0) || (( bSelect && (flags & 3) == 3) && bToggle)) pItem->flags &= ~1; else if ( ( bSelect && (flags & 2) == 0) || ((!bSelect && (flags & 3) == 2) && bToggle)) pItem->flags |= 1; } else if (bSelect) { if (m_pCurve == NULL) m_pCurve = pCurve; if (m_pCurve == pCurve) addItem(pNode, rectNode); } } // Selection commit method. void qtractorCurveSelect::update ( bool bCommit ) { // Remove unselected... int iUpdate = 0; ItemList::Iterator iter = m_items.begin(); const ItemList::Iterator& iter_end = m_items.end(); while (iter != iter_end) { Item *pItem = iter.value(); if (bCommit) { if (pItem->flags & 1) pItem->flags |= 2; else pItem->flags &= ~2; } if ((pItem->flags & 3) == 0) { delete pItem; iter = m_items.erase(iter); ++iUpdate; } else ++iter; } // Did we remove any? if (iUpdate > 0) commit(); } // Selection commit method. void qtractorCurveSelect::commit (void) { // Reset united selection rectangle... m_rect.setRect(0, 0, 0, 0); ItemList::ConstIterator iter = m_items.constBegin(); const ItemList::ConstIterator iter_end = m_items.constEnd(); for ( ; iter != iter_end; ++iter) { Item *pItem = iter.value(); m_rect = m_rect.united(pItem->rectNode); } if (m_items.isEmpty()) { m_pAnchorNode = NULL; m_pCurve = NULL; } } // Reset event selection. void qtractorCurveSelect::clear (void) { m_rect.setRect(0, 0, 0, 0); qDeleteAll(m_items); m_items.clear(); m_pAnchorNode = NULL; m_pCurve = NULL; } // end of qtractorCurveSelect.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioMadFile.h0000644000175000001440000000012311563576072021473 xustar000000000000000027 mtime=1305410618.253123 26 atime=1381134670.52808 30 ctime=1381134670.528080105 qtractor-0.5.11/src/qtractorAudioMadFile.h0000644000175000001440000000707511563576072020773 0ustar00rncbcusers00000000000000// qtractorAudioMadFile.h // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorAudioMadFile_h #define __qtractorAudioMadFile_h #include "qtractorAudioFile.h" #include #include #ifdef CONFIG_LIBMAD // libmad API #include #endif //---------------------------------------------------------------------- // class qtractorAudioMadFile -- Buffered audio file declaration. // class qtractorAudioMadFile : public qtractorAudioFile { public: // Constructor. qtractorAudioMadFile(unsigned int iBufferSize = 0); // Destructor. virtual ~qtractorAudioMadFile(); // Virtual method mockups. bool open (const QString& sFilename, int iMode = Read); int read (float **ppFrames, unsigned int iFrames); int write (float **ppFrames, unsigned int iFrames); bool seek (unsigned long iOffset); void close (); // Virtual accessor mockups. int mode() const; unsigned short channels() const; unsigned long frames() const; // Specialty methods. unsigned int sampleRate() const; protected: // Special decode method. bool input(); bool decode(); // Internal ring-buffer helper methods. unsigned int readable() const; unsigned int writable() const; private: // Instance variables. int m_iMode; FILE *m_pFile; unsigned int m_iBitRate; unsigned short m_iChannels; unsigned int m_iSampleRate; unsigned long m_iFramesEst; bool m_bEndOfStream; #ifdef CONFIG_LIBMAD struct mad_stream m_madStream; struct mad_frame m_madFrame; struct mad_synth m_madSynth; #endif // Input buffer stuff. unsigned int m_iInputBufferSize; unsigned char *m_pInputBuffer; // Output ring-buffer stuff. unsigned int m_iRingBufferSize; unsigned int m_iRingBufferMask; unsigned int m_iRingBufferRead; unsigned int m_iRingBufferWrite; float **m_ppRingBuffer; // Decoding frame mapping for sample-accurate seeking. unsigned long m_iSeekOffset; // Decoded frame node. struct FrameNode { // Member constructor. FrameNode(unsigned long i = 0, unsigned long o = 0, unsigned int c = 0) : iInputOffset(i), iOutputOffset(o), iDecodeCount(c) {} // Member fields. unsigned long iInputOffset; // Bytes from input file. unsigned long iOutputOffset; // Sample frames on output. unsigned int iDecodeCount; // Decoder iteration count. }; // Decoded frame list type. typedef QList FrameList; // Frame list factory method. static FrameList *createFrameList(const QString& sFilename); // Frame list instance; FrameList *m_pFrameList; // Current decoded frame node. FrameNode m_curr; }; #endif // __qtractorAudioMadFile_h // end of qtractorAudioMadFile.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorOptionsForm.ui0000644000175000001440000000012312203714301021632 xustar000000000000000027 mtime=1376753857.794319 26 atime=1381134667.92408 30 ctime=1381134667.925080064 qtractor-0.5.11/src/qtractorOptionsForm.ui0000644000175000001440000032625212203714301021133 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorOptionsForm 0 0 520 480 Options - Qtractor :/images/qtractor.png true 4 8 false 0 &General 75 true Session true 50 false Default session &file format: TransportModeComboBox 50 false Default session file format (suffix) Qt::Horizontal 120 20 50 false Whether to create new sessions based on template &New session template: 1 0 320 0 50 false New session template true 22 22 24 24 50 false Browse for new session template :/images/fileOpen.png 50 false Whether to save backup versions of existing sessions Save &backup versions of existing sessions: 50 false Which mode to rename existing session files Increment previous version (default) Increment current version 75 true Options true 50 false Whether to ask for confirmation on removal &Confirm removals Alt+C 50 false Number of &recent files: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter MaxRecentFilesSpinBox 0 0 50 false The maximum number of recent files to keep in menu 0 20 5 50 false Whether to capture standard output (stdout/stderr) into messages window Capture standard &output Alt+O 50 false Whether to show the complete directory path of loaded session files S&how complete path of session files Alt+P Qt::Horizontal 20 20 50 false Whether to remove audio peak files on session close Auto-remove audio pea&k files Alt+K 50 false Whether to keep all tool windows on top of the main window Keep tool &windows always on top Alt+K 50 false Whether to try dropping multiple audio files into the same track &Drop multiple audio files into the same track Alt+S 50 false Whether to reverse mouse middle-button role on keyboard modifiers (Shift/Ctrl) Re&verse middle-button modifier role (Shift/Ctrl) Alt+V Qt::Vertical 20 4 75 true Transport true 50 false Transport &mode: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter TransportModeComboBox 50 false Transport control mode (JACK) None Slave Master Full Qt::Horizontal 20 20 50 false &Loop recording mode (takes): Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter LoopRecordingModeComboBox 50 false Loop recording mode (takes) None First Last &Audio 75 true Capture / Export true 9 6 60 32767 50 false Audio compression quality to use on capture (record) and export 1 9 1 4 50 false Audio sample format to use on capture (record) and export 50 false Audio file type to use on capture (record) and export Qt::Horizontal 20 20 50 false File &type: AudioCaptureTypeComboBox 50 false Sample &format: AudioCaptureFormatComboBox 50 false &Quality: AudioCaptureQualitySpinBox Qt::Horizontal 120 20 75 true Playback true 50 false Whether to apply time-stretching when tempo changes Aut&omatic time-stretching Alt+O Qt::Horizontal 20 20 50 false Sample-&rate converter type: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter AudioResampleTypeComboBox 50 false Sample-rate converter quality Sinc (Best Quality) Sinc (Medium Quality) Sinc (Fastest) Zero Order Hold Linear 50 false Whether to use WSOLA time-stretching &WSOLA time-stretching Alt+W 50 false Whether to apply WSOLA quick seek time-stretching WSOLA quic&k seek Alt+K 50 false Whether to have separate audition/pre-listening player output ports Dedicated au&dition/pre-listening player outputs: Alt+D 50 false Whether to auto-connect dedicated audio player outputs Auto-&connect Alt+C Qt::Horizontal 120 20 Qt::Vertical 20 4 75 true Metronome true 50 false Whether to enable the audio metronome &Enable audio metronome Alt+E 50 false &File (bar): MetroBarFilenameComboBox 1 0 320 0 50 false Metronome Audio filename (bar) true 22 22 24 24 50 false Qt::TabFocus Browse for sample audio file (bar) :/images/fileOpen.png 50 false &Gain (bar): MetroBarGainSpinBox 66 0 50 false Metronome gain (bar) dB 1 -60.000000000000000 12.000000000000000 0.000000000000000 50 false &File (beat): MetroBeatFilenameComboBox 1 0 320 0 50 false Metronome Audio filename (beat) true 22 22 24 24 50 false Qt::TabFocus Browse for sample audio file (beat) :/images/fileOpen.png 50 false &Gain (beat): MetroBeatGainSpinBox 66 0 50 false Metronome gain (beat) dB 1 -60.000000000000000 12.000000000000000 0.000000000000000 50 false Whether to have separate audio metronome output ports Dedicated a&udio metronome outputs: Alt+U 50 false Whether to auto-connect dedicated audio metronome outputs Auto-co&nnect Alt+N &MIDI 75 true Capture / Export true 50 false File &format: MidiCaptureFormatComboBox 50 false MIDI file format to use on capture (record) and export Qt::Horizontal 20 20 50 false &Quantize: MidiCaptureQuantizeComboBox 80 32767 50 false MIDI capture (record) quantization 75 true Playback true 9 6 50 false Queue &timer (resolution): MidiQueueTimerComboBox 50 false Queue timer (resolution) Qt::Horizontal 120 20 50 false Whether to have separate MIDI player output ports Dedicated MIDI p&layer outputs Alt+L 75 true Control true 9 6 50 false &MMC: MidiMmcModeComboBox 50 false MIDI Machine Control (MMC) mode None Input Output Duplex 50 false &Device: MidiMmcDeviceComboBox 50 false MIDI Machine Control (MMC) device id. Qt::Horizontal 4 20 50 false &SPP: MidiSppModeComboBox 50 false MIDI Song Position pointer (SPP) control mode None Input Output Duplex Qt::Horizontal 4 20 50 false Cloc&k: MidiClockModeComboBox 50 false MIDI Clock control mode None Input Output Duplex 50 false Whether to have separate MIDI control ports Dedicated MIDI &control input/output Alt+C Qt::Vertical 20 4 75 true Metronome true 50 false Whether to enable the MIDI metronome &Enable MIDI metronome Alt+E 50 false &Channel: MetroChannelSpinBox 50 false Metronome MIDI channel 1 16 10 Qt::Horizontal 120 20 50 false &Note (bar): MetroBarNoteComboBox 120 0 50 false Metronome MIDI note (bar) 50 false &Velocity (bar): MetroBarVelocitySpinBox 50 false Metronome MIDI velocity (bar) 1 127 96 Qt::Horizontal 4 20 50 false &Duration (bar): MetroBarDurationSpinBox 50 false Metronome MIDI velocity (bar) 1 9999 8 24 50 false &Note (beat): MetroBeatNoteComboBox 120 0 50 false Metronome MIDI note (beat) 50 false &Velocity (beat): MetroBeatVelocitySpinBox 50 false Metronome MIDI velocity (beat) 1 127 64 50 false &Duration (beat): MetroBeatDurationSpinBox 50 false Metronome MIDI velocity (beat) 1 9999 8 16 50 false Whether to have separate MIDI metronome output port Dedicated M&IDI metronome output Alt+I &Display 75 true Defaults true 50 false &Time display format: DisplayFormatComboBox 50 false Time display format Frames Time BBT Qt::Horizontal 20 20 50 false &Base font size: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter BaseFontSizeComboBox 50 false Base application font size (pt.) true (default) 6 7 8 9 10 11 12 75 true Meters true 50 false &Audio: AudioMeterLevelComboBox 66 0 50 false Audio meter level Over 0 dB 3 dB 6 dB 10 dB 66 24 50 false Audio meter color 22 22 24 24 50 false Qt::TabFocus Select custom audio meter color :/images/formColor.png ... Qt::Horizontal 4 20 50 false &MIDI: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter MidiMeterLevelComboBox 66 0 50 false MIDI meter level Peak Over 66 24 50 false MIDI meter color 22 22 24 24 50 false Qt::TabFocus Select custom MIDI meter color :/images/formColor.png ... Qt::Horizontal 4 20 50 false Reset meter colors to default &Reset Alt+R false 75 true Messages true 9 6 180 0 180 32767 50 false Sample messages text font display true QFrame::StyledPanel QFrame::Sunken Qt::AlignCenter 50 false Select font for the messages text display &Font... Alt+F false Qt::Horizontal 20 20 50 false Whether to keep a maximum number of lines in the messages window M&essages limit: Alt+M 50 false The maximum number of message lines to keep in view lines 100 10000 100 1000 Qt::Vertical 20 4 75 true Logging true 8 4 1 0 320 0 50 false Messages log file true 22 22 24 24 50 false Qt::TabFocus Browse for the messages log file location :/images/fileOpen.png 50 false Whether to activate a messages logging to file. Messages &log file: Alt+M &Plugins 6 9 75 true Paths true 80 16777215 50 false Plugin type 320 0 50 false Plugin path true 22 22 24 24 50 false Browse plugin path ... :/images/fileOpen.png 60 22 60 24 50 false Add plugin path &Add Qt::ToolButtonTextBesideIcon 32767 72 50 false Plugin paths true QAbstractItemView::SelectRows true 60 22 60 24 50 false Remove plugin path &Remove Qt::ToolButtonTextBesideIcon 60 22 60 24 50 false Move up path &Up Qt::ToolButtonTextBesideIcon 60 22 60 24 50 false Move up path &Down Qt::ToolButtonTextBesideIcon 50 false &LV2 Presets directory: Lv2PresetDirComboBox 360 0 50 false LV2 Presets directory (default: ~/.lv2) true 22 22 24 24 50 false Browse LV2 Presets directory ... :/images/fileOpen.png 75 true Instruments true 9 6 50 false Whether to have separate audio output ports Dedicated audi&o outputs: Alt+O 50 false Whether to auto-connect dedicated audio output ports Au&to-connect Alt+T Qt::Horizontal 20 20 Qt::Vertical 20 4 75 true Editor true 9 6 50 false Whether to open plugin's editor (GUI) by default Open plugin's &editor (GUI) by default Alt+G 75 true Experimental true 9 6 50 false Whether to use a dummy plugin type when scanning for VST plugins Dummy &VST plugin scan (RECOMMENDED) Alt+V Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok OptionsTabWidget SessionFormatComboBox SessionTemplateCheckBox SessionTemplatePathComboBox SessionTemplatePathToolButton SessionBackupCheckBox SessionBackupModeComboBox ConfirmRemoveCheckBox StdoutCaptureCheckBox CompletePathCheckBox PeakAutoRemoveCheckBox KeepToolsOnTopCheckBox TrackViewDropSpanCheckBox MidButtonModifierCheckBox MaxRecentFilesSpinBox TransportModeComboBox LoopRecordingModeComboBox AudioCaptureTypeComboBox AudioCaptureFormatComboBox AudioCaptureQualitySpinBox AudioAutoTimeStretchCheckBox AudioWsolaTimeStretchCheckBox AudioWsolaQuickSeekCheckBox AudioPlayerBusCheckBox AudioPlayerAutoConnectCheckBox AudioResampleTypeComboBox AudioMetronomeCheckBox MetroBarFilenameComboBox MetroBarFilenameToolButton MetroBarGainSpinBox MetroBeatFilenameComboBox MetroBeatFilenameToolButton MetroBeatGainSpinBox AudioMetroBusCheckBox AudioMetroAutoConnectCheckBox MidiCaptureFormatComboBox MidiCaptureQuantizeComboBox MidiQueueTimerComboBox MidiPlayerBusCheckBox MidiMmcModeComboBox MidiMmcDeviceComboBox MidiSppModeComboBox MidiClockModeComboBox MidiControlBusCheckBox MidiMetronomeCheckBox MetroChannelSpinBox MetroBarNoteComboBox MetroBarVelocitySpinBox MetroBarDurationSpinBox MetroBeatNoteComboBox MetroBeatVelocitySpinBox MetroBeatDurationSpinBox MidiMetroBusCheckBox DisplayFormatComboBox BaseFontSizeComboBox AudioMeterLevelComboBox AudioMeterColorLineEdit AudioMeterColorToolButton MidiMeterLevelComboBox MidiMeterColorLineEdit MidiMeterColorToolButton ResetMeterColorsPushButton MessagesFontPushButton MessagesLimitCheckBox MessagesLimitLinesSpinBox MessagesLogCheckBox MessagesLogPathComboBox MessagesLogPathToolButton PluginTypeComboBox PluginPathComboBox PluginPathBrowseToolButton PluginPathAddToolButton PluginPathListWidget PluginPathRemoveToolButton PluginPathUpToolButton PluginPathDownToolButton Lv2PresetDirComboBox Lv2PresetDirToolButton AudioOutputBusCheckBox AudioOutputAutoConnectCheckBox OpenEditorCheckBox DummyVstScanCheckBox DialogButtonBox qtractor-0.5.11/src/PaxHeaders.10084/qtractorDssiPlugin.h0000644000175000001440000000012312161335204021252 xustar000000000000000027 mtime=1371912836.382031 26 atime=1381134670.47908 30 ctime=1381134670.479080104 qtractor-0.5.11/src/qtractorDssiPlugin.h0000644000175000001440000001031212161335204020536 0ustar00rncbcusers00000000000000// qtractorDssiPlugin.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorDsiiPlugin_h #define __qtractorDssiPlugin_h #include "qtractorLadspaPlugin.h" #include //---------------------------------------------------------------------------- // qtractorDssiPluginType -- DSSI plugin type instance. // class qtractorDssiPluginType : public qtractorLadspaPluginType { public: // Constructor. qtractorDssiPluginType(qtractorPluginFile *pFile, unsigned long iIndex, const DSSI_Descriptor *pDssiDescriptor = NULL) : qtractorLadspaPluginType(pFile, iIndex, qtractorPluginType::Dssi), m_pDssiDescriptor(pDssiDescriptor) {} // Destructor. ~qtractorDssiPluginType() { close(); } // Derived methods. bool open(); void close(); // Factory method (static) static qtractorDssiPluginType *createType( qtractorPluginFile *pFile, unsigned long iIndex); // DSSI descriptor method (static) static const DSSI_Descriptor *dssi_descriptor( qtractorPluginFile *pFile, unsigned long iIndex); // Specific accessors. const DSSI_Descriptor *dssi_descriptor() const { return m_pDssiDescriptor; } const QString& dssi_editor() const { return m_sDssiEditor; } private: // DSSI descriptor itself. const DSSI_Descriptor *m_pDssiDescriptor; // DSSI GUI excutable filename. QString m_sDssiEditor; }; //---------------------------------------------------------------------------- // qtractorDssiPlugin -- DSSI plugin instance. // class qtractorDssiPlugin : public qtractorLadspaPlugin { public: // Constructors. qtractorDssiPlugin(qtractorPluginList *pList, qtractorDssiPluginType *pDssiType); // Destructor. ~qtractorDssiPlugin(); // Channel/instance number accessors. void setChannels(unsigned short iChannels); // Do the actual (de)activation. void activate(); void deactivate(); // The main plugin processing procedure. void process(float **ppIBuffer, float **ppOBuffer, unsigned int nframes); // Parameter update method. void updateParam(qtractorPluginParam *pParam, float fValue, bool bUpdate); // Bank/program selector override. void selectProgram(int iBank, int iProg); // Provisional program/patch accessor. bool getProgram(int iIndex, Program& program) const; // Continuous controller handler. void setController(int iController, int iValue); // Configuration (CLOB) stuff. void configure(const QString& sKey, const QString& sValue); // GUI Editor stuff. void openEditor(QWidget */*pParent*/); void closeEditor(); // GUI editor visibility state. void setEditorVisible(bool bVisible); bool isEditorVisible() const; // Specific accessors. const DSSI_Descriptor *dssi_descriptor() const; // Update all control output ports... void updateControlOuts(bool bForce = false); // Reset(null) internal editor reference. void clearEditor(); // Idle editor update (static) static void idleEditorAll(); protected: // Post-(re)initializer. void resetChannels(); private: // Care of multiple instances here. class DssiMulti *m_pDssiMulti; // Internal editor structure accessor... struct DssiEditor *m_pDssiEditor; // GUI editor visiability status. bool m_bEditorVisible; // Controller port map. qtractorPluginParam *m_apControllerMap[128]; // Tracking changes on output control ports. float *m_pfControlOutsLast; }; #endif // __qtractorDssiPlugin_h // end of qtractorDssiPlugin.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiTimer.cpp0000644000175000001440000000012311331527151021411 xustar000000000000000027 mtime=1265020521.610577 26 atime=1381134667.31608 30 ctime=1381134667.317080054 qtractor-0.5.11/src/qtractorMidiTimer.cpp0000644000175000001440000001065211331527151020704 0ustar00rncbcusers00000000000000// qtractorMidiTimer.cpp // /**************************************************************************** Copyright (C) 2005-2010, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorMidiTimer.h" #include #include //---------------------------------------------------------------------- // class qtractorMidiTimer::Key -- ALSA sequencer timer key stuff. // // Setters. void qtractorMidiTimer::Key::setAlsaTimer ( int iAlsaTimer ) { if (iAlsaTimer == 0) iAlsaTimer = ((SND_TIMER_CLASS_GLOBAL & 0x7f) << 24); m_iAlsaTimer = iAlsaTimer; } void qtractorMidiTimer::Key::setAlsaTimer ( int iClass, int iCard, int iDevice, int iSubDev ) { if (iClass < 0 || iClass == SND_TIMER_CLASS_NONE) iClass = SND_TIMER_CLASS_GLOBAL; setAlsaTimer((unsigned long) ((iClass & 0x7f) << 24) | ((iCard & 0x7f) << 16) | ((iDevice & 0x7f) << 8) | (iSubDev & 0x7f)); } //---------------------------------------------------------------------- // class qtractorMidiTimer -- ALSA sequencer timer stuff (singleton). // // Constructor. qtractorMidiTimer::qtractorMidiTimer (void) { m_keys.clear(); m_names.clear(); m_keys.append(0); m_names.append(QObject::tr("(default)")); snd_timer_query_t *pTimerQuery = NULL; if (snd_timer_query_open(&pTimerQuery, "hw", 0) >= 0) { snd_timer_id_t *pTimerID = NULL; snd_timer_id_alloca(&pTimerID); snd_timer_id_set_class(pTimerID, SND_TIMER_CLASS_NONE); while (snd_timer_query_next_device(pTimerQuery, pTimerID) >= 0) { int iClass = snd_timer_id_get_class(pTimerID); if (iClass < 0) break; int iSClass = snd_timer_id_get_sclass(pTimerID); if (iSClass < 0) iSClass = 0; int iCard = snd_timer_id_get_card(pTimerID); if (iCard < 0) iCard = 0; int iDevice = snd_timer_id_get_device(pTimerID); if (iDevice < 0) iDevice = 0; int iSubDev = snd_timer_id_get_subdevice(pTimerID); if (iSubDev < 0) iSubDev = 0; char szTimer[64]; snprintf(szTimer, sizeof(szTimer) - 1, "hw:CLASS=%i,SCLASS=%i,CARD=%i,DEV=%i,SUBDEV=%i", iClass, iSClass, iCard, iDevice, iSubDev); snd_timer_t *pTimer = NULL; if (snd_timer_open(&pTimer, szTimer, SND_TIMER_OPEN_NONBLOCK) >= 0) { snd_timer_info_t *pTimerInfo; snd_timer_info_alloca(&pTimerInfo); if (snd_timer_info(pTimer, pTimerInfo) >= 0) { qtractorMidiTimer::Key key(iClass, iCard, iDevice, iSubDev); long iResol = snd_timer_info_get_resolution(pTimerInfo); QString sTimerName = QString::fromUtf8( snd_timer_info_get_name(pTimerInfo)); QString sTimerText; if (!snd_timer_info_is_slave(pTimerInfo) && iResol > 0) sTimerText = QObject::tr("%1 Hz").arg(1000000000L / iResol); else sTimerText = QObject::tr("slave"); m_keys.append(key.alsaTimer()); m_names.append(QObject::tr("%1 (%2)") .arg(sTimerName).arg(sTimerText)); } snd_timer_close(pTimer); } } snd_timer_query_close(pTimerQuery); } } // Destructor. qtractorMidiTimer::~qtractorMidiTimer (void) { m_names.clear(); m_keys.clear(); } // Returns the number of available timers. int qtractorMidiTimer::count (void) const { return m_keys.count(); } // Index of the a timer key. int qtractorMidiTimer::indexOf ( int iKey ) const { int iIndex = m_keys.indexOf(iKey); if (iIndex < 0) iIndex = 0; return iIndex; } // Key from index. int qtractorMidiTimer::key ( int iIndex ) const { if (iIndex < 0 || iIndex >= m_names.count()) iIndex = 0; return m_keys.at(iIndex); } // Name from index. const QString& qtractorMidiTimer::name ( int iIndex ) const { if (iIndex < 0 || iIndex >= m_names.count()) iIndex = 0; return m_names.at(iIndex); } // end of qtractorMidiTimer.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorSessionCommand.cpp0000644000175000001440000000012312065723502022453 xustar000000000000000027 mtime=1356310338.523936 26 atime=1381134666.56708 30 ctime=1381134666.567080042 qtractor-0.5.11/src/qtractorSessionCommand.cpp0000644000175000001440000001370612065723502021751 0ustar00rncbcusers00000000000000// qtractorSessionCommand.cpp // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorSessionCommand.h" #include "qtractorTimeScaleCommand.h" //---------------------------------------------------------------------- // class qtractorSessionCommand - implementation // // Constructor. qtractorSessionCommand::qtractorSessionCommand ( const QString& sName, qtractorSession *pSession ) : qtractorCommand(sName), m_pSession(pSession) { } // Destructor. qtractorSessionCommand::~qtractorSessionCommand (void) { } //---------------------------------------------------------------------- // class qtractorSessionLoopCommand - implementation // // Constructor. qtractorSessionLoopCommand::qtractorSessionLoopCommand ( qtractorSession *pSession, unsigned long iLoopStart, unsigned long iLoopEnd ) : qtractorSessionCommand(QObject::tr("session loop"), pSession), m_iLoopStart(iLoopStart), m_iLoopEnd(iLoopEnd) { } // Session-loop command methods. bool qtractorSessionLoopCommand::redo (void) { qtractorSession *pSession = session(); if (pSession == NULL) return false; // Save the previous session loop state alright... unsigned long iLoopStart = pSession->loopStart(); unsigned long iLoopEnd = pSession->loopEnd(); // Just set new bounds... pSession->setLoop(m_iLoopStart, m_iLoopEnd); // Restore edit cursors too... if (m_iLoopStart < m_iLoopEnd) { pSession->setEditHead(m_iLoopStart); pSession->setEditTail(m_iLoopEnd); } // Swap it nice, finally. m_iLoopStart = iLoopStart; m_iLoopEnd = iLoopEnd; return true; } bool qtractorSessionLoopCommand::undo (void) { // As we swap the prev/loop this is non-idempotent. return redo(); } //---------------------------------------------------------------------- // class qtractorSessionPunchCommand - implementation // // Constructor. qtractorSessionPunchCommand::qtractorSessionPunchCommand ( qtractorSession *pSession, unsigned long iPunchIn, unsigned long iPunchOut ) : qtractorSessionCommand(QObject::tr("session punch"), pSession), m_iPunchIn(iPunchIn), m_iPunchOut(iPunchOut) { } // Session-punch command methods. bool qtractorSessionPunchCommand::redo (void) { qtractorSession *pSession = session(); if (pSession == NULL) return false; // Save the previous session punch state alright... unsigned long iPunchIn = pSession->punchIn(); unsigned long iPunchOut = pSession->punchOut(); // Just set new bounds... pSession->setPunch(m_iPunchIn, m_iPunchOut); // Restore edit cursors too... if (m_iPunchIn < m_iPunchOut) { pSession->setEditHead(m_iPunchIn); pSession->setEditTail(m_iPunchOut); } // Swap it nice, finally. m_iPunchIn = iPunchIn; m_iPunchOut = iPunchOut; return true; } bool qtractorSessionPunchCommand::undo (void) { // As we swap the prev/tempo this is non-idempotent. return redo(); } //---------------------------------------------------------------------- // class qtractorSessionEditCommand - implementation // // Constructor. qtractorSessionEditCommand::qtractorSessionEditCommand ( qtractorSession *pSession, const qtractorSession::Properties& properties ) : qtractorSessionCommand(QObject::tr("session properties"), pSession), m_pPropertiesCommand(NULL), m_pTempoCommand(NULL), m_iTicksPerBeat(0) { // Actual properties command... m_pPropertiesCommand = new qtractorPropertyCommand ( name(), pSession->properties(), properties); // Append tempo/time-siganture changes... float fTempo = properties.timeScale.tempo(); unsigned short iBeatsPerBar = properties.timeScale.beatsPerBar(); unsigned short iBeatDivisor = properties.timeScale.beatDivisor(); if (pSession->tempo() != fTempo || pSession->beatsPerBar() != iBeatsPerBar || pSession->beatDivisor() != iBeatDivisor) { qtractorTimeScale *pTimeScale = pSession->timeScale(); qtractorTimeScale::Cursor& cursor = pTimeScale->cursor(); qtractorTimeScale::Node *pNode = cursor.seekFrame(0); m_pTempoCommand = new qtractorTimeScaleUpdateNodeCommand( pTimeScale, pNode->frame, fTempo, 2, iBeatsPerBar, iBeatDivisor); } // Append time resolution changes too... unsigned short iTicksPerBeat = properties.timeScale.ticksPerBeat(); if (pSession->ticksPerBeat() != iTicksPerBeat) m_iTicksPerBeat = iTicksPerBeat; } // Destructor. qtractorSessionEditCommand::~qtractorSessionEditCommand (void) { if (m_pTempoCommand) delete m_pTempoCommand; if (m_pPropertiesCommand) delete m_pPropertiesCommand; } // Session-edit command methods. bool qtractorSessionEditCommand::redo (void) { bool bResult = false; if (m_pPropertiesCommand) bResult = m_pPropertiesCommand->redo(); if (bResult && m_pTempoCommand) bResult = m_pTempoCommand->redo(); if (bResult && m_iTicksPerBeat > 0) session()->updateTimeResolution(); return bResult; } bool qtractorSessionEditCommand::undo (void) { bool bResult = false; if (m_pPropertiesCommand) bResult = m_pPropertiesCommand->undo(); if (bResult && m_pTempoCommand) bResult = m_pTempoCommand->undo(); if (bResult && m_iTicksPerBeat > 0) session()->updateTimeResolution(); return bResult; } // end of qtractorSessionCommand.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorRubberBand.cpp0000644000175000001440000000012312166526620021543 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134668.06808 30 ctime=1381134668.068080066 qtractor-0.5.11/src/qtractorRubberBand.cpp0000644000175000001440000000445512166526620021042 0ustar00rncbcusers00000000000000// qtractorRubberBand.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorRubberBand.h" #include //---------------------------------------------------------------------------- // qtractorRubberBand -- Custom rubber-band widget. // Constructor. qtractorRubberBand::qtractorRubberBand ( Shape shape, QWidget *widget, int thick ) : QRubberBand(shape, widget) { m_pStyle = new qtractorRubberBand::Style(thick); setStyle(m_pStyle); } // Destructor. qtractorRubberBand::~qtractorRubberBand (void) { delete m_pStyle; } // Rubberband thickness accessor. void qtractorRubberBand::setThickness ( int thick ) { m_pStyle->thickness = thick; } int qtractorRubberBand::thickness (void) const { return m_pStyle->thickness; } // Custom virtual override. int qtractorRubberBand::Style::styleHint ( StyleHint sh, const QStyleOption *opt, const QWidget *widget, QStyleHintReturn *hint ) const { int ret = QCommonStyle::styleHint(sh, opt, widget, hint); if (sh == QStyle::SH_RubberBand_Mask) { QStyleHintReturnMask *mask = qstyleoption_cast (hint); QRect rect(mask->region.boundingRect()); QRegion regn(rect); rect.setX(rect.x() + thickness); rect.setY(rect.y() + thickness); rect.setWidth(rect.width() - thickness); rect.setHeight(rect.height() - thickness); mask->region = regn.subtracted(QRegion(rect)); } return ret; } // end of qtractorRubberBand.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorVstPlugin.cpp0000644000175000001440000000012312166526620021470 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134666.95008 30 ctime=1381134666.950080048 qtractor-0.5.11/src/qtractorVstPlugin.cpp0000644000175000001440000013045712166526620020771 0ustar00rncbcusers00000000000000// qtractorVstPlugin.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #ifdef CONFIG_VST #include "qtractorVstPlugin.h" #include "qtractorPluginForm.h" #include "qtractorMidiBuffer.h" #include "qtractorSession.h" #include "qtractorOptions.h" #include #include #include #include #if QT_VERSION < 0x040500 namespace Qt { const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000); } #endif #if defined(Q_WS_X11) #include #include #include typedef void (*XEventProc)(XEvent *); #endif #if !defined(VST_2_3_EXTENSIONS) #ifdef CONFIG_VESTIGE typedef int32_t VstInt32; typedef intptr_t VstIntPtr; #else typedef long VstInt32; typedef long VstIntPtr; #endif #define VSTCALLBACK #endif typedef AEffect* (*VST_GetPluginInstance) (audioMasterCallback); static VstIntPtr VSTCALLBACK qtractorVstPlugin_HostCallback (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void *ptr, float opt); // Specific extended flags that saves us // from calling canDo() in audio callbacks. enum qtractorVstPluginFlagsEx { effFlagsExCanSendVstEvents = 1 << 0, effFlagsExCanSendVstMidiEvents = 1 << 1, effFlagsExCanSendVstTimeInfo = 1 << 2, effFlagsExCanReceiveVstEvents = 1 << 3, effFlagsExCanReceiveVstMidiEvents = 1 << 4, effFlagsExCanReceiveVstTimeInfo = 1 << 5, effFlagsExCanProcessOffline = 1 << 6, effFlagsExCanUseAsInsert = 1 << 7, effFlagsExCanUseAsSend = 1 << 8, effFlagsExCanMixDryWet = 1 << 9, effFlagsExCanMidiProgramNames = 1 << 10 }; // Some VeSTige missing opcodes and flags. #ifdef CONFIG_VESTIGE const int effGetParamLabel = 6; const int effGetParamDisplay = 7; const int effGetChunk = 23; const int effSetChunk = 24; const int effFlagsProgramChunks = 32; #endif //--------------------------------------------------------------------- // qtractorVstPlugin::EditorWidget - Helpers for own editor widget. #if defined(Q_WS_X11) static bool g_bXError = false; static int tempXErrorHandler ( Display *, XErrorEvent * ) { g_bXError = true; return 0; } static XEventProc getXEventProc ( Display *pDisplay, Window w ) { int iSize; unsigned long iBytes, iCount; unsigned char *pData; XEventProc eventProc = NULL; Atom aType, aName = XInternAtom(pDisplay, "_XEventProc", false); g_bXError = false; XErrorHandler oldErrorHandler = XSetErrorHandler(tempXErrorHandler); XGetWindowProperty(pDisplay, w, aName, 0, 1, false, AnyPropertyType, &aType, &iSize, &iCount, &iBytes, &pData); if (g_bXError == false && iCount == 1) eventProc = (XEventProc) (pData); XSetErrorHandler(oldErrorHandler); return eventProc; } static Window getXChildWindow ( Display *pDisplay, Window w ) { Window wRoot, wParent, *pwChildren; unsigned int iChildren = 0; XQueryTree(pDisplay, w, &wRoot, &wParent, &pwChildren, &iChildren); return (iChildren > 0 ? pwChildren[0] : 0); } #endif // Q_WS_X11 //---------------------------------------------------------------------------- // qtractorVstPlugin::EditorWidget -- Plugin editor wrapper widget. // // Dynamic singleton list of VST editors. static QList g_vstEditors; class qtractorVstPlugin::EditorWidget : public QWidget { public: // Constructor. EditorWidget(QWidget *pParent, Qt::WindowFlags wflags = 0) : QWidget(pParent, wflags), #if defined(Q_WS_X11) m_pDisplay(QX11Info::display()), m_wVstEditor(0), m_pVstEventProc(NULL), m_bButtonPress(false), #endif m_pVstPlugin(NULL) {} // Destructor. ~EditorWidget() { close(); } // Specialized editor methods. void open(qtractorVstPlugin *pVstPlugin) { m_pVstPlugin = pVstPlugin; // Start the proper (child) editor... long value = 0; void *ptr = (void *) winId(); #if defined(Q_WS_X11) value = (long) m_pDisplay; #endif // Make it the right size struct ERect { short top; short left; short bottom; short right; } *pRect; if (m_pVstPlugin->vst_dispatch(0, effEditGetRect, 0, 0, &pRect, 0.0f)) { int w = pRect->right - pRect->left; int h = pRect->bottom - pRect->top; if (w > 0 && h > 0) QWidget::setFixedSize(w, h); } m_pVstPlugin->vst_dispatch(0, effEditOpen, 0, value, ptr, 0.0f); #if defined(Q_WS_X11) m_wVstEditor = getXChildWindow(m_pDisplay, (Window) winId()); if (m_wVstEditor) m_pVstEventProc = getXEventProc(m_pDisplay, m_wVstEditor); #endif g_vstEditors.append(this); // Final stabilization... m_pVstPlugin->updateEditorTitle(); m_pVstPlugin->setEditorVisible(true); m_pVstPlugin->idleEditor(); } // Close the editor widget. void close() { QWidget::close(); if (m_pVstPlugin) { m_pVstPlugin->vst_dispatch(0, effEditClose, 0, 0, NULL, 0.0f); // m_pVstPlugin->setEditorVisible(false); m_pVstPlugin = NULL; } int iIndex = g_vstEditors.indexOf(this); if (iIndex >= 0) g_vstEditors.removeAt(iIndex); } #if defined(Q_WS_X11) // Local X11 event filter. bool x11EventFilter(XEvent *pEvent) { if (m_pVstEventProc && pEvent->xany.window == m_wVstEditor) { // Avoid mouse tracking events... switch (pEvent->xany.type) { case ButtonPress: m_bButtonPress = true; break; case ButtonRelease: m_bButtonPress = false; break; case MotionNotify: if (!m_bButtonPress) return false; // Fall thru... default: break; } // Process as intended... (*m_pVstEventProc)(pEvent); return true; } else { return false; } } #endif qtractorVstPlugin *plugin() const { return m_pVstPlugin; } protected: // Visibility event handlers. void showEvent(QShowEvent *pShowEvent) { QWidget::showEvent(pShowEvent); if (m_pVstPlugin && m_pVstPlugin->isFormVisible()) (m_pVstPlugin->form())->toggleEditor(true); } void closeEvent(QCloseEvent *pCloseEvent) { if (m_pVstPlugin && m_pVstPlugin->isFormVisible()) (m_pVstPlugin->form())->toggleEditor(false); QWidget::closeEvent(pCloseEvent); } void moveEvent(QMoveEvent *pMoveEvent) { QWidget::moveEvent(pMoveEvent); #if defined(Q_WS_X11) if (m_wVstEditor) { XMoveWindow(m_pDisplay, m_wVstEditor, 0, 0); // QWidget::update(); } #endif } private: // Instance variables... #if defined(Q_WS_X11) Display *m_pDisplay; Window m_wVstEditor; XEventProc m_pVstEventProc; bool m_bButtonPress; #endif qtractorVstPlugin *m_pVstPlugin; }; //---------------------------------------------------------------------------- // qtractorVstPluginType::Effect -- VST AEffect instance. // class qtractorVstPluginType::Effect { public: // Constructor. Effect(AEffect *pVstEffect = NULL) : m_pVstEffect(pVstEffect) {} // Specific methods. bool open(qtractorPluginFile *pFile); void close(); // Specific accessors. AEffect *vst_effect() const { return m_pVstEffect; } // VST host dispatcher. int vst_dispatch( long opcode, long index, long value, void *ptr, float opt) const; private: // VST descriptor itself. AEffect *m_pVstEffect; }; // Specific methods. bool qtractorVstPluginType::Effect::open ( qtractorPluginFile *pFile ) { // Do we have an effect descriptor already? if (m_pVstEffect == NULL) m_pVstEffect = qtractorVstPluginType::vst_effect(pFile); if (m_pVstEffect == NULL) return false; #ifdef CONFIG_DEBUG_0 qDebug("AEffect[%p]::open(%p)", m_pVstEffect, pFile); #endif // vst_dispatch(effIdentify, 0, 0, NULL, 0); vst_dispatch(effOpen, 0, 0, NULL, 0.0f); // vst_dispatch(effMainsChanged, 0, 0, NULL, 0.0f); return true; } void qtractorVstPluginType::Effect::close (void) { if (m_pVstEffect == NULL) return; #ifdef CONFIG_DEBUG_0 qDebug("AEffect[%p]::close()", m_pVstEffect); #endif // vst_dispatch(effMainsChanged, 0, 0, NULL, 0.0f); vst_dispatch(effClose, 0, 0, NULL, 0.0f); m_pVstEffect = NULL; } // VST host dispatcher. int qtractorVstPluginType::Effect::vst_dispatch ( long opcode, long index, long value, void *ptr, float opt ) const { if (m_pVstEffect == NULL) return 0; #ifdef CONFIG_DEBUG_0 qDebug("AEffect[%p]::dispatcher(%ld, %ld, %ld, %p, %g)", m_pVstEffect, opcode, index, value, ptr, opt); #endif return m_pVstEffect->dispatcher(m_pVstEffect, opcode, index, value, ptr, opt); } //---------------------------------------------------------------------------- // qtractorVstPluginType -- VST plugin type instance. // // Derived methods. bool qtractorVstPluginType::open (void) { // Do we have an effect descriptor already? if (m_pEffect == NULL) m_pEffect = new Effect(); if (!m_pEffect->open(file())) return false; AEffect *pVstEffect = m_pEffect->vst_effect(); if (pVstEffect == NULL) return false; #ifdef CONFIG_DEBUG qDebug("qtractorVstPluginType[%p]::open() filename=\"%s\" index=%lu", this, filename().toUtf8().constData(), index()); #endif // Retrieve plugin type names. char szName[256]; ::memset(szName, 0, sizeof(szName)); if (vst_dispatch(effGetEffectName, 0, 0, (void *) szName, 0.0f)) m_sName = szName; else m_sName = QFileInfo(filename()).baseName(); // Sanitize plugin label. m_sLabel = m_sName.simplified().replace(QRegExp("[\\s|\\.|\\-]+"), "_"); // Retrieve plugin unique identifier. #ifdef CONFIG_VESTIGE_OLD m_iUniqueID = qHash(filename()); #else m_iUniqueID = pVstEffect->uniqueID; #endif // Specific inquiries... m_iFlagsEx = 0; // if (vst_canDo("sendVstEvents")) m_iFlagsEx |= effFlagsExCanSendVstEvents; if (vst_canDo("sendVstMidiEvent")) m_iFlagsEx |= effFlagsExCanSendVstMidiEvents; // if (vst_canDo("sendVstTimeInfo")) m_iFlagsEx |= effFlagsExCanSendVstTimeInfo; // if (vst_canDo("receiveVstEvents")) m_iFlagsEx |= effFlagsExCanReceiveVstEvents; if (vst_canDo("receiveVstMidiEvent")) m_iFlagsEx |= effFlagsExCanReceiveVstMidiEvents; // if (vst_canDo("receiveVstTimeInfo")) m_iFlagsEx |= effFlagsExCanReceiveVstTimeInfo; // if (vst_canDo("offline")) m_iFlagsEx |= effFlagsExCanProcessOffline; // if (vst_canDo("plugAsChannelInsert")) m_iFlagsEx |= effFlagsExCanUseAsInsert; // if (vst_canDo("plugAsSend")) m_iFlagsEx |= effFlagsExCanUseAsSend; // if (vst_canDo("mixDryWet")) m_iFlagsEx |= effFlagsExCanMixDryWet; // if (vst_canDo("midiProgramNames")) m_iFlagsEx |= effFlagsExCanMidiProgramNames; // Compute and cache port counts... m_iControlIns = pVstEffect->numParams; m_iControlOuts = 0; m_iAudioIns = pVstEffect->numInputs; m_iAudioOuts = pVstEffect->numOutputs; m_iMidiIns = ((m_iFlagsEx & effFlagsExCanReceiveVstMidiEvents) || (pVstEffect->flags & effFlagsIsSynth) ? 1 : 0); m_iMidiOuts = ((m_iFlagsEx & effFlagsExCanSendVstMidiEvents) ? 1 : 0); // Cache flags. m_bRealtime = true; m_bConfigure = (pVstEffect->flags & effFlagsProgramChunks); m_bEditor = (pVstEffect->flags & effFlagsHasEditor); // HACK: JUCE based VST plugins, which are the most found // with a GUI editor, need to skip explicit shared library // unloading, to avoid mysterious crashes later... if (m_bEditor) file()->setAutoUnload(false); return true; } void qtractorVstPluginType::close (void) { if (m_pEffect == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorVstPluginType[%p]::close()", this); #endif m_pEffect->close(); delete m_pEffect; m_pEffect = NULL; } // Factory method (static) qtractorVstPluginType *qtractorVstPluginType::createType ( qtractorPluginFile *pFile ) { // Sanity check... if (pFile == NULL) return NULL; // Retrieve effect instance if any... AEffect *pVstEffect = vst_effect(pFile); if (pVstEffect == NULL) return NULL; // Yep, most probably its a valid plugin effect... return new qtractorVstPluginType(pFile, new Effect(pVstEffect)); } // Effect instance method (static) AEffect *qtractorVstPluginType::vst_effect ( qtractorPluginFile *pFile ) { VST_GetPluginInstance pfnGetPluginInstance = (VST_GetPluginInstance) pFile->resolve("VSTPluginMain"); if (pfnGetPluginInstance == NULL) pfnGetPluginInstance = (VST_GetPluginInstance) pFile->resolve("main"); if (pfnGetPluginInstance == NULL) return NULL; // Does the VST plugin instantiate OK? AEffect *pVstEffect = (*pfnGetPluginInstance)(qtractorVstPlugin_HostCallback); if (pVstEffect == NULL) return NULL; if (pVstEffect->magic != kEffectMagic) return NULL; return pVstEffect; } // VST host dispatcher. int qtractorVstPluginType::vst_dispatch ( long opcode, long index, long value, void *ptr, float opt ) const { if (m_pEffect == NULL) return 0; return m_pEffect->vst_dispatch(opcode, index, value, ptr, opt); } // VST flag inquirer. bool qtractorVstPluginType::vst_canDo ( const char *pszCanDo ) const { if (m_pEffect == NULL) return false; return (m_pEffect->vst_dispatch(effCanDo, 0, 0, (void *) pszCanDo, 0.0f) > 0); } //---------------------------------------------------------------------------- // qtractorVstPlugin -- VST plugin instance. // // Dynamic singleton list of VST plugins. static QHash g_vstPlugins; // Constructors. qtractorVstPlugin::qtractorVstPlugin ( qtractorPluginList *pList, qtractorVstPluginType *pVstType ) : qtractorPlugin(pList, pVstType), m_ppEffects(NULL), m_ppIBuffer(NULL), m_ppOBuffer(NULL), m_pEditorWidget(NULL) { #ifdef CONFIG_DEBUG qDebug("qtractorVstPlugin[%p] filename=\"%s\" index=%lu typeHint=%d", this, type()->filename().toUtf8().constData(), type()->index(), int(type()->typeHint())); #endif // Allocate I/O audio buffer pointers. unsigned short iAudioIns = pVstType->audioIns(); unsigned short iAudioOuts = pVstType->audioOuts(); if (iAudioIns > 0) m_ppIBuffer = new float * [iAudioIns]; if (iAudioOuts > 0) m_ppOBuffer = new float * [iAudioOuts]; // Create all existing parameters... unsigned short iParamCount = pVstType->controlIns(); for (unsigned short i = 0; i < iParamCount; ++i) addParam(new qtractorVstPluginParam(this, i)); // Instantiate each instance properly... setChannels(channels()); } // Destructor. qtractorVstPlugin::~qtractorVstPlugin (void) { // Cleanup all plugin instances... setChannels(0); // Deallocate I/O audio buffer pointers. if (m_ppIBuffer) delete [] m_ppIBuffer; if (m_ppOBuffer) delete [] m_ppOBuffer; } // Channel/instance number accessors. void qtractorVstPlugin::setChannels ( unsigned short iChannels ) { // Check our type... qtractorVstPluginType *pVstType = static_cast (type()); if (pVstType == NULL) return; // Estimate the (new) number of instances... unsigned short iOldInstances = instances(); unsigned short iInstances = pVstType->instances(iChannels, list()->isMidi()); // Now see if instance count changed anyhow... if (iInstances == iOldInstances) return; // Gotta go for a while... bool bActivated = isActivated(); setActivated(false); // Set new instance number... setInstances(iInstances); // Close old instances, all the way... if (m_ppEffects) { for (unsigned short i = 1; i < iOldInstances; ++i) { g_vstPlugins.remove(m_ppEffects[i]->vst_effect()); m_ppEffects[i]->close(); delete m_ppEffects[i]; } g_vstPlugins.remove(m_ppEffects[0]->vst_effect()); delete [] m_ppEffects; m_ppEffects = NULL; } // Bail out, if none are about to be created... if (iInstances < 1) { setActivated(bActivated); return; } #ifdef CONFIG_DEBUG qDebug("qtractorVstPlugin[%p]::setChannels(%u) instances=%u", this, iChannels, iInstances); #endif // Allocate new instances... m_ppEffects = new qtractorVstPluginType::Effect * [iInstances]; m_ppEffects[0] = pVstType->effect(); g_vstPlugins.insert(m_ppEffects[0]->vst_effect(), this); for (unsigned short i = 1; i < iInstances; ++i) { m_ppEffects[i] = new qtractorVstPluginType::Effect(); m_ppEffects[i]->open(pVstType->file()); g_vstPlugins.insert(m_ppEffects[i]->vst_effect(), this); } // (Re)issue all configuration as needed... realizeConfigs(); realizeValues(); // But won't need it anymore. releaseConfigs(); releaseValues(); // Setup all those instance alright... for (unsigned short i = 0; i < iInstances; ++i) { // And now all other things as well... qtractorVstPluginType::Effect *pEffect = m_ppEffects[i]; pEffect->vst_dispatch(effSetSampleRate, 0, 0, NULL, float(sampleRate())); pEffect->vst_dispatch(effSetBlockSize, 0, bufferSize(), NULL, 0.0f); // pEffect->vst_dispatch(effSetProgram, 0, 0, NULL, 0.0f); #if 0 // !VST_FORCE_DEPRECATED unsigned short j; for (j = 0; j < pVstType->audioIns(); ++j) pEffect->vst_dispatch(effConnectInput, j, 1, NULL, 0.0f); for (j = 0; j < pVstType->audioOuts(); ++j) pEffect->vst_dispatch(effConnectOutput, j, 1, NULL, 0.0f); #endif } // (Re)activate instance if necessary... setActivated(bActivated); } // Do the actual activation. void qtractorVstPlugin::activate (void) { for (unsigned short i = 0; i < instances(); ++i) { vst_dispatch(i, effMainsChanged, 0, 1, NULL, 0.0f); #ifndef CONFIG_VESTIGE vst_dispatch(i, effStartProcess, 0, 0, NULL, 0.0f); #endif } } // Do the actual deactivation. void qtractorVstPlugin::deactivate (void) { for (unsigned short i = 0; i < instances(); ++i) { #ifndef CONFIG_VESTIGE vst_dispatch(i, effStopProcess, 0, 0, NULL, 0.0f); #endif vst_dispatch(i, effMainsChanged, 0, 0, NULL, 0.0f); } } // The main plugin processing procedure. void qtractorVstPlugin::process ( float **ppIBuffer, float **ppOBuffer, unsigned int nframes ) { if (m_ppEffects == NULL) return; // To process MIDI events, if any... qtractorMidiManager *pMidiManager = NULL; const unsigned short iMidiIns = type()->midiIns(); const unsigned short iMidiOuts = type()->midiOuts(); if (iMidiIns > 0) pMidiManager = list()->midiManager(); // We'll cross channels over instances... const unsigned short iInstances = instances(); const unsigned short iChannels = channels(); const unsigned short iAudioIns = audioIns(); const unsigned short iAudioOuts = audioOuts(); unsigned short iIChannel = 0; unsigned short iOChannel = 0; unsigned short i, j; // For each plugin instance... for (i = 0; i < iInstances; ++i) { AEffect *pVstEffect = vst_effect(i); // For each instance audio input port... for (j = 0; j < iAudioIns; ++j) { m_ppIBuffer[j] = ppIBuffer[iIChannel]; if (++iIChannel >= iChannels) iIChannel = 0; } // For each instance audio output port... for (j = 0; j < iAudioOuts; ++j) { m_ppOBuffer[j] = ppOBuffer[iOChannel]; ::memset(m_ppOBuffer[j], 0, nframes * sizeof(float)); if (++iOChannel >= iChannels) iOChannel = 0; } // Make it run MIDI, if applicable... if (pMidiManager) { pVstEffect->dispatcher(pVstEffect, effProcessEvents, 0, 0, pMidiManager->vst_events_in(), 0.0f); } // Make it run audio... if (pVstEffect->flags & effFlagsCanReplacing) { pVstEffect->processReplacing( pVstEffect, m_ppIBuffer, m_ppOBuffer, nframes); } #if 0 // !VST_FORCE_DEPRECATED else { pVstEffect->process( pVstEffect, m_ppIBuffer, m_ppOBuffer, nframes); } #endif // Wrap channels?... if (iIChannel < iChannels - 1) ++iIChannel; if (iOChannel < iChannels - 1) ++iOChannel; } if (pMidiManager && iMidiOuts > 0) pMidiManager->vst_events_swap(); } // Parameter update method. void qtractorVstPlugin::updateParam ( qtractorPluginParam *pParam, float fValue, bool /*bUpdate*/ ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorVstPlugin[%p]::updateParam(%lu, %g, %d)", this, pParam->index(), fValue, int(bUpdate)); #endif // Maybe we're not pretty instantiated yet... for (unsigned short i = 0; i < instances(); ++i) { AEffect *pVstEffect = vst_effect(i); if (pVstEffect) pVstEffect->setParameter(pVstEffect, pParam->index(), fValue); } } // Bank/program selector. void qtractorVstPlugin::selectProgram ( int iBank, int iProg ) { if (iBank < 0 || iProg < 0) return; // HACK: We don't change program-preset when // we're supposed to be multi-timbral... if ((list()->flags() & qtractorPluginList::MidiBus) == qtractorPluginList::MidiBus) return; #ifdef CONFIG_DEBUG qDebug("qtractorVstPlugin[%p]::selectProgram(%d, %d)", this, iBank, iProg); #endif int iIndex = 0; if (iBank >= 0 && iProg >= 0) iIndex = (iBank << 7) + iProg; for (unsigned short i = 0; i < instances(); ++i) vst_dispatch(i, effSetProgram, 0, iIndex, NULL, 0.0f); // Reset parameters default value... AEffect *pVstEffect = vst_effect(0); if (pVstEffect) { const qtractorPlugin::Params& params = qtractorPlugin::params(); qtractorPlugin::Params::ConstIterator param = params.constBegin(); const qtractorPlugin::Params::ConstIterator param_end = params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); float *pfValue = pParam->subject()->data(); *pfValue = pVstEffect->getParameter(pVstEffect, pParam->index()); pParam->setDefaultValue(*pfValue); } } } // Provisional program/patch accessor. bool qtractorVstPlugin::getProgram ( int iIndex, Program& program ) const { // Iteration sanity check... AEffect *pVstEffect = vst_effect(0); if (pVstEffect == NULL) return false; if (iIndex < 0 || iIndex >= pVstEffect->numPrograms) return false; char szName[256]; ::memset(szName, 0, sizeof(szName)); #ifndef CONFIG_VESTIGE if (vst_dispatch(0, effGetProgramNameIndexed, iIndex, 0, (void *) szName, 0.0f) == 0) { #endif int iOldIndex = vst_dispatch(0, effGetProgram, 0, 0, NULL, 0.0f); vst_dispatch(0, effSetProgram, 0, iIndex, NULL, 0.0f); vst_dispatch(0, effGetProgramName, 0, 0, (void *) szName, 0.0f); vst_dispatch(0, effSetProgram, 0, iOldIndex, NULL, 0.0f); #ifndef CONFIG_VESTIGE } #endif // Map this to that... program.bank = 0; program.prog = iIndex; program.name = szName; return true; } // Configuration (CLOB) stuff. void qtractorVstPlugin::configure ( const QString& sKey, const QString& sValue ) { if (sKey == "chunk") { // Load the BLOB (base64 encoded)... QByteArray data = qUncompress(QByteArray::fromBase64(sValue.toLatin1())); const char *pData = data.constData(); int iData = data.size(); #ifdef CONFIG_DEBUG qDebug("qtractorVstPlugin[%p]::configure() chunk.size=%d checksum=0x%04x", this, iData, qChecksum(pData, iData)); #endif for (unsigned short i = 0; i < instances(); ++i) vst_dispatch(i, effSetChunk, 0, iData, (void *) pData, 0.0f); } } // Plugin configuration/state snapshot. void qtractorVstPlugin::freezeConfigs (void) { // HACK: Make sure all parameter values are in sync, // provided freezeConfigs() are always called when // saving plugin's state and before parameter values. updateParamValues(false); if (!type()->isConfigure()) return; AEffect *pVstEffect = vst_effect(0); if (pVstEffect == NULL) return; // Save plugin state into chunk configuration... char *pData = NULL; int iData = vst_dispatch(0, effGetChunk, 0, 0, (void *) &pData, 0.0f); if (iData < 1 || pData == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorVstPlugin[%p]::freezeConfigs() chunk.size=%d checksum=0x%04x", this, iData, qChecksum(pData, iData)); #endif // Set special plugin configuration item (base64 encoded)... QByteArray data = qCompress(QByteArray(pData, iData)).toBase64(); for (int i = data.size() - (data.size() % 72); i >= 0; i -= 72) data.insert(i, "\n "); // Indentation. setConfig("chunk", data.constData()); } void qtractorVstPlugin::releaseConfigs (void) { #ifdef CONFIG_DEBUG qDebug("qtractorVstPlugin[%p]::releaseConfigs()", this); #endif clearConfigs(); } // Specific accessors. AEffect *qtractorVstPlugin::vst_effect ( unsigned short iInstance ) const { if (m_ppEffects == NULL) return NULL; return m_ppEffects[iInstance]->vst_effect(); } // VST host dispatcher. int qtractorVstPlugin::vst_dispatch( unsigned short iInstance, long opcode, long index, long value, void *ptr, float opt) const { if (m_ppEffects == NULL) return 0; return m_ppEffects[iInstance]->vst_dispatch(opcode, index, value, ptr, opt); } // Open editor. void qtractorVstPlugin::openEditor ( QWidget */*pParent*/ ) { // Is it already there? if (m_pEditorWidget) { if (!m_pEditorWidget->isVisible()) m_pEditorWidget->show(); m_pEditorWidget->raise(); m_pEditorWidget->activateWindow(); return; } #ifdef CONFIG_DEBUG qDebug("qtractorVstPlugin[%p]::openEditor()", this); #endif // Create the new parent frame... Qt::WindowFlags wflags = Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint; qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions && pOptions->bKeepToolsOnTop) wflags |= Qt::Tool; m_pEditorWidget = new EditorWidget(NULL, wflags); m_pEditorWidget->open(this); } // Close editor. void qtractorVstPlugin::closeEditor (void) { if (m_pEditorWidget == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorVstPlugin[%p]::closeEditor()", this); #endif // Close the parent widget, if any. delete m_pEditorWidget; m_pEditorWidget = NULL; } // Idle editor. void qtractorVstPlugin::idleEditor (void) { if (m_pEditorWidget == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorVstPlugin[%p]::idleEditor()", this); #endif vst_dispatch(0, effEditIdle, 0, 0, NULL, 0.0f); m_pEditorWidget->update(); } // GUI editor visibility state. void qtractorVstPlugin::setEditorVisible ( bool bVisible ) { if (m_pEditorWidget) m_pEditorWidget->setVisible(bVisible); } bool qtractorVstPlugin::isEditorVisible (void) const { return (m_pEditorWidget ? m_pEditorWidget->isVisible() : false); } // Update editor widget caption. void qtractorVstPlugin::setEditorTitle ( const QString& sTitle ) { qtractorPlugin::setEditorTitle(sTitle); if (m_pEditorWidget) m_pEditorWidget->setWindowTitle(sTitle); } // Idle editor (static). void qtractorVstPlugin::idleEditorAll (void) { QListIterator iter(g_vstEditors); while (iter.hasNext()) { qtractorVstPlugin *pVstPlugin = iter.next()->plugin(); if (pVstPlugin) pVstPlugin->idleEditor(); } } // Our own editor widget accessor. QWidget *qtractorVstPlugin::editorWidget (void) const { return static_cast (m_pEditorWidget); } // Our own editor widget size accessor. void qtractorVstPlugin::resizeEditor ( int w, int h ) { if (m_pEditorWidget && w > 0 && h > 0) m_pEditorWidget->resize(w, h); } // Global VST plugin lookup. qtractorVstPlugin *qtractorVstPlugin::findPlugin ( AEffect *pVstEffect ) { return g_vstPlugins.value(pVstEffect, NULL); } #if defined(Q_WS_X11) // Global X11 event filter. bool qtractorVstPlugin::x11EventFilter ( void *pvEvent ) { XEvent *pEvent = (XEvent *) pvEvent; QListIterator iter(g_vstEditors); while (iter.hasNext()) { if (iter.next()->x11EventFilter(pEvent)) return true; } return false; } #endif // Parameter update method. void qtractorVstPlugin::updateParamValues ( bool bUpdate ) { // Make sure all cached parameter values are in sync // with plugin parameter values; update cache otherwise. AEffect *pVstEffect = vst_effect(0); if (pVstEffect) { const qtractorPlugin::Params& params = qtractorPlugin::params(); qtractorPlugin::Params::ConstIterator param = params.constBegin(); const qtractorPlugin::Params::ConstIterator param_end = params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); float fValue = pVstEffect->getParameter(pVstEffect, pParam->index()); if (pParam->value() != fValue) { pParam->setValue(fValue, bUpdate); if (isFormVisible()) form()->changeParamValue(pParam->index()); } } } } //---------------------------------------------------------------------------- // qtractorVstPluginParam -- VST plugin control input port instance. // // Constructors. qtractorVstPluginParam::qtractorVstPluginParam ( qtractorVstPlugin *pVstPlugin, unsigned long iIndex ) : qtractorPluginParam(pVstPlugin, iIndex) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorVstPluginParam[%p] pVstPlugin=%p iIndex=%lu", this, pVstPlugin, iIndex); #endif qtractorVstPluginType *pVstType = static_cast (pVstPlugin->type()); char szName[64]; szName[0] = (char) 0; if (pVstType) pVstType->vst_dispatch(effGetParamName, iIndex, 0, (void *) szName, 0.0f); if (!szName[0]) ::snprintf(szName, sizeof(szName), "Param #%lu", iIndex + 1); // Default dummy name. setName(szName); setMinValue(0.0f); setMaxValue(1.0f); ::memset(&m_props, 0, sizeof(m_props)); if (pVstType && pVstType->vst_dispatch( effGetParameterProperties, iIndex, 0, (void *) &m_props, 0.0f)) { #ifdef CONFIG_DEBUG_0 qDebug(" VstParamProperties(%lu) {", iIndex); qDebug(" .label = \"%s\"", m_props.label); qDebug(" .shortLabel = \"%s\"", m_props.shortLabel); qDebug(" .category = %d", m_props.category); qDebug(" .categoryLabel = \"%s\"", m_props.categoryLabel); qDebug(" .minInteger = %d", int(m_props.minInteger)); qDebug(" .maxInteger = %d", int(m_props.maxInteger)); qDebug(" .stepInteger = %d", int(m_props.stepInteger)); qDebug(" .stepFloat = %g", m_props.stepFloat); #ifndef CONFIG_VESTIGE_OLD qDebug(" .smallStepFloat = %g", m_props.smallStepFloat); qDebug(" .largeStepFloat = %g", m_props.largeStepFloat); qDebug(" .largeStepInteger = %d", int(m_props.largeStepInteger)); qDebug(" >IsSwitch = %d", (m_props.flags & kVstParameterIsSwitch ? 1 : 0)); qDebug(" >UsesIntegerMinMax = %d", (m_props.flags & kVstParameterUsesIntegerMinMax ? 1 : 0)); qDebug(" >UsesFloatStep = %d", (m_props.flags & kVstParameterUsesFloatStep ? 1 : 0)); qDebug(" >UsesIntStep = %d", (m_props.flags & kVstParameterUsesIntStep ? 1 : 0)); qDebug(" >SupportsDisplayIndex = %d", (m_props.flags & kVstParameterSupportsDisplayIndex ? 1 : 0)); qDebug(" >SupportsDisplayCategory = %d", (m_props.flags & kVstParameterSupportsDisplayCategory ? 1 : 0)); qDebug(" >CanRamp = %d", (m_props.flags & kVstParameterCanRamp ? 1 : 0)); qDebug(" .displayIndex = %d", m_props.displayIndex); qDebug(" .numParametersInCategory = %d", m_props.numParametersInCategory); #endif qDebug("}"); #endif if (isBoundedBelow()) setMinValue(float(m_props.minInteger)); if (isBoundedAbove()) setMaxValue(float(m_props.maxInteger)); } // ATTN: Set default value as initial one... if (pVstType && pVstType->effect()) { AEffect *pVstEffect = (pVstType->effect())->vst_effect(); if (pVstEffect) qtractorPluginParam::setValue( pVstEffect->getParameter(pVstEffect, iIndex), true); } setDefaultValue(qtractorPluginParam::value()); // Initialize port value... // reset(); } // Destructor. qtractorVstPluginParam::~qtractorVstPluginParam (void) { } // Port range hints predicate methods. bool qtractorVstPluginParam::isBoundedBelow (void) const { #ifdef CONFIG_VESTIGE_OLD return false; #else return (m_props.flags & kVstParameterUsesIntegerMinMax); #endif } bool qtractorVstPluginParam::isBoundedAbove (void) const { #ifdef CONFIG_VESTIGE_OLD return false; #else return (m_props.flags & kVstParameterUsesIntegerMinMax); #endif } bool qtractorVstPluginParam::isDefaultValue (void) const { return true; } bool qtractorVstPluginParam::isLogarithmic (void) const { return false; } bool qtractorVstPluginParam::isSampleRate (void) const { return false; } bool qtractorVstPluginParam::isInteger (void) const { #ifdef CONFIG_VESTIGE_OLD return false; #else return (m_props.flags & kVstParameterUsesIntStep); #endif } bool qtractorVstPluginParam::isToggled (void) const { #ifdef CONFIG_VESTIGE_OLD return false; #else return (m_props.flags & kVstParameterIsSwitch); #endif } bool qtractorVstPluginParam::isDisplay (void) const { #ifdef CONFIG_VESTIGE_OLD return false; #else return true; #endif } // Current display value. QString qtractorVstPluginParam::display (void) const { qtractorVstPluginType *pVstType = NULL; if (plugin()) pVstType = static_cast (plugin()->type()); if (pVstType) { QString sDisplay; char szText[64]; // Grab parameter display value... szText[0] = '\0'; pVstType->vst_dispatch(effGetParamDisplay, index(), 0, (void *) szText, 0.0f); if (szText[0]) { // Got sDisplay += QString(szText).trimmed(); // Grab parameter name... szText[0] = '\0'; pVstType->vst_dispatch(effGetParamLabel, index(), 0, (void *) szText, 0.0f); if (szText[0]) sDisplay += ' ' + QString(szText).trimmed(); // Got it. return sDisplay; } } // Default parameter display value... return qtractorPluginParam::display(); } //---------------------------------------------------------------------- // VST host callback file selection helpers. #ifndef CONFIG_VESTIGE static VstIntPtr qtractorVstPlugin_openFileSelector ( AEffect *effect, VstFileSelect *pvfs ) { qtractorVstPlugin *pVstPlugin = qtractorVstPlugin::findPlugin(effect); if (pVstPlugin == NULL) return 0; #ifdef CONFIG_DEBUG qDebug("qtractorVstPlugin_openFileSelector(%p, %p) command=%d reserved=%d", effect, pvfs, int(pvfs->command), int(pvfs->reserved)); #endif pvfs->reserved = 0; pvfs->nbReturnPath = 0; if (pvfs->command == kVstFileLoad || pvfs->command == kVstFileSave) { QString sFilename; QStringList filters; for (int i = 0; i < pvfs->nbFileTypes; ++i) { filters.append(QObject::tr("%1 (*.%2)") .arg(pvfs->fileTypes[i].name).arg(pvfs->fileTypes[i].dosType)); } filters.append(QObject::tr("All files (*.*)")); QString sFilter = filters.join(";;"); QString sDirectory = pvfs->initialPath; QString sTitle = QString("%1 - %2") .arg(pvfs->title).arg((pVstPlugin->type())->name()); if (pvfs->command == kVstFileLoad) { sFilename = QFileDialog::getOpenFileName( pVstPlugin->editorWidget(), sTitle, sDirectory, sFilter); } else { sFilename = QFileDialog::getSaveFileName( pVstPlugin->editorWidget(), sTitle, sDirectory, sFilter); } if (!sFilename.isEmpty()) { if (pvfs->returnPath == NULL) { pvfs->returnPath = new char [sFilename.length() + 1]; pvfs->reserved = 1; } ::strcpy(pvfs->returnPath, sFilename.toUtf8().constData()); pvfs->nbReturnPath = 1; } } else if (pvfs->command == kVstDirectorySelect) { QString sDirectory = pvfs->initialPath; QString sTitle = QString("%1 - %2") .arg(pvfs->title).arg((pVstPlugin->type())->name()); sDirectory = QFileDialog::getExistingDirectory( pVstPlugin->editorWidget(), sTitle, sDirectory); if (!sDirectory.isEmpty()) { if (pvfs->returnPath == NULL) { pvfs->returnPath = new char [sDirectory.length() + 1]; pvfs->reserved = 1; } ::strcpy(pvfs->returnPath, sDirectory.toUtf8().constData()); pvfs->nbReturnPath = 1; } } return pvfs->nbReturnPath; } static VstIntPtr qtractorVstPlugin_closeFileSelector ( AEffect *effect, VstFileSelect *pvfs ) { qtractorVstPlugin *pVstPlugin = qtractorVstPlugin::findPlugin(effect); if (pVstPlugin == NULL) return 0; #ifdef CONFIG_DEBUG qDebug("qtractorVstPlugin_closeFileSelector(%p, %p) command=%d reserved=%d", effect, pvfs, int(pvfs->command), int(pvfs->reserved)); #endif if (pvfs->reserved == 1 && pvfs->returnPath) { delete [] pvfs->returnPath; pvfs->returnPath = NULL; pvfs->reserved = 0; } return 1; } #endif // !CONFIG_VESTIGE //---------------------------------------------------------------------- // The magnificient host callback, which every VSTi plugin will call. #ifdef CONFIG_DEBUG #define VST_HC_FMT "qtractorVstPlugin_HostCallback(%p, %s(%d), %d, %d, %p, %g)" #define VST_HC_DEBUG(s) qDebug(VST_HC_FMT, \ effect, (s), int(opcode), int(index), int(value), ptr, opt) #define VST_HC_DEBUGX(s) qDebug(VST_HC_FMT " [%s]", \ effect, (s), int(opcode), int(index), int(value), ptr, opt, (char *) ptr) #else #define VST_HC_DEBUG(s) #define VST_HC_DEBUGX(s) #endif static VstIntPtr VSTCALLBACK qtractorVstPlugin_HostCallback ( AEffect *effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void *ptr, float opt ) { VstIntPtr ret = 0; qtractorVstPlugin *pVstPlugin = NULL; static VstTimeInfo s_vstTimeInfo; qtractorSession *pSession = qtractorSession::getInstance(); switch (opcode) { // VST 1.0 opcodes... case audioMasterVersion: VST_HC_DEBUG("audioMasterVersion"); ret = 2; // vst2.x break; case audioMasterAutomate: VST_HC_DEBUG("audioMasterAutomate"); // effect->setParameter(effect, index, opt); pVstPlugin = qtractorVstPlugin::findPlugin(effect); if (pVstPlugin) { pVstPlugin->updateParamValue(index, opt, false); // QApplication::processEvents(); } break; case audioMasterCurrentId: VST_HC_DEBUG("audioMasterCurrentId"); break; case audioMasterIdle: VST_HC_DEBUG("audioMasterIdle"); pVstPlugin = qtractorVstPlugin::findPlugin(effect); if (pVstPlugin) { pVstPlugin->updateParamValues(false); pVstPlugin->idleEditor(); // QApplication::processEvents(); } break; case audioMasterGetTime: // VST_HC_DEBUG("audioMasterGetTime"); if (pSession) { ::memset(&s_vstTimeInfo, 0, sizeof(s_vstTimeInfo)); unsigned long iPlayHead = pSession->playHead(); qtractorTimeScale::Cursor& cursor = pSession->timeScale()->cursor(); qtractorTimeScale::Node *pNode = cursor.seekFrame(iPlayHead); s_vstTimeInfo.samplePos = double(iPlayHead); s_vstTimeInfo.sampleRate = double(pSession->sampleRate()); s_vstTimeInfo.flags = 0; if (pSession->isPlaying()) s_vstTimeInfo.flags |= (kVstTransportChanged | kVstTransportPlaying); if (pNode) { unsigned short bars = 0; unsigned int beats = 0; unsigned long ticks = pNode->tickFromFrame(iPlayHead) - pNode->tick; if (ticks >= (unsigned long) pNode->ticksPerBeat) { beats += (unsigned int) (ticks / pNode->ticksPerBeat); ticks -= (unsigned long) (beats * pNode->ticksPerBeat); } if (beats >= (unsigned int) pNode->beatsPerBar) { bars += (unsigned short) (beats / pNode->beatsPerBar); // beats -= (unsigned int) (bars * pNode->beatsPerBar); } s_vstTimeInfo.ppqPos = double(pNode->beat + beats) + (double(ticks) / double(pNode->ticksPerBeat)); s_vstTimeInfo.flags |= kVstPpqPosValid; s_vstTimeInfo.tempo = double(pNode->tempo); s_vstTimeInfo.flags |= kVstTempoValid; s_vstTimeInfo.barStartPos = double(pNode->beat) + double(bars * pNode->beatsPerBar); s_vstTimeInfo.flags |= kVstBarsValid; if (pSession->isLooping()) { s_vstTimeInfo.cycleStartPos = double(pNode->beatFromFrame(pSession->loopStart())); s_vstTimeInfo.cycleEndPos = double(pNode->beatFromFrame(pSession->loopEnd())); s_vstTimeInfo.flags |= kVstCyclePosValid; } s_vstTimeInfo.timeSigNumerator = pNode->beatsPerBar; s_vstTimeInfo.timeSigDenominator = (1 << pNode->beatDivisor); s_vstTimeInfo.flags |= kVstTimeSigValid; } ret = (VstIntPtr) &s_vstTimeInfo; } break; case audioMasterProcessEvents: VST_HC_DEBUG("audioMasterProcessEvents"); pVstPlugin = qtractorVstPlugin::findPlugin(effect); if (pVstPlugin) { qtractorMidiManager *pMidiManager = NULL; qtractorPluginList *pPluginList = pVstPlugin->list(); if (pPluginList) pMidiManager = pPluginList->midiManager(); if (pMidiManager) { pMidiManager->vst_events_copy((VstEvents *) ptr); ret = 1; // supported and processed. } } break; case audioMasterIOChanged: VST_HC_DEBUG("audioMasterIOChanged"); break; case audioMasterSizeWindow: VST_HC_DEBUG("audioMasterSizeWindow"); pVstPlugin = qtractorVstPlugin::findPlugin(effect); if (pVstPlugin) { pVstPlugin->resizeEditor(int(index), int(value)); ret = 1; // supported. } break; case audioMasterGetSampleRate: VST_HC_DEBUG("audioMasterGetSampleRate"); pVstPlugin = qtractorVstPlugin::findPlugin(effect); if (pVstPlugin) ret = (VstIntPtr) pVstPlugin->sampleRate(); break; case audioMasterGetBlockSize: VST_HC_DEBUG("audioMasterGetBlockSize"); pVstPlugin = qtractorVstPlugin::findPlugin(effect); if (pVstPlugin) ret = (VstIntPtr) pVstPlugin->bufferSize(); break; case audioMasterGetInputLatency: VST_HC_DEBUG("audioMasterGetInputLatency"); break; case audioMasterGetOutputLatency: VST_HC_DEBUG("audioMasterGetOutputLatency"); break; case audioMasterGetCurrentProcessLevel: VST_HC_DEBUG("audioMasterGetCurrentProcessLevel"); break; case audioMasterGetAutomationState: VST_HC_DEBUG("audioMasterGetAutomationState"); ret = 1; // off. break; #if !defined(VST_2_3_EXTENSIONS) case audioMasterGetSpeakerArrangement: VST_HC_DEBUG("audioMasterGetSpeakerArrangement"); break; #endif case audioMasterGetVendorString: VST_HC_DEBUG("audioMasterGetVendorString"); ::strcpy((char *) ptr, QTRACTOR_DOMAIN); ret = 1; // ok. break; case audioMasterGetProductString: VST_HC_DEBUG("audioMasterGetProductString"); ::strcpy((char *) ptr, QTRACTOR_TITLE); ret = 1; // ok. break; case audioMasterGetVendorVersion: VST_HC_DEBUG("audioMasterGetVendorVersion"); break; case audioMasterVendorSpecific: VST_HC_DEBUG("audioMasterVendorSpecific"); break; case audioMasterCanDo: VST_HC_DEBUGX("audioMasterCanDo"); if (::strcmp("receiveVstMidiEvent", (char *) ptr) == 0 || ::strcmp("sendVstMidiEvent", (char *) ptr) == 0 || ::strcmp("sendVstTimeInfo", (char *) ptr) == 0 || ::strcmp("midiProgramNames", (char *) ptr) == 0 || ::strcmp("sizeWindow", (char *) ptr) == 0) { ret = 1; // can do. } #ifndef CONFIG_VESTIGE else if (::strcmp("openFileSelector", (char *) ptr) == 0 || ::strcmp("closeFileSelector", (char *) ptr) == 0) { ret = 1; // can do. } #endif break; case audioMasterGetLanguage: VST_HC_DEBUG("audioMasterGetLanguage"); ret = (VstIntPtr) kVstLangEnglish; break; #if 0 // !VST_FORCE_DEPRECATED case audioMasterPinConnected: VST_HC_DEBUG("audioMasterPinConnected"); break; // VST 2.0 opcodes... case audioMasterWantMidi: VST_HC_DEBUG("audioMasterWantMidi"); break; case audioMasterSetTime: VST_HC_DEBUG("audioMasterSetTime"); break; case audioMasterTempoAt: VST_HC_DEBUG("audioMasterTempoAt"); if (pSession) ret = (VstIntPtr) (pSession->tempo() * 10000.0f); break; case audioMasterGetNumAutomatableParameters: VST_HC_DEBUG("audioMasterGetNumAutomatableParameters"); break; case audioMasterGetParameterQuantization: VST_HC_DEBUG("audioMasterGetParameterQuantization"); ret = 1; // full single float precision break; case audioMasterNeedIdle: VST_HC_DEBUG("audioMasterNeedIdle"); break; case audioMasterGetPreviousPlug: VST_HC_DEBUG("audioMasterGetPreviousPlug"); break; case audioMasterGetNextPlug: VST_HC_DEBUG("audioMasterGetNextPlug"); break; case audioMasterWillReplaceOrAccumulate: VST_HC_DEBUG("audioMasterWillReplaceOrAccumulate"); ret = 1; break; case audioMasterSetOutputSampleRate: VST_HC_DEBUG("audioMasterSetOutputSampleRate"); break; case audioMasterSetIcon: VST_HC_DEBUG("audioMasterSetIcon"); break; case audioMasterOpenWindow: VST_HC_DEBUG("audioMasterOpenWindow"); break; case audioMasterCloseWindow: VST_HC_DEBUG("audioMasterCloseWindow"); break; #endif case audioMasterGetDirectory: VST_HC_DEBUG("audioMasterGetDirectory"); break; case audioMasterUpdateDisplay: VST_HC_DEBUG("audioMasterUpdateDisplay"); pVstPlugin = qtractorVstPlugin::findPlugin(effect); if (pVstPlugin) { pVstPlugin->updateParamValues(false); // QApplication::processEvents(); ret = 1; // supported. } break; case audioMasterBeginEdit: VST_HC_DEBUG("audioMasterBeginEdit"); break; case audioMasterEndEdit: VST_HC_DEBUG("audioMasterEndEdit"); break; #ifndef CONFIG_VESTIGE case audioMasterOpenFileSelector: VST_HC_DEBUG("audioMasterOpenFileSelector"); ret = qtractorVstPlugin_openFileSelector(effect, (VstFileSelect *) ptr); break; case audioMasterCloseFileSelector: VST_HC_DEBUG("audioMasterCloseFileSelector"); ret = qtractorVstPlugin_closeFileSelector(effect, (VstFileSelect *) ptr); break; #endif default: VST_HC_DEBUG("audioMasterUnknown"); break; } return ret; } #endif // CONFIG_VST // end of qtractorVstPlugin.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioSndFile.cpp0000644000175000001440000000012311563576072022051 xustar000000000000000027 mtime=1305410618.253123 26 atime=1381134671.09308 30 ctime=1381134671.093080114 qtractor-0.5.11/src/qtractorAudioSndFile.cpp0000644000175000001440000001236411563576072021346 0ustar00rncbcusers00000000000000// qtractorAudioSndFile.cpp // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorAudioSndFile.h" //---------------------------------------------------------------------- // class qtractorAudioSndFile -- Buffered audio file implementation. // // Constructor. qtractorAudioSndFile::qtractorAudioSndFile ( unsigned short iChannels, unsigned int iSampleRate, unsigned int iBufferSize ) { // Need a minimum of specification, at least for write mode. ::memset(&m_sfinfo, 0, sizeof(m_sfinfo)); m_sfinfo.channels = iChannels; m_sfinfo.samplerate = iSampleRate; // Initialize other stuff. m_pSndFile = NULL; m_iMode = qtractorAudioSndFile::None; m_pBuffer = NULL; m_iBufferSize = 1024; // Adjust size the next nearest power-of-two. while (m_iBufferSize < iBufferSize) m_iBufferSize <<= 1; } // Destructor. qtractorAudioSndFile::~qtractorAudioSndFile (void) { close(); } // Open method. bool qtractorAudioSndFile::open ( const QString& sFilename, int iMode ) { #ifdef DEBUG_0 qDebug("qtractorAudioSndFile::open(\"%s\", %d)", sFilename.toUtf8().constData(), iMode); #endif close(); // Whether for Read or Write... int sfmode; switch (iMode) { case qtractorAudioSndFile::Read: sfmode = SFM_READ; break; case qtractorAudioSndFile::Write: sfmode = SFM_WRITE; break; default: return false; } // As said, need a minimum of specification for write mode. if (sfmode & SFM_WRITE) { if (m_sfinfo.channels == 0 || m_sfinfo.samplerate == 0) return false; m_sfinfo.format = qtractorAudioFileFactory::defaultFormat(); } // Now open it. QByteArray aFilename = sFilename.toUtf8(); m_pSndFile = ::sf_open(aFilename.constData(), sfmode, &m_sfinfo); if (m_pSndFile == NULL) return false; // Set open mode (deterministically). m_iMode = iMode; // Allocate initial de/interleaving buffer stuff. m_pBuffer = new float [m_sfinfo.channels * m_iBufferSize]; return true; } // Read method. int qtractorAudioSndFile::read ( float **ppFrames, unsigned int iFrames ) { #ifdef DEBUG_0 qDebug("qtractorAudioSndFile::read(%p, %d)", ppFrames, iFrames); #endif allocBufferCheck(iFrames); int nread = ::sf_readf_float(m_pSndFile, m_pBuffer, iFrames); if (nread > 0) { unsigned short i; unsigned int n, k = 0; for (n = 0; n < (unsigned int) nread; ++n) { for (i = 0; i < (unsigned short) m_sfinfo.channels; ++i) ppFrames[i][n] = m_pBuffer[k++]; } } return nread; } // Write method. int qtractorAudioSndFile::write ( float **ppFrames, unsigned int iFrames ) { #ifdef DEBUG_0 qDebug("qtractorAudioSndFile::write(%p, %d)", ppFrames, iFrames); #endif allocBufferCheck(iFrames); unsigned short i; unsigned int n, k = 0; for (n = 0; n < iFrames; ++n) { for (i = 0; i < (unsigned short) m_sfinfo.channels; ++i) m_pBuffer[k++] = ppFrames[i][n]; } return ::sf_writef_float(m_pSndFile, m_pBuffer, iFrames); } // Seek method. bool qtractorAudioSndFile::seek ( unsigned long iOffset ) { #ifdef DEBUG_0 qDebug("qtractorAudioSndFile::seek(%d)", iOffset); #endif return (::sf_seek(m_pSndFile, iOffset, SEEK_SET) == long(iOffset)); } // Close method. void qtractorAudioSndFile::close (void) { #ifdef DEBUG_0 qDebug("qtractorAudioSndFile::close()"); #endif if (m_pSndFile) { ::sf_close(m_pSndFile); m_pSndFile = NULL; m_iMode = qtractorAudioSndFile::None; } if (m_pBuffer) { delete [] m_pBuffer; m_pBuffer = NULL; } } // Open mode accessor. int qtractorAudioSndFile::mode (void) const { return m_iMode; } // Open channel(s) accessor. unsigned short qtractorAudioSndFile::channels (void) const { return m_sfinfo.channels; } // Total number of frames specialty. unsigned long qtractorAudioSndFile::frames (void) const { return m_sfinfo.frames; } // Sample rate specialty. unsigned int qtractorAudioSndFile::sampleRate (void) const { return m_sfinfo.samplerate; } // De/interleaving buffer stuff. void qtractorAudioSndFile::allocBufferCheck ( unsigned int iBufferSize ) { // Only reallocate a new buffer if new size is greater... if (iBufferSize > m_iBufferSize && m_sfinfo.channels > 0) { // Destroy previously existing buffer. if (m_pBuffer) delete [] m_pBuffer; // Allocate new extended one; again, // adjust size the next nearest power-of-two. while (m_iBufferSize < iBufferSize) m_iBufferSize <<= 1; m_pBuffer = new float [m_sfinfo.channels * m_iBufferSize]; } } // end of qtractorAudioSndFile.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorConnect.h0000644000175000001440000000012312166526620020573 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134666.49508 30 ctime=1381134666.495080041 qtractor-0.5.11/src/qtractorConnect.h0000644000175000001440000002516312166526620020071 0ustar00rncbcusers00000000000000// qtractorConnect.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorConnect_h #define __qtractorConnect_h #include #include #include // Forward declarations. class qtractorPortListItem; class qtractorClientListItem; class qtractorClientListView; class qtractorConnectorView; class qtractorConnect; class QPainter; class QTimer; class QPaintEvent; class QResizeEvent; class QMouseEvent; class QDragMoveEvent; class QDragEnterEvent; class QDragLeaveEvent; class QDropEvent; class QContextMenuEvent; //---------------------------------------------------------------------- // qtractorPortListItem -- Port list item. // class qtractorPortListItem : public QTreeWidgetItem { public: // Constructor. qtractorPortListItem(qtractorClientListItem *pClientItem, const QString& sPortName); // Default destructor. ~qtractorPortListItem(); // Instance accessors. void setPortName(const QString& sPortName); const QString& clientName() const; const QString& portName() const; // Complete client:port name helper. QString clientPortName(); // Connections client item accessor. qtractorClientListItem *clientItem() const; // Client port cleanup marker. void markPort(int iMark); void markClientPort(int iMark); int portMark(); // Connected port list primitives. void addConnect(qtractorPortListItem *pPortItem); void removeConnect(qtractorPortListItem *pPortItem); void cleanConnects(); // Connected port finders. qtractorPortListItem *findConnect(qtractorPortListItem *pPortItem); // Connection list accessor. const QList& connects() const; // To virtually distinguish between list view items. int rtti() const; // Connectiopn highlight methods. void setHilite (bool bHilite); bool isHilite() const; // Proxy sort override method. // - Natural decimal sorting comparator. bool operator< (const QTreeWidgetItem& other) const; private: // Instance variables. qtractorClientListItem *m_pClientItem; QString m_sPortName; int m_iPortMark; bool m_bHilite; // Connection cache list. QList m_connects; }; //---------------------------------------------------------------------------- // qtractorClientListItem -- Client list item. // class qtractorClientListItem : public QTreeWidgetItem { public: // Constructor. qtractorClientListItem(qtractorClientListView *pClientListView, const QString& sClientName); // Default destructor. ~qtractorClientListItem(); // Port finder. qtractorPortListItem *findPortItem(const QString& sPortName); // Instance accessors. void setClientName(const QString& sClientName); const QString& clientName() const; // Readable flag accessor. bool isReadable(); // Client port cleanup marker. void markClient(int iMark); void markClientPorts(int iMark); void cleanClientPorts(int iMark); int clientMark() const; // Connection highlight methods. void setHilite (bool bHilite); bool isHilite() const; // Client item openness status. void setOpen(bool bOpen); bool isOpen() const; // Proxy sort override method. // - Natural decimal sorting comparator. bool operator< (const QTreeWidgetItem& other) const; private: // Instance variables. QString m_sClientName; int m_iClientMark; int m_iHilite; }; //---------------------------------------------------------------------------- // qtractorClientListView -- Client list view, supporting drag-n-drop. // class qtractorClientListView : public QTreeWidget { Q_OBJECT public: // Constructor. qtractorClientListView(QWidget *pParent = NULL); // Default destructor. virtual ~qtractorClientListView(); // Client finder. qtractorClientListItem *findClientItem(const QString& sClientName); // Client:port finder. qtractorPortListItem *findClientPortItem(const QString& sClientPort); // Main controller accessors. void setBinding(qtractorConnect *pConnect); qtractorConnect *binding() const; // Readable flag accessors. void setReadable(bool bReadable); bool isReadable() const; // Client name filter helpers. void setClientName(const QString& sClientName); QString clientName() const; // Port name filter helpers. void setPortName(const QString& sPortName); QString portName() const; // Maintained current client name list. const QStringList& clientNames() const; // Override clear method. void clear(); // Whether items are all open (expanded) or closed (collapsed). void setOpenAll(bool bOpen); // Client ports cleanup marker. void markClientPorts(int iMark); void cleanClientPorts(int iMark); // Client:port refreshner (return newest item count). virtual int updateClientPorts() = 0; // Client:port hilite update stabilization. void hiliteClientPorts(); // Redirect this one as public. QTreeWidgetItem *itemFromIndex(const QModelIndex& index) const { return QTreeWidget::itemFromIndex(index); } // Auto-open timer methods. void setAutoOpenTimeout(int iAutoOpenTimeout); int autoOpenTimeout(); // Do proper contents refresh/update. void refresh(); // Natural decimal sorting comparator. static bool lessThan(const QTreeWidgetItem& i1, const QTreeWidgetItem& i2); protected slots: // Auto-open timeout slot. void timeoutSlot(); protected: // Client:port filter function via regular expression. bool isClientName(const QString& sClientName); bool isPortName(const QString& sPortName); // Trap for help/tool-tip events. bool eventFilter(QObject *pObject, QEvent *pEvent); // Drag-n-drop stuff. QTreeWidgetItem *dragDropItem(const QPoint& pos); // Drag-n-drop stuff -- reimplemented virtual methods. void dragEnterEvent(QDragEnterEvent *pDragEnterEvent); void dragMoveEvent(QDragMoveEvent *pDragMoveEvent); void dragLeaveEvent(QDragLeaveEvent *); void dropEvent(QDropEvent *pDropEvent); // Handle mouse events for drag-and-drop stuff. void mousePressEvent(QMouseEvent *pMouseEvent); void mouseMoveEvent(QMouseEvent *pMouseEvent); // Context menu request event handler. void contextMenuEvent(QContextMenuEvent *); private: // Local instance variables. qtractorConnect *m_pConnect; bool m_bReadable; // Auto-open timer. int m_iAutoOpenTimeout; QTimer *m_pAutoOpenTimer; // Item we'll eventually drag-and-dropping something. QTreeWidgetItem *m_pDragItem; QTreeWidgetItem *m_pDropItem; // The point from where drag started. QPoint m_posDrag; // The current highlighted item. QTreeWidgetItem *m_pHiliteItem; // Client:port regular expression filters. QRegExp m_rxClientName; QRegExp m_rxPortName; // Maintained list of client names. QStringList m_clientNames; }; //---------------------------------------------------------------------- // qtractorConnectorView -- Connector view widget. // class qtractorConnectorView : public QWidget { Q_OBJECT public: // Constructor. qtractorConnectorView(QWidget *pParent = NULL); // Default destructor. ~qtractorConnectorView(); // Main controller accessors. void setBinding(qtractorConnect *pConnect); qtractorConnect *binding() const; public slots: // Useful slots (should this be protected?). void contentsChanged(); protected: // Specific event handlers. void paintEvent(QPaintEvent *); // Context menu request event handler. void contextMenuEvent(QContextMenuEvent *); private: // Legal client/port item position helper. int itemY(QTreeWidgetItem *pListItem) const; // Drawing methods. void drawConnectionLine(QPainter *pPainter, int x1, int y1, int x2, int y2, int h1, int h2); // Local instance variables. qtractorConnect *m_pConnect; }; //---------------------------------------------------------------------------- // qtractorConnect -- Connections controller. // class qtractorConnect : public QObject { Q_OBJECT public: // Constructor. qtractorConnect( qtractorClientListView *pOListView, qtractorClientListView *pIListView, qtractorConnectorView *pConnectorView); // Default destructor. virtual ~qtractorConnect(); // QTreeWidgetItem types. enum { ClientItem = 1001, PortItem = 1002 }; // Widget accesors. qtractorClientListView *OListView() { return m_pOListView; } qtractorClientListView *IListView() { return m_pIListView; } qtractorConnectorView *ConnectorView() { return m_pConnectorView; } // Connector line style accessors. void setBezierLines(bool bBezierLines); bool isBezierLines(); // Explicit connection tests. bool canConnectSelected(); bool canDisconnectSelected(); bool canDisconnectAll(); public slots: // Explicit connection slots. bool connectSelected(); bool disconnectSelected(); bool disconnectAll(); // Complete/incremental contents rebuilder; // check dirty status if incremental. void updateContents(bool bClear); // Incremental contents refreshner; check dirty status. void refresh(); // Context menu helper. void contextMenu(const QPoint& gpos); signals: // Contents change signal. void contentsChanged(); // Connection change signal. void connectChanged(); protected: // Connect/Disconnection primitives. virtual bool connectPorts(qtractorPortListItem *pOPort, qtractorPortListItem *pIPort) = 0; virtual bool disconnectPorts(qtractorPortListItem *pOPort, qtractorPortListItem *pIPort) = 0; // Update port connection references. virtual void updateConnections() = 0; private: // Connect/Disconnection local primitives. bool connectPortsEx(qtractorPortListItem *pOPort, qtractorPortListItem *pIPort); bool disconnectPortsEx(qtractorPortListItem *pOPort, qtractorPortListItem *pIPort); // Connection methods (unguarded). bool connectSelectedEx(); bool disconnectSelectedEx(); bool disconnectAllEx(); // Controlled widgets. qtractorClientListView *m_pOListView; qtractorClientListView *m_pIListView; qtractorConnectorView *m_pConnectorView; // How we'll draw connector lines. bool m_bBezierLines; }; #endif // __qtractorConnect_h // end of qtractorConnect.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMmcEvent.h0000644000175000001440000000012212146231030020701 xustar000000000000000027 mtime=1368994328.053655 26 atime=1381134667.69908 29 ctime=1381134667.69908006 qtractor-0.5.11/src/qtractorMmcEvent.h0000644000175000001440000000741512146231030020200 0ustar00rncbcusers00000000000000// qtractorMmcEvent.h // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMmcEvent_h #define __qtractorMmcEvent_h #include //---------------------------------------------------------------------- // qtractorMmcEvent - MMC custom event. // class qtractorMmcEvent { public: // MMC command codes. enum Command { STOP = 0x01, PLAY = 0x02, DEFERRED_PLAY = 0x03, FAST_FORWARD = 0x04, REWIND = 0x05, RECORD_STROBE = 0x06, RECORD_EXIT = 0x07, RECORD_PAUSE = 0x08, PAUSE = 0x09, EJECT = 0x0a, CHASE = 0x0b, COMMAND_ERROR_RESET = 0x0c, MMC_RESET = 0x0d, JOG_START = 0x20, JOG_STOP = 0x21, WRITE = 0x40, MASKED_WRITE = 0x41, READ = 0x42, UPDATE = 0x43, LOCATE = 0x44, VARIABLE_PLAY = 0x45, SEARCH = 0x46, SHUTTLE = 0x47, STEP = 0x48, ASSIGN_SYSTEM_MASTER = 0x49, GENERATOR_COMMAND = 0x4a, MTC_COMMAND = 0x4b, MOVE = 0x4c, ADD = 0x4d, SUBTRACT = 0x4e, DROP_FRAME_ADJUST = 0x4f, PROCEDURE = 0x50, EVENT = 0x51, GROUP = 0x52, COMMAND_SEGMENT = 0x53, DEFERRED_VARIABLE_PLAY = 0x54, RECORD_STROBE_VARIABLE = 0x55, WAIT = 0x7c, RESUME = 0x7f }; // MMC sub-command codes (as for MASKED_WRITE). enum SubCommand { TRACK_NONE = 0x00, TRACK_RECORD = 0x4f, TRACK_MUTE = 0x62, TRACK_SOLO = 0x66 // Custom-implementation ;) }; // Default contructor (fake). qtractorMmcEvent() : m_cmd(Command(0)) {} // Contructor. qtractorMmcEvent(unsigned char *pSysex) : m_cmd(Command(pSysex[4])), m_data((const char *) &pSysex[6], (int) pSysex[5]) {} // Copy contructor. qtractorMmcEvent(const qtractorMmcEvent& mmce) : m_cmd(mmce.m_cmd), m_data(mmce.m_data) {} // Accessors. Command cmd() const { return m_cmd; } unsigned char *data() const { return (unsigned char *) m_data.constData(); } unsigned short len() const { return (unsigned short) m_data.length(); } // Retrieve MMC time-code and standard frame position (SMPTE?). unsigned long locate() const; // Retrieve MMC shuttle-speed and direction. float shuttle() const; // Retrieve MMC step and direction. int step() const; // Retrieve MMC masked-write sub-command data. SubCommand scmd() const; int track() const; bool isOn() const; private: // Instance variables. Command m_cmd; QByteArray m_data; }; #endif // __qtractorMmcEvent_h // end of qtractorMmcEvent.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorPasteRepeatForm.h0000644000175000001440000000012312164325352022240 xustar000000000000000027 mtime=1372695274.495194 26 atime=1381134670.70408 30 ctime=1381134670.704080108 qtractor-0.5.11/src/qtractorPasteRepeatForm.h0000644000175000001440000000400412164325352021525 0ustar00rncbcusers00000000000000// qtractorPasteRepeatForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorPasteRepeatForm_h #define __qtractorPasteRepeatForm_h #include "ui_qtractorPasteRepeatForm.h" // Forward declarations. class qtractorTimeScale; //---------------------------------------------------------------------------- // qtractorPasteRepeatForm -- UI wrapper form. class qtractorPasteRepeatForm : public QDialog { Q_OBJECT public: // Constructor. qtractorPasteRepeatForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorPasteRepeatForm(); // Accepted dialog accessors. void setRepeatCount(unsigned short iRepeatCount); unsigned short repeatCount() const; void setRepeatPeriod(unsigned long iRepeatPeriod); unsigned long repeatPeriod() const; protected slots: void accept(); void reject(); void changed(); void formatChanged(int); void stabilizeForm(); private: // The Qt-designer UI struct... Ui::qtractorPasteRepeatForm m_ui; // Instance variables... qtractorTimeScale *m_pTimeScale; int m_iDirtyCount; }; #endif // __qtractorPasteRepeatForm_h // end of qtractorPasteRepeatForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioVorbisFile.cpp0000644000175000001440000000012211563576072022570 xustar000000000000000027 mtime=1305410618.253123 26 atime=1381134667.73208 29 ctime=1381134667.73208006 qtractor-0.5.11/src/qtractorAudioVorbisFile.cpp0000644000175000001440000002402711563576072022065 0ustar00rncbcusers00000000000000// qtractorAudioVorbisFile.cpp // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorAudioVorbisFile.h" #ifdef CONFIG_LIBVORBIS // libvorbis encoder API. #include #endif #include #include #include //---------------------------------------------------------------------- // class qtractorAudioVorbisFile -- Buffered audio file implementation. // // Constructor. qtractorAudioVorbisFile::qtractorAudioVorbisFile ( unsigned short iChannels, unsigned int iSampleRate, unsigned int iBufferSize ) { // Initialize state variables. m_iMode = qtractorAudioVorbisFile::None; m_pFile = NULL; // Estimate channel and sample-rate (for encoder purposes only). m_iChannels = iChannels; m_iSampleRate = iSampleRate; m_iFrames = 0; #ifdef CONFIG_LIBVORBIS m_ovinfo = NULL; m_ovsect = 0; #endif // CONFIG_LIBVORBIS // Estimate buffer size. m_iBufferSize = (4096 << 1); // Adjust size the next nearest power-of-two. while (m_iBufferSize < iBufferSize) m_iBufferSize <<= 1; } // Destructor. qtractorAudioVorbisFile::~qtractorAudioVorbisFile (void) { close(); } // Open method. bool qtractorAudioVorbisFile::open ( const QString& sFilename, int iMode ) { #ifdef DEBUG_0 qDebug("qtractorAudioVorbisFile::open(\"%s\", %d)", sFilename.toUtf8().constData(), iMode); #endif close(); // As said, need a minimum of specification for write mode. if (iMode == Write && (m_iChannels == 0 || m_iSampleRate == 0)) return false; // Whether for Read or Write... const char *pszMode; switch (iMode) { case Read: pszMode = "rb"; break; case Write: pszMode = "wb"; break; default: return false; } // Now open it. QByteArray aFilename = sFilename.toUtf8(); m_pFile = ::fopen(aFilename.constData(), pszMode); if (m_pFile == NULL) return false; #ifdef CONFIG_LIBVORBIS // Now's time for the vorbis stuff... switch (iMode) { case Read: { // Open the Ogg Vorbis file for decoding... if (::ov_open(m_pFile, &m_ovfile, NULL, 0) < 0) { close(); return false; } // Grab the vorbis file info... m_ovinfo = ::ov_info(&m_ovfile, -1); m_ovsect = 0; break; } case Write: { // Init the Ogg Vorbis structs for encoding... m_ovinfo = new vorbis_info; vorbis_info_init(m_ovinfo); // Using a VBR quality mode: // Quality=0.1 (lowest quality, smallest file) // Quality=1.0 (highest quality, largest file). int iQuality = qtractorAudioFileFactory::defaultQuality(); if (vorbis_encode_init_vbr(m_ovinfo, (long) m_iChannels, (long) m_iSampleRate, 0.1f * float(iQuality)) != 0) { close(); return false; } // Add a comments vorbis_comment_init(&m_ovcomment); vorbis_comment_add_tag(&m_ovcomment, (char *) "ENCODER", (char *) "qtractorAudioVorbisFile"); // Set up the analysis state and auxiliary encoding storage. vorbis_analysis_init(&m_ovdsp, m_ovinfo); vorbis_block_init(&m_ovdsp, &m_ovblock); // Set up our packet->stream encoder; // pick a random serial number; that way we can more // likely build chained streams just by concatenation... ::srand(::time(NULL)); ogg_stream_init(&m_ovstate, ::rand()); // Vorbis streams begin with three headers; the initial header // (with most of the codec setup parameters) which is mandated // by the ogg bitstream spec; the second header holds any comment // fields; the third header holds the bitstream codebook. // We merely need to make the headers, then pass them to // libvorbis one at a time; libvorbis handles the additional // ogg bitstream constraints. ogg_packet ovhcodec; ogg_packet ovhcomment; ogg_packet ovhcodebook; vorbis_analysis_headerout(&m_ovdsp, &m_ovcomment, &ovhcodec, &ovhcomment, &ovhcodebook); // Automatically placed in its own page... ogg_stream_packetin(&m_ovstate, &ovhcodec); ogg_stream_packetin(&m_ovstate, &ovhcomment); ogg_stream_packetin(&m_ovstate, &ovhcodebook); // This ensures the actual audio data will // start on a new page, as per spec... ogg_page ovpage; while (ogg_stream_flush(&m_ovstate, &ovpage)) { fwrite(ovpage.header, 1, ovpage.header_len, m_pFile); fwrite(ovpage.body, 1, ovpage.body_len, m_pFile); } // Done on write/encoder overhead. break; } } // Set open mode (deterministically). m_iMode = iMode; return true; #else // CONFIG_LIBVORBIS return false; #endif } // Read method. int qtractorAudioVorbisFile::read ( float **ppFrames, unsigned int iFrames ) { #ifdef DEBUG_0 qDebug("qtractorAudioVorbisFile::read(%p, %d)", ppFrames, iFrames); #endif int nread = 0; #ifdef CONFIG_LIBVORBIS float **ppBuffer; nread = ::ov_read_float(&m_ovfile, &ppBuffer, iFrames, &m_ovsect); if (nread < 0) // HACK: Just in case things get go thru... nread = ::ov_read_float(&m_ovfile, &ppBuffer, iFrames, &m_ovsect); if (nread > 0) { unsigned short i; for (i = 0; i < (unsigned short) m_ovinfo->channels; ++i) { ::memcpy(ppFrames[i], ppBuffer[i], nread * sizeof(float)); } } #endif // CONFIG_LIBVORBIS return nread; } // Write method. int qtractorAudioVorbisFile::write ( float **ppFrames, unsigned int iFrames ) { #ifdef DEBUG_0 qDebug("qtractorAudioVorbisFile::write(%p, %d)", ppFrames, iFrames); #endif int nwrite = 0; #ifdef CONFIG_LIBVORBIS // Expose the buffer to submit data... float **ppBuffer = vorbis_analysis_buffer(&m_ovdsp, iFrames); // Uninterleaved samples... for (unsigned short i = 0; i < m_iChannels; ++i) ::memcpy(ppBuffer[i], ppFrames[i], iFrames * sizeof(float)); // Tell the library how much we actually submitted... vorbis_analysis_wrote(&m_ovdsp, iFrames); // Flush this block... flush(); // We've wrote it all, hopefully... m_iFrames += iFrames; nwrite = iFrames; #endif // CONFIG_LIBVORBIS return nwrite; } // Flush encoder buffers... void qtractorAudioVorbisFile::flush ( bool fEos ) { #ifdef CONFIG_LIBVORBIS // End of file: this can be done implicitly in the mainline, // but it's easier to see here in non-clever fashion; // tell the library we're at end of stream so that it can handle // the last frame and mark end of stream in the output properly... if (fEos) vorbis_analysis_wrote(&m_ovdsp, 0); // Vorbis does some data preanalysis, then divides up blocks // for more involved (potentially parallel) processing. // Get a single block for encoding now... ogg_packet ovpacket; // raw packet of data for decode. ogg_page ovpage; // ogg bitstream page; vorbis packets are inside. while (vorbis_analysis_blockout(&m_ovdsp, &m_ovblock) == 1) { // Analysis, assume we want to use bitrate management... vorbis_analysis(&m_ovblock, NULL); vorbis_bitrate_addblock(&m_ovblock); // Probably we should do this also as left-over processing... while (vorbis_bitrate_flushpacket(&m_ovdsp, &ovpacket)) { // Weld the packet into the bitstream... ogg_stream_packetin(&m_ovstate, &ovpacket); // Write out pages (if any)... while (ogg_stream_pageout(&m_ovstate, &ovpage)) { fwrite(ovpage.header, 1, ovpage.header_len, m_pFile); fwrite(ovpage.body, 1, ovpage.body_len, m_pFile); if (ogg_page_eos(&ovpage)) break; } } } #endif // CONFIG_LIBVORBIS } // Seek method. bool qtractorAudioVorbisFile::seek ( unsigned long iOffset ) { #ifdef DEBUG_0 qDebug("qtractorAudioVorbisFile::seek(%d)", iOffset); #endif #ifdef CONFIG_LIBVORBIS return (::ov_pcm_seek(&m_ovfile, iOffset) == 0); #else return false; #endif } // Close method. void qtractorAudioVorbisFile::close (void) { #ifdef DEBUG_0 qDebug("qtractorAudioVorbisFile::close()"); #endif if (m_pFile) { #ifdef CONFIG_LIBVORBIS // Reinitialize libvorbis stuff... switch (m_iMode) { case Read: ::ov_clear(&m_ovfile); // ::fclose(m_pFile); -- already closed on ov_clear? break; case Write: flush(true); ogg_stream_clear(&m_ovstate); vorbis_block_clear(&m_ovblock); vorbis_dsp_clear(&m_ovdsp); vorbis_comment_clear(&m_ovcomment); vorbis_info_clear(m_ovinfo); delete m_ovinfo; ::fclose(m_pFile); break; } #else ::fclose(m_pFile); #endif m_pFile = NULL; } // Reset all other state relevant variables. #ifdef CONFIG_LIBVORBIS m_ovsect = 0; ::memset(&m_ovfile, 0, sizeof(m_ovfile)); ::memset(&m_ovstate, 0, sizeof(m_ovstate)); ::memset(&m_ovblock, 0, sizeof(m_ovblock)); ::memset(&m_ovdsp, 0, sizeof(m_ovdsp)); ::memset(&m_ovcomment, 0, sizeof(m_ovcomment)); m_ovinfo = NULL; #endif m_iMode = qtractorAudioVorbisFile::None; m_iFrames = 0; } // Open mode accessor. int qtractorAudioVorbisFile::mode (void) const { return m_iMode; } // Open channel(s) accessor. unsigned short qtractorAudioVorbisFile::channels (void) const { #ifdef CONFIG_LIBVORBIS return (m_ovinfo ? m_ovinfo->channels : 0); #else return 0; #endif } // Estimated number of frames specialty (aprox. 8secs). unsigned long qtractorAudioVorbisFile::frames (void) const { #ifdef CONFIG_LIBVORBIS if (m_iMode == Read) return ::ov_pcm_total((OggVorbis_File *) &m_ovfile, -1); #endif return m_iFrames; } // Sample rate specialty. unsigned int qtractorAudioVorbisFile::sampleRate (void) const { #ifdef CONFIG_LIBVORBIS return (m_ovinfo ? m_ovinfo->rate : 0); #else return 0; #endif } // end of qtractorAudioVorbisFile.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorShortcutForm.ui0000644000175000001440000000012212024640067022021 xustar000000000000000026 mtime=1347633207.75856 26 atime=1381134668.17508 30 ctime=1381134668.175080067 qtractor-0.5.11/src/qtractorShortcutForm.ui0000644000175000001440000000563412024640067021321 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorShortcutForm 0 0 520 360 Keyboard Shortcuts :/images/helpShortcuts.png false false false true QAbstractItemView::SingleSelection QAbstractItemView::SelectRows 3 Action Description Shortcut Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok ShortcutTable DialogButtonBox qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiSysexForm.ui0000644000175000001440000000012212067456742022140 xustar000000000000000026 mtime=1356750306.99751 26 atime=1381134666.35708 30 ctime=1381134666.357080039 qtractor-0.5.11/src/qtractorMidiSysexForm.ui0000644000175000001440000002242212067456742021432 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorMidiSysexForm 0 0 480 320 MIDI SysEx - Qtractor :/images/qtractorTracks.png false true false true Name Size Data (hex) Import from SysEx file &Import... :/images/formOpen.png Alt+I Export to SysEx file E&xport... :/images/formSave.png Alt+X Qt::Vertical 20 4 Move SysEx item up on list order &Up :/images/formMoveUp.png Alt+U Move SysEx item down on list order &Down :/images/formMoveDown.png Alt+D Qt::TabFocus Open SysEx :/images/formOpen.png 320 0 Sysex name true Qt::TabFocus Save SysEx :/images/formSave.png Qt::TabFocus Delete SysEx :/images/formRemove.png Create SysEx item &Add :/images/formAdd.png Alt+A Monospace Update SysEx item Upda&te :/images/formEdit.png Alt+T Remove SysEx item &Remove :/images/formRemove.png Alt+R Qt::Vertical 20 4 Qt::Horizontal QDialogButtonBox::Reset|QDialogButtonBox::Cancel|QDialogButtonBox::Ok SysexListView ImportButton ExportButton MoveUpButton MoveDownButton OpenButton NameComboBox SaveButton DeleteButton SysexTextEdit AddButton UpdateButton RemoveButton DialogButtonBox qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiToolsForm.cpp0000644000175000001440000000012312073012112022243 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134666.64308 30 ctime=1381134666.644080043 qtractor-0.5.11/src/qtractorMidiToolsForm.cpp0000644000175000001440000012155012073012112021536 0ustar00rncbcusers00000000000000// qtractorMidiToolsForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorMidiToolsForm.h" #include "qtractorAbout.h" #include "qtractorMidiEditor.h" #include "qtractorMidiClip.h" #include "qtractorMidiEditCommand.h" #include "qtractorOptions.h" #include "qtractorSession.h" #include #include #include #include #include // This shall hold the default preset name. static QString g_sDefPreset; class TimeshiftCurve : public QWidget { public: // Constructor. TimeshiftCurve(QWidget *pParent = 0) : QWidget(pParent), m_p(0.0) {} // Accessors. void setTimeshift(float p) { m_p = p; update(); } // Characteristic method. static float timeshift(float t, float p) { if (p > 0.0f) t = ::sqrtf(t * ::powf(1.0f - (10.0f * ::logf(t) / p), 0.1f * p)); // t = ::powf(t, p); else if (p < 0.0f) t = ::sqrtf(1.0f - ((1.0f - t) * ::powf(1.0f + (::logf(1.0f - t) / p), -p))); // t = 1.0f - ::powf(1.0f - t, -p); return t; } protected: // Paint event method. void paintEvent(QPaintEvent */*pPaintEvent*/) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); int w = QWidget::width(); int h = QWidget::height(); int x = w >> 1; int y = h >> 1; QPen pen(Qt::gray); painter.setPen(pen); painter.drawLine(x, 0, x, h); painter.drawLine(0, y, w, y); QPainterPath path; path.moveTo(0, h); for (x = 4; x < w; x += 4) { float t = float(x) / float(w); path.lineTo(x, h - int(timeshift(t, m_p) * float(h))); } path.lineTo(w, 0); pen.setColor(Qt::red); pen.setWidth(2); painter.setPen(pen); painter.drawPath(path); } private: // Instance variables float m_p; }; //---------------------------------------------------------------------------- // qtractorMidiToolsForm -- UI wrapper form. // Constructor. qtractorMidiToolsForm::qtractorMidiToolsForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::WindowModal); m_pTimeScale = NULL; m_iDirtyCount = 0; m_iUpdate = 0; // Special timeshift characteristic curve display... m_pTimeshiftCurve = new TimeshiftCurve(); QVBoxLayout *pFrameLayout = new QVBoxLayout(); pFrameLayout->setMargin(1); pFrameLayout->addWidget(m_pTimeshiftCurve); m_ui.TimeshiftFrame->setLayout(pFrameLayout); m_ui.PresetNameComboBox->setValidator( new QRegExpValidator(QRegExp("[\\w-]+"), m_ui.PresetNameComboBox)); m_ui.PresetNameComboBox->setInsertPolicy(QComboBox::NoInsert); if (g_sDefPreset.isEmpty()) g_sDefPreset = tr("(default)"); // Set some time spin-box specialties... m_ui.TransposeTimeSpinBox->setDeltaValue(true); m_ui.ResizeDurationSpinBox->setDeltaValue(true); // Reinitialize random seed. ::srand(::time(NULL)); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { // Copy from global time-scale instance... if (m_pTimeScale) delete m_pTimeScale; m_pTimeScale = new qtractorTimeScale(*pSession->timeScale()); m_ui.TransposeTimeSpinBox->setTimeScale(m_pTimeScale); m_ui.ResizeDurationSpinBox->setTimeScale(m_pTimeScale); // Fill-up snap-per-beat items... QStringList items = qtractorTimeScale::snapItems(1); m_ui.QuantizeTimeComboBox->clear(); m_ui.QuantizeTimeComboBox->insertItems(0, items); m_ui.QuantizeDurationComboBox->clear(); m_ui.QuantizeDurationComboBox->insertItems(0, items); m_ui.QuantizeSwingComboBox->clear(); m_ui.QuantizeSwingComboBox->insertItems(0, items); // Default quantization value... unsigned short iSnapPerBeat = m_pTimeScale->snapPerBeat(); if (iSnapPerBeat > 0) --iSnapPerBeat; int iSnapIndex = qtractorTimeScale::indexFromSnap(iSnapPerBeat); m_ui.QuantizeTimeComboBox->setCurrentIndex(iSnapIndex); m_ui.QuantizeDurationComboBox->setCurrentIndex(iSnapIndex); m_ui.QuantizeSwingComboBox->setCurrentIndex(0); m_ui.QuantizeSwingTypeComboBox->setCurrentIndex(0); } // Scale-quantize stuff... m_ui.QuantizeScaleKeyComboBox->clear(); m_ui.QuantizeScaleKeyComboBox->insertItems(0, qtractorMidiEditor::scaleKeyNames()); m_ui.QuantizeScaleKeyComboBox->setCurrentIndex(0); m_ui.QuantizeScaleComboBox->clear(); m_ui.QuantizeScaleComboBox->insertItems(0, qtractorMidiEditor::scaleTypeNames()); m_ui.QuantizeScaleComboBox->setCurrentIndex(0); // Choose BBT to be default format here. formatChanged(qtractorTimeScale::BBT); // Load initial preset names; loadPreset(g_sDefPreset); timeshiftSpinBoxChanged(m_ui.TimeshiftSpinBox->value()); refreshPresets(); // Draw timeshift curve always. // Try to restore old window positioning. // adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.PresetNameComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(presetChanged(const QString&))); QObject::connect(m_ui.PresetNameComboBox, SIGNAL(activated(const QString &)), SLOT(presetActivated(const QString&))); QObject::connect(m_ui.PresetSaveToolButton, SIGNAL(clicked()), SLOT(presetSave())); QObject::connect(m_ui.PresetDeleteToolButton, SIGNAL(clicked()), SLOT(presetDelete())); QObject::connect(m_ui.QuantizeCheckBox, SIGNAL(toggled(bool)), SLOT(stabilizeForm())); QObject::connect(m_ui.QuantizeTimeCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.QuantizeTimeComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.QuantizeTimeSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.QuantizeDurationCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.QuantizeDurationComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.QuantizeDurationSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.QuantizeSwingCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.QuantizeSwingComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.QuantizeSwingSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.QuantizeSwingTypeComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.QuantizeSwingSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.QuantizeScaleCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.QuantizeScaleKeyComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.QuantizeScaleComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.TransposeCheckBox, SIGNAL(toggled(bool)), SLOT(stabilizeForm())); QObject::connect(m_ui.TransposeNoteCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.TransposeNoteSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.TransposeTimeCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.TransposeTimeSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(changed())); QObject::connect(m_ui.TransposeFormatComboBox, SIGNAL(activated(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.NormalizeCheckBox, SIGNAL(toggled(bool)), SLOT(stabilizeForm())); QObject::connect(m_ui.NormalizePercentCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.NormalizePercentSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.NormalizeValueCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.NormalizeValueSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.RandomizeCheckBox, SIGNAL(toggled(bool)), SLOT(stabilizeForm())); QObject::connect(m_ui.RandomizeNoteCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.RandomizeNoteSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.RandomizeTimeCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.RandomizeTimeSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.RandomizeDurationCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.RandomizeDurationSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.RandomizeValueCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.RandomizeValueSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.ResizeCheckBox, SIGNAL(toggled(bool)), SLOT(stabilizeForm())); QObject::connect(m_ui.ResizeDurationCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.ResizeDurationSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(changed())); QObject::connect(m_ui.ResizeFormatComboBox, SIGNAL(activated(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.ResizeValueCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.ResizeValueSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.ResizeValue2ComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.ResizeValue2SpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.RescaleCheckBox, SIGNAL(toggled(bool)), SLOT(stabilizeForm())); QObject::connect(m_ui.RescaleTimeCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.RescaleTimeSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.RescaleDurationCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.RescaleDurationSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.RescaleValueCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.RescaleValueSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.TimeshiftCheckBox, SIGNAL(toggled(bool)), SLOT(stabilizeForm())); QObject::connect(m_ui.TimeshiftSpinBox, SIGNAL(valueChanged(double)), SLOT(timeshiftSpinBoxChanged(double))); QObject::connect(m_ui.TimeshiftSlider, SIGNAL(valueChanged(int)), SLOT(timeshiftSliderChanged(int))); QObject::connect(m_ui.TimeshiftDurationCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); } // Destructor. qtractorMidiToolsForm::~qtractorMidiToolsForm (void) { // Don't forget to get rid of local time-scale instance... if (m_pTimeScale) delete m_pTimeScale; } // Set (initial) tool page. void qtractorMidiToolsForm::setToolIndex ( int iToolIndex ) { // Set the proper tool page. m_ui.ToolTabWidget->setCurrentIndex(iToolIndex); switch (iToolIndex) { case qtractorMidiEditor::Quantize: m_ui.QuantizeCheckBox->setChecked(true); break; case qtractorMidiEditor::Transpose: m_ui.TransposeCheckBox->setChecked(true); break; case qtractorMidiEditor::Normalize: m_ui.NormalizeCheckBox->setChecked(true); break; case qtractorMidiEditor::Randomize: m_ui.RandomizeCheckBox->setChecked(true); break; case qtractorMidiEditor::Resize: m_ui.ResizeCheckBox->setChecked(true); break; case qtractorMidiEditor::Rescale: m_ui.RescaleCheckBox->setChecked(true); break; case qtractorMidiEditor::Timeshift: m_ui.TimeshiftCheckBox->setChecked(true); break; default: break; } // Done. stabilizeForm(); } // Retrieve the current export type, if the case arises. int qtractorMidiToolsForm::toolIndex (void) const { return m_ui.ToolTabWidget->currentIndex(); } // Preset management methods... void qtractorMidiToolsForm::loadPreset ( const QString& sPreset ) { // An existing preset is about to be loaded... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { QList vlist; QSettings& settings = pOptions->settings(); // Get the preset entry... settings.beginGroup("/MidiTools"); if (!sPreset.isEmpty() && sPreset != g_sDefPreset) settings.beginGroup('/' + sPreset); // Quantize tool... vlist = settings.value("/Quantize").toList(); if (vlist.count() > 4) { // m_ui.QuantizeCheckBox->setChecked(vlist[0].toBool()); m_ui.QuantizeTimeCheckBox->setChecked(vlist[1].toBool()); m_ui.QuantizeTimeComboBox->setCurrentIndex(vlist[2].toInt()); m_ui.QuantizeDurationCheckBox->setChecked(vlist[3].toBool()); m_ui.QuantizeDurationComboBox->setCurrentIndex(vlist[4].toInt()); } // Swing-quantize tool... if (vlist.count() > 8) { m_ui.QuantizeSwingCheckBox->setChecked(vlist[5].toBool()); m_ui.QuantizeSwingComboBox->setCurrentIndex(vlist[6].toInt()); m_ui.QuantizeSwingSpinBox->setValue(vlist[7].toInt()); m_ui.QuantizeSwingTypeComboBox->setCurrentIndex(vlist[8].toInt()); } // Percent-quantize tool... if (vlist.count() > 10) { m_ui.QuantizeTimeSpinBox->setValue(vlist[9].toInt()); m_ui.QuantizeDurationSpinBox->setValue(vlist[10].toInt()); } // Scale-quantize tool... if (vlist.count() > 13) { m_ui.QuantizeScaleCheckBox->setChecked(vlist[11].toBool()); m_ui.QuantizeScaleKeyComboBox->setCurrentIndex(vlist[12].toInt()); m_ui.QuantizeScaleComboBox->setCurrentIndex(vlist[13].toInt()); } // Transpose tool... vlist = settings.value("/Transpose").toList(); if (vlist.count() > 4) { // m_ui.TransposeCheckBox->setChecked(vlist[0].toBool()); m_ui.TransposeNoteCheckBox->setChecked(vlist[1].toBool()); m_ui.TransposeNoteSpinBox->setValue(vlist[2].toInt()); m_ui.TransposeTimeCheckBox->setChecked(vlist[3].toBool()); m_ui.TransposeTimeSpinBox->setValue(vlist[4].toUInt()); } // Normalize tool... vlist = settings.value("/Normalize").toList(); if (vlist.count() > 4) { // m_ui.NormalizeCheckBox->setChecked(vlist[0].toBool()); m_ui.NormalizePercentCheckBox->setChecked(vlist[1].toBool()); m_ui.NormalizePercentSpinBox->setValue(vlist[2].toInt()); m_ui.NormalizeValueCheckBox->setChecked(vlist[3].toBool()); m_ui.NormalizeValueSpinBox->setValue(vlist[4].toInt()); } // Randomize tool... vlist = settings.value("/Randomize").toList(); if (vlist.count() > 8) { // m_ui.RandomizeCheckBox->setChecked(vlist[0].toBool()); m_ui.RandomizeNoteCheckBox->setChecked(vlist[1].toBool()); m_ui.RandomizeNoteSpinBox->setValue(vlist[2].toInt()); m_ui.RandomizeTimeCheckBox->setChecked(vlist[3].toBool()); m_ui.RandomizeTimeSpinBox->setValue(vlist[4].toInt()); m_ui.RandomizeDurationCheckBox->setChecked(vlist[5].toBool()); m_ui.RandomizeDurationSpinBox->setValue(vlist[6].toInt()); m_ui.RandomizeValueCheckBox->setChecked(vlist[7].toBool()); m_ui.RandomizeValueSpinBox->setValue(vlist[8].toInt()); } // Resize tool... vlist = settings.value("/Resize").toList(); if (vlist.count() > 4) { // m_ui.ResizeCheckBox->setChecked(vlist[0].toBool()); m_ui.ResizeValueCheckBox->setChecked(vlist[1].toBool()); m_ui.ResizeValueSpinBox->setValue(vlist[2].toInt()); m_ui.ResizeDurationCheckBox->setChecked(vlist[3].toBool()); m_ui.ResizeDurationSpinBox->setValue(vlist[4].toUInt()); } // Resize value mode tool... if (vlist.count() > 6) { m_ui.ResizeValue2ComboBox->setCurrentIndex(vlist[5].toInt()); m_ui.ResizeValue2SpinBox->setValue(vlist[6].toInt()); } // Rescale tool... vlist = settings.value("/Rescale").toList(); if (vlist.count() > 6) { // m_ui.RescaleCheckBox->setChecked(vlist[0].toBool()); m_ui.RescaleTimeCheckBox->setChecked(vlist[1].toBool()); m_ui.RescaleTimeSpinBox->setValue(vlist[2].toInt()); m_ui.RescaleDurationCheckBox->setChecked(vlist[3].toBool()); m_ui.RescaleDurationSpinBox->setValue(vlist[4].toInt()); m_ui.RescaleValueCheckBox->setChecked(vlist[5].toBool()); m_ui.RescaleValueSpinBox->setValue(vlist[6].toInt()); } // Timeshift tool... vlist = settings.value("/Timeshift").toList(); if (vlist.count() > 2) { // m_ui.TimeshiftCheckBox->setChecked(vlist[0].toBool()); m_ui.TimeshiftSpinBox->setValue(vlist[1].toDouble()); m_ui.TimeshiftDurationCheckBox->setChecked(vlist[2].toBool()); } // All loaded. if (!sPreset.isEmpty() && sPreset != g_sDefPreset) settings.endGroup(); settings.endGroup(); } } void qtractorMidiToolsForm::savePreset ( const QString& sPreset ) { // The current state preset is about to be saved... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { QList vlist; QSettings& settings = pOptions->settings(); // Set preset entry... settings.beginGroup("/MidiTools"); if (!sPreset.isEmpty() && sPreset != g_sDefPreset) settings.beginGroup('/' + sPreset); // Quantize tool... vlist.clear(); vlist.append(m_ui.QuantizeCheckBox->isChecked()); vlist.append(m_ui.QuantizeTimeCheckBox->isChecked()); vlist.append(m_ui.QuantizeTimeComboBox->currentIndex()); vlist.append(m_ui.QuantizeDurationCheckBox->isChecked()); vlist.append(m_ui.QuantizeDurationComboBox->currentIndex()); vlist.append(m_ui.QuantizeSwingCheckBox->isChecked()); vlist.append(m_ui.QuantizeSwingComboBox->currentIndex()); vlist.append(m_ui.QuantizeSwingSpinBox->value()); vlist.append(m_ui.QuantizeSwingTypeComboBox->currentIndex()); vlist.append(m_ui.QuantizeTimeSpinBox->value()); vlist.append(m_ui.QuantizeDurationSpinBox->value()); vlist.append(m_ui.QuantizeScaleCheckBox->isChecked()); vlist.append(m_ui.QuantizeScaleKeyComboBox->currentIndex()); vlist.append(m_ui.QuantizeScaleComboBox->currentIndex()); settings.setValue("/Quantize", vlist); // Transpose tool... vlist.clear(); vlist.append(m_ui.TransposeCheckBox->isChecked()); vlist.append(m_ui.TransposeNoteCheckBox->isChecked()); vlist.append(m_ui.TransposeNoteSpinBox->value()); vlist.append(m_ui.TransposeTimeCheckBox->isChecked()); vlist.append((unsigned int) m_ui.TransposeTimeSpinBox->value()); settings.setValue("/Transpose", vlist); // Normalize tool... vlist.clear(); vlist.append(m_ui.NormalizeCheckBox->isChecked()); vlist.append(m_ui.NormalizePercentCheckBox->isChecked()); vlist.append(m_ui.NormalizePercentSpinBox->value()); vlist.append(m_ui.NormalizeValueCheckBox->isChecked()); vlist.append(m_ui.NormalizeValueSpinBox->value()); settings.setValue("/Normalize", vlist); // Randomize tool... vlist.clear(); vlist.append(m_ui.RandomizeCheckBox->isChecked()); vlist.append(m_ui.RandomizeNoteCheckBox->isChecked()); vlist.append(m_ui.RandomizeNoteSpinBox->value()); vlist.append(m_ui.RandomizeTimeCheckBox->isChecked()); vlist.append(m_ui.RandomizeTimeSpinBox->value()); vlist.append(m_ui.RandomizeDurationCheckBox->isChecked()); vlist.append(m_ui.RandomizeDurationSpinBox->value()); vlist.append(m_ui.RandomizeValueCheckBox->isChecked()); vlist.append(m_ui.RandomizeValueSpinBox->value()); settings.setValue("/Randomize", vlist); // Resize tool... vlist.clear(); vlist.append(m_ui.ResizeCheckBox->isChecked()); vlist.append(m_ui.ResizeValueCheckBox->isChecked()); vlist.append(m_ui.ResizeValueSpinBox->value()); vlist.append(m_ui.ResizeDurationCheckBox->isChecked()); vlist.append((unsigned int) m_ui.ResizeDurationSpinBox->value()); vlist.append(m_ui.ResizeValue2ComboBox->currentIndex()); vlist.append(m_ui.ResizeValue2SpinBox->value()); settings.setValue("/Resize", vlist); // Rescale tool... vlist.clear(); vlist.append(m_ui.RescaleCheckBox->isChecked()); vlist.append(m_ui.RescaleTimeCheckBox->isChecked()); vlist.append(m_ui.RescaleTimeSpinBox->value()); vlist.append(m_ui.RescaleDurationCheckBox->isChecked()); vlist.append(m_ui.RescaleDurationSpinBox->value()); vlist.append(m_ui.RescaleValueCheckBox->isChecked()); vlist.append(m_ui.RescaleValueSpinBox->value()); settings.setValue("/Rescale", vlist); // Timeshift tool... vlist.clear(); vlist.append(m_ui.TimeshiftCheckBox->isChecked()); vlist.append(m_ui.TimeshiftSpinBox->value()); vlist.append(m_ui.TimeshiftDurationCheckBox->isChecked()); settings.setValue("/Timeshift", vlist); // All saved. if (!sPreset.isEmpty() && sPreset != g_sDefPreset) settings.endGroup(); settings.endGroup(); } } // Preset list loader. void qtractorMidiToolsForm::refreshPresets (void) { ++m_iUpdate; const QString sOldPreset = m_ui.PresetNameComboBox->currentText(); m_ui.PresetNameComboBox->clear(); qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { QSettings& settings = pOptions->settings(); settings.beginGroup("/MidiTools"); m_ui.PresetNameComboBox->insertItems(0, settings.childGroups()); m_ui.PresetNameComboBox->model()->sort(0); settings.endGroup(); } m_ui.PresetNameComboBox->addItem(g_sDefPreset); m_ui.PresetNameComboBox->setEditText(sOldPreset); m_iDirtyCount = 0; --m_iUpdate; stabilizeForm(); } // Preset management slots... void qtractorMidiToolsForm::presetChanged ( const QString& sPreset ) { if (m_iUpdate > 0) return; if (!sPreset.isEmpty() && m_ui.PresetNameComboBox->findText(sPreset) >= 0) ++m_iDirtyCount; stabilizeForm(); } void qtractorMidiToolsForm::presetActivated ( const QString& sPreset ) { ++m_iUpdate; loadPreset(sPreset); m_iDirtyCount = 0; --m_iUpdate; stabilizeForm(); } void qtractorMidiToolsForm::presetSave (void) { savePreset(m_ui.PresetNameComboBox->currentText()); refreshPresets(); } void qtractorMidiToolsForm::presetDelete (void) { if (m_iUpdate > 0) return; const QString& sPreset = m_ui.PresetNameComboBox->currentText(); if (sPreset.isEmpty() || sPreset == g_sDefPreset) return; // A preset entry is about to be deleted... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { // Prompt user if he/she's sure about this... if (pOptions->bConfirmRemove) { if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("About to delete preset:\n\n" "\"%1\"\n\n" "Are you sure?") .arg(sPreset), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; } // Go ahead... QSettings& settings = pOptions->settings(); settings.beginGroup("/MidiTools"); settings.remove(sPreset); settings.endGroup(); refreshPresets(); } } // Create edit command based on given selection. qtractorMidiEditCommand *qtractorMidiToolsForm::editCommand ( qtractorMidiClip *pMidiClip, qtractorMidiEditSelect *pSelect, unsigned long iTimeOffset ) { // Create command, it will be handed over... qtractorMidiEditCommand *pEditCommand = new qtractorMidiEditCommand(pMidiClip, tr("none")); // Set composite command title. QStringList tools; if (m_ui.QuantizeCheckBox->isChecked()) tools.append(tr("quantize")); if (m_ui.TransposeCheckBox->isChecked()) tools.append(tr("transpose")); if (m_ui.NormalizeCheckBox->isChecked()) tools.append(tr("normalize")); if (m_ui.RandomizeCheckBox->isChecked()) tools.append(tr("randomize")); if (m_ui.ResizeCheckBox->isChecked()) tools.append(tr("resize")); if (m_ui.RescaleCheckBox->isChecked()) tools.append(tr("rescale")); if (m_ui.TimeshiftCheckBox->isChecked()) tools.append(tr("timeshift")); pEditCommand->setName(tools.join(", ")); const qtractorMidiEditSelect::ItemList& items = pSelect->items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); // Seed time range with a value from the list of selected events. long iMinTime = 0; long iMaxTime = 0; if (pSelect->anchorEvent()) iMinTime = iMaxTime = pSelect->anchorEvent()->time(); // First scan pass for the normalize and resize value ramp tools: // find maximum and minimum times and values from the selection... int iMaxValue = 0; int iMinValue = 0; if (m_ui.NormalizeCheckBox->isChecked() || (m_ui.ResizeCheckBox->isChecked() && m_ui.ResizeValueCheckBox->isChecked() && m_ui.ResizeValue2ComboBox->currentIndex() > 0)) { // Make it through one time... for (int i = 0 ; iter != iter_end; ++i, ++iter) { qtractorMidiEvent *pEvent = iter.key(); long iTime = pEvent->time(); if (iMinTime > iTime || i == 0) iMinTime = iTime; if (iMaxTime < iTime) iMaxTime = iTime; bool bPitchBend = (pEvent->type() == qtractorMidiEvent::PITCHBEND); int iValue = (bPitchBend ? pEvent->pitchBend() : pEvent->value()); if (iMinValue > iValue || i == 0) iMinValue = iValue; if (iMaxValue < iValue) iMaxValue = iValue; } // Get it back to front... iter = items.constBegin(); } // Go for the main pass... qtractorTimeScale::Cursor cursor(m_pTimeScale); for ( ; iter != iter_end; ++iter) { qtractorMidiEvent *pEvent = iter.key(); long iTime = pEvent->time(); long iDuration = pEvent->duration(); bool bPitchBend = (pEvent->type() == qtractorMidiEvent::PITCHBEND); int iValue = (bPitchBend ? pEvent->pitchBend() : pEvent->value()); qtractorTimeScale::Node *pNode = cursor.seekTick(iTime + iTimeOffset); // Quantize tool... if (m_ui.QuantizeCheckBox->isChecked()) { tools.append(tr("quantize")); // Swing quantize... if (m_ui.QuantizeSwingCheckBox->isChecked()) { unsigned short p = qtractorTimeScale::snapFromIndex( m_ui.QuantizeSwingComboBox->currentIndex() + 1); unsigned long q = pNode->ticksPerBeat / p; if (q > 0) { long d0 = 0; unsigned long t0 = q * (iTime / q); if ((iTime / q) % 2) { d0 = long(t0 + q) - long(iTime); } else { d0 = long(iTime) - long(t0); } long ds = (d0 * m_ui.QuantizeSwingSpinBox->value()) / 100; switch (m_ui.QuantizeSwingTypeComboBox->currentIndex()) { case 2: // Cubic... ds = (ds * d0) / long(q); case 1: // Quadratic... ds = (ds * d0) / long(q); case 0: // Linear... iTime += ds; if (iTime < 0) iTime = 0; break; } } } // Time quantize... if (m_ui.QuantizeTimeCheckBox->isChecked()) { unsigned short p = qtractorTimeScale::snapFromIndex( m_ui.QuantizeTimeComboBox->currentIndex() + 1); unsigned long q = pNode->ticksPerBeat / p; iTime = q * ((iTime + (q >> 1)) / q); // Time percent quantize... p = 100 - m_ui.QuantizeTimeSpinBox->value(); iTime += ((long(pEvent->time()) - iTime) * p) / 100; if (iTime < 0) iTime = 0; } // Duration quantize... if (m_ui.QuantizeDurationCheckBox->isChecked() && pEvent->type() == qtractorMidiEvent::NOTEON) { unsigned short p = qtractorTimeScale::snapFromIndex( m_ui.QuantizeDurationComboBox->currentIndex() + 1); unsigned long q = pNode->ticksPerBeat / p; iDuration = q * ((iDuration + q - 1) / q); // Duration percent quantize... p = 100 - m_ui.QuantizeDurationSpinBox->value(); iDuration += ((long(pEvent->duration()) - iDuration) * p) / 100; if (iDuration < 0) iDuration = 0; } pEditCommand->resizeEventTime(pEvent, iTime, iDuration); // Scale quantize... if (m_ui.QuantizeScaleCheckBox->isChecked()) { int iNote = qtractorMidiEditor::snapToScale(pEvent->note(), m_ui.QuantizeScaleKeyComboBox->currentIndex(), m_ui.QuantizeScaleComboBox->currentIndex()); pEditCommand->moveEvent(pEvent, iNote, iTime); } } // Transpose tool... if (m_ui.TransposeCheckBox->isChecked()) { tools.append(tr("transpose")); int iNote = int(pEvent->note()); if (m_ui.TransposeNoteCheckBox->isChecked() && pEvent->type() == qtractorMidiEvent::NOTEON) { iNote += m_ui.TransposeNoteSpinBox->value(); if (iNote < 0) iNote = 0; else if (iNote > 127) iNote = 127; } if (m_ui.TransposeTimeCheckBox->isChecked()) { iTime += pNode->tickFromFrame( pNode->frameFromTick(iTime + iTimeOffset) + m_ui.TransposeTimeSpinBox->value()) - (iTime + iTimeOffset); if (iTime < 0) iTime = 0; } pEditCommand->moveEvent(pEvent, iNote, iTime); } // Normalize tool... if (m_ui.NormalizeCheckBox->isChecked()) { tools.append(tr("normalize")); int p, q = iMaxValue; if (m_ui.NormalizeValueCheckBox->isChecked()) p = m_ui.NormalizeValueSpinBox->value(); else p = (bPitchBend ? 8192 : 128); if (m_ui.NormalizePercentCheckBox->isChecked()) { p *= m_ui.NormalizePercentSpinBox->value(); q *= 100; } if (q > 0) { iValue = (iValue * p) / q; if (bPitchBend) { if (iValue > +8191) iValue = +8191; else if (iValue < -8191) iValue = -8191; } else { if (iValue > 127) iValue = 127; else if (iValue < 0) iValue = 0; } } pEditCommand->resizeEventValue(pEvent, iValue); } // Randomize tool... if (m_ui.RandomizeCheckBox->isChecked()) { tools.append(tr("randomize")); int p, q; if (m_ui.RandomizeNoteCheckBox->isChecked()) { int iNote = int(pEvent->note()); p = m_ui.RandomizeNoteSpinBox->value(); q = 127; if (p > 0) { iNote += (p * (q - (::rand() % (q << 1)))) / 100; if (iNote > 127) iNote = 127; else if (iNote < 0) iNote = 0; pEditCommand->moveEvent(pEvent, iNote, iTime); } } if (m_ui.RandomizeTimeCheckBox->isChecked()) { p = m_ui.RandomizeTimeSpinBox->value(); q = pNode->ticksPerBeat; if (p > 0) { iTime += (p * (q - (::rand() % (q << 1)))) / 100; if (iTime < 0) iTime = 0; pEditCommand->resizeEventTime(pEvent, iTime, iDuration); } } if (m_ui.RandomizeDurationCheckBox->isChecked()) { p = m_ui.RandomizeDurationSpinBox->value(); q = pNode->ticksPerBeat; if (p > 0) { iDuration += (p * (q - (::rand() % (q << 1)))) / 100; if (iDuration < 0) iDuration = 0; pEditCommand->resizeEventTime(pEvent, iTime, iDuration); } } if (m_ui.RandomizeValueCheckBox->isChecked()) { p = m_ui.RandomizeValueSpinBox->value(); q = (bPitchBend ? 8192 : 128); if (p > 0) { iValue += (p * (q - (::rand() % (q << 1)))) / 100; if (bPitchBend) { if (iValue > +8191) iValue = +8191; else if (iValue < -8191) iValue = -8191; } else { if (iValue > 127) iValue = 127; else if (iValue < 0) iValue = 0; } pEditCommand->resizeEventValue(pEvent, iValue); } } } // Resize tool... if (m_ui.ResizeCheckBox->isChecked()) { tools.append(tr("resize")); if (m_ui.ResizeDurationCheckBox->isChecked()) { iDuration = pNode->tickFromFrame( pNode->frameFromTick(iTime + iTimeOffset) + m_ui.ResizeDurationSpinBox->value()) - (iTime + iTimeOffset); pEditCommand->resizeEventTime(pEvent, iTime, iDuration); } if (m_ui.ResizeValueCheckBox->isChecked()) { int p = (bPitchBend && iValue < 0 ? -1 : 1); // sign iValue = p * m_ui.ResizeValueSpinBox->value(); if (bPitchBend) iValue <<= 6; // *128 if (m_ui.ResizeValue2ComboBox->currentIndex() > 0) { int iValue2 = p * m_ui.ResizeValue2SpinBox->value(); if (bPitchBend) iValue2 <<= 6; // *128 int iDeltaValue = iValue2 - iValue; long iDeltaTime = iMaxTime - iMinTime; if (iDeltaTime > 0) iValue += iDeltaValue * (iTime - iMinTime) / iDeltaTime; } pEditCommand->resizeEventValue(pEvent, iValue); } } // Rescale tool... if (m_ui.RescaleCheckBox->isChecked()) { tools.append(tr("rescale")); int p; if (m_ui.RescaleTimeCheckBox->isChecked()) { p = m_ui.RescaleTimeSpinBox->value(); iTime = iMinTime + ((iTime - iMinTime) * p) / 100; if (iTime < 0) iTime = 0; pEditCommand->moveEvent(pEvent, pEvent->note(), iTime); } if (m_ui.RescaleDurationCheckBox->isChecked()) { p = m_ui.RescaleDurationSpinBox->value(); iDuration = (iDuration * p) / 100; if (iDuration < 0) iDuration = 0; pEditCommand->resizeEventTime(pEvent, iTime, iDuration); } if (m_ui.RescaleValueCheckBox->isChecked()) { p = m_ui.RescaleValueSpinBox->value(); iValue = (iValue * p) / 100; if (bPitchBend) { if (iValue > +8191) iValue = +8191; else if (iValue < -8191) iValue = -8191; } else { if (iValue > 127) iValue = 127; else if (iValue < 0) iValue = 0; } pEditCommand->resizeEventValue(pEvent, iValue); } } // Timeshift tool... if (m_ui.TimeshiftCheckBox->isChecked()) { tools.append(tr("timeshift")); qtractorSession *pSession = qtractorSession::getInstance(); unsigned long iEditHeadTime = pSession->tickFromFrame(pSession->editHead()) - iTimeOffset; unsigned long iEditTailTime = pSession->tickFromFrame(pSession->editTail()) - iTimeOffset; float d = float(iEditTailTime - iEditHeadTime); float p = float(m_ui.TimeshiftSpinBox->value()); if ((p < -1e-6f || p > 1e-6f) && (d > 0.0f)) { float t = float(iTime - iEditHeadTime); float t1 = t / d; float t2 = (t + float(iDuration)) / d; if (t1 > 0.0f && t1 < 1.0f) t1 = TimeshiftCurve::timeshift(t1, p); if (m_ui.TimeshiftDurationCheckBox->isChecked() && (t2 > 0.0f && t2 < 1.0f)) t2 = TimeshiftCurve::timeshift(t2, p); t1 = t1 * d + float(iEditHeadTime); if (m_ui.TimeshiftDurationCheckBox->isChecked()) { t2 = t2 * d + float(iEditHeadTime); pEditCommand->resizeEventTime(pEvent, t1, t2 - t1); } else { pEditCommand->moveEvent(pEvent, pEvent->note(), t1); } } } } // Done. return pEditCommand; } // Common change slot. void qtractorMidiToolsForm::changed (void) { if (m_iUpdate > 0) return; ++m_iDirtyCount; stabilizeForm(); } // Accept settings (OK button slot). void qtractorMidiToolsForm::accept (void) { // Save as default preset... savePreset(g_sDefPreset); // Just go with dialog acceptance. QDialog::accept(); } // Reject settings (Cancel button slot). void qtractorMidiToolsForm::reject (void) { // Bail out... QDialog::reject(); } // Display format has changed. void qtractorMidiToolsForm::formatChanged ( int iDisplayFormat ) { qtractorTimeScale::DisplayFormat displayFormat = qtractorTimeScale::DisplayFormat(iDisplayFormat); m_ui.TransposeFormatComboBox->setCurrentIndex(iDisplayFormat); m_ui.ResizeFormatComboBox->setCurrentIndex(iDisplayFormat); if (m_pTimeScale) { // Set from local time-scale instance... m_pTimeScale->setDisplayFormat(displayFormat); m_ui.TransposeTimeSpinBox->updateDisplayFormat(); m_ui.ResizeDurationSpinBox->updateDisplayFormat(); } stabilizeForm(); } // Stabilize current form state. void qtractorMidiToolsForm::stabilizeForm (void) { int iEnabled = 0; bool bEnabled; bool bEnabled2; // Preset status... const QString& sPreset = m_ui.PresetNameComboBox->currentText(); bool bExists = (m_ui.PresetNameComboBox->findText(sPreset) >= 0); bEnabled = (!sPreset.isEmpty() && sPreset != g_sDefPreset); m_ui.PresetSaveToolButton->setEnabled(bEnabled && (!bExists || m_iDirtyCount > 0)); m_ui.PresetDeleteToolButton->setEnabled(bEnabled && bExists); // Quantize tool... bEnabled = m_ui.QuantizeCheckBox->isChecked(); m_ui.QuantizeTimeCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.QuantizeTimeCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.QuantizeTimeComboBox->setEnabled(bEnabled2); m_ui.QuantizeTimeSpinBox->setEnabled(bEnabled2); m_ui.QuantizeDurationCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.QuantizeDurationCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.QuantizeDurationComboBox->setEnabled(bEnabled2); m_ui.QuantizeDurationSpinBox->setEnabled(bEnabled2); // if (bEnabled) // bEnabled = m_ui.QuantizeTimeCheckBox->isChecked(); m_ui.QuantizeSwingCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.QuantizeSwingCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.QuantizeSwingComboBox->setEnabled(bEnabled2); m_ui.QuantizeSwingSpinBox->setEnabled(bEnabled2); m_ui.QuantizeSwingTypeComboBox->setEnabled(bEnabled2); m_ui.QuantizeScaleCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.QuantizeScaleCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.QuantizeScaleKeyComboBox->setEnabled(bEnabled2); m_ui.QuantizeScaleComboBox->setEnabled(bEnabled2); // Transpose tool... bEnabled = m_ui.TransposeCheckBox->isChecked(); m_ui.TransposeNoteCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.TransposeNoteCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.TransposeNoteSpinBox->setEnabled(bEnabled2); m_ui.TransposeTimeCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.TransposeTimeCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.TransposeTimeSpinBox->setEnabled(bEnabled2); m_ui.TransposeFormatComboBox->setEnabled(bEnabled2); // Normalize tool... bEnabled = m_ui.NormalizeCheckBox->isChecked(); m_ui.NormalizePercentCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.NormalizePercentCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.NormalizePercentSpinBox->setEnabled(bEnabled2); m_ui.NormalizeValueCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.NormalizeValueCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.NormalizeValueSpinBox->setEnabled(bEnabled2); // Randomize tool... bEnabled = m_ui.RandomizeCheckBox->isChecked(); m_ui.RandomizeNoteCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.RandomizeNoteCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.RandomizeNoteSpinBox->setEnabled(bEnabled2); m_ui.RandomizeTimeCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.RandomizeTimeCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.RandomizeTimeSpinBox->setEnabled(bEnabled2); m_ui.RandomizeDurationCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.RandomizeDurationCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.RandomizeDurationSpinBox->setEnabled(bEnabled2); m_ui.RandomizeValueCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.RandomizeValueCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.RandomizeValueSpinBox->setEnabled(bEnabled2); // Resize tool... bEnabled = m_ui.ResizeCheckBox->isChecked(); m_ui.ResizeDurationCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.ResizeDurationCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.ResizeDurationSpinBox->setEnabled(bEnabled2); m_ui.ResizeFormatComboBox->setEnabled(bEnabled2); m_ui.ResizeValueCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.ResizeValueCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.ResizeValueSpinBox->setEnabled(bEnabled2); if (bEnabled2) bEnabled2 = (m_ui.ResizeValue2ComboBox->currentIndex() > 0); m_ui.ResizeValue2SpinBox->setEnabled(bEnabled2); // Rescale tool... bEnabled = m_ui.RescaleCheckBox->isChecked(); m_ui.RescaleTimeCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.RescaleTimeCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.RescaleTimeSpinBox->setEnabled(bEnabled2); m_ui.RescaleDurationCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.RescaleDurationCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.RescaleDurationSpinBox->setEnabled(bEnabled2); m_ui.RescaleValueCheckBox->setEnabled(bEnabled); bEnabled2 = bEnabled && m_ui.RescaleValueCheckBox->isChecked(); if (bEnabled2) ++iEnabled; m_ui.RescaleValueSpinBox->setEnabled(bEnabled2); // Timeshift tool... bEnabled = m_ui.TimeshiftCheckBox->isChecked(); if (bEnabled) ++iEnabled; m_ui.TimeshiftLabel->setEnabled(bEnabled); m_ui.TimeshiftSpinBox->setEnabled(bEnabled); m_ui.TimeshiftSlider->setEnabled(bEnabled); m_ui.TimeshiftText->setEnabled(bEnabled); m_ui.TimeshiftDurationCheckBox->setEnabled(bEnabled); m_pTimeshiftCurve->setVisible(bEnabled); m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(iEnabled > 0); } // Timeshift characteristic stuff. void qtractorMidiToolsForm::timeshiftSpinBoxChanged ( double p ) { if (m_iUpdate > 0) return; ++m_iUpdate; int i = 0; // = int(10000.0f * float(p) / 100.0f); if (p > +0.001) i = + int(2000.0f * ::log10f(1000.0f * float(+ p))); else if (p < -0.001) i = - int(2000.0f * ::log10f(1000.0f * float(- p))); #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiToolsForm::timeshiftSpinBoxChanged(%g) i=%d", float(p), i); #endif m_ui.TimeshiftSlider->setValue(i); m_pTimeshiftCurve->setTimeshift(float(p)); --m_iUpdate; changed(); } void qtractorMidiToolsForm::timeshiftSliderChanged ( int i ) { if (m_iUpdate > 0) return; ++m_iUpdate; float p = 0.0f; // = 100.0f * float(i) / 10000.0f; if (i > 0) p = + 0.001f * ::powf(10.0f, (0.0005f * float(+ i))); else if (i < 0) p = - 0.001f * ::powf(10.0f, (0.0005f * float(- i))); #ifdef CONFIG_DEBUG qDebug("qtractorMidiToolsForm::timeshiftSliderChanged(%d) p=%g", i, p); #endif m_ui.TimeshiftSpinBox->setValue(double(p)); m_pTimeshiftCurve->setTimeshift(p); --m_iUpdate; changed(); } // end of qtractorMidiToolsForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditSelect.cpp0000644000175000001440000000012312073104061022351 xustar000000000000000027 mtime=1357678641.548312 26 atime=1381134667.36708 30 ctime=1381134667.367080055 qtractor-0.5.11/src/qtractorMidiEditSelect.cpp0000644000175000001440000000743512073104061021651 0ustar00rncbcusers00000000000000// qtractorMidiEditSelect.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorMidiEditSelect.h" #include "qtractorMidiSequence.h" //------------------------------------------------------------------------- // qtractorMidiEditSelect -- MIDI event selection capsule. // Constructor. qtractorMidiEditSelect::qtractorMidiEditSelect (void) { m_pAnchorEvent = NULL; } // Default destructor. qtractorMidiEditSelect::~qtractorMidiEditSelect (void) { clear(); } // Event selection item lookup. qtractorMidiEditSelect::Item *qtractorMidiEditSelect::findItem ( qtractorMidiEvent *pEvent ) { // Check if this very event already exists... return m_items.value(pEvent, NULL); } // Item insertion method. void qtractorMidiEditSelect::addItem ( qtractorMidiEvent *pEvent, const QRect& rectEvent, const QRect& rectView, unsigned long iDeltaTime ) { m_items.insert(pEvent, new Item(rectEvent, rectView, iDeltaTime)); m_rectEvent = m_rectEvent.united(rectEvent); m_rectView = m_rectView.united(rectView); if (m_pAnchorEvent == NULL || m_pAnchorEvent->time() > pEvent->time()) m_pAnchorEvent = pEvent; } // Item selection method. void qtractorMidiEditSelect::selectItem ( qtractorMidiEvent *pEvent, const QRect& rectEvent, const QRect& rectView, bool bSelect, bool bToggle ) { Item *pItem = findItem(pEvent); if (pItem) { unsigned int flags = pItem->flags; if ( (!bSelect && (flags & 2) == 0) || (( bSelect && (flags & 3) == 3) && bToggle)) pItem->flags &= ~1; else if ( ( bSelect && (flags & 2) == 0) || ((!bSelect && (flags & 3) == 2) && bToggle)) pItem->flags |= 1; } else if (bSelect) addItem(pEvent, rectEvent, rectView); } // Selection commit method. void qtractorMidiEditSelect::update ( bool bCommit ) { // Remove unselected... int iUpdate = 0; ItemList::Iterator iter = m_items.begin(); const ItemList::Iterator& iter_end = m_items.end(); while (iter != iter_end) { Item *pItem = iter.value(); if (bCommit) { if (pItem->flags & 1) pItem->flags |= 2; else pItem->flags &= ~2; } if ((pItem->flags & 3) == 0) { delete pItem; iter = m_items.erase(iter); ++iUpdate; } else ++iter; } // Did we remove any? if (iUpdate > 0) commit(); } // Selection commit method. void qtractorMidiEditSelect::commit (void) { // Reset united selection rectangle... m_rectEvent.setRect(0, 0, 0, 0); m_rectView.setRect(0, 0, 0, 0); ItemList::ConstIterator iter = m_items.constBegin(); const ItemList::ConstIterator iter_end = m_items.constEnd(); for ( ; iter != iter_end; ++iter) { Item *pItem = iter.value(); m_rectEvent = m_rectEvent.united(pItem->rectEvent); m_rectView = m_rectView.united(pItem->rectView); } } // Reset event selection. void qtractorMidiEditSelect::clear (void) { m_rectEvent.setRect(0, 0, 0, 0); m_rectView.setRect(0, 0, 0, 0); qDeleteAll(m_items); m_items.clear(); m_pAnchorEvent = NULL; } // end of qtractorMidiEditSelect.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorClipFadeFunctor.h0000644000175000001440000000012211577214260022210 xustar000000000000000027 mtime=1308432560.720676 26 atime=1381134668.98808 29 ctime=1381134668.98808008 qtractor-0.5.11/src/qtractorClipFadeFunctor.h0000644000175000001440000000234211577214260021501 0ustar00rncbcusers00000000000000// qtractorClipFadeFunctor.h // /**************************************************************************** Copyright (C) 2010, rncbc aka Rui Nuno Capela. All rights reserved. Adapted and refactored from Robert Penner's easing equations. Copyright (C) 2001, Robert Penner. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorClipFadeFunctor_h #define __qtractorClipFadeFunctor_h #include "qtractorClip.h" #endif // __qtractorClipFadeFunctor_h // end of qtractorClipFade.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorTrackTime.h0000644000175000001440000000012312157362665021074 xustar000000000000000027 mtime=1371399605.725538 26 atime=1381134668.01508 30 ctime=1381134668.015080065 qtractor-0.5.11/src/qtractorTrackTime.h0000644000175000001440000000637012157362665020371 0ustar00rncbcusers00000000000000// qtractorTrackTime.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorTrackTime_h #define __qtractorTrackTime_h #include "qtractorScrollView.h" #include "qtractorTimeScale.h" #include // Forward declarations. class qtractorTracks; class QResizeEvent; class QMouseEvent; class QKeyEvent; //---------------------------------------------------------------------------- // qtractorTrackTime -- Track time scale widget. class qtractorTrackTime : public qtractorScrollView { Q_OBJECT public: // Constructor. qtractorTrackTime(qtractorTracks *pTracks, QWidget *pParent = 0); // Rectangular contents update. void updateContents(const QRect& rect); // Overall contents update. void updateContents(); protected: // Resize event handler. void resizeEvent(QResizeEvent *pResizeEvent); // Draw the time scale. void drawContents(QPainter *pPainter, const QRect& rect); // Check if some position header is to be dragged... bool dragHeadStart(const QPoint& pos); // Handle selection with mouse. void mousePressEvent(QMouseEvent *pMouseEvent); void mouseMoveEvent(QMouseEvent *pMouseEvent); void mouseReleaseEvent(QMouseEvent *pMouseEvent); // Tempo-map dialog accessor. void mouseDoubleClickEvent(QMouseEvent *pMouseEvent); // Reset drag/select state. void resetDragState(); // Keyboard event handler. void keyPressEvent(QKeyEvent *pKeyEvent); // Context menu request slot (dummy). void contextMenuEvent(QContextMenuEvent *); // Trap for help/tool-tip events. bool eventFilter(QObject *pObject, QEvent *pEvent); // Show dragging tooltip... void showToolTip(unsigned long iFrame) const; void showToolTip(const QRect& rect) const; protected slots: // To have timeline in h-sync with main track view. void contentsXMovingSlot(int cx, int cy); // (Re)create the time scale pixmap. void updatePixmap(int cx, int cy); private: // The logical parent binding. qtractorTracks *m_pTracks; // Local double-buffering pixmap. QPixmap m_pixmap; // The current selecting/dragging head stuff. enum DragState { DragNone = 0, DragStart, DragSelect, DragPlayHead, DragMarker, DragEditHead, DragEditTail, DragLoopStart, DragLoopEnd, DragPunchIn, DragPunchOut } m_dragState, m_dragCursor; QRect m_rectDrag; QPoint m_posDrag; qtractorTimeScale::Marker *m_pDragMarker; }; #endif // __qtractorTrackTime_h // end of qtractorTrackTime.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiControlObserver.h0000644000175000001440000000012312161335204023124 xustar000000000000000027 mtime=1371912836.382031 26 atime=1381134667.26408 30 ctime=1381134667.264080053 qtractor-0.5.11/src/qtractorMidiControlObserver.h0000644000175000001440000000710612161335204022417 0ustar00rncbcusers00000000000000// qtractorMidiControlObserver.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiControlObserver_h #define __qtractorMidiControlObserver_h #include "qtractorObserver.h" #include "qtractorMidiControl.h" // Forward declarations. class qtractorCurveList; //---------------------------------------------------------------------- // class qtractorMidiControlObserver -- MIDI controller observers. // class qtractorMidiControlObserver : public qtractorObserver { public: // Constructor. qtractorMidiControlObserver(qtractorSubject *pSubject); // Destructor. virtual ~qtractorMidiControlObserver(); // Key accessors. void setType(qtractorMidiControl::ControlType ctype) { m_ctype = ctype; } qtractorMidiControl::ControlType type() const { return m_ctype; } void setChannel(unsigned short iChannel) { m_iChannel = iChannel; } unsigned short channel() const { return m_iChannel; } void setParam(unsigned short iParam) { m_iParam = iParam; } unsigned short param() const { return m_iParam; } // Properties accessors. void setLogarithmic(bool bLogarithmic) { m_bLogarithmic = bLogarithmic; } bool isLogarithmic() const { return m_bLogarithmic; } void setFeedback(bool bFeedback) { m_bFeedback = bFeedback; } bool isFeedback() const { return m_bFeedback; } void setInvert(bool bInvert) { m_bInvert = bInvert; } bool isInvert() const { return m_bInvert; } void setHook(bool bHook) { m_bHook = bHook; } bool isHook() const { return m_bHook; } // Normalized scale accessors. void setScaleValue(float fScale) { setValue(valueFromScale(fScale, m_bLogarithmic)); } float scaleValue() const { return scaleFromValue(value(), m_bLogarithmic); } // MIDI mapped value converters. void setMidiValue(unsigned short iMidiValue); unsigned short midiValue() const; // Normalized scale convertors. float valueFromScale(float fScale, bool bLogarithmic) const; float scaleFromValue(float fValue, bool bLogarithmic) const; // Special indirect automation relatives accessors. void setCurveList(qtractorCurveList *pCurveList) { m_pCurveList = pCurveList; } qtractorCurveList *curveList() const { return m_pCurveList; } protected: // Updater. virtual void update(bool bUpdate); private: // Key members. qtractorMidiControl::ControlType m_ctype; unsigned short m_iChannel; unsigned short m_iParam; // Property members. bool m_bLogarithmic; bool m_bFeedback; bool m_bInvert; bool m_bHook; // Tracking/catch-up members. bool m_bMidiValueInit; bool m_bMidiValueSync; float m_fMidiValue; // Special indirect automation relatives. qtractorCurveList *m_pCurveList; }; #endif // __qtractorMidiControlObserver_h // end of qtractorMidiControlObserver.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiControlCommand.h0000644000175000001440000000012312156127233022720 xustar000000000000000027 mtime=1371057819.151017 26 atime=1381134666.91608 30 ctime=1381134666.916080047 qtractor-0.5.11/src/qtractorMidiControlCommand.h0000644000175000001440000000561212156127233022213 0ustar00rncbcusers00000000000000// qtractorMidiControlCommand.h // /**************************************************************************** Copyright (C) 2010-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiControlCommand_h #define __qtractorMidiControlCommand_h #include "qtractorCommand.h" #include "qtractorMidiControl.h" // Forward declarations... class qtractorMidiControlObserver; //---------------------------------------------------------------------- // class qtractorMidiControlObserverCommand - declaration. // class qtractorMidiControlObserverCommand : public qtractorCommand { public: // Constructor. qtractorMidiControlObserverCommand(const QString& sName, qtractorMidiControlObserver *pMidiObserver = NULL); protected: // Map/unmap observer methods. bool mapMidiObserver() const; bool unmapMidiObserver() const; private: // Instance variables. qtractorMidiControlObserver *m_pMidiObserver; }; //---------------------------------------------------------------------- // class qtractorMidiControlObserverMapCommand - declaration. // class qtractorMidiControlObserverMapCommand : public qtractorMidiControlObserverCommand { public: // Constructor. qtractorMidiControlObserverMapCommand(qtractorMidiControlObserver *pMidiObserver) : qtractorMidiControlObserverCommand( QObject::tr("set controller"), pMidiObserver) {} // MIDI control observer command methods. bool redo() { return mapMidiObserver(); } bool undo() { return unmapMidiObserver(); } }; //---------------------------------------------------------------------- // class qtractorMidiControlObserverUnmapCommand - declaration. // class qtractorMidiControlObserverUnmapCommand : public qtractorMidiControlObserverCommand { public: // Constructor. qtractorMidiControlObserverUnmapCommand(qtractorMidiControlObserver *pMidiObserver) : qtractorMidiControlObserverCommand( QObject::tr("reset controller"), pMidiObserver) {} // MIDI control observer command methods. bool redo() { return unmapMidiObserver(); } bool undo() { return mapMidiObserver(); } }; #endif // __qtractorMidiControlCommand_h // end of qtractorMidiControlCommand.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorPluginListView.h0000644000175000001440000000012312073012112022106 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134666.91708 30 ctime=1381134666.917080048 qtractor-0.5.11/src/qtractorPluginListView.h0000644000175000001440000001425512073012112021404 0ustar00rncbcusers00000000000000// qtractorPluginListView.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorPluginListView_h #define __qtractorPluginListView_h #include // Forward declarations. class qtractorPlugin; class qtractorPluginList; class qtractorPluginForm; class qtractorRubberBand; //---------------------------------------------------------------------------- // qtractorPluginListItem -- Plugin list item. class qtractorPluginListItem : public QListWidgetItem { public: // Constructors. qtractorPluginListItem(qtractorPlugin *pPlugin); // Destructor. ~qtractorPluginListItem(); // Plugin container accessor. qtractorPlugin *plugin() const; // Special plugin form accessor. qtractorPluginForm *pluginForm(); // Activation methods. void updateActivated(); // Last known item rectangle. void setDirectAccessWidth(int iDirectAccessWidth) { m_iDirectAccessWidth = iDirectAccessWidth; } int directAccessWidth() const { return m_iDirectAccessWidth; } protected: // Common item initializer. void initItem(qtractorPlugin *pPlugin); private: // The plugin reference. qtractorPlugin *m_pPlugin; // Last known item logical width. int m_iDirectAccessWidth; }; //---------------------------------------------------------------------------- // qtractorPluginListView -- Plugin chain list widget instance. // class qtractorPluginListView : public QListWidget { Q_OBJECT public: // Construcctor. qtractorPluginListView(QWidget *pParent = 0); // Destructor. ~qtractorPluginListView(); // Plugin list accessors. void setPluginList(qtractorPluginList *pPluginList); qtractorPluginList *pluginList() const; // Special scrollbar style accessors. void setTinyScrollBar(bool bTinyScrollBar); bool isTinyScrollBar() const; // Plugin list refreshner; void refresh(); // Master clean-up. void clear(); // Get an item index, given the plugin reference... int pluginItem(qtractorPlugin *pPlugin); // Common pixmap accessors. static QIcon *itemIcon(int iIndex); // Show insert pseudo-plugin audio bus connections. static void insertPluginBus(qtractorPlugin *pPlugin, int iBusMode); signals: // Plugin chain changed somehow. void contentsChanged(); public slots: // User interaction slots. void addPlugin(); void addInsertPlugin(); void addAuxSendPlugin(); void removePlugin(); void moveUpPlugin(); void moveDownPlugin(); void directAccessPlugin(); void propertiesPlugin(); void editPlugin(); protected slots: // User interaction slots. void activatePlugin(); void activateAllPlugins(); void deactivateAllPlugins(); void removeAllPlugins(); // Insert specific slots. void insertPluginOutputs(); void insertPluginInputs(); // Audio specific slots. void audioOutputs(); void audioOutputBus(); void audioOutputAutoConnect(); // Drop item slots. void dropMove(); void dropCopy(); void dropCancel(); // Simple click handler. void itemDoubleClickedSlot(QListWidgetItem *); void itemActivatedSlot(QListWidgetItem *); protected: // Move item on list. void moveItem(qtractorPluginListItem *pItem, qtractorPluginListItem *pNextItem); // Copy item on list. void copyItem(qtractorPluginListItem *pItem, qtractorPluginListItem *pNextItem); // Trap for help/tool-tip events. bool eventFilter(QObject *pObject, QEvent *pEvent); // To get precize clicking for in-place (de)activation, // and for drag-n-drop stuff -- reimplemented virtual methods. void mousePressEvent(QMouseEvent *pMouseEvent); void mouseMoveEvent(QMouseEvent *pMouseEvent); void mouseReleaseEvent(QMouseEvent *pMouseEvent); void dragEnterEvent(QDragEnterEvent *pDragEnterEvent); void dragMoveEvent(QDragMoveEvent *pDragMoveEvent); void dragLeaveEvent(QDragLeaveEvent *); void dropEvent(QDropEvent *pDropEvent); void wheelEvent(QWheelEvent *pWheelEvent); // Drag-n-drop stuff. bool canDropEvent(QDropEvent *pDropEvent); bool canDropItem(QDropEvent *pDropEvent); // Ensure given item is brought to viewport visibility... void ensureVisibleItem(qtractorPluginListItem *pItem); // Show and move rubber-band item. void moveRubberBand(qtractorPluginListItem *pDropItem); // Context menu event handler. void contextMenuEvent(QContextMenuEvent *pContextMenuEvent); // MIDI codec methods (static). static void encodeItem (QMimeData *pMimeData, qtractorPluginListItem *pItem); static bool canDecodeItem(const QMimeData *pMimeData); static qtractorPluginListItem *decodeItem(const QMimeData *pMimeData); // Show insert pseudo-plugin audio bus connections. void insertPluginBus(int iBusMode); // Direct access parameter handle. void dragDirectAccess(const QPoint& pos); private: // Instance variables. qtractorPluginList *m_pPluginList; // The current dragging item stuff. enum DragState { DragNone = 0, DragDirectAccess } m_dragState, m_dragCursor; // The mouse clicked item for in-place (de)activation. qtractorPluginListItem *m_pClickedItem; // The point from where drag started. QPoint m_posDrag; // Item we'll eventually drag around. qtractorPluginListItem *m_pDragItem; // Item we'll eventually drop something. qtractorPluginListItem *m_pDropItem; // To show the point where drop will go. qtractorRubberBand *m_pRubberBand; // Common pixmap stuff. static QIcon *g_pItemIcons[2]; static int g_iItemRefCount; }; #endif // __qtractorPluginListView_h // end of qtractorPluginListView.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditView.h0000644000175000001440000000012312156061017021516 xustar000000000000000027 mtime=1371038223.355862 26 atime=1381134671.09008 30 ctime=1381134671.090080114 qtractor-0.5.11/src/qtractorMidiEditView.h0000644000175000001440000000673112156061017021014 0ustar00rncbcusers00000000000000// qtractorMidiEditView.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiEditView_h #define __qtractorMidiEditView_h #include "qtractorScrollView.h" #include "qtractorMidiEvent.h" #include // Forward declarations. class qtractorMidiEditor; class QResizeEvent; class QMouseEvent; class QKeyEvent; class QToolButton; //---------------------------------------------------------------------------- // qtractorMidiEditView -- MIDI sequence main view widget. class qtractorMidiEditView : public qtractorScrollView { Q_OBJECT public: // Constructor. qtractorMidiEditView(qtractorMidiEditor *pEditor, QWidget *pParent); // Destructor. ~qtractorMidiEditView(); // Update sequence view content height. void updateContentsHeight(); // Update sequence view content width. void updateContentsWidth(int iContentsWidth = 0); // Contents update overloaded methods. void updateContents(const QRect& rect); void updateContents(); // Current event selection accessors. void setEventType(qtractorMidiEvent::EventType eventType); qtractorMidiEvent::EventType eventType() const; protected: // Virtual size hint. QSize sizeHint() const { return QSize(480, 240); } // Scrollbar/tools layout management. void setVBarGeometry(QScrollBar& vbar, int x, int y, int w, int h); // Resize event handler. void resizeEvent(QResizeEvent *pResizeEvent); // Draw the track view void drawContents(QPainter *pPainter, const QRect& rect); // Focus lost event. void focusOutEvent(QFocusEvent *pFocusEvent); // Keyboard event handler (made public explicitly). void keyPressEvent(QKeyEvent *pKeyEvent); // Handle item selection with mouse. void mousePressEvent(QMouseEvent *pMouseEvent); void mouseMoveEvent(QMouseEvent *pMouseEvent); void mouseReleaseEvent(QMouseEvent *pMouseEvent); // Handle zoom with mouse wheel. void wheelEvent(QWheelEvent *pWheelEvent); // Trap for help/tool-tip and leave events. bool eventFilter(QObject *pObject, QEvent *pEvent); protected slots: // To have track view in sync with track list. void contentsXMovingSlot(int cx, int cy); void contentsYMovingSlot(int cx, int cy); // (Re)create the complete track view pixmap. void updatePixmap(int cx, int cy); private: // The logical parent binding. qtractorMidiEditor *m_pEditor; // Local zoom control widgets. QToolButton *m_pVzoomIn; QToolButton *m_pVzoomOut; QToolButton *m_pVzoomReset; // Local double-buffering pixmap. QPixmap m_pixmap; // Current selection holder. qtractorMidiEvent::EventType m_eventType; }; #endif // __qtractorMidiEditView_h // end of qtractorMidiEditView.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorEditRangeForm.ui0000644000175000001440000000012312165325675022064 xustar000000000000000027 mtime=1372957629.743777 26 atime=1381134667.92708 30 ctime=1381134667.933080064 qtractor-0.5.11/src/qtractorEditRangeForm.ui0000644000175000001440000002373412165325675021364 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorEditRangeForm 0 0 340 280 Qt::StrongFocus Range - Qtractor :/images/qtractor.png:/images/qtractor.png Range Selection range &Selection false Loop range &Loop false Punch range &Punch false Edit range &Edit false Custom range &Custom true St&art: RangeStartSpinBox 120 0 Clip start Qt::Horizontal QSizePolicy::Fixed 14 14 En&d: RangeEndSpinBox 120 0 Clip offset Qt::Vertical 8 8 Options Apply to clips in range Cl&ips true Apply to Automation nodes in range A&utomation true Apply to Loop points in range L&oop Apply to Punch In/Out points in range Pu&nch Apply to location Markers in range Mar&kers Apply to Tempo Map nodes in range Te&mpo Map &Format Time display format Frames Time BBT Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qtractorTimeSpinBox QSpinBox
qtractorSpinBox.h
SelectionRangeRadioButton LoopRangeRadioButton PunchRangeRadioButton EditRangeRadioButton CustomRangeRadioButton RangeStartSpinBox RangeEndSpinBox ClipsCheckBox AutomationCheckBox LoopCheckBox PunchCheckBox MarkersCheckBox TempoMapCheckBox FormatComboBox DialogButtonBox
qtractor-0.5.11/src/PaxHeaders.10084/qtractorPluginCommand.h0000644000175000001440000000012311713063454021735 xustar000000000000000027 mtime=1328310060.341966 26 atime=1381134667.59208 30 ctime=1381134667.592080058 qtractor-0.5.11/src/qtractorPluginCommand.h0000644000175000001440000001772111713063454021234 0ustar00rncbcusers00000000000000// qtractorPluginCommand.h // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorPluginCommand_h #define __qtractorPluginCommand_h #include "qtractorCommand.h" #include "qtractorPlugin.h" #include // Forward declarations... class qtractorAuxSendPlugin; class qtractorPluginPortWidget; class qtractorMidiManager; //---------------------------------------------------------------------- // class qtractorPluginCommand - declaration. // class qtractorPluginCommand : public qtractorCommand { public: // Constructor. qtractorPluginCommand(const QString& sName, qtractorPlugin *pPlugin = NULL); // Destructor. virtual ~qtractorPluginCommand(); // Plugin list accessors. const QList& plugins() const { return m_plugins; } void addPlugin(qtractorPlugin *pPlugin) { m_plugins.append(pPlugin); } protected: // Add new plugin(s) command method. bool addPlugins(); // Remove existing plugin(s) command method. bool removePlugins(); private: // Instance variables. QList m_plugins; }; //---------------------------------------------------------------------- // class qtractorAddPluginCommand - declaration. // class qtractorAddPluginCommand : public qtractorPluginCommand { public: // Constructor. qtractorAddPluginCommand(qtractorPlugin *pPlugin = NULL); // Plugin insertion command methods. bool redo(); bool undo(); }; //---------------------------------------------------------------------- // class qtractorAddInsertPluginCommand - declaration. // class qtractorAddInsertPluginCommand : public qtractorPluginCommand { public: // Constructor. qtractorAddInsertPluginCommand(qtractorPlugin *pPlugin = NULL); // Plugin insertion command methods. bool redo(); bool undo(); }; //---------------------------------------------------------------------- // class qtractorAddAuxSendPluginCommand - declaration. // class qtractorAddAuxSendPluginCommand : public qtractorPluginCommand { public: // Constructor. qtractorAddAuxSendPluginCommand(qtractorPlugin *pPlugin = NULL); // Plugin insertion command methods. bool redo(); bool undo(); }; //---------------------------------------------------------------------- // class qtractorAuxSendPluginCommand - declaration. // class qtractorAuxSendPluginCommand : public qtractorPluginCommand { public: // Constructor. qtractorAuxSendPluginCommand(qtractorAuxSendPlugin *pAuxSendPlugin, const QString& sAudioBusName); // Plugin insertion command methods. bool redo(); bool undo(); private: // Instance variables. QString m_sAudioBusName; }; //---------------------------------------------------------------------- // class qtractorRemovePluginCommand - declaration. // class qtractorRemovePluginCommand : public qtractorPluginCommand { public: // Constructor. qtractorRemovePluginCommand(qtractorPlugin *pPlugin = NULL); // Plugin-removal command methods. bool redo(); bool undo(); }; //---------------------------------------------------------------------- // class qtractorInsertPluginCommand - declaration. // class qtractorInsertPluginCommand : public qtractorPluginCommand { public: // Constructor. qtractorInsertPluginCommand(const QString& sName, qtractorPlugin *pPlugin, qtractorPlugin *pNextPlugin); // Plugin-move command methods. bool redo(); bool undo(); protected: // The anchor plugin reference. void setNextPlugin(qtractorPlugin *pNextPlugin) { m_pNextPlugin = pNextPlugin; } qtractorPlugin *nextPlugin() const { return m_pNextPlugin; } private: // Instance variables. qtractorPlugin *m_pNextPlugin; }; //---------------------------------------------------------------------- // class qtractorMovePluginCommand - declaration. // class qtractorMovePluginCommand : public qtractorInsertPluginCommand { public: // Constructor. qtractorMovePluginCommand(qtractorPlugin *pPlugin, qtractorPlugin *pNextPlugin, qtractorPluginList *pPluginList); // Plugin-move command methods. bool redo(); bool undo(); private: // Instance variables. qtractorPluginList *m_pPluginList; }; //---------------------------------------------------------------------- // class qtractorActivatePluginCommand - declaration. // class qtractorActivatePluginCommand : public qtractorPluginCommand { public: // Constructor. qtractorActivatePluginCommand(qtractorPlugin *pPlugin, bool bActivated); // Plugin-activate command methods. bool redo(); bool undo(); private: // Instance variables. bool m_bActivated; }; //---------------------------------------------------------------------- // class qtractorResetPluginCommand - declaration. // class qtractorResetPluginCommand : public qtractorPluginCommand { public: // Constructor. qtractorResetPluginCommand(qtractorPlugin *pPlugin); // Plugin-reset command methods. bool redo(); bool undo(); private: // Instance variables. QString m_sPreset; QStringList m_vlist; }; //---------------------------------------------------------------------- // class qtractorPresetPluginCommand - declaration. // class qtractorPresetPluginCommand : public qtractorPluginCommand { public: // Constructor. qtractorPresetPluginCommand(qtractorPlugin *pPlugin, const QString& sPreset, const QStringList& vlist); // Plugin-preset command methods. bool redo(); bool undo(); private: // Instance variables. QString m_sPreset; QStringList m_vlist; }; //---------------------------------------------------------------------- // class qtractorPluginParamCommand - declaration. // class qtractorPluginParamCommand : public qtractorCommand { public: // Constructor. qtractorPluginParamCommand( qtractorPluginParam *pParam, float fValue, bool bUpdate); // Plugin-port command methods. bool redo(); bool undo(); // Plugin-port accessor. qtractorPluginParam *param() const { return m_pParam; } // Plugin-port value retrieval. float value() const { return m_fValue; } // Last known panning predicate. float prevValue() const { return m_fPrevValue; } private: // Instance variables. qtractorPluginParam *m_pParam; float m_fValue; bool m_bUpdate; float m_fPrevValue; }; //---------------------------------------------------------------------- // class qtractorAudioOutputBusCommand - declaration. // class qtractorAudioOutputBusCommand : public qtractorCommand { public: // Constructor. qtractorAudioOutputBusCommand(qtractorMidiManager *pMidiManager, bool bAudioOutputBus, bool bAudioOutputAutoConnect); // Plugin audio ouput bus command methods. bool redo(); bool undo(); private: // Instance variables. qtractorMidiManager *m_pMidiManager; bool m_bAudioOutputBus; bool m_bAudioOutputAutoConnect; }; //---------------------------------------------------------------------- // class qtractorDirectAccessParamCommand - declaration. // class qtractorDirectAccessParamCommand : public qtractorPluginCommand { public: // Constructor. qtractorDirectAccessParamCommand(qtractorPlugin *pPlugin, long iDirectAccessParamIndex); // Plugin-change command methods. bool redo(); bool undo(); private: // Instance variables. long m_iDirectAccessParamIndex; }; #endif // __qtractorPluginCommand_h // end of qtractorPluginCommand.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorClipFadeFunctor.cpp0000644000175000001440000000012311577214260022544 xustar000000000000000027 mtime=1308432560.720676 26 atime=1381134667.28308 30 ctime=1381134667.315080054 qtractor-0.5.11/src/qtractorClipFadeFunctor.cpp0000644000175000001440000001435611577214260022044 0ustar00rncbcusers00000000000000// qtractorClipFadeFunctor.cpp // /**************************************************************************** Copyright (C) 2010, rncbc aka Rui Nuno Capela. All rights reserved. Adapted and refactored from Robert Penner's easing equations. Copyright (C) 2001, Robert Penner. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ /* TERMS OF USE - EASING EQUATIONS Open source under the BSD License. Copyright (C) 2001 Robert Penner All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "qtractorClipFadeFunctor.h" //--------------------------------------------------------------------------- // Functor argument normalization. // // t = (x - x0) / (x1 - x0) // a = y1 - y0 // b = y0 // // Linear fade. // struct FadeLinear { float operator() (float t, float a, float b) const { return a * t + b; } }; // Quadratic (t^2) fade in: accelerating from zero velocity. // struct FadeInQuad { float operator() (float t, float a, float b) const { return a * (t * t) + b; } }; // Quadratic (t^2) fade out: decelerating to zero velocity. // struct FadeOutQuad { float operator() (float t, float a, float b) const { return a * (t * (2.0f - t)) + b; } }; // Quadratic (t^2) fade in-out: acceleration until halfway, then deceleration. // struct FadeInOutQuad { float operator() (float t, float a, float b) const { t *= 2.0f; if (t < 1.0f) { return 0.5f * a * (t * t) + b; } else { t -= 1.0f; return 0.5f * a * (1.0f - (t * (t - 2.0f))) + b; } } }; // Cubic (t^3) fade in: accelerating from zero velocity. // struct FadeInCubic { float operator() (float t, float a, float b) const { return a * (t * t * t) + b; } }; // Cubic (t^3) fade out: decelerating from zero velocity. // struct FadeOutCubic { float operator() (float t, float a, float b) const { t -= 1.0f; return a * ((t * t * t) + 1.0f) + b; } }; // Cubic (t^3) fade in-out: acceleration until halfway, then deceleration. // struct FadeInOutCubic { float operator() (float t, float a, float b) const { t *= 2.0f; if (t < 1.0f) { return 0.5f * a * (t * t * t) + b; } else { t -= 2.0f; return 0.5f * a * ((t * t * t) + 2.0f) + b; } } }; // Fade model class. // struct FadeMode { FadeMode(float y0, float y1) : a(y1 - y0), b(y0) {} float a, b; }; // Fade-in mode. // struct FadeInMode : public FadeMode { FadeInMode() : FadeMode(0.0f, 1.0f) {} }; // Fade-out mode. // struct FadeOutMode : public FadeMode { FadeOutMode() : FadeMode(1.0f, 0.0f) {} }; // Fade functor template class. // template class FadeCurve : public qtractorClip::FadeFunctor { public: FadeCurve() : m_mode(M()), m_func(F()) {} float operator() (float t) const { return m_func(t, m_mode.a, m_mode.b); } private: M m_mode; F m_func; }; // Fade functor factory class (static). // qtractorClip::FadeFunctor *qtractorClip::createFadeFunctor ( FadeMode fadeMode, FadeType fadeType ) { switch (fadeMode) { case FadeIn: switch (fadeType) { case Linear: return new FadeCurve (); case InQuad: return new FadeCurve (); case OutQuad: return new FadeCurve (); case InOutQuad: return new FadeCurve (); case InCubic: return new FadeCurve (); case OutCubic: return new FadeCurve (); case InOutCubic: return new FadeCurve (); default: break; } break; case FadeOut: switch (fadeType) { case Linear: return new FadeCurve (); case InQuad: return new FadeCurve (); case OutQuad: return new FadeCurve (); case InOutQuad: return new FadeCurve (); case InCubic: return new FadeCurve (); case OutCubic: return new FadeCurve (); case InOutCubic: return new FadeCurve (); default: break; } break; default: break; } return NULL; } // end of qtractorClipFadeFunctor.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorNsmClient.h0000644000175000001440000000012312145664254021101 xustar000000000000000027 mtime=1368877228.984108 26 atime=1381134667.36808 30 ctime=1381134667.368080055 qtractor-0.5.11/src/qtractorNsmClient.h0000644000175000001440000000645712145664254020404 0ustar00rncbcusers00000000000000// qtractorNsmClient.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorNsmClient_h #define __qtractorNsmClient_h #include #ifdef CONFIG_LIBLO #include #endif //--------------------------------------------------------------------------- // qtractorNsmClient - NSM OSC client agent. class qtractorNsmClient : public QObject { Q_OBJECT public: // Constructor. qtractorNsmClient(const QString& nsm_url, QObject *pParent = 0); // Destructor. ~qtractorNsmClient(); // Session activation accessor. bool is_active() const; // Session manager accessors. const QString& manager() const; const QString& capabilities() const; // Session client accessors. const QString& path_name() const; const QString& display_name() const; const QString& client_id() const; // Session client methods. void announce(const QString& app_name, const QString& capabilities); void dirty(bool is_dirty); void visible(bool is_visible); void progress(float percent); void message(int priority, const QString& mesg); // Status/error codes enum ReplyCode { ERR_OK = 0, ERR_GENERAL = -1, ERR_INCOMPATIBLE_API = -2, ERR_BLACKLISTED = -3, ERR_LAUNCH_FAILED = -4, ERR_NO_SUCH_FILE = -5, ERR_NO_SESSION_OPEN = -6, ERR_UNSAVED_CHANGES = -7, ERR_NOT_NOW = -8, ERR_BAD_PROJECT = -9, ERR_CREATE_FAILED = -10 }; // Session client reply methods. void open_reply(ReplyCode reply_code = ERR_OK); void save_reply(ReplyCode reply_code = ERR_OK); // Server methods response methods. void nsm_announce_error( const char *mesg); void nsm_announce_reply( const char *mesg, const char *manager, const char *capabilities); void nsm_open( const char *path_name, const char *display_name, const char *client_id); void nsm_save(); void nsm_loaded(); void nsm_show(); void nsm_hide(); protected: void reply(const QString& path, ReplyCode reply_code); signals: // Session client callbacks. void active(bool is_active); void open(); void save(); void loaded(); void show(); void hide(); private: // Instance variables. #ifdef CONFIG_LIBLO lo_address m_address; lo_server_thread m_thread; lo_server m_server; #endif bool m_active; QString m_manager; QString m_capabilities; QString m_path_name; QString m_display_name; QString m_client_id; }; #endif // __qtractorNsmClient_h // end of qtractorNsmClient.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorFiles.h0000644000175000001440000000012312166526620020244 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134666.35908 30 ctime=1381134666.359080039 qtractor-0.5.11/src/qtractorFiles.h0000644000175000001440000000777412166526620017552 0ustar00rncbcusers00000000000000// qtractorFiles.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorFiles_h #define __qtractorFiles_h #include "qtractorAudioListView.h" #include "qtractorMidiListView.h" #include // Forward declarations. class qtractorFilesTabWidget; class QHBoxLayout; class QToolButton; //------------------------------------------------------------------------- // qtractorFiles - File/Groups dockable window. // class qtractorFiles : public QDockWidget { Q_OBJECT public: // Constructor. qtractorFiles(QWidget *pParent); // Destructor. ~qtractorFiles(); // The fixed tab page indexes. enum PageIndex { Audio = 0, Midi = 1 }; // File list view accessors. qtractorAudioListView *audioListView() const; qtractorMidiListView *midiListView() const; // Clear evrything on sight. void clear(); // Check whether one of the widgets has focus (oveerride method). bool hasFocus() const; // Tell whether a file item is currently selected. bool isFileSelected() const; // File addition Convenience helper methods. void addAudioFile (const QString& sFilename, bool bAutoRemove); void addMidiFile (const QString& sFilename, bool bAutoRemove); // File selection Convenience helper methods. void selectAudioFile (const QString& sFilename); void selectMidiFile (const QString& sFilename, int iTrackChannel); // Audition/pre-listening player methods. void setPlayState(bool bOn); bool isPlayState() const; public slots: // Cut current file item(s) to clipboard. void cutItemSlot(); // Copy current file item(s) to clipboard. void copyItemSlot(); // Paste file item(s) from clipboard. void pasteItemSlot(); // Remove current group/file item(s). void removeItemSlot(); protected slots: // Add a new group item below the current one. void newGroupSlot(); // Add a new file item below the current group one. void openFileSlot(); // Rename current group/file item. void renameItemSlot(); // Audition/pre-listening player slots. void playSlot(bool bOn); // Clean-up unused file items. void cleanupSlot(); // Tab page switch slots. void pageAudioSlot(); void pageMidiSlot(); // Usual stabilizing slot. void stabilizeSlot(); protected: // Just about to notify main-window that we're closing. void closeEvent(QCloseEvent *); // Context menu request event handler. void contextMenuEvent(QContextMenuEvent *); // Retrieve current selected file list view. qtractorFileListView *currentFileListView() const; private: // File type selection tab widget. qtractorFilesTabWidget *m_pTabWidget; // Specific file type widgets. qtractorAudioListView *m_pAudioListView; qtractorMidiListView *m_pMidiListView; // Audition/pre-listening controls. QWidget *m_pPlayWidget; QHBoxLayout *m_pPlayLayout; QToolButton *m_pPlayButton; int m_iPlayUpdate; // List view actions. QAction *m_pNewGroupAction; QAction *m_pOpenFileAction; QAction *m_pCutItemAction; QAction *m_pCopyItemAction; QAction *m_pPasteItemAction; QAction *m_pRenameItemAction; QAction *m_pRemoveItemAction; QAction *m_pPlayItemAction; QAction *m_pCleanupAction; }; #endif // __qtractorFiles_h // end of qtractorFiles.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorTrack.h0000644000175000001440000000012212217361266020245 xustar000000000000000026 mtime=1379787446.61859 26 atime=1381134671.21008 30 ctime=1381134671.211080116 qtractor-0.5.11/src/qtractorTrack.h0000644000175000001440000002546312217361266017547 0ustar00rncbcusers00000000000000// qtractorTrack.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorTrack_h #define __qtractorTrack_h #include "qtractorList.h" #include "qtractorMidiControl.h" #include // Forward declarations. class qtractorSession; class qtractorDocument; class qtractorInstrumentList; class qtractorPluginList; class qtractorMonitor; class qtractorClip; class qtractorBus; class qtractorSubject; class qtractorMidiControlObserver; class qtractorAudioBufferThread; class qtractorCurveList; class qtractorCurveFile; class qtractorCurve; // Special forward declarations. class QDomElement; class QPainter; class QRect; //------------------------------------------------------------------------- // qtractorTrack -- Track container. class qtractorTrack : public qtractorList::Link { public: // Track type symbology. enum TrackType { None = 0, Audio, Midi }; // Tool button specific types: enum ToolType { Record, Mute, Solo }; // Constructor. qtractorTrack(qtractorSession *pSession, TrackType trackType = None); // Default constructor. ~qtractorTrack(); // Reset track. void clear(); // Track open/close methods. bool open(); void close(); // Session accessor. qtractorSession *session() const; // Track name accessors. void setTrackName(const QString& sTrackName); const QString& trackName() const; void updateTrackName(); // Track type accessors. void setTrackType(TrackType trackType); TrackType trackType() const; // Record monitoring state accessors. void setMonitor(bool bMonitor); bool isMonitor() const; // Record status accessors. void setRecord(bool bRecord); bool isRecord() const; // Mute status accessors. void setMute(bool bMute); bool isMute() const; // Solo status accessors. void setSolo(bool bSolo); bool isSolo() const; // Track gain (volume) accessor. void setGain(float fGain); float gain() const; float prevGain() const; // Track stereo-panning accessor. void setPanning(float fPanning); float panning() const; float prevPanning() const; // MIDI specific: track-tag accessors. void setMidiTag(unsigned short iMidiTag); unsigned short midiTag() const; // MIDI specific: omni (capture) mode acessors. void setMidiOmni(bool bMidiOmni); bool isMidiOmni() const; // MIDI specific: channel acessors. void setMidiChannel(unsigned short iMidiChannel); unsigned short midiChannel() const; // MIDI specific: bank select method acessors (optional). void setMidiBankSelMethod(int iMidiBankSelMethod); int midiBankSelMethod() const; // MIDI specific: bank acessors (optional). void setMidiBank(int iMidiBank); int midiBank() const; // MIDI specific: program acessors (optional). void setMidiProg(int iMidiProg); int midiProg() const; // Assigned bus name accessors. void setInputBusName(const QString& sBusName); const QString& inputBusName() const; void setOutputBusName(const QString& sBusName); const QString& outputBusName() const; // Assigned bus accessors. qtractorBus *inputBus() const; qtractorBus *outputBus() const; // Track monitor accessors. qtractorMonitor *monitor() const; // Track plugin-chain accessor. qtractorPluginList *pluginList() const; // Base height (in pixels). enum { HeightMin = 24, HeightBase = 72 }; // Normalized view height accessors. void updateHeight(); void setHeight(int iHeight); int height() const; // Visual height accessors. void updateZoomHeight(); void setZoomHeight(int iZoomHeight); int zoomHeight() const; // Clip list management methods. const qtractorList& clips() const; void addClip(qtractorClip *pClip); void insertClip(qtractorClip *pClip); void unlinkClip(qtractorClip *pClip); void removeClip(qtractorClip *pClip); // Current clip on record (capture). void setClipRecord(qtractorClip *pClipRecord, unsigned long iClipRecordStart = 0); qtractorClip *clipRecord() const; // Current clip on record absolute start frame (capture). unsigned long clipRecordStart() const; unsigned long clipRecordEnd(unsigned long iFrameTime) const; // Background color accessors. void setBackground(const QColor& bg); const QColor& background() const; // Foreground color accessors. void setForeground(const QColor& fg); const QColor& foreground() const; // Generate a default track color. static QColor trackColor(int iTrack); // Track special process cycle executive. void process(qtractorClip *pClip, unsigned long iFrameStart, unsigned long iFrameEnd); // Track special process record executive (audio recording only). void process_record( unsigned long iFrameStart, unsigned long iFrameEnd); // Track special process automation executive. void process_curve(unsigned long iFrame); // Track paint method. void drawTrack(QPainter *pPainter, const QRect& trackRect, unsigned long iTrackStart, unsigned long iTrackEnd, qtractorClip *pClip = NULL); // MIDI track instrument patching. void setMidiPatch(qtractorInstrumentList *pInstruments); // Track loop point setler. void setLoop(unsigned long iLoopStart, unsigned long iLoopEnd); // Update all clips editors. void updateClipEditors(); // Audio buffer ring-cache (playlist) methods. qtractorAudioBufferThread *syncThread(); // Track state (monitor, record, mute, solo) button setup. qtractorSubject *monitorSubject() const; qtractorSubject *recordSubject() const; qtractorSubject *muteSubject() const; qtractorSubject *soloSubject() const; qtractorMidiControlObserver *monitorObserver() const; qtractorMidiControlObserver *recordObserver() const; qtractorMidiControlObserver *muteObserver() const; qtractorMidiControlObserver *soloObserver() const; // Track state (monitor) notifier (proto-slot). void monitorChangeNotify(bool bOn); // Track state (record, mute, solo) notifier (proto-slot). void stateChangeNotify(ToolType toolType, bool bOn); // Document element methods. bool loadElement(qtractorDocument *pDocument, QDomElement *pElement); bool saveElement(qtractorDocument *pDocument, QDomElement *pElement) const; // Load/save track state (record, mute, solo) controllers (MIDI). void loadControllers(QDomElement *pElement); void saveControllers(qtractorDocument *pDocument, QDomElement *pElement) const; // Map track state (record, mute, solo) controllers (MIDI). void mapControllers(); // Track automation curve list accessor. qtractorCurveList *curveList() const; // Track automation curve serializer accessor. qtractorCurveFile *curveFile() const; // Track automation current curve accessor. qtractorCurve *currentCurve() const; // Track automation curve serialization methods. static void loadCurveFile( QDomElement *pElement, qtractorCurveFile *pCurveFile); void saveCurveFile(qtractorDocument *pDocument, QDomElement *pElement, qtractorCurveFile *pCurveFile) const; void applyCurveFile(qtractorCurveFile *pCurveFile) const; // Track properties structure. struct Properties { // Default constructor. Properties() { clear(); } // Copy constructor. Properties(const Properties& props) { copy(props); } // Assignment operator, Properties& operator=(const Properties& props) { return copy(props); } // Helper copy method. Properties& copy(const Properties& props); // Helper clear/reset method. void clear(); // Members. QString trackName; TrackType trackType; bool monitor; bool record; bool mute; bool solo; float gain; float panning; QString inputBusName; QString outputBusName; bool midiOmni; unsigned short midiChannel; int midiBankSelMethod; int midiBank; int midiProg; QColor foreground; QColor background; }; // Alternate properties accessor. Properties& properties(); // Track type textual helper methods. static TrackType trackTypeFromText (const QString& sText); static QString textFromTrackType (TrackType trackType); // Take(record) descriptor/id registry methods. class TakeInfo; TakeInfo *takeInfo(int iTakeID) const; int takeInfoId(TakeInfo *pTakeInfo) const; int takeInfoNew(TakeInfo *pTakeInfo) const; void takeInfoAdd(int iTakeID, TakeInfo *pTakeInfo) const; void clearTakeInfo() const; // Update tracks/list-view. void updateTracks(); private: qtractorSession *m_pSession; // Session reference. Properties m_props; // Track properties. qtractorBus *m_pInputBus; // Track assigned input bus. qtractorBus *m_pOutputBus; // Track assigned input bus. qtractorMonitor *m_pMonitor; // Track monitor. unsigned short m_iMidiTag; // MIDI specific: track-tag; int m_iHeight; // View height (normalized). int m_iZoomHeight; // View height (zoomed). qtractorList m_clips; // List of clips. qtractorClip *m_pClipRecord; // Current clip on record (capture). unsigned long m_iClipRecordStart; // Current clip on record start frame. qtractorPluginList *m_pPluginList; // Plugin chain (audio). // Audio buffer ring-cache (playlist). qtractorAudioBufferThread *m_pSyncThread; // MIDI track/channel (volume, panning) observers. class MidiVolumeObserver; class MidiPanningObserver; MidiVolumeObserver *m_pMidiVolumeObserver; MidiPanningObserver *m_pMidiPanningObserver; // State (monitor, record, mute, solo) observer stuff. qtractorMidiControlObserver *m_pMonitorObserver; class StateObserver; StateObserver *m_pRecordObserver; StateObserver *m_pMuteObserver; StateObserver *m_pSoloObserver; qtractorSubject *m_pMonitorSubject; qtractorSubject *m_pRecordSubject; qtractorSubject *m_pMuteSubject; qtractorSubject *m_pSoloSubject; qtractorMidiControl::Controllers m_controllers; qtractorCurveFile *m_pCurveFile; // Take(record) descriptor/id registry. mutable QHash m_idtakes; mutable QHash m_takeids; // MIDI bank/program observer. class MidiProgramObserver; MidiProgramObserver *m_pMidiProgramObserver; }; #endif // __qtractorTrack_h // end of qtractorTrack.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorTrackView.h0000644000175000001440000000012312222775622021102 xustar000000000000000027 mtime=1380711314.912284 26 atime=1381134671.19908 30 ctime=1381134671.200080115 qtractor-0.5.11/src/qtractorTrackView.h0000644000175000001440000003641712222775622020404 0ustar00rncbcusers00000000000000// qtractorTrackView.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorTrackView_h #define __qtractorTrackView_h #include "qtractorScrollView.h" #include "qtractorRubberBand.h" #include "qtractorTrack.h" #include "qtractorCurve.h" #include // Forward declarations. class qtractorTracks; class qtractorClipSelect; class qtractorCurveSelect; class qtractorMidiSequence; class qtractorSessionCursor; class qtractorTrackListItem; class qtractorCurveEditCommand; class QToolButton; class QDragEnterEvent; class QDragLeaveEvent; class QDragMoveEvent; class QDropEvent; class QMouseEvent; class QResizeEvent; class QKeyEvent; class QMimeData; class QCursor; //---------------------------------------------------------------------------- // qtractorTrackViewInfo -- Track view state info. struct qtractorTrackViewInfo { int trackIndex; // Track index. unsigned long trackStart; // First track frame on view. unsigned long trackEnd; // Last track frame on view. QRect trackRect; // The track view rectangle. }; //---------------------------------------------------------------------------- // qtractorTrackView -- Track view widget. class qtractorTrackView : public qtractorScrollView { Q_OBJECT public: // Constructor. qtractorTrackView(qtractorTracks *pTracks, QWidget *pParent = 0); // Destructor. ~qtractorTrackView(); // Track view state reset. void clear(); // Update track view content height. void updateContentsHeight(); // Update track view content width. void updateContentsWidth(int iContentsWidth = 0); // Contents update overloaded methods. void updateContents(const QRect& rect); void updateContents(); // Special recording visual feedback. void updateContentsRecord(); // The current clip selection mode. enum SelectMode { SelectClip, SelectRange, SelectRect }; enum SelectEdit { EditNone = 0, EditHead = 1, EditTail = 2, EditBoth = 3 }; // Selection flags enum { SelectNone = 0, SelectClear = 1, SelectToggle = 2, SelectCommit = 4 }; // Convert selection flags from keyboard modifiers. static int selectFlags(const Qt::KeyboardModifiers modifiers); // Clip selection mode accessors. void setSelectMode(SelectMode selectMode); SelectMode selectMode() const; // Select every clip under a given (rubber-band) rectangle. void selectClipRect(const QRect& rectDrag, SelectMode selectMode, int flags, SelectEdit selectEdit = EditNone); // Select every clip of a given track-range. void selectClipTrackRange(qtractorTrack *pTrackPtr, bool bReset = true); // Select every clip of a given track. void selectClipTrack(qtractorTrack *pTrackPtr, bool bReset = true); // Select all clip contents. void selectClipAll(); // Invert selection on all tracks and clips. void selectClipInvert(); // Select all clips of given filename and track/channel. void selectClipFile(qtractorTrack::TrackType trackType, const QString& sFilename, int iTrackChannel, bool bSelect); // Select curve nodes under a given (rubber-band) rectangle. void selectCurveRect(const QRect& rectDrag, SelectMode selectMode, int flags, SelectEdit selectEdit = EditNone); // Select every current curve/automation node of a given track-range. void selectCurveTrackRange(qtractorTrack *pTrackPtr, bool bReset = true); // Select every current curve/automation node of a given track. void selectCurveTrack(qtractorTrack *pTrackPtr, bool bReset = true); // Select all current track curve/automation nodes. void selectCurveAll(); // Invert selection on current track curve/automation nodes. void selectCurveInvert(); // Contents update overloaded methods. void updateRect(const QRect& rect); // Whether there's any clip currently editable. qtractorClip *currentClip() const; // Clip selection accessor. qtractorClipSelect *clipSelect() const; // Clear current selection (no notify). void clearSelect(); // Whether there's any clip currently selected. bool isClipSelected() const; // Whether there's any curve/automation currently selected. bool isCurveSelected() const; // Whether there's a single track selection. qtractorTrack *singleTrackSelected(); // Whether there's anything on clipboard. static bool isClipboard(); // Paste from clipboard (start). void pasteClipboard( unsigned short iPasteCount = 1, unsigned long iPastePeriod = 0); // Retrieve current paste period. // (as from current clipboard width) unsigned long pastePeriod() const; // Clip selection command types. enum Command { Cut, Copy, Delete, Split }; // Clip selection executive method. void executeClipSelect( qtractorTrackView::Command cmd, qtractorClip *pClip = NULL); // Intra-drag-n-drop clip move method. void moveClipSelect(qtractorTrack *pTrack); // Paste from clipboard (execute). void pasteClipSelect(qtractorTrack *pTrack); // Curve/automation selection executive method. void executeCurveSelect(qtractorTrackView::Command cmd); // Intra-drag-n-drop curve/automation node move method. void moveCurveSelect(const QPoint& pos); // Paste from clipboard (execute). void pasteCurveSelect(const QPoint& pos); // Play-head positioning. void setPlayHead(unsigned long iPlayHead, bool bSyncView = false); unsigned long playHead() const; int playHeadX() const; // Edit-head/tail positioning. void setEditHead(unsigned long iEditHead); int editHeadX() const; void setEditTail(unsigned long iEditTail); int editTailX() const; // Make given frame position visible in view. void ensureVisibleFrame(unsigned long iFrame); // Current session cursor accessor. qtractorSessionCursor *sessionCursor() const; // Clip cloner helper. static qtractorClip *cloneClip(qtractorClip *pClip); // Multi-item drop mode (whether to span clips horixontally). void setDropSpan(bool bDropSpan); bool isDropSpan() const; // Snap-to-bar zebra mode. void setSnapZebra(bool bSnapZebra); bool isSnapZebra() const; // Snap-to-beat grid mode. void setSnapGrid(bool bSnapGrid); bool isSnapGrid() const; // Floating tool-tips mode. void setToolTips(bool bToolTips); bool isToolTips() const; // Automation curve node editing mode. void setCurveEdit(bool bCurveEdit); bool isCurveEdit() const; protected: // Resize event handler. void resizeEvent(QResizeEvent *pResizeEvent); // Draw the track view void drawContents(QPainter *pPainter, const QRect& rect); // Get track from given contents vertical position. qtractorTrack *trackAt(const QPoint& pos, bool bSelectTrack = false, qtractorTrackViewInfo *pTrackViewInfo = NULL) const; // Get clip from given contents position. qtractorClip *clipAt(const QPoint& pos, bool bSelectTrack = false, QRect *pClipRect = NULL) const; // Get clip from given contents position. qtractorClip *clipAtTrack(const QPoint& pos, QRect *pClipRect, qtractorTrack *pTrack, qtractorTrackViewInfo *pTrackViewInfo) const; // Get automation curve node from given contents position. qtractorCurve::Node *nodeAtTrack(const QPoint& pos, qtractorTrack *pTrack, qtractorTrackViewInfo *pTrackViewInfo) const; qtractorCurve::Node *nodeAt(const QPoint& pos) const; // Get contents visible rectangle from given track. bool trackInfo(qtractorTrack *pTrack, qtractorTrackViewInfo *pTrackViewInfo) const; // Get contents rectangle from given clip. bool clipInfo(qtractorClip *pClip, QRect *pClipRect) const; // Drag-n-drop event stuffers (for clips). qtractorTrack *dragClipMove(const QPoint& pos, bool bKeyStep = false); qtractorTrack *dragClipDrop(const QPoint& pos, bool bKeyStep = false, const QMimeData *pMimeData = NULL); qtractorTrack *dragClipDropEvent(QDropEvent *pDropEvent); bool canClipDropEvent(QDropEvent *pDropEvent); // Drag-n-drop event stuffers (for curve/automation nodes). void dragCurveMove(const QPoint& pos, bool bKeyStep = false); // Drag-n-drop event handlers. void dragEnterEvent(QDragEnterEvent *pDragEnterEvent); void dragMoveEvent(QDragMoveEvent *pDragMoveEvent); void dragLeaveEvent(QDragLeaveEvent *pDragLeaveEvent); void dropEvent(QDropEvent *pDropEvent); bool dropClip(const QPoint& pos, const QMimeData *pMimeData = NULL); // Handle item selection with mouse. void mousePressEvent(QMouseEvent *pMouseEvent); void mouseMoveEvent(QMouseEvent *pMouseEvent); void mouseReleaseEvent(QMouseEvent *pMouseEvent); // Handle item/clip editing from mouse. void mouseDoubleClickEvent(QMouseEvent *pMouseEvent); // Handle zoom with mouse wheel. void wheelEvent(QWheelEvent *pWheelEvent); // Focus lost event. void focusOutEvent(QFocusEvent *pFocusEvent); // Trap for help/tool-tip events. bool eventFilter(QObject *pObject, QEvent *pEvent); // Clip file(item) selection convenience method. void selectClipFile(bool bReset); // Clip selection sanity check method. bool queryClipSelect(qtractorClip *pClip = NULL); // Update whole clip selection. void updateClipSelect(); // Draw/hide the whole current clip selection. void showClipSelect() const; void hideClipSelect() const; // Show selection tooltip... void showToolTip(const QRect& rect, int dx) const; // Draw/hide the whole drop rectagle list void updateClipDropRects(int y, int h) const; void showClipDropRects() const; void hideClipDropRects() const; // Draw/hide a dragging rectangular selection. void moveRubberBand(qtractorRubberBand **ppRubberBand, const QRect& rectDrag, int thick = 1) const; // Clip fade-in/out handle and resize detection. bool dragMoveStart(const QPoint& pos); // Clip fade-in/out handle drag-move methods. void dragClipFadeMove(const QPoint& pos); void dragClipFadeDrop(const QPoint& pos); // Clip resize drag-move methods. void dragClipResizeMove(const QPoint& pos); void dragClipResizeDrop(const QPoint& pos, bool bTimeStretch = false); // Automation curve node drag-move methods. void dragCurveNode(const QPoint& pos, bool bToggle); // Common tool-tip builder for automation nodes. QString nodeToolTip(qtractorCurve *pCurve, qtractorCurve::Node *pNode) const; // Reset drag/select/move state. void resetDragState(); // Keyboard event handler. void keyPressEvent(QKeyEvent *pKeyEvent); // Keyboard step handler. bool keyStep(int iKey); // Vertical line positioning. void drawPositionX(int& iPositionX, int x, bool bSyncView = false); protected slots: // To have track view in v-sync with track list. void contentsYMovingSlot(int cx, int cy); // (Re)create the complete track view pixmap. void updatePixmap(int cx, int cy); // Drag-reset timer slot. void dragTimeout(); private: // The logical parent binding. qtractorTracks *m_pTracks; // Local zoom control widgets. QToolButton *m_pHzoomIn; QToolButton *m_pHzoomOut; QToolButton *m_pVzoomIn; QToolButton *m_pVzoomOut; QToolButton *m_pXzoomReset; // Local double-buffering pixmap. QPixmap m_pixmap; // To maintain the current track/clip positioning. qtractorSessionCursor *m_pSessionCursor; // Drag-n-dropping stuff. struct DropItem { // Item constructor. DropItem(const QString& sPath, int iChannel = -1) : path(sPath), channel(iChannel), rubberBand(NULL) {} // Item destructor. ~DropItem() { if (rubberBand) { rubberBand->hide(); delete rubberBand; } } // Item members. QString path; int channel; QRect rect; qtractorRubberBand *rubberBand; }; QList m_dropItems; qtractorTrack::TrackType m_dropType; // The current selecting/dragging clip stuff. enum DragState { DragNone = 0, DragStart, DragSelect, DragClipMove, DragClipStep, DragClipDrop, DragClipPaste, DragClipPasteDrop, DragClipFadeIn, DragClipFadeOut, DragClipResizeLeft, DragClipResizeRight, DragCurveMove, DragCurveStep, DragCurvePaste, DragCurveNode } m_dragState, m_dragCursor; qtractorClip *m_pClipDrag; QPoint m_posDrag; QRect m_rectDrag; QRect m_rectHandle; int m_iDragClipX; bool m_bDragTimer; QPoint m_posStep; qtractorRubberBand *m_pRubberBand; qtractorClipSelect *m_pClipSelect; qtractorCurveSelect *m_pCurveSelect; // The clip select mode. SelectMode m_selectMode; // The multi-item drop mode. bool m_bDropSpan; // Snap-to-beat/bar grid/zebra view mode. bool m_bSnapZebra; bool m_bSnapGrid; // Floating tool-tips mode. bool m_bToolTips; // Automation curve node editing mode. bool m_bCurveEdit; // The local clipboard items. struct ClipItem { // Clipboard item constructor. ClipItem(qtractorClip *pClip, const QRect& clipRect, unsigned long iClipStart, unsigned long iClipOffset, unsigned long iClipLength) : clip(pClip), rect(clipRect), clipStart(iClipStart), clipOffset(iClipOffset), clipLength(iClipLength), fadeInLength(0), fadeOutLength(0) {} // Clipboard item members. qtractorClip *clip; QRect rect; unsigned long clipStart; unsigned long clipOffset; unsigned long clipLength; unsigned long fadeInLength; unsigned long fadeOutLength; }; struct NodeItem { // Clipboard item constructor. NodeItem(qtractorCurve::Node *pNode, const QRect& nodeRect, unsigned long iFrame, float fValue) : node(pNode), rect(nodeRect), frame(iFrame), value(fValue) {} // Clipboard item members. qtractorCurve::Node *node; QRect rect; unsigned long frame; float value; }; // The local clipboard stuff (singleton). static struct ClipBoard { // Clipboard constructor. ClipBoard() : singleTrack(NULL), frames(0) {} // Destructor. ~ClipBoard() { clear(); } // Clipboard stuffer methods. void addClip(qtractorClip *pClip, const QRect& clipRect, unsigned long iClipStart, unsigned long iClipOffset, unsigned long iClipLength); void addNode(qtractorCurve::Node *pNode, const QRect& nodeRect, unsigned long iFrame, float fValue); // Clipboard reset method. void clear(); // Clipboard members. QList clips; QList nodes; qtractorTrack *singleTrack; unsigned long frames; } g_clipboard; // Playhead and edit frame positioning. unsigned long m_iPlayHead; // Playhead and edit shadow pixel positioning. int m_iPlayHeadX; int m_iEditHeadX; int m_iEditTailX; // Record rolling update width. int m_iLastRecordX; // Paste interim parameters. unsigned short m_iPasteCount; unsigned long m_iPastePeriod; // Single track dragging interim parameters. bool m_bDragSingleTrack; int m_iDragSingleTrackY; int m_iDragSingleTrackHeight; // Automation curve editing node. qtractorCurve *m_pDragCurve; qtractorCurve::Node *m_pDragCurveNode; int m_iDragCurveX; qtractorCurveEditCommand *m_pCurveEditCommand; }; #endif // __qtractorTrackView_h // end of qtractorTrackView.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorTimeScaleForm.cpp0000644000175000001440000000012312166526620022227 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134671.10808 30 ctime=1381134671.108080114 qtractor-0.5.11/src/qtractorTimeScaleForm.cpp0000644000175000001440000005520212166526620021522 0ustar00rncbcusers00000000000000// qtractorTimeScaleForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorTimeScaleForm.h" #include "qtractorTimeScaleCommand.h" #include "qtractorAbout.h" #include "qtractorOptions.h" #include "qtractorSession.h" #include "qtractorMainForm.h" #include "qtractorTracks.h" #include "qtractorTrackView.h" #include #include #include #include #include #include #include //---------------------------------------------------------------------- // class qtractorTimeScaleItemDelegate -- Custom time-scale item delegate. // class qtractorTimeScaleItemDelegate : public QItemDelegate { public: // Constructor. qtractorTimeScaleItemDelegate(QObject *pParent = 0) : QItemDelegate(pParent) {} protected: // Modified render method. void paint(QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const { QStyleOptionViewItem opt(option); switch (index.column()) { case 0: // Bar case 1: // Time case 2: // Tempo opt.displayAlignment = Qt::AlignHCenter; break; case 3: // Marker default: opt.displayAlignment = Qt::AlignLeft; break; } QItemDelegate::paint(painter, opt, index); } }; //---------------------------------------------------------------------- // class qtractorTimeScaleListItem -- Custom time-scale tempo node item. // class qtractorTimeScaleListItem : public QTreeWidgetItem { public: // Constructors. qtractorTimeScaleListItem(QTreeWidget *pTreeWidget, qtractorTimeScaleListItem *pListItem, qtractorTimeScale *pTimeScale, qtractorTimeScale::Node *pNode, qtractorTimeScale::Marker *pMarker, qtractorTimeScale::DisplayFormat displayFormat) : QTreeWidgetItem(pTreeWidget, pListItem), m_pNode(pNode), m_pMarker(pMarker) { const QChar dash = '-'; if (pNode) { QTreeWidgetItem::setText(0, QString::number(m_pNode->bar + 1)); QTreeWidgetItem::setText(1, pTimeScale->textFromFrameEx( displayFormat, m_pNode->frame)); QTreeWidgetItem::setText(2, QString("%1 %2/%3") .arg(m_pNode->tempo, 0, 'f', 1) .arg(m_pNode->beatsPerBar) .arg(1 << m_pNode->beatDivisor)); } else QTreeWidgetItem::setText(2, dash); if (pMarker) { if (pNode == NULL) { unsigned int iBar = pTimeScale->barFromFrame(pMarker->frame); QTreeWidgetItem::setText(0, QString::number(iBar + 1)); QTreeWidgetItem::setText(1, pTimeScale->textFromFrameEx( displayFormat, pMarker->frame)); } QTreeWidgetItem::setText(3, pMarker->text); QTreeWidgetItem::setForeground(3, pMarker->color); } else QTreeWidgetItem::setText(3, dash); } // Node accessor. qtractorTimeScale::Node *node() const { return m_pNode; } // Marker accessor. qtractorTimeScale::Marker *marker() const { return m_pMarker; } private: // Instance variables. qtractorTimeScale::Node *m_pNode; qtractorTimeScale::Marker *m_pMarker; }; //---------------------------------------------------------------------------- // qtractorTimeScaleForm -- UI wrapper form. // Constructor. qtractorTimeScaleForm::qtractorTimeScaleForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::WindowModal); // Initialize locals. m_pTimeScale = NULL; m_pTempoTap = new QTime(); m_iTempoTap = 0; m_fTempoTap = 0.0f; m_iDirtySetup = 0; m_iDirtyCount = 0; m_iDirtyTotal = 0; QHeaderView *pHeader = m_ui.TimeScaleListView->header(); pHeader->setDefaultAlignment(Qt::AlignLeft); #if QT_VERSION >= 0x050000 // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionResizeMode(QHeaderView::ResizeToContents); pHeader->setSectionsMovable(false); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setResizeMode(QHeaderView::ResizeToContents); pHeader->setMovable(false); #endif m_ui.TimeScaleListView->setItemDelegate( new qtractorTimeScaleItemDelegate(m_ui.TimeScaleListView)); m_ui.TimeScaleListView->setContextMenuPolicy(Qt::CustomContextMenu); // (Re)initial contents. // Default is main session time-scale of course... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) setTimeScale(pSession->timeScale()); // Try to restore normal window positioning. adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.TimeScaleListView, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), SLOT(selectItem())); QObject::connect(m_ui.TimeScaleListView, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(contextMenu(const QPoint&))); QObject::connect(m_ui.BarSpinBox, SIGNAL(valueChanged(int)), SLOT(barChanged(int))); QObject::connect(m_ui.TimeSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(timeChanged(unsigned long))); QObject::connect(m_ui.TimeSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(refreshItems())); QObject::connect(m_ui.TempoSpinBox, SIGNAL(valueChanged(float, unsigned short, unsigned short)), SLOT(tempoChanged())); QObject::connect(m_ui.TempoSpinBox, SIGNAL(valueChanged(const QString&)), SLOT(tempoChanged())); QObject::connect(m_ui.TempoPushButton, SIGNAL(clicked()), SLOT(tempoTap())); QObject::connect(m_ui.MarkerTextLineEdit, SIGNAL(textChanged(const QString&)), SLOT(changed())); QObject::connect(m_ui.MarkerColorToolButton, SIGNAL(clicked()), SLOT(markerColor())); QObject::connect(m_ui.RefreshPushButton, SIGNAL(clicked()), SLOT(refresh())); QObject::connect(m_ui.AddPushButton, SIGNAL(clicked()), SLOT(addItem())); QObject::connect(m_ui.UpdatePushButton, SIGNAL(clicked()), SLOT(updateItem())); QObject::connect(m_ui.RemovePushButton, SIGNAL(clicked()), SLOT(removeItem())); QObject::connect(m_ui.ClosePushButton, SIGNAL(clicked()), SLOT(reject())); stabilizeForm(); } // Time-scale accessor. void qtractorTimeScaleForm::setTimeScale ( qtractorTimeScale *pTimeScale ) { m_pTimeScale = pTimeScale; m_ui.TimeSpinBox->setTimeScale(m_pTimeScale); refreshItems(); } qtractorTimeScale *qtractorTimeScaleForm::timeScale (void) const { return m_pTimeScale; } // Select(ed) node by frame (time) void qtractorTimeScaleForm::setFrame ( unsigned long iFrame ) { if (m_pTimeScale == NULL) return; ++m_iDirtySetup; qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(iFrame); if (pNode) { iFrame = pNode->frameSnapToBar(iFrame); pNode = cursor.seekFrame(iFrame); } if (pNode) { // Make this into view... m_ui.BarSpinBox->setValue(pNode->barFromFrame(iFrame) + 1); m_ui.TimeSpinBox->setValue(iFrame); m_ui.TempoSpinBox->setTempo(pNode->tempo, false); m_ui.TempoSpinBox->setBeatsPerBar(pNode->beatsPerBar, false); m_ui.TempoSpinBox->setBeatDivisor(pNode->beatDivisor, false); } qtractorTimeScale::Marker *pMarker = m_pTimeScale->markers().seekFrame(iFrame); if (pMarker && pMarker->frame == iFrame) setCurrentMarker(pMarker); else setCurrentMarker(NULL); // Done. m_iDirtySetup = 0; // Locate nearest list item... if (pNode) setCurrentItem(pNode, iFrame); stabilizeForm(); } unsigned long qtractorTimeScaleForm::frame (void) const { return m_ui.TimeSpinBox->value(); } unsigned short qtractorTimeScaleForm::bar (void) const { return m_ui.BarSpinBox->value() - 1; } // Current dirty flag accessor. bool qtractorTimeScaleForm::isDirty (void) { return (m_iDirtyTotal > 0); } // Refresh all list and views. void qtractorTimeScaleForm::refreshItems (void) { if (m_pTimeScale == NULL) return; // (Re)Load complete tempo-map listing ... m_ui.TimeScaleListView->clear(); const qtractorTimeScale::DisplayFormat displayFormat = m_ui.TimeSpinBox->displayFormat(); qtractorTimeScale::Node *pNode = m_pTimeScale->nodes().first(); qtractorTimeScale::Marker *pMarker = m_pTimeScale->markers().first(); qtractorTimeScaleListItem *pListItem = NULL; while (pNode) { while (pMarker && pMarker->frame < pNode->frame) { pListItem = new qtractorTimeScaleListItem(m_ui.TimeScaleListView, pListItem, m_pTimeScale, NULL, pMarker, displayFormat); pMarker = pMarker->next(); } if (pMarker && pMarker->frame == pNode->frame) { pListItem = new qtractorTimeScaleListItem(m_ui.TimeScaleListView, pListItem, m_pTimeScale, pNode, pMarker, displayFormat); pMarker = pMarker->next(); } else { pListItem = new qtractorTimeScaleListItem(m_ui.TimeScaleListView, pListItem, m_pTimeScale, pNode, NULL, displayFormat); } pNode = pNode->next(); } while (pMarker) { pListItem = new qtractorTimeScaleListItem(m_ui.TimeScaleListView, pListItem, m_pTimeScale, NULL, pMarker, displayFormat); pMarker = pMarker->next(); } } void qtractorTimeScaleForm::refresh (void) { refreshItems(); timeChanged(frame()); m_iDirtyCount = 0; } // Current node list accessors. void qtractorTimeScaleForm::setCurrentItem ( qtractorTimeScale::Node *pNode, unsigned long iFrame ) { ++m_iDirtySetup; qtractorTimeScale::Marker *pMarker = m_pTimeScale->markers().seekFrame(iFrame); int iItemCount = m_ui.TimeScaleListView->topLevelItemCount(); for (int i = iItemCount - 1; i >= 0; --i) { qtractorTimeScaleListItem *pListItem = static_cast ( m_ui.TimeScaleListView->topLevelItem(i)); if (pListItem && (pListItem->node() == pNode || (pMarker && pListItem->marker() == pMarker))) { m_ui.TimeScaleListView->setCurrentItem(pListItem); break; } } m_iDirtySetup = 0; } // Set current marker text & color... void qtractorTimeScaleForm::setCurrentMarker ( qtractorTimeScale::Marker *pMarker ) { QPalette pal; if (pMarker) pal.setColor(QPalette::Text, pMarker->color); else pal.setColor(QPalette::Text, Qt::darkGray); m_ui.MarkerTextLineEdit->setPalette(pal); if (pMarker) m_ui.MarkerTextLineEdit->setText(pMarker->text); else m_ui.MarkerTextLineEdit->clear(); } // Make given frame visble at the main tracks view. void qtractorTimeScaleForm::ensureVisibleFrame ( unsigned long iFrame ) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm && pMainForm->tracks()) pMainForm->tracks()->trackView()->ensureVisibleFrame(iFrame); } // Time-scale node selection slot. void qtractorTimeScaleForm::selectItem (void) { if (m_pTimeScale == NULL) return; if (m_iDirtySetup > 0) return; // Check if we need an update?... qtractorTimeScaleListItem *pListItem = static_cast ( m_ui.TimeScaleListView->currentItem()); if (pListItem == NULL) return; qtractorTimeScale::Node *pNode = pListItem->node(); qtractorTimeScale::Marker *pMarker = pListItem->marker(); if (pNode == NULL && pMarker == NULL) return; if (m_iDirtyCount > 0) { QMessageBox::StandardButtons buttons = QMessageBox::Discard | QMessageBox::Cancel; if (m_ui.UpdatePushButton->isEnabled()) buttons |= QMessageBox::Apply; switch (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Some settings have been changed.\n\n" "Do you want to apply the changes?"), buttons)) { case QMessageBox::Apply: updateItem(); // Fall thru... case QMessageBox::Discard: break;; default: // Cancel. return; } } // Get new one into view... ++m_iDirtySetup; if (pNode) { m_ui.BarSpinBox->setValue(pNode->bar + 1); m_ui.TimeSpinBox->setValue(pNode->frame); m_ui.TempoSpinBox->setTempo(pNode->tempo, false); m_ui.TempoSpinBox->setBeatsPerBar(pNode->beatsPerBar, false); m_ui.TempoSpinBox->setBeatDivisor(pNode->beatDivisor, false); ensureVisibleFrame(pNode->frame); } if (pMarker && pNode == NULL) { unsigned int iBar = m_pTimeScale->barFromFrame(pMarker->frame); m_ui.BarSpinBox->setValue(iBar + 1); m_ui.TimeSpinBox->setValue(pMarker->frame); ensureVisibleFrame(pMarker->frame); } setCurrentMarker(pMarker); m_iDirtySetup = 0; m_iDirtyCount = 0; stabilizeForm(); } // Check whether the current view is elligible for action. unsigned int qtractorTimeScaleForm::flags (void) const { if (m_pTimeScale == NULL) return 0; unsigned int iFlags = 0; float fTempo = m_ui.TempoSpinBox->tempo(); unsigned short iBeatsPerBar = m_ui.TempoSpinBox->beatsPerBar(); unsigned short iBeatDivisor = m_ui.TempoSpinBox->beatDivisor(); unsigned short iBar = bar(); qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekBar(iBar); if (pNode && pNode->bar == iBar) { iFlags |= UpdateNode; if (pNode->prev()) iFlags |= RemoveNode; } if (pNode && ::fabs(pNode->tempo - fTempo) < 0.05f // && pNode->beatType == iBeatType && pNode->beatsPerBar == iBeatsPerBar && pNode->beatDivisor == iBeatDivisor) iFlags &= ~UpdateNode; else iFlags |= AddNode; if (pNode && pNode->bar == iBar) iFlags &= ~AddNode; if (pNode && (pNode = pNode->next()) // real assignment && ::fabs(pNode->tempo - fTempo) < 0.05f // && pNode->beatType == iBeatType && pNode->beatsPerBar == iBeatsPerBar && pNode->beatDivisor == iBeatDivisor) iFlags &= ~AddNode; unsigned long iFrame = m_pTimeScale->frameFromBar(iBar); qtractorTimeScale::Marker *pMarker = m_pTimeScale->markers().seekFrame(iFrame); const QString& sMarkerText = m_ui.MarkerTextLineEdit->text().simplified(); const QColor& rgbMarkerColor = m_ui.MarkerTextLineEdit->palette().text().color(); if (pMarker && pMarker->frame == iFrame) { iFlags |= UpdateMarker; iFlags |= RemoveMarker; } if (pMarker && pMarker->text == sMarkerText && pMarker->color == rgbMarkerColor) iFlags &= ~UpdateMarker; else if (!sMarkerText.isEmpty()) iFlags |= AddMarker; if (pMarker && pMarker->frame == iFrame) iFlags &= ~AddMarker; return iFlags; } // Add node method. void qtractorTimeScaleForm::addItem (void) { if (m_pTimeScale == NULL) return; // Make it as an undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; unsigned int iFlags = flags(); unsigned long iFrame = frame(); if (iFlags & AddNode) { pSession->execute( new qtractorTimeScaleAddNodeCommand( m_pTimeScale, iFrame, m_ui.TempoSpinBox->tempo(), 2, m_ui.TempoSpinBox->beatsPerBar(), m_ui.TempoSpinBox->beatDivisor())); ++m_iDirtyTotal; } if (iFlags & AddMarker) { pSession->execute( new qtractorTimeScaleAddMarkerCommand( m_pTimeScale, iFrame, m_ui.MarkerTextLineEdit->text().simplified(), m_ui.MarkerTextLineEdit->palette().text().color())); ++m_iDirtyTotal; } refresh(); } // Update current node. void qtractorTimeScaleForm::updateItem (void) { if (m_pTimeScale == NULL) return; // Make it as an undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; unsigned int iFlags = flags(); unsigned short iBar = bar(); if (iFlags & UpdateNode) { qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekBar(iBar); if (pNode && pNode->bar == iBar) { unsigned long iFrame = pNode->frameFromBar(iBar); pSession->execute( new qtractorTimeScaleUpdateNodeCommand( m_pTimeScale, iFrame, m_ui.TempoSpinBox->tempo(), 2, m_ui.TempoSpinBox->beatsPerBar(), m_ui.TempoSpinBox->beatDivisor())); ++m_iDirtyTotal; } } if (iFlags & UpdateMarker) { unsigned long iFrame = m_pTimeScale->frameFromBar(iBar); qtractorTimeScale::Marker *pMarker = m_pTimeScale->markers().seekFrame(iFrame); if (pMarker && pMarker->frame == iFrame) { pSession->execute( new qtractorTimeScaleUpdateMarkerCommand( m_pTimeScale, iFrame, m_ui.MarkerTextLineEdit->text().simplified(), m_ui.MarkerTextLineEdit->palette().text().color())); ++m_iDirtyTotal; } } refresh(); } // Remove current node. void qtractorTimeScaleForm::removeItem (void) { if (m_pTimeScale == NULL) return; // Make it as an undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; unsigned int iFlags = flags(); unsigned short iBar = bar(); if (iFlags & RemoveNode) { qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekBar(iBar); if (pNode && pNode->bar == iBar && pNode->prev()) { // Prompt user if he/she's sure about this... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions && pOptions->bConfirmRemove) { // Show the warning... if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("About to remove tempo node:\n\n" "%1 (%2) %3 %4/%5\n\n" "Are you sure?") .arg(pNode->bar + 1) .arg(m_pTimeScale->textFromTick(pNode->tick)) .arg(pNode->tempo, 0, 'f', 1) .arg(pNode->beatsPerBar) .arg(1 << pNode->beatDivisor), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; } // Go!... pSession->execute( new qtractorTimeScaleRemoveNodeCommand(m_pTimeScale, pNode)); ++m_iDirtyTotal; } } if (iFlags & RemoveMarker) { unsigned long iFrame = m_pTimeScale->frameFromBar(iBar); qtractorTimeScale::Marker *pMarker = m_pTimeScale->markers().seekFrame(iFrame); if (pMarker && pMarker->frame == iFrame) { // Go! we just don't ask user about a thing... pSession->execute( new qtractorTimeScaleRemoveMarkerCommand( m_pTimeScale, pMarker)); ++m_iDirtyTotal; } } refresh(); } // Make changes due. void qtractorTimeScaleForm::barChanged ( int iBar ) { if (m_pTimeScale == NULL) return; if (m_iDirtySetup > 0) return; ++m_iDirtySetup; if (iBar > 0) --iBar; qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekBar(iBar); unsigned long iFrame = (pNode ? pNode->frameFromBar(iBar) : 0); m_ui.TimeSpinBox->setValue(iFrame); qtractorTimeScale::Marker *pMarker = m_pTimeScale->markers().seekFrame(iFrame); if (pMarker && pMarker->frame == iFrame) setCurrentMarker(pMarker); else setCurrentMarker(NULL); m_iDirtySetup = 0; // Locate nearest list item... if (pNode) setCurrentItem(pNode, iFrame); ensureVisibleFrame(iFrame); ++m_iDirtyCount; stabilizeForm(); } void qtractorTimeScaleForm::timeChanged ( unsigned long iFrame ) { if (m_pTimeScale == NULL) return; if (m_iDirtySetup > 0) return; ++m_iDirtySetup; qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(iFrame); if (pNode) { iFrame = pNode->frameSnapToBar(iFrame); pNode = cursor.seekFrame(iFrame); } if (pNode) m_ui.BarSpinBox->setValue(pNode->barFromFrame(iFrame) + 1); qtractorTimeScale::Marker *pMarker = m_pTimeScale->markers().seekFrame(iFrame); if (pMarker && pMarker->frame == iFrame) setCurrentMarker(pMarker); else setCurrentMarker(NULL); m_iDirtySetup = 0; // Locate nearest list item... if (pNode) setCurrentItem(pNode, iFrame); ensureVisibleFrame(iFrame); ++m_iDirtyCount; stabilizeForm(); } // Tempo signature has changed. void qtractorTimeScaleForm::tempoChanged (void) { if (m_iDirtySetup > 0) return; #ifdef CONFIG_DEBUG qDebug("qtractorTimeScaleForm::tempoChanged()"); #endif m_iTempoTap = 0; m_fTempoTap = 0.0f; changed(); } // Something has changed. void qtractorTimeScaleForm::changed (void) { if (m_iDirtySetup > 0) return; ++m_iDirtyCount; stabilizeForm(); } // Reject settings (Close button slot). void qtractorTimeScaleForm::reject (void) { bool bReject = true; // Check if there's any pending changes... if (m_iDirtyCount > 0) { if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Some settings have been changed.\n\n" "Do you want to discard the changes?"), QMessageBox::Discard | QMessageBox::Cancel) == QMessageBox::Cancel) { bReject = false; } } if (bReject) QDialog::reject(); } // Tempo tap click. void qtractorTimeScaleForm::tempoTap (void) { #ifdef CONFIG_DEBUG qDebug("qtractorTimeScaleForm::tempoTap()"); #endif int iTimeTap = m_pTempoTap->restart(); if (iTimeTap > 200 && iTimeTap < 2000) { // Magic! m_fTempoTap += (60000.0f / float(iTimeTap)); if (++m_iTempoTap > 2) { m_fTempoTap /= float(m_iTempoTap); m_iTempoTap = 1; // Median-like averaging... m_ui.TempoSpinBox->setTempo(int(m_fTempoTap), true); } } else { m_iTempoTap = 0; m_fTempoTap = 0.0f; } } // Marker color selection. void qtractorTimeScaleForm::markerColor (void) { #ifdef CONFIG_DEBUG qDebug("qtractorTimeScaleForm::markerColor()"); #endif QPalette pal(m_ui.MarkerTextLineEdit->palette()); const QColor& color = QColorDialog::getColor(pal.text().color()); if (color.isValid()) { pal.setColor(QPalette::Text, color); m_ui.MarkerTextLineEdit->setPalette(pal); changed(); } } // Stabilize current form state. void qtractorTimeScaleForm::stabilizeForm (void) { unsigned int iFlags = flags(); // m_ui.RefreshPushButton->setEnabled(m_iDirtyCount > 0); m_ui.AddPushButton->setEnabled(iFlags & (AddNode | AddMarker)); m_ui.UpdatePushButton->setEnabled(iFlags & (UpdateNode | UpdateMarker)); m_ui.RemovePushButton->setEnabled(iFlags & (RemoveNode | RemoveMarker)); } // Time-scale list view context menu handler. void qtractorTimeScaleForm::contextMenu ( const QPoint& /*pos*/ ) { // Build the device context menu... QMenu menu(this); QAction *pAction; unsigned int iFlags = flags(); pAction = menu.addAction( QIcon(":/images/formAdd.png"), tr("&Add"), this, SLOT(addItem())); pAction->setEnabled(iFlags & (AddNode | AddMarker)); pAction = menu.addAction( QIcon(":/images/formAccept.png"), tr("&Update"), this, SLOT(updateItem())); pAction->setEnabled(iFlags & (UpdateNode | UpdateMarker)); pAction = menu.addAction( QIcon(":/images/formRemove.png"), tr("&Remove"), this, SLOT(removeItem())); pAction->setEnabled(iFlags & (RemoveNode | RemoveMarker)); menu.addSeparator(); pAction = menu.addAction( QIcon(":/images/formRefresh.png"), tr("&Refresh"), this, SLOT(refresh())); // pAction->setEnabled(m_iDirtyCount > 0); // menu.exec(m_ui.BusListView->mapToGlobal(pos)); menu.exec(QCursor::pos()); } // end of qtractorTimeScaleForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTimeStretch.cpp0000644000175000001440000000012312104565062021763 xustar000000000000000027 mtime=1360194098.037625 26 atime=1381134666.81608 30 ctime=1381134666.816080046 qtractor-0.5.11/src/qtractorTimeStretch.cpp0000644000175000001440000004506612104565062021265 0ustar00rncbcusers00000000000000// qtractorTimeStretch.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. Adapted and refactored from the SoundTouch library (L)GPL, Copyright (C) 2001-2012, Olli Parviainen. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorTimeStretch.h" #include // Cross-correlation value calculation over the overlap period. // #if defined(__SSE__) #include // SSE detection. static inline bool sse_enabled (void) { #if defined(__GNUC__) unsigned int eax, ebx, ecx, edx; #if defined(__x86_64__) || (!defined(PIC) && !defined(__PIC__)) __asm__ __volatile__ ( "cpuid\n\t" \ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ : "a" (1) : "cc"); #else __asm__ __volatile__ ( "push %%ebx\n\t" \ "cpuid\n\t" \ "movl %%ebx,%1\n\t" \ "pop %%ebx\n\t" \ : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) \ : "a" (1) : "cc"); #endif return (edx & (1 << 25)); #else return false; #endif } // SSE enabled version. static inline float sse_cross_corr ( const float *pV1, const float *pV2, unsigned int iOverlapLength ) { __m128 vCorr, vNorm, vTemp, *pVec2; // Note. It means a major slow-down if the routine needs to tolerate // unaligned __m128 memory accesses. It's way faster if we can skip // unaligned slots and use _mm_load_ps instruction instead of _mm_loadu_ps. // This can mean up to ~ 10-fold difference (incl. part of which is // due to skipping every second round for stereo sound though). // // Little cheating allowed, return valid correlation only for // aligned locations, meaning every second round for stereo sound. //if (((unsigned long) pV1) & 15) return -1e38f; // Skip unaligned locations. // No cheating allowed, use unaligned load & take the resulting // performance hit. -- use _mm_loadu_ps() instead of _mm_load_ps(); // Ensure overlapLength is divisible by 8 // assert((m_iOverlapLength % 8) == 0); iOverlapLength >>= 4; // Calculates the cross-correlation value between 'pV1' and 'pV2' vectors // Note: pV2 _must_ be aligned to 16-bit boundary, pV1 need not. pVec2 = (__m128 *) pV2; vCorr = _mm_setzero_ps(); vNorm = _mm_setzero_ps(); // Unroll the loop by factor of 4 * 4 operations for (unsigned int i = 0; i < iOverlapLength; ++i) { // vCorr += pV1[0..3] * pV2[0..3] vTemp = _mm_loadu_ps(pV1); vCorr = _mm_add_ps(vCorr, _mm_mul_ps(vTemp, pVec2[0])); vNorm = _mm_add_ps(vNorm, _mm_mul_ps(vTemp, vTemp)); // vCorr += pV1[4..7] * pV2[4..7] vTemp = _mm_loadu_ps(pV1 + 4); vCorr = _mm_add_ps(vCorr, _mm_mul_ps(vTemp, pVec2[1])); vNorm = _mm_add_ps(vNorm, _mm_mul_ps(vTemp, vTemp)); // vCorr += pV1[8..11] * pV2[8..11] vTemp = _mm_loadu_ps(pV1 + 8); vCorr = _mm_add_ps(vCorr, _mm_mul_ps(vTemp, pVec2[2])); vNorm = _mm_add_ps(vNorm, _mm_mul_ps(vTemp, vTemp)); // vCorr += pV1[12..15] * pV2[12..15] vTemp = _mm_loadu_ps(pV1 + 12); vCorr = _mm_add_ps(vCorr, _mm_mul_ps(vTemp, pVec2[3])); vNorm = _mm_add_ps(vNorm, _mm_mul_ps(vTemp, vTemp)); pV1 += 16; pVec2 += 4; } float *pvNorm = (float *) &vNorm; float fNorm = (pvNorm[0] + pvNorm[1] + pvNorm[2] + pvNorm[3]); if (fNorm < 1e-9f) fNorm = 1.0f; // avoid div by zero float *pvCorr = (float *) &vCorr; return (pvCorr[0] + pvCorr[1] + pvCorr[2] + pvCorr[3]) / ::sqrtf(fNorm); } #endif // Standard (slow) version. static inline float std_cross_corr ( const float *pV1, const float *pV2, unsigned int iOverlapLength ) { float fCorr = 0.0f; float fNorm = 0.0f; for (unsigned int i = 0; i < iOverlapLength; ++i) { fCorr += pV1[i] * pV2[i]; fNorm += pV1[i] * pV1[i]; } if (fNorm < 1e-9f) fNorm = 1.0f; // avoid div by zero return fCorr / ::sqrtf(fNorm); } //--------------------------------------------------------------------------- // qtractorTimeStretch - Time-stretch (tempo change) effect for processed sound. // // Constructor. qtractorTimeStretch::qtractorTimeStretch ( unsigned short iChannels, unsigned int iSampleRate ) : m_iChannels(0) { setChannels(iChannels); m_fTempo = 1.0f; m_bQuickSeek = false; m_bMidBufferDirty = false; m_ppMidBuffer = NULL; m_ppRefMidBuffer = NULL; m_ppRefMidBufferUnaligned = NULL; m_ppFrames = NULL; m_iOverlapLength = 0; #if defined(__SSE__) if (sse_enabled()) m_pfnCrossCorr = sse_cross_corr; else #endif m_pfnCrossCorr = std_cross_corr; setParameters(iSampleRate); } // Destructor. qtractorTimeStretch::~qtractorTimeStretch (void) { if (m_ppFrames) { for (unsigned short i = 0; i < m_iChannels; ++i) { delete [] m_ppMidBuffer[i]; delete [] m_ppRefMidBufferUnaligned[i]; } delete [] m_ppMidBuffer; delete [] m_ppRefMidBufferUnaligned; delete [] m_ppRefMidBuffer; delete [] m_ppFrames; } } // Sets the number of channels, 1=mono, 2=stereo. void qtractorTimeStretch::setChannels ( unsigned short iChannels ) { if (m_iChannels == iChannels) return; m_iChannels = iChannels; m_inputBuffer.setChannels(m_iChannels); m_outputBuffer.setChannels(m_iChannels); } // Get the assigne number of channels, 1=mono, 2=stereo. unsigned short qtractorTimeStretch::channels (void) const { return m_iChannels; } // Sets new target tempo; less than 1.0 values represent // slower tempo, greater than 1.0 represents faster tempo. void qtractorTimeStretch::setTempo ( float fTempo ) { // Set new is tempo scaling. m_fTempo = fTempo; calcSeekWindowLength(); calcOverlapLength(); // Calculate ideal skip length (according to tempo value) m_fNominalSkip = m_fTempo * (m_iSeekWindowLength - m_iOverlapLength); m_fSkipFract = 0; // Calculate how many samples are needed in the input buffer // to process another batch of samples. m_iFramesReq = (unsigned int) (m_fNominalSkip + 0.5f) + m_iOverlapLength; if (m_iFramesReq < m_iSeekWindowLength) m_iFramesReq = m_iSeekWindowLength; m_iFramesReq += m_iSeekLength; clear(); // These will be enough for most purposes, and // shoudl avoid in-the-fly buffer re-allocations... m_inputBuffer.ensureCapacity(m_iFramesReq); m_outputBuffer.ensureCapacity(m_iFramesReq); } // Get assigned target tempo. float qtractorTimeStretch::tempo (void) const { return m_fTempo; } // Set quick-seek mode (hierachical search). void qtractorTimeStretch::setQuickSeek ( bool bQuickSeek ) { m_bQuickSeek = bQuickSeek; } // Get quick-seek mode. bool qtractorTimeStretch::isQuickSeek (void) const { return m_bQuickSeek; } // Sets routine control parameters. // These control are certain time constants defining // how the sound is stretched to the desired duration. // // iSampleRate = sample rate of the sound. // iSequenceMs = one processing sequence length in milliseconds. // iSeekWindowMs = seeking window length for scanning the best // overlapping position. // iOverlapMs = overlapping length. void qtractorTimeStretch::setParameters ( unsigned int iSampleRate, unsigned int iSequenceMs, unsigned int iSeekWindowMs, unsigned int iOverlapMs ) { m_iSampleRate = iSampleRate; m_iSequenceMs = iSequenceMs; m_iSeekWindowMs = iSeekWindowMs; m_iOverlapMs = iOverlapMs; m_bAutoSequenceMs = (iSequenceMs < 1); m_bAutoSeekWindowMs = (iSeekWindowMs < 1); // Set tempo to recalculate required frames... setTempo(m_fTempo); } // Get routine control parameters, see setParameters() function. // Any of the parameters to this function can be NULL, in such case // corresponding parameter value isn't returned. void qtractorTimeStretch::getParameters ( unsigned int *piSampleRate, unsigned int *piSequenceMs, unsigned int *piSeekWindowMs, unsigned int *piOverlapMs ) { if (piSampleRate) *piSampleRate = m_iSampleRate; if (piSequenceMs) *piSequenceMs = m_iSequenceMs; if (piSeekWindowMs) *piSeekWindowMs = m_iSeekWindowMs; if (piOverlapMs) *piOverlapMs = m_iOverlapMs; } // Clears mid sample frame buffer. void qtractorTimeStretch::clearMidBuffer (void) { if (m_bMidBufferDirty) { for (unsigned short i = 0; i < m_iChannels; ++i) ::memset(m_ppMidBuffer[i], 0, 2 * m_iOverlapLength * sizeof(float)); m_bMidBufferDirty = false; } } // Clears input and mid sample frame buffers. void qtractorTimeStretch::clearInput (void) { m_inputBuffer.clear(); clearMidBuffer(); } // Clears all sample frame buffers. void qtractorTimeStretch::clear (void) { m_outputBuffer.clear(); m_inputBuffer.clear(); clearMidBuffer(); } // Seeks for the optimal overlap-mixing position. // // The best position is determined as the position where // the two overlapped sample sequences are 'most alike', // in terms of the highest cross-correlation value over // the overlapping period. unsigned int qtractorTimeStretch::seekBestOverlapPosition (void) { float fBestCorr, fCorr; unsigned int iBestOffs, iPrevBestOffs; unsigned short i, iStep; int iOffs, j, k; // Slopes the amplitude of the 'midBuffer' samples calcCrossCorrReference(); fBestCorr = -1e38f; // A reasonable lower limit. // Scans for the best correlation value by testing each // possible position over the permitted range. if (m_bQuickSeek) { // Hierachical search... iPrevBestOffs = (m_iSeekLength + 1) >> 1; iOffs = iBestOffs = iPrevBestOffs; for (iStep = 64; iStep > 0; iStep >>= 2) { for (k = -1; k <= 1; k += 2) { for (j = 1; j < 4 || iStep == 64; ++j) { iOffs = iPrevBestOffs + k * j * iStep; if (iOffs < 0 || iOffs >= (int) m_iSeekLength) break; for (i = 0; i < m_iChannels; ++i) { // Calculates correlation value for the mixing // position corresponding to iOffs. fCorr = (*m_pfnCrossCorr)( m_inputBuffer.ptrBegin(i) + iOffs, m_ppRefMidBuffer[i], m_iOverlapLength); // Checks for the highest correlation value. if (fCorr > fBestCorr) { fBestCorr = fCorr; iBestOffs = iOffs; } } } } iPrevBestOffs = iBestOffs; } } else { // Linear search... iBestOffs = 0; for (iOffs = 0; iOffs < (int) m_iSeekLength; ++iOffs) { for (i = 0; i < m_iChannels; ++i) { // Calculates correlation value for the mixing // position corresponding to iOffs. fCorr = (*m_pfnCrossCorr)( m_inputBuffer.ptrBegin(i) + iOffs, m_ppRefMidBuffer[i], m_iOverlapLength); // Checks for the highest correlation value. if (fCorr > fBestCorr) { fBestCorr = fCorr; iBestOffs = iOffs; } } } } return iBestOffs; } // Processes as many processing frames of the samples // from input-buffer, store the result into output-buffer. void qtractorTimeStretch::processFrames (void) { unsigned short i; unsigned int j, k; float *pInput, *pOutput; unsigned int iSkip, iOffset; int iTemp; // If mid-buffer is empty, move the first // frames of the input stream into it... if (!m_bMidBufferDirty) { // Wait until we've got overlapLength samples if (m_inputBuffer.frames() < m_iOverlapLength) return; m_inputBuffer.receiveFrames(m_ppMidBuffer, m_iOverlapLength); m_bMidBufferDirty = true; } // Process frames as long as there are enough in // input-buffer to form a processing block. while (m_inputBuffer.frames() >= m_iFramesReq) { // If tempo differs from the nominal, // scan for the best overlapping position... iOffset = seekBestOverlapPosition(); // Mix the frames in the input-buffer at position of iOffset // with the samples in mid-buffer using sliding overlapping; // first partially overlap with the end of the previous // sequence (that's in the mid-buffer). m_outputBuffer.ensureCapacity(m_iOverlapLength); // Overlap... for (i = 0; i < m_iChannels; ++i) { pInput = m_inputBuffer.ptrBegin(i); pOutput = m_outputBuffer.ptrEnd(i); for (j = 0; j < m_iOverlapLength ; ++j) { k = m_iOverlapLength - j; pOutput[j] = (pInput[j + iOffset] * j + m_ppMidBuffer[i][j] * k) / m_iOverlapLength; } } // Commit... m_outputBuffer.putFrames(m_iOverlapLength); // Then copy sequence samples from input-buffer to output... iTemp = (m_iSeekWindowLength - 2 * m_iOverlapLength); if (iTemp > 0) { // Temporary mapping... for (i = 0; i < m_iChannels; ++i) { m_ppFrames[i] = m_inputBuffer.ptrBegin(i) + (iOffset + m_iOverlapLength); } m_outputBuffer.putFrames(m_ppFrames, iTemp); } // Copies the end of the current sequence from input-buffer to // mid-buffer for being mixed with the beginning of the next // processing sequence and so on // assert(iOffset + m_iSeekWindowLength <= m_inputBuffer.frames()); m_inputBuffer.readFrames(m_ppMidBuffer, m_iOverlapLength, (iOffset + m_iSeekWindowLength - m_iOverlapLength)); m_bMidBufferDirty = true; // Remove the processed samples from the input-buffer. Update // the difference between integer & nominal skip step to skip-fract // in order to prevent the error from accumulating over time. m_fSkipFract += m_fNominalSkip; // real skip size iSkip = (int) m_fSkipFract; // rounded to integer skip // Maintain the fraction part, i.e. real vs. integer skip m_fSkipFract -= iSkip; m_inputBuffer.receiveFrames(iSkip); } } // Adds frames of samples into the input of the object. void qtractorTimeStretch::putFrames ( float **ppFrames, unsigned int iFrames ) { // Add the frames into the input buffer. m_inputBuffer.putFrames(ppFrames, iFrames); // Process the samples in input buffer. processFrames(); } // Output frames from beginning of the sample buffer. // Copies requested frames output buffer and removes them // from the sample buffer. If there are less than frames() // samples in the buffer, returns all that available. unsigned int qtractorTimeStretch::receiveFrames ( float **ppFrames, unsigned int iFrames ) { return m_outputBuffer.receiveFrames(ppFrames, iFrames); } // Returns number of frames currently available. unsigned int qtractorTimeStretch::frames() const { return m_outputBuffer.frames(); } // Flush any last samples that are hiding in the internal processing pipeline. void qtractorTimeStretch::flushInput (void) { if (m_bMidBufferDirty) { // Prepare a dummy empty buffer... unsigned short i; float dummy[256]; ::memset(&dummy[0], 0, sizeof(dummy)); for (i = 0; i < m_iChannels; ++i) m_ppFrames[i] = &dummy[0]; // Push the last active frames out from the pipeline // by feeding blank samples into processing until // new samples appear in the output... unsigned int iFrames = frames(); for (i = 0; i < 128; ++i) { putFrames(m_ppFrames, 256); // Any new samples appeared in the output? if (frames() > iFrames) break; } } clearInput(); } //--------------------------------------------------------------------------- // Floating point arithmetics specific algorithm implementations. // // Slopes the amplitude of the mid-buffer samples // so that cross correlation is faster to calculate void qtractorTimeStretch::calcCrossCorrReference (void) { for (unsigned int j = 0 ; j < m_iOverlapLength ; ++j) { float fTemp = (float) j * (float) (m_iOverlapLength - j); for (unsigned short i = 0; i < m_iChannels; ++i) m_ppRefMidBuffer[i][j] = (float) (m_ppMidBuffer[i][j] * fTemp); } } // Calculates overlap period length in frames and reallocate ref-mid-buffer. void qtractorTimeStretch::calcOverlapLength (void) { // Must be divisible by 8... unsigned int iNewOverlapLength = (m_iSampleRate * m_iOverlapMs) / 1000; if (iNewOverlapLength < 16) iNewOverlapLength = 16; iNewOverlapLength -= (iNewOverlapLength % 8); unsigned int iOldOverlapLength = m_iOverlapLength; m_iOverlapLength = iNewOverlapLength; if (m_iOverlapLength > iOldOverlapLength) { unsigned short i; if (m_ppFrames) { for (i = 0; i < m_iChannels; ++i) { delete [] m_ppMidBuffer; delete [] m_ppRefMidBufferUnaligned; } delete [] m_ppMidBuffer; delete [] m_ppRefMidBufferUnaligned; delete [] m_ppRefMidBuffer; delete [] m_ppFrames; } m_ppFrames = new float * [m_iChannels]; m_ppMidBuffer = new float * [m_iChannels]; m_ppRefMidBufferUnaligned = new float * [m_iChannels]; m_ppRefMidBuffer = new float * [m_iChannels]; for (i = 0; i < m_iChannels; ++i) { m_ppMidBuffer[i] = new float [2 * m_iOverlapLength]; m_ppRefMidBufferUnaligned[i] = new float[2 * m_iOverlapLength + 16 / sizeof(float)]; // Ensure that ref-mid-buffer is aligned // to 16 byte boundary for efficiency m_ppRefMidBuffer[i] = (float *) ((((unsigned long) m_ppRefMidBufferUnaligned[i]) + 15) & -16); } m_bMidBufferDirty = true; clearMidBuffer(); } } // Calculates processing sequence length according to tempo setting. void qtractorTimeStretch::calcSeekWindowLength (void) { // Adjust tempo param according to tempo, // so that variating processing sequence length is used... // at varius tempo settings, between the given low...top limits #define AUTO_TEMPO_MIN 0.5f // auto setting low tempo range (-50%) #define AUTO_TEMPO_MAX 2.0f // auto setting top tempo range (+100%) #define AUTO_TEMPO_DIFF (AUTO_TEMPO_MAX - AUTO_TEMPO_MIN) // iSequenceMs setting values at above low & top tempo. #define AUTO_SEQ_MIN 40.0f #define AUTO_SEQ_MAX 125.0f #define AUTO_SEQ_DIFF (AUTO_SEQ_MAX - AUTO_SEQ_MIN) #define AUTO_SEQ_K (AUTO_SEQ_DIFF / AUTO_TEMPO_DIFF) #define AUTO_SEQ_C (AUTO_SEQ_MIN - (AUTO_SEQ_K * AUTO_TEMPO_MIN)) // iSeekWindowMs setting values at above low & top tempo. #define AUTO_SEEK_MIN 15.0f #define AUTO_SEEK_MAX 25.0f #define AUTO_SEEK_DIFF (AUTO_SEEK_MAX - AUTO_SEEK_MIN) #define AUTO_SEEK_K (AUTO_SEEK_DIFF / AUTO_TEMPO_DIFF) #define AUTO_SEEK_C (AUTO_SEEK_MIN - (AUTO_SEEK_K * AUTO_TEMPO_MIN)) #define AUTO_LIMITS(x, a, b) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x))) if (m_bAutoSequenceMs) { float fSeq = AUTO_SEQ_C + AUTO_SEQ_K * m_fTempo; fSeq = AUTO_LIMITS(fSeq, AUTO_SEQ_MIN, AUTO_SEQ_MAX); m_iSequenceMs = (unsigned int) (fSeq + 0.5f); } if (m_bAutoSeekWindowMs) { float fSeek = AUTO_SEEK_C + AUTO_SEEK_K * m_fTempo; fSeek = AUTO_LIMITS(fSeek, AUTO_SEEK_MIN, AUTO_SEEK_MAX); m_iSeekWindowMs = (unsigned int) (fSeek + 0.5f); } // Update seek window lengths. m_iSeekLength = (m_iSampleRate * m_iSeekWindowMs) / 1000; m_iSeekWindowLength = (m_iSampleRate * m_iSequenceMs) / 1000; } // end of qtractorTimeStretch.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorPluginSelectForm.cpp0000644000175000001440000000012312166526620022757 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134667.12408 30 ctime=1381134667.125080051 qtractor-0.5.11/src/qtractorPluginSelectForm.cpp0000644000175000001440000002733412166526620022257 0ustar00rncbcusers00000000000000// qtractorPluginSelectForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorPluginSelectForm.h" #ifdef CONFIG_LV2 #include "qtractorLv2Plugin.h" #endif #include "qtractorOptions.h" #include #include #include #include #include #include static qtractorPluginPath g_pluginPath; //---------------------------------------------------------------------------- // qtractorPluginSelectForm -- UI wrapper form. // Constructor. qtractorPluginSelectForm::qtractorPluginSelectForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::WindowModal); m_iChannels = 0; m_bMidi = false; // Populate plugin type hints... m_ui.PluginTypeComboBox->addItem( qtractorPluginType::textFromHint(qtractorPluginType::Any)); #ifdef CONFIG_LADSPA m_ui.PluginTypeComboBox->addItem( qtractorPluginType::textFromHint(qtractorPluginType::Ladspa)); #endif #ifdef CONFIG_DSSI m_ui.PluginTypeComboBox->addItem( qtractorPluginType::textFromHint(qtractorPluginType::Dssi)); #endif #ifdef CONFIG_VST m_ui.PluginTypeComboBox->addItem( qtractorPluginType::textFromHint(qtractorPluginType::Vst)); #endif #ifdef CONFIG_LV2 m_ui.PluginTypeComboBox->addItem( qtractorPluginType::textFromHint(qtractorPluginType::Lv2)); #endif QHeaderView *pHeader = m_ui.PluginListView->header(); // pHeader->setDefaultSectionSize(240); #if QT_VERSION >= 0x050000 // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionsMovable(false); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setMovable(false); #endif pHeader->setStretchLastSection(true); QTreeWidgetItem *pHeaderItem = m_ui.PluginListView->headerItem(); pHeaderItem->setTextAlignment(0, Qt::AlignLeft); // Name. pHeaderItem->setTextAlignment(5, Qt::AlignLeft); // Filename. pHeaderItem->setTextAlignment(6, Qt::AlignLeft); // Index. pHeaderItem->setTextAlignment(7, Qt::AlignLeft); // Instances. pHeaderItem->setTextAlignment(8, Qt::AlignLeft); // Type. pHeader->resizeSection(0, 240); // Name. m_ui.PluginListView->resizeColumnToContents(1); // Audio. m_ui.PluginListView->resizeColumnToContents(2); // MIDI. m_ui.PluginListView->resizeColumnToContents(3); // Controls. m_ui.PluginListView->resizeColumnToContents(4); // Modes. pHeader->resizeSection(5, 120); // Path. m_ui.PluginListView->resizeColumnToContents(6); // Index m_ui.PluginListView->resizeColumnToContents(7); // Instances m_ui.PluginListView->setSortingEnabled(true); m_ui.PluginListView->sortItems(0, Qt::AscendingOrder); m_ui.PluginTypeProgressBar->hide(); // Initialize conveniency options... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { pOptions->loadComboBoxHistory(m_ui.PluginSearchComboBox); m_ui.PluginSearchComboBox->setEditText( pOptions->sPluginSearch); m_ui.PluginTypeComboBox->setCurrentIndex(pOptions->iPluginType); m_ui.PluginActivateCheckBox->setChecked(pOptions->bPluginActivate); g_pluginPath.setPaths(qtractorPluginType::Ladspa, pOptions->ladspaPaths); g_pluginPath.setPaths(qtractorPluginType::Dssi, pOptions->dssiPaths); g_pluginPath.setPaths(qtractorPluginType::Vst, pOptions->vstPaths); g_pluginPath.setPaths(qtractorPluginType::Lv2, pOptions->lv2Paths); } // Let the search begin... m_ui.PluginSearchComboBox->setFocus(); typeHintChanged(m_ui.PluginTypeComboBox->currentIndex()); adjustSize(); // Restore last seen dialog position and extent... if (pOptions) pOptions->loadWidgetGeometry(this, true); // UI signal/slot connections... QObject::connect(m_ui.PluginResetToolButton, SIGNAL(clicked()), SLOT(reset())); QObject::connect(m_ui.PluginSearchComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(refresh())); QObject::connect(m_ui.PluginTypeComboBox, SIGNAL(activated(int)), SLOT(typeHintChanged(int))); QObject::connect(m_ui.PluginListView, SIGNAL(itemSelectionChanged()), SLOT(stabilize())); // QObject::connect(m_ui.PluginListView, // SIGNAL(itemActivated(QTreeWidgetItem *, int)), // SLOT(accept())); QObject::connect(m_ui.PluginListView, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), SLOT(accept())); QObject::connect(m_ui.PluginActivateCheckBox, SIGNAL(clicked()), SLOT(stabilize())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); } // Destructor. qtractorPluginSelectForm::~qtractorPluginSelectForm (void) { // Save other conveniency options, if convenient thought... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { pOptions->iPluginType = m_ui.PluginTypeComboBox->currentIndex(); pOptions->sPluginSearch = m_ui.PluginSearchComboBox->currentText(); pOptions->saveComboBoxHistory(m_ui.PluginSearchComboBox); pOptions->bPluginActivate= m_ui.PluginActivateCheckBox->isChecked(); // Save aslast seen dialog position and extent... pOptions->saveWidgetGeometry(this, true); } } // Base number of channels accessors. void qtractorPluginSelectForm::setChannels ( unsigned short iChannels, bool bMidi ) { m_iChannels = iChannels; m_bMidi = bMidi; refresh(); } unsigned short qtractorPluginSelectForm::channels (void) const { return m_iChannels; } bool qtractorPluginSelectForm::isMidi (void) const { return m_bMidi; } // Final selection accessors.. int qtractorPluginSelectForm::pluginCount (void) const { return m_selectedItems.count(); } QString qtractorPluginSelectForm::pluginFilename ( int iPlugin ) const { return m_selectedItems.at(iPlugin)->text(5); } unsigned long qtractorPluginSelectForm::pluginIndex ( int iPlugin ) const { return m_selectedItems.at(iPlugin)->text(6).toULong(); } qtractorPluginType::Hint qtractorPluginSelectForm::pluginTypeHint ( int iPlugin ) const { const QString& sText = m_selectedItems.at(iPlugin)->text(8); return qtractorPluginType::hintFromText(sText); } bool qtractorPluginSelectForm::isPluginActivated (void) const { return m_ui.PluginActivateCheckBox->isChecked(); } // Plugin type hint change slot. void qtractorPluginSelectForm::typeHintChanged ( int iTypeHint ) { qtractorPluginType::Hint typeHint = qtractorPluginType::hintFromText( m_ui.PluginTypeComboBox->itemText(iTypeHint)); if (g_pluginPath.typeHint() != typeHint) { g_pluginPath.setTypeHint(typeHint); g_pluginPath.open(); g_pluginPath.clear(); } refresh(); } // Reset plugin listing. void qtractorPluginSelectForm::reset (void) { m_ui.PluginSearchComboBox->lineEdit()->clear(); // refresh(); } // Refresh plugin listing. void qtractorPluginSelectForm::refresh (void) { // if (m_iChannels == 0) // return; m_ui.PluginListView->clear(); // FIXME: Should this be a global (singleton) registry? if (g_pluginPath.types().isEmpty()) { // Tell the world we'll take some time... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); int iFile = 0; qtractorPluginType::Hint typeHint = qtractorPluginType::hintFromText( m_ui.PluginTypeComboBox->currentText()); m_ui.PluginTypeProgressBar->setMaximum(g_pluginPath.files().count()); m_ui.PluginTypeProgressBar->show(); QListIterator file_iter(g_pluginPath.files()); while (file_iter.hasNext()) { m_ui.PluginTypeProgressBar->setValue(++iFile); QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); qtractorPluginFile *pFile = file_iter.next(); if (pFile->open()) { pFile->getTypes(g_pluginPath, typeHint); pFile->close(); } } #ifdef CONFIG_LV2 if (typeHint == qtractorPluginType::Any || typeHint == qtractorPluginType::Lv2) { qtractorLv2PluginType::getTypes(g_pluginPath); } #endif m_ui.PluginTypeProgressBar->hide(); // We're formerly done. QApplication::restoreOverrideCursor(); } QString sSearch = m_ui.PluginSearchComboBox->currentText().simplified(); QRegExp rx(sSearch.replace(QRegExp("[\\s]+"), ".*"), Qt::CaseInsensitive); QStringList cols; QList items; QListIterator type_iter(g_pluginPath.types()); while (type_iter.hasNext()) { qtractorPluginType *pType = type_iter.next(); const QString& sFilename = pType->filename(); const QString& sName = pType->name(); if (rx.isEmpty() || rx.indexIn(sName) >= 0 || rx.indexIn(sFilename) >= 0) { // Try primary instantiation... int iAudioIns = pType->audioIns(); int iAudioOuts = pType->audioOuts(); int iMidiIns = pType->midiIns(); int iMidiOuts = pType->midiOuts(); int iControlIns = pType->controlIns(); int iControlOuts = pType->controlOuts(); // All that to check whether it will get properly instantiated. unsigned short iInstances = pType->instances(m_iChannels, m_bMidi); cols.clear(); cols << sName; cols << QString("%1:%2").arg(iAudioIns).arg(iAudioOuts); cols << QString("%1:%2").arg(iMidiIns).arg(iMidiOuts); cols << QString("%1:%2").arg(iControlIns).arg(iControlOuts); QStringList modes; if (pType->isEditor()) modes << tr("GUI"); if (pType->isConfigure()) modes << tr("EXT"); if (pType->isRealtime()) modes << tr("RT"); if (modes.isEmpty()) cols << "-"; else cols << modes.join(","); cols << sFilename; cols << QString::number(pType->index()); cols << QString::number(iInstances); cols << qtractorPluginType::textFromHint(pType->typeHint()); QTreeWidgetItem *pItem = new QTreeWidgetItem(cols); if (iInstances < 1) { pItem->setFlags(pItem->flags() & ~Qt::ItemIsSelectable); int iColumnCount = m_ui.PluginListView->columnCount(); const QPalette& pal = m_ui.PluginListView->palette(); const QColor& rgbForeground = pal.color(QPalette::Disabled, QPalette::WindowText); for (int i = 0; i < iColumnCount; ++i) pItem->setForeground(i, rgbForeground); } pItem->setTextAlignment(1, Qt::AlignHCenter); // Audio pItem->setTextAlignment(2, Qt::AlignHCenter); // MIDI pItem->setTextAlignment(3, Qt::AlignHCenter); // Controls pItem->setTextAlignment(4, Qt::AlignHCenter); // Modes items.append(pItem); } } m_ui.PluginResetToolButton->setEnabled(!rx.isEmpty()); m_ui.PluginListView->addTopLevelItems(items); // m_ui.PluginListView->resizeColumnToContents(0); // Name. QHeaderView *pHeader = m_ui.PluginListView->header(); m_ui.PluginListView->sortItems( pHeader->sortIndicatorSection(), pHeader->sortIndicatorOrder()); stabilize(); } // Stabilize slot. void qtractorPluginSelectForm::stabilize (void) { m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled( !m_ui.PluginListView->selectedItems().isEmpty()); } // Accept slot. void qtractorPluginSelectForm::accept (void) { // Are we done? m_selectedItems = m_ui.PluginListView->selectedItems(); if (!m_selectedItems.isEmpty()) QDialog::accept(); } // end of qtractorPluginSelectForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTrackCommand.h0000644000175000001440000000012312221411230021523 xustar000000000000000027 mtime=1380323992.023236 26 atime=1381134671.09308 30 ctime=1381134671.093080114 qtractor-0.5.11/src/qtractorTrackCommand.h0000644000175000001440000001736312221411230021024 0ustar00rncbcusers00000000000000// qtractorTrackCommand.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorTrackCommand_h #define __qtractorTrackCommand_h #include "qtractorPropertyCommand.h" #include "qtractorSession.h" #include // Forward declarations. class qtractorClipCommand; //---------------------------------------------------------------------- // class qtractorTrackCommand - declaration. // class qtractorTrackCommand : public qtractorCommand { public: // Constructor. qtractorTrackCommand(const QString& sName, qtractorTrack *pTrack); // Destructor. virtual ~qtractorTrackCommand(); // Track accessor. qtractorTrack *track() const { return m_pTrack; } protected: // Extra track list item. struct TrackItem { // Constructor. TrackItem(qtractorTrack *pTrack, bool bOn) : track(pTrack), on(bOn) {} // Item members. qtractorTrack *track; bool on; }; // Track command methods. bool addTrack(qtractorTrack *pAfterTrack = NULL); bool removeTrack(); private: // Instance variables. qtractorTrack *m_pTrack; }; //---------------------------------------------------------------------- // class qtractorAddTrackCommand - declaration. // class qtractorAddTrackCommand : public qtractorTrackCommand { public: // Constructor. qtractorAddTrackCommand(qtractorTrack *pTrack, qtractorTrack *pAfterTrack = NULL); // Track insertion command methods. bool redo(); bool undo(); private: // Instance variables. qtractorTrack *m_pAfterTrack; }; //---------------------------------------------------------------------- // class qtractorRemoveTrackCommand - declaration. // class qtractorRemoveTrackCommand : public qtractorTrackCommand { public: // Constructor. qtractorRemoveTrackCommand(qtractorTrack *pTrack); // Track-removal command methods. bool redo(); bool undo(); }; //---------------------------------------------------------------------- // class qtractorMoveTrackCommand - declaration. // class qtractorMoveTrackCommand : public qtractorTrackCommand { public: // Constructor. qtractorMoveTrackCommand(qtractorTrack *pTrack, qtractorTrack *pNextTrack); // Track-move command methods. bool redo(); bool undo(); private: // Instance variables. qtractorTrack *m_pNextTrack; }; //---------------------------------------------------------------------- // class qtractorResizeTrackCommand - declaration. // class qtractorResizeTrackCommand : public qtractorTrackCommand { public: // Constructor. qtractorResizeTrackCommand(qtractorTrack *pTrack, int iZoomHeight); // Track-move command methods. bool redo(); bool undo(); private: // Instance variables. int m_iZoomHeight; }; //---------------------------------------------------------------------- // class qtractorInportTracksCommand - declaration. // class qtractorImportTrackCommand : public qtractorCommand { public: // Constructor. qtractorImportTrackCommand(qtractorTrack *pAfterTrack); // Destructor. ~qtractorImportTrackCommand(); // Add track to command list. void addTrack(qtractorTrack *pTrack); // Track-import command methods. bool redo(); bool undo(); private: // Instance variables. qtractorTrack *m_pAfterTrack; QList m_trackCommands; // Session properties backup stuff. qtractorSession::Properties m_sessionProps; qtractorPropertyCommand *m_pSaveCommand; int m_iSaveCount; }; //---------------------------------------------------------------------- // class qtractorEditTrackCommand - declaration. // class qtractorEditTrackCommand : public qtractorPropertyCommand { public: // Constructor. qtractorEditTrackCommand(qtractorTrack *pTrack, const qtractorTrack::Properties& props); // Overridden track-edit command methods. bool redo(); bool undo(); private: // Instance variables. qtractorTrack *m_pTrack; }; //---------------------------------------------------------------------- // class qtractorTrackControlCommand - declaration. // class qtractorTrackControlCommand : public qtractorTrackCommand { public: // Constructor. qtractorTrackControlCommand(const QString& sName, qtractorTrack *pTrack, bool bMidiControl = false); protected: // Primitive control predicates. bool midiControlFeedback(); private: // Instance variables. bool m_bMidiControl; int m_iMidiControlFeedback; }; //---------------------------------------------------------------------- // class qtractorTrackStateCommand - declaration. // class qtractorTrackStateCommand : public qtractorTrackControlCommand { public: // Constructor. qtractorTrackStateCommand(qtractorTrack *pTrack, qtractorTrack::ToolType toolType, bool bOn, bool bMidiControl = false); // Destructor. ~qtractorTrackStateCommand(); // Track-button command methods. bool redo(); bool undo(); private: // Instance variables. qtractorTrack::ToolType m_toolType; bool m_bOn; // Extra track list. QList m_tracks; // Special sub-command needed to track recording clips. qtractorClipCommand *m_pClipCommand; int m_iRecordCount; }; //---------------------------------------------------------------------- // class qtractorTrackMonitorCommand - declaration. // class qtractorTrackMonitorCommand : public qtractorTrackControlCommand { public: // Constructor. qtractorTrackMonitorCommand(qtractorTrack *pTrack, bool bMonitor, bool bMidiControl = false); // Destructor. ~qtractorTrackMonitorCommand(); // Track-monitoring command methods. bool redo(); bool undo() { return redo(); } private: // Instance variables. bool m_bMonitor; // Extra track list. QList m_tracks; }; //---------------------------------------------------------------------- // class qtractorTrackGainCommand - declaration. // class qtractorTrackGainCommand : public qtractorTrackControlCommand { public: // Constructor. qtractorTrackGainCommand(qtractorTrack *pTrack, float fGain, bool bMidiControl = false); // Track-gain command methods. bool redo(); bool undo() { return redo(); } // Gain value retrieval. float gain() const { return m_fGain; } // Last known gain predicate. float prevGain() const { return m_fPrevGain; } private: // Instance variables. float m_fGain; float m_fPrevGain; }; //---------------------------------------------------------------------- // class qtractorTrackPanningCommand - declaration. // class qtractorTrackPanningCommand : public qtractorTrackControlCommand { public: // Constructor. qtractorTrackPanningCommand(qtractorTrack *pTrack, float fPanning, bool bMidiControl = false); // Track-panning command methods. bool redo(); bool undo() { return redo(); } // Panning value retrieval. float panning() const { return m_fPanning; } // Last known panning predicate. float prevPanning() const { return m_fPrevPanning; } private: // Instance variables. float m_fPanning; float m_fPrevPanning; }; #endif // __qtractorTrackCommand_h // end of qtractorTrackCommand.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorCtlEvent.h0000644000175000001440000000012311450205162020714 xustar000000000000000027 mtime=1285622386.245739 26 atime=1381134667.24408 30 ctime=1381134667.244080053 qtractor-0.5.11/src/qtractorCtlEvent.h0000644000175000001440000000410611450205162020204 0ustar00rncbcusers00000000000000// qtractorCtlEvent.h // /**************************************************************************** Copyright (C) 2010, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorCtlEvent_h #define __qtractorCtlEvent_h #include "qtractorMidiEvent.h" //---------------------------------------------------------------------- // qtractorCtlEvent - MIDI Control custom event. // class qtractorCtlEvent { public: // Contructor. qtractorCtlEvent(qtractorMidiEvent::EventType ctype = qtractorMidiEvent::CONTROLLER, unsigned short iChannel = 0, unsigned short iParam = 0, unsigned short iValue = 0) : m_ctype(ctype), m_channel(iChannel), m_param(iParam), m_value(iValue) {} // Copy constructor. qtractorCtlEvent(const qtractorCtlEvent& ctle) : m_ctype(ctle.m_ctype), m_channel(ctle.m_channel), m_param(ctle.m_param), m_value(ctle.m_value) {} // Accessors. qtractorMidiEvent::EventType type() const { return m_ctype; } unsigned short channel() const { return m_channel; } unsigned short param() const { return m_param; } unsigned short value() const { return m_value; } private: // Instance variables. qtractorMidiEvent::EventType m_ctype; unsigned short m_channel; unsigned short m_param; unsigned short m_value; }; #endif // __qtractorCtlEvent_h // end of qtractorCtlEvent.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioListView.cpp0000644000175000001440000000012312166526620022265 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134667.54908 30 ctime=1381134667.549080058 qtractor-0.5.11/src/qtractorAudioListView.cpp0000644000175000001440000001435712166526620021566 0ustar00rncbcusers00000000000000// qtractorAudioListView.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorAudioListView.h" #include "qtractorAudioFile.h" #include "qtractorOptions.h" #include #include #include //---------------------------------------------------------------------- // class qtractorAudioFileItem -- audio file list view item. // // Constructors. qtractorAudioFileItem::qtractorAudioFileItem ( const QString& sPath, qtractorAudioFile *pFile ) : qtractorFileListItem(sPath) { QTreeWidgetItem::setTextAlignment( qtractorAudioListView::Channels, Qt::AlignRight); QTreeWidgetItem::setTextAlignment( qtractorAudioListView::Frames, Qt::AlignRight); QTreeWidgetItem::setTextAlignment( qtractorAudioListView::Rate, Qt::AlignRight); QTreeWidgetItem::setIcon(qtractorAudioListView::Name, QIcon(":/images/itemAudioFile.png")); QTreeWidgetItem::setText(qtractorAudioListView::Channels, QString::number(pFile->channels())); QTreeWidgetItem::setText(qtractorAudioListView::Frames, QString::number(pFile->frames())); QTreeWidgetItem::setText(qtractorAudioListView::Rate, QString::number(pFile->sampleRate())); QString sTime; unsigned int hh, mm, ss, zzz; float secs = (float) pFile->frames() / (float) pFile->sampleRate(); hh = mm = ss = 0; if (secs >= 3600.0f) { hh = (unsigned int) (secs / 3600.0f); secs -= (float) hh * 3600.0f; } if (secs >= 60.0f) { mm = (unsigned int) (secs / 60.0f); secs -= (float) mm * 60.0f; } if (secs >= 0.0f) { ss = (unsigned int) secs; secs -= (float) ss; } zzz = (unsigned int) (secs * 1000.0f); sTime.sprintf("%02u:%02u:%02u.%03u", hh, mm, ss, zzz); QTreeWidgetItem::setText(qtractorAudioListView::Time, sTime); QTreeWidgetItem::setText(qtractorAudioListView::Path, sPath); } // Tooltip renderer. QString qtractorAudioFileItem::toolTip (void) const { return QObject::tr( "%1 (%2)\n%3 channels, %4 frames, %5 Hz\n%6") .arg(QTreeWidgetItem::text(qtractorAudioListView::Name)) .arg(QTreeWidgetItem::text(qtractorAudioListView::Time)) .arg(QTreeWidgetItem::text(qtractorAudioListView::Channels)) .arg(QTreeWidgetItem::text(qtractorAudioListView::Frames)) .arg(QTreeWidgetItem::text(qtractorAudioListView::Rate)) .arg(QTreeWidgetItem::text(qtractorAudioListView::Path)); } //---------------------------------------------------------------------------- // qtractorAudioListView -- Group/File list view, supporting drag-n-drop. // // Constructor. qtractorAudioListView::qtractorAudioListView ( QWidget *pParent ) : qtractorFileListView(qtractorFileList::Audio, pParent) { QTreeWidget::setColumnCount(qtractorAudioListView::LastColumn + 1); QTreeWidgetItem *pHeaderItem = QTreeWidget::headerItem(); pHeaderItem->setText(qtractorAudioListView::Name, tr("Name")); pHeaderItem->setText(qtractorAudioListView::Channels, tr("Ch")); pHeaderItem->setText(qtractorAudioListView::Frames, tr("Frames")); pHeaderItem->setText(qtractorAudioListView::Rate, tr("Rate")); pHeaderItem->setText(qtractorAudioListView::Time, tr("Time")); pHeaderItem->setText(qtractorAudioListView::Path, tr("Path")); pHeaderItem->setText(qtractorAudioListView::LastColumn, QString::null); pHeaderItem->setTextAlignment( qtractorAudioListView::Channels, Qt::AlignRight); pHeaderItem->setTextAlignment( qtractorAudioListView::Frames, Qt::AlignRight); pHeaderItem->setTextAlignment( qtractorAudioListView::Rate, Qt::AlignRight); QHeaderView *pHeader = QTreeWidget::header(); pHeader->resizeSection(qtractorAudioListView::Name, 160); QTreeWidget::resizeColumnToContents(qtractorAudioListView::Channels); QTreeWidget::resizeColumnToContents(qtractorAudioListView::Frames); QTreeWidget::resizeColumnToContents(qtractorAudioListView::Rate); QTreeWidget::resizeColumnToContents(qtractorAudioListView::Time); pHeader->resizeSection(qtractorAudioListView::Path, 160); } // Prompt for proper file list open. QStringList qtractorAudioListView::getOpenFileNames (void) { QStringList files; const QString& sTitle = tr("Open Audio Files") + " - " QTRACTOR_TITLE; #if 0//QT_VERSION < 0x040400 // Ask for the filename to open... files = QFileDialog::getOpenFileNames(this, sTitle, recentDir(), qtractorAudioFileFactory::filters()); #else // Construct open-files dialog... QFileDialog fileDialog(this, sTitle, recentDir(), qtractorAudioFileFactory::filters()); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::ExistingFiles); fileDialog.setDefaultSuffix(qtractorAudioFileFactory::defaultExt()); // Stuff sidebar... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(pOptions->sAudioDir)); fileDialog.setSidebarUrls(urls); } // Show dialog... if (fileDialog.exec()) files = fileDialog.selectedFiles(); #endif return files; } // File item factory method. qtractorFileListItem *qtractorAudioListView::createFileItem ( const QString& sPath ) { qtractorFileListItem *pFileItem = NULL; qtractorAudioFile *pFile = qtractorAudioFileFactory::createAudioFile(sPath); if (pFile == NULL) return NULL; if (pFile->open(sPath)) { pFileItem = new qtractorAudioFileItem(sPath, pFile); pFile->close(); } delete pFile; return pFileItem; } // end of qtractorAudioListView.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorCurveSelect.h0000644000175000001440000000012312223511102021405 xustar000000000000000027 mtime=1380880962.062114 26 atime=1381134671.09808 30 ctime=1381134671.098080114 qtractor-0.5.11/src/qtractorCurveSelect.h0000644000175000001440000000570012223511102020676 0ustar00rncbcusers00000000000000// qtractorCurveSelect.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorCurveSelect_h #define __qtractorCurveSelect_h #include "qtractorCurve.h" #include #include //------------------------------------------------------------------------- // qtractorCurveSelect -- MIDI event selection capsule. class qtractorCurveSelect { public: // Constructor. qtractorCurveSelect(); // Default destructor. ~qtractorCurveSelect(); // Selection item struct. struct Item { // Item constructor. Item(const QRect& rect): rectNode(rect), flags(1) {} // Item members. QRect rectNode; unsigned int flags; }; typedef QHash ItemList; // Event selection item lookup. Item *findItem(qtractorCurve::Node *pNode); // Event insertion method. void addItem(qtractorCurve::Node *pNode, const QRect& rectNode); // Event removal method. void removeItem(qtractorCurve::Node *pNode); // Event selection method. void selectItem(qtractorCurve *pCurve, qtractorCurve::Node *pNode, const QRect& rectNode, bool bSelect = true, bool bToggle = false); // The united selection rectangle. const QRect& rect() const { return m_rect; } // Selection list accessor. const ItemList& items() const { return m_items; } // Selection update method. void update(bool bCommit); // Selection commit method. void commit(); // Reset event selection. void clear(); // Selection curve accessors. void setCurve ( qtractorCurve *pCurve ) { m_pCurve = pCurve; } qtractorCurve *curve() const { return m_pCurve; } qtractorCurve::Node *anchorNode() const { return m_pAnchorNode; } // Selection curve testimony. bool isCurrentCurve ( qtractorCurve *pCurve ) const { return (m_pCurve && m_pCurve == pCurve); } private: // The node selection list. ItemList m_items; // The united selection rectangle. QRect m_rect; // There must be only one curve. qtractorCurve *m_pCurve; // The most probable anchor node. qtractorCurve::Node *m_pAnchorNode; }; #endif // __qtractorCurveSelect_h // end of qtractorCurveSelect.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorTakeRangeForm.ui0000644000175000001440000000012312165325675022063 xustar000000000000000027 mtime=1372957629.743777 26 atime=1381134667.31608 30 ctime=1381134667.316080054 qtractor-0.5.11/src/qtractorTakeRangeForm.ui0000644000175000001440000002004112165325675021347 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorTakeRangeForm 0 0 360 260 Qt::StrongFocus Take - Qtractor :/images/qtractor.png:/images/qtractor.png Range En&d: TakeEndSpinBox Selection range &Selection false Qt::Horizontal QSizePolicy::Fixed 14 14 Edit range &Edit false Custom range &Custom true Loop range &Loop false 120 0 Clip start 120 0 Clip offset St&art: TakeStartSpinBox Punch range &Punch false Select 0 0 100 100 Current take Format Time display format Frames Time BBT Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qtractorTimeSpinBox QSpinBox
qtractorSpinBox.h
SelectionRangeRadioButton LoopRangeRadioButton PunchRangeRadioButton EditRangeRadioButton CustomRangeRadioButton TakeStartSpinBox TakeEndSpinBox CurrentTakeListBox FormatComboBox
qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditTime.h0000644000175000001440000000012012066537040021503 xustar000000000000000024 mtime=1356512800.799 26 atime=1381134667.66108 30 ctime=1381134667.661080059 qtractor-0.5.11/src/qtractorMidiEditTime.h0000644000175000001440000000644512066537040021006 0ustar00rncbcusers00000000000000// qtractorMidiEditTime.h // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiEditTime_h #define __qtractorMidiEditTime_h #include "qtractorScrollView.h" #include "qtractorTimeScale.h" #include // Forward declarations. class qtractorMidiEditor; class QResizeEvent; class QMouseEvent; class QKeyEvent; //---------------------------------------------------------------------------- // qtractorMidiEditTime -- MIDI sequence time scale widget. class qtractorMidiEditTime : public qtractorScrollView { Q_OBJECT public: // Constructor. qtractorMidiEditTime(qtractorMidiEditor *pEditor, QWidget *pParent); // Rectangular contents update. void updateContents(const QRect& rect); // Overall contents update. void updateContents(); protected: // Resize event handler. void resizeEvent(QResizeEvent *pResizeEvent); // Draw the time scale. void drawContents(QPainter *pPainter, const QRect& rect); // Check if some position header is to be dragged... bool dragHeadStart(const QPoint& pos); // Handle item selection with mouse. void mousePressEvent(QMouseEvent *pMouseEvent); void mouseMoveEvent(QMouseEvent *pMouseEvent); void mouseReleaseEvent(QMouseEvent *pMouseEvent); // Tempo-map dialog accessor. void mouseDoubleClickEvent(QMouseEvent *pMouseEvent); // Keyboard event handler. void keyPressEvent(QKeyEvent *pKeyEvent); // Reset drag/select state. void resetDragState(); // Context menu request slot (dummy). void contextMenuEvent(QContextMenuEvent *); // Trap for help/tool-tip events. bool eventFilter(QObject *pObject, QEvent *pEvent); // Show dragging tooltip... void showToolTip(unsigned long iFrame) const; void showToolTip(const QRect& rect) const; protected slots: // To have timeline in h-sync with main track view. void contentsXMovingSlot(int cx, int cy); // (Re)create the time scale pixmap. void updatePixmap(int cx, int cy); private: // The logical parent binding. qtractorMidiEditor *m_pEditor; // Local double-buffering pixmap. QPixmap m_pixmap; // The current selecting/dragging head stuff. enum DragState { DragNone = 0, DragStart, DragSelect, DragPlayHead, DragMarker, DragEditHead, DragEditTail, DragLoopStart, DragLoopEnd, DragPunchIn, DragPunchOut } m_dragState, m_dragCursor; QRect m_rectDrag; QPoint m_posDrag; qtractorTimeScale::Marker *m_pDragMarker; }; #endif // __qtractorMidiEditTime_h // end of qtractorMidiEditTime.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiControl.h0000644000175000001440000000012312073012112021404 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134670.52808 30 ctime=1381134670.528080105 qtractor-0.5.11/src/qtractorMidiControl.h0000644000175000001440000002205012073012112020672 0ustar00rncbcusers00000000000000// qtractorMidiControl.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. Copyright (C) 2009, gizzmo aka Mathias Krause. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiControl_h #define __qtractorMidiControl_h #include "qtractorCtlEvent.h" #include #include // Forward declarations. class qtractorTrack; class qtractorDocument; class qtractorCtlEvent; class qtractorMidiControlObserver; class QDomElement; //---------------------------------------------------------------------- // qtractorMidiControl -- MIDI control map (singleton). // class qtractorMidiControl { public: // Controller types. typedef qtractorMidiEvent::EventType ControlType; // Controller command types. enum Command { TRACK_GAIN = 1, TRACK_PANNING = 2, TRACK_MONITOR = 3, TRACK_RECORD = 4, TRACK_MUTE = 5, TRACK_SOLO = 6 }; // Key param masks (wildcard flags). enum { TrackParam = 0x4000, TrackParamMask = 0x3fff }; // MIDI control map key. class MapKey { public: // Constructor. MapKey(ControlType ctype = qtractorMidiEvent::CONTROLLER, unsigned short iChannel = 0, unsigned short iParam = 0) : m_ctype(ctype), m_iChannel(iChannel), m_iParam(iParam) {} // Type accessors. void setType(ControlType ctype) { m_ctype = ctype; } ControlType type() const { return m_ctype; } // Channel accessors. void setChannel(unsigned short iChannel) { m_iChannel = iChannel; } unsigned short channel() const { return m_iChannel; } bool isChannel() const { return ((m_iChannel & TrackParamMask) == m_iChannel); } bool isChannelTrack() const { return (m_iChannel & TrackParam); } // Controller accessors. void setParam(unsigned short iParam) { m_iParam = iParam; } unsigned short param() const { return m_iParam; } bool isParam() const { return ((m_iParam & TrackParamMask ) == m_iParam); } bool isParamTrack() const { return (m_iParam & TrackParam); } // Generic key matcher. bool match(ControlType ctype, unsigned short iChannel, unsigned short iParam) const { return (type() == ctype && (isChannelTrack() || channel() == iChannel) && (isParamTrack() || param() == iParam)); } // Hash key comparator. bool operator== (const MapKey& key) const { return (key.m_ctype == m_ctype) && (key.m_iChannel == m_iChannel) && (key.m_iParam == m_iParam); } private: // Instance (key) member variables. ControlType m_ctype; unsigned short m_iChannel; unsigned short m_iParam; }; // MIDI control map data value. class MapVal { public: // Constructor. MapVal(Command command = Command(0), int iTrack = 0, bool bFeedback = false) : m_command(command), m_iTrack(iTrack), m_bFeedback(bFeedback), m_bValueInit(false), m_bValueSync(false), m_fValue(0.0f) {} // Command accessors void setCommand(Command command) { m_command = command; } Command command() const { return m_command; } // Track offset accessor. void setTrack(int iTrack) { m_iTrack = iTrack; } int track() const { return m_iTrack; } // Feedback flag accessor. void setFeedback(bool bFeedback) { m_bFeedback = bFeedback; } int isFeedback() const { return m_bFeedback; } // Tracking/catch-up methods. bool sync(float fValue, float fOldValue) { if (m_bValueInit && !m_bValueSync) { const float v0 = m_fValue; const float v1 = fOldValue; if ((fValue > v0 && v1 >= v0 && fValue >= v1) || (fValue < v0 && v0 >= v1 && v1 >= fValue)) m_bValueSync = true; } if (!m_bValueSync) m_bValueInit = true; m_fValue = fValue; return m_bValueSync; } void syncReset() { m_bValueSync = false; } float value() const { return m_fValue; } private: // Instance (value) member variables. Command m_command; int m_iTrack; bool m_bFeedback; // Tracking/catch-up members. bool m_bValueInit; bool m_bValueSync; float m_fValue; }; // MIDI control map type. typedef QHash ControlMap; // Constructor. qtractorMidiControl(); // Destructor. ~qtractorMidiControl(); static qtractorMidiControl *getInstance(); // Clear control map (reset to default). void clear(); // Insert new controller mappings. void mapChannelParam(ControlType ctype, unsigned short iChannel, unsigned short iParam, Command command, int iTrack = 0, bool bFeedback = false); void mapChannelTrack(ControlType ctype, unsigned short iParam, Command command, int iTrack = 0, bool bFeedback = false); void mapChannelParamTrack(ControlType ctype, unsigned short iChannel, unsigned short iParam, Command command, int iTrack = 0, bool bFeedback = false); // Remove existing controller mapping. void unmapChannelParam(ControlType ctype, unsigned short iChannel, unsigned short iParam); // Check if given channel, param triplet is currently mapped. bool isChannelParamMapped(ControlType ctype, unsigned short iChannel, unsigned short iParam) const; // Re-send all (track) controllers. void sendAllControllers(int iFirstTrack = 0) const; void sendController(ControlType ctype, unsigned short iChannel, unsigned short iParam, int iValue) const; // Process incoming controller messages. bool processEvent(const qtractorCtlEvent& ctle); // Process incoming command. void processTrackCommand( Command command, int iTrack, float fValue, bool bCubic = false); void processTrackCommand( Command command, int iTrack, bool bValue); // Control map accessor. const ControlMap& controlMap() const { return m_controlMap; } // Insert/remove observer mappings. void mapMidiObserver(qtractorMidiControlObserver *pMidiObserver); void unmapMidiObserver(qtractorMidiControlObserver *pMidiObserver); // Observer map predicate. bool isMidiObserverMapped(qtractorMidiControlObserver *pMidiObserver) const; // Observer finder. qtractorMidiControlObserver *findMidiObserver( ControlType ctype, unsigned short iChannel, unsigned short iParam) const; // Forward declaration. class Document; // Document element methods. bool loadElement(qtractorDocument *pDocument, QDomElement *pElement); bool saveElement(qtractorDocument *pDocument, QDomElement *pElement); // Document file methods. bool loadDocument(const QString& sFilename); bool saveDocument(const QString& sFilename); // Parameter controllers (MIDI). struct Controller { QString name; unsigned long index; ControlType ctype; unsigned short channel; unsigned short param; bool logarithmic; bool feedback; bool invert; bool hook; }; typedef QList Controllers; // Load/save meter controllers (MIDI). static void loadControllers( QDomElement *pElement, Controllers& controllers); static void saveControllers(qtractorDocument *pDocument, QDomElement *pElement, const Controllers& controllers); // Document textual helpers. static ControlType typeFromText(const QString& sText); static const QString& textFromType(ControlType ctype); static ControlType typeFromName(const QString& sName); static const QString& nameFromType(ControlType ctype); static unsigned short keyFromText(const QString& sText); static QString textFromKey(unsigned short iKey); static Command commandFromText(const QString& sText); static const QString& textFromCommand(Command command); static Command commandFromName(const QString& sName); static const QString& nameFromCommand(Command command); protected: // Find incoming controller event map. ControlMap::Iterator findEvent(const qtractorCtlEvent& ctle); // Overloaded controller value senders. void sendTrackController( ControlType ctype, qtractorTrack *pTrack, Command command, unsigned short iChannel, unsigned short iParam) const; void sendTrackController(int iTrack, Command command, int iValue); private: // MIDI control map. ControlMap m_controlMap; // MIDI observer map. typedef QHash ObserverMap; // MIDI observer map. ObserverMap m_observerMap; // Pseudo-singleton instance. static qtractorMidiControl *g_pMidiControl; }; // Hash key function inline uint qHash ( const qtractorMidiControl::MapKey& key ) { return qHash(uint(key.type()) ^ key.channel() ^ key.param()); } #endif // __qtractorMidiControl_h // end of qtractorMidiControl.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditList.h0000644000175000001440000000012312156061017021517 xustar000000000000000027 mtime=1371038223.355862 26 atime=1381134666.35708 30 ctime=1381134666.357080039 qtractor-0.5.11/src/qtractorMidiEditList.h0000644000175000001440000000700412156061017021007 0ustar00rncbcusers00000000000000// qtractorMidiEditList.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiEditList_h #define __qtractorMidiEditList_h #include "qtractorScrollView.h" #include // Forward declarations. class qtractorMidiEditor; class QResizeEvent; class QMouseEvent; class QKeyEvent; //---------------------------------------------------------------------------- // qtractorMidiEditList -- MIDI sequence key scale widget. class qtractorMidiEditList : public qtractorScrollView { Q_OBJECT public: // Constructor. qtractorMidiEditList(qtractorMidiEditor *pEditor, QWidget *pParent); // Destructor. ~qtractorMidiEditList(); // Item height constants (in pixels). enum { ItemHeightMin = 4, ItemHeightBase = 8, ItemHeightMax = 32 }; // Item height methods. void setItemHeight(unsigned short iItemHeight); unsigned short itemHeight() const; // Update key-list content height. void updateContentsHeight(); // Rectangular contents update. void updateContents(const QRect& rect); // Overall contents update. void updateContents(); // Piano keyboard note handler. void dragNoteOn(int iNote, int iVelocity = 1); // Piano keyboard position handler. void dragNoteOn(const QPoint& pos, int iVelocity = 1); protected: // Virtual size hint. QSize sizeHint() const { return QSize(60, 240); } // Resize event handler. void resizeEvent(QResizeEvent *pResizeEvent); // Draw the time scale. void drawContents(QPainter *pPainter, const QRect& rect); // Reset drag/select/move state. void resetDragState(); // Handle item selection with mouse. void mousePressEvent(QMouseEvent *pMouseEvent); void mouseMoveEvent(QMouseEvent *pMouseEvent); void mouseReleaseEvent(QMouseEvent *pMouseEvent); // Keyboard event handler. void keyPressEvent(QKeyEvent *pKeyEvent); // Handle zoom with mouse wheel. void wheelEvent(QWheelEvent *pWheelEvent); // Trap for help/tool-tip events. bool eventFilter(QObject *pObject, QEvent *pEvent); protected slots: // To have timeline in h-sync with main track view. void contentsYMovingSlot(int cx, int cy); // (Re)create the time scale pixmap. void updatePixmap(int cx, int cy); private: // The logical parent binding. qtractorMidiEditor *m_pEditor; // Local double-buffering pixmap. QPixmap m_pixmap; // Current item height. unsigned short m_iItemHeight; // The current selecting/dragging list stuff. enum DragState { DragNone = 0, DragStart, DragSelect } m_dragState; QRect m_rectDrag; QPoint m_posDrag; // The current note being keyed on. int m_iNoteOn; int m_iNoteVel; QRect m_rectNote; }; #endif // __qtractorMidiEditList_h // end of qtractorMidiEditList.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioMonitor.cpp0000644000175000001440000000012312121562322022134 xustar000000000000000027 mtime=1363600594.061657 26 atime=1381134667.63108 30 ctime=1381134667.631080059 qtractor-0.5.11/src/qtractorAudioMonitor.cpp0000644000175000001440000002323112121562322021424 0ustar00rncbcusers00000000000000// qtractorAudioMonitor.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAudioMonitor.h" #include #if defined(__SSE__) #include // SSE detection. static inline bool sse_enabled (void) { #if defined(__GNUC__) unsigned int eax, ebx, ecx, edx; #if defined(__x86_64__) || (!defined(PIC) && !defined(__PIC__)) __asm__ __volatile__ ( "cpuid\n\t" \ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ : "a" (1) : "cc"); #else __asm__ __volatile__ ( "push %%ebx\n\t" \ "cpuid\n\t" \ "movl %%ebx,%1\n\t" \ "pop %%ebx\n\t" \ : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) \ : "a" (1) : "cc"); #endif return (edx & (1 << 25)); #else return false; #endif } // SSE enabled processor versions. static inline void sse_process ( float *pFrames, unsigned int iFrames, float fGain, float *pfValue ) { __m128 v0 = _mm_load_ps1(&fGain); __m128 v1 = _mm_load_ps1(pfValue); __m128 v2; for (; (long(pFrames) & 15) && (iFrames > 0); --iFrames) *pFrames++ *= fGain; for (; iFrames >= 4; iFrames -= 4) { v2 = _mm_mul_ps(_mm_loadu_ps(pFrames), v0); v1 = _mm_max_ps(v2, v1); _mm_store_ps(pFrames, v2); pFrames += 4; } for (; iFrames > 0; --iFrames) *pFrames++ *= fGain; *pfValue = *(float *) &v1; // CHEAT: take 1st of 4 possible values. } static inline void sse_process_ramp ( float *pFrames, unsigned int iFrames, float fGainIter, float fGainLast, float *pfValue ) { __m128 v1 = _mm_load_ps1(pfValue); __m128 v2; const float fGainStep = 4.0f * (fGainLast - fGainIter) / float(iFrames); for (; (long(pFrames) & 15) && (iFrames > 0); --iFrames) *pFrames++ *= fGainIter; for (; iFrames >= 4; iFrames -= 4) { v2 = _mm_mul_ps(_mm_loadu_ps(pFrames), _mm_load_ps1(&fGainIter)); v1 = _mm_max_ps(v2, v1); _mm_store_ps(pFrames, v2); fGainIter += fGainStep; pFrames += 4; } for (; iFrames > 0; --iFrames) *pFrames++ *= fGainIter; *pfValue = *(float *) &v1; // CHEAT: take 1st of 4 possible values. } static inline void sse_process_meter ( float *pFrames, unsigned int iFrames, float *pfValue ) { __m128 v1 = _mm_load_ps1(pfValue); for (; (long(pFrames) & 15) && (iFrames > 0); --iFrames) ++pFrames; for (; iFrames >= 4; iFrames -= 4) { v1 = _mm_max_ps(_mm_loadu_ps(pFrames), v1); pFrames += 4; } *pfValue = *(float *) &v1; // CHEAT: take 1st of 4 possible values. } #endif // Standard processor versions. static inline void std_process ( float *pFrames, unsigned int iFrames, float fGain, float *pfValue ) { for (unsigned int n = 0; n < iFrames; ++n) { pFrames[n] *= fGain; if (*pfValue < pFrames[n]) *pfValue = pFrames[n]; } } static inline void std_process_ramp ( float *pFrames, unsigned int iFrames, float fGainIter, float fGainLast, float *pfValue ) { const float fGainStep = (fGainLast - fGainIter) / float(iFrames); for (unsigned int n = 0; n < iFrames; ++n) { pFrames[n] *= fGainIter; if (*pfValue < pFrames[n]) *pfValue = pFrames[n]; fGainIter += fGainStep; } } static inline void std_process_meter ( float *pFrames, unsigned int iFrames, float *pfValue ) { for (unsigned int n = 0; n < iFrames; ++n) { if (*pfValue < pFrames[n]) *pfValue = pFrames[n]; } } //---------------------------------------------------------------------------- // qtractorAudioMonitor -- Audio monitor bridge value processor. // Constructor. qtractorAudioMonitor::qtractorAudioMonitor ( unsigned short iChannels, float fGain, float fPanning ) : qtractorMonitor(fGain, fPanning), m_iChannels(0), m_pfValues(NULL), m_pfGains(NULL), m_pfPrevGains(NULL), m_iProcessRamp(0) { qtractorMonitor::gainSubject()->setMaxValue(2.0f); // +6dB #if defined(__SSE__) if (sse_enabled()) { m_pfnProcess = sse_process; m_pfnProcessRamp = sse_process_ramp; m_pfnProcessMeter = sse_process_meter; } else { #endif m_pfnProcess = std_process; m_pfnProcessRamp = std_process_ramp; m_pfnProcessMeter = std_process_meter; #if defined(__SSE__) } #endif setChannels(iChannels); } // Destructor. qtractorAudioMonitor::~qtractorAudioMonitor (void) { setChannels(0); } // Channel property accessors. void qtractorAudioMonitor::setChannels ( unsigned short iChannels ) { // Check if channels will really change... if (m_iChannels == iChannels) return; // Delete old value holders... if (m_pfValues) { delete [] m_pfValues; m_pfValues = NULL; } // Delete old panning-gains holders... if (m_pfGains) { delete [] m_pfGains; m_pfGains = NULL; } if (m_pfPrevGains) { delete [] m_pfPrevGains; m_pfPrevGains = NULL; } // Set new value holders... m_iChannels = iChannels; if (m_iChannels > 0) { m_pfValues = new float [m_iChannels]; m_pfGains = new float [m_iChannels]; m_pfPrevGains = new float [m_iChannels]; for (unsigned short i = 0; i < m_iChannels; ++i) m_pfValues[i] = m_pfGains[i] = m_pfPrevGains[i] = 0.0f; // Initial population... update(); } } unsigned short qtractorAudioMonitor::channels (void) const { return m_iChannels; } // Value holder accessor. float qtractorAudioMonitor::value ( unsigned short iChannel ) const { float fValue = m_pfValues[iChannel]; m_pfValues[iChannel] = 0.0f; return fValue; } // Reset channel gain trackers. void qtractorAudioMonitor::reset (void) { for (unsigned short i = 0; i < m_iChannels; ++i) m_pfPrevGains[i] = 0.0f; ++m_iProcessRamp; } // Batch processors. void qtractorAudioMonitor::process ( float **ppFrames, unsigned int iFrames, unsigned short iChannels ) { if (iChannels < 1) iChannels = m_iChannels; if (m_iProcessRamp > 0) { m_iProcessRamp = 0; // Do ramp-processing... if (iChannels == m_iChannels) { for (unsigned short i = 0; i < m_iChannels; ++i) { (*m_pfnProcessRamp)(ppFrames[i], iFrames, m_pfPrevGains[i], m_pfGains[i], &m_pfValues[i]); // m_pfPrevGains[i] = m_pfGains[i]; } } else if (iChannels > m_iChannels) { unsigned short i = 0; for (unsigned short j = 0; j < iChannels; ++j) { (*m_pfnProcessRamp)(ppFrames[j], iFrames, m_pfPrevGains[i], m_pfGains[i], &m_pfValues[i]); // m_pfPrevGains[i] = m_pfGains[i]; if (++i >= m_iChannels) i = 0; } } else { // (iChannels < m_iChannels) unsigned short j = 0; for (unsigned short i = 0; i < m_iChannels; ++i) { (*m_pfnProcessRamp)(ppFrames[j], iFrames, m_pfPrevGains[i], m_pfGains[i], &m_pfValues[i]); // m_pfPrevGains[i] = m_pfGains[i]; if (++j >= iChannels) j = 0; } } // Done ramp-processing. } else { // Do normal-processing... if (iChannels == m_iChannels) { for (unsigned short i = 0; i < m_iChannels; ++i) { (*m_pfnProcess)(ppFrames[i], iFrames, m_pfGains[i], &m_pfValues[i]); } } else if (iChannels > m_iChannels) { unsigned short i = 0; for (unsigned short j = 0; j < iChannels; ++j) { (*m_pfnProcess)(ppFrames[j], iFrames, m_pfGains[i], &m_pfValues[i]); if (++i >= m_iChannels) i = 0; } } else { // (iChannels < m_iChannels) unsigned short j = 0; for (unsigned short i = 0; i < m_iChannels; ++i) { (*m_pfnProcess)(ppFrames[j], iFrames, m_pfGains[i], &m_pfValues[i]); if (++j >= iChannels) j = 0; } } // Done normal-processing. } } void qtractorAudioMonitor::process_meter ( float **ppFrames, unsigned int iFrames, unsigned short iChannels ) { if (iChannels < 1) iChannels = m_iChannels; if (iChannels == m_iChannels) { for (unsigned short i = 0; i < m_iChannels; ++i) (*m_pfnProcessMeter)(ppFrames[i], iFrames, &m_pfValues[i]); } else if (iChannels > m_iChannels) { unsigned short j = 0; for (unsigned short i = 0; i < iChannels; ++i) { (*m_pfnProcessMeter)(ppFrames[i], iFrames, &m_pfValues[j]); if (++j >= m_iChannels) j = 0; } } else { // (iChannels < m_iChannels) unsigned short i = 0; for (unsigned short j = 0; j < m_iChannels; ++j) { (*m_pfnProcessMeter)(ppFrames[i], iFrames, &m_pfValues[j]); if (++i >= iChannels) i = 0; } } } // Rebuild the whole panning-gain array... void qtractorAudioMonitor::update (void) { const float fPan = 0.5f * (1.0f + panning()); const float fGain = gain(); float afGains[2] = { fGain, fGain }; // (Re)compute equal-power stereo-panning gains... if (fPan < 0.499f || fPan > 0.501f) { #ifdef QTRACTOR_MONITOR_PANNING_SQRT afGains[0] *= M_SQRT2 * ::sqrtf(1.0f - fPan); afGains[1] *= M_SQRT2 * ::sqrtf(fPan); #else afGains[0] *= M_SQRT2 * ::cosf(fPan * M_PI_2); afGains[1] *= M_SQRT2 * ::sinf(fPan * M_PI_2); #endif } // Apply to multi-channel gain array (paired fashion)... unsigned short i, iChannels = (m_iChannels - (m_iChannels % 2)); for (i = 0; i < iChannels; ++i) { m_pfPrevGains[i] = m_pfGains[i]; m_pfGains[i] = afGains[i % 2]; } for ( ; i < m_iChannels; ++i) { m_pfPrevGains[i] = m_pfGains[i]; m_pfGains[i] = fGain; } // Trigger ramp-processing... ++m_iProcessRamp; } // end of qtractorAudioMonitor.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiSysexForm.cpp0000644000175000001440000000012312166526620022277 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134667.28208 30 ctime=1381134667.283080053 qtractor-0.5.11/src/qtractorMidiSysexForm.cpp0000644000175000001440000006606512166526620021603 0ustar00rncbcusers00000000000000// qtractorMidiSysexForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiSysexForm.h" #include "qtractorMidiSysex.h" #include "qtractorMidiEngine.h" #include "qtractorSession.h" #include "qtractorMidiFile.h" #include "qtractorOptions.h" #include #include #include #include #include #include //---------------------------------------------------------------------- // class qtractorMidiSysexItem -- custom list view item. // class qtractorMidiSysexItem : public QTreeWidgetItem { public: // Constructors. qtractorMidiSysexItem(qtractorMidiSysex *pSysex) : QTreeWidgetItem(), m_pSysex(pSysex) { update(); } qtractorMidiSysexItem(QTreeWidget *pTreeWidget, QTreeWidgetItem *pItem, qtractorMidiSysex *pSysex) : QTreeWidgetItem(pTreeWidget, pItem), m_pSysex(pSysex) { update(); } // Destructor. ~qtractorMidiSysexItem() { delete m_pSysex; } // Accessors. void setSysex(qtractorMidiSysex *pSysex) { m_pSysex = pSysex; update(); } qtractorMidiSysex *sysex() const { return m_pSysex; } // Updator. void update() { QTreeWidgetItem::setText(0, m_pSysex->name()); QTreeWidgetItem::setText(1, QString::number(m_pSysex->size())); QTreeWidgetItem::setText(2, m_pSysex->text()); } private: // Instance variable. qtractorMidiSysex *m_pSysex; }; //---------------------------------------------------------------------- // class qtractorMidiSysexForm -- instrument file manager form. // // Constructor. qtractorMidiSysexForm::qtractorMidiSysexForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::WindowModal); m_pSysexList = NULL; m_iDirtyCount = 0; m_iDirtyItem = 0; m_iDirtySysex = 0; m_iUpdateSysex = 0; QHeaderView *pHeader = m_ui.SysexListView->header(); pHeader->setDefaultAlignment(Qt::AlignLeft); #if QT_VERSION >= 0x050000 // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionResizeMode(1, QHeaderView::ResizeToContents); pHeader->setSectionsMovable(false); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setResizeMode(1, QHeaderView::ResizeToContents); pHeader->setMovable(false); #endif m_ui.NameComboBox->setInsertPolicy(QComboBox::NoInsert); m_ui.NameComboBox->setCompleter(NULL); refreshSysex(); refreshForm(); stabilizeForm(); // adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.SysexListView, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), SLOT(stabilizeForm())); QObject::connect(m_ui.ImportButton, SIGNAL(clicked()), SLOT(importSlot())); QObject::connect(m_ui.ExportButton, SIGNAL(clicked()), SLOT(exportSlot())); QObject::connect(m_ui.MoveUpButton, SIGNAL(clicked()), SLOT(moveUpSlot())); QObject::connect(m_ui.MoveDownButton, SIGNAL(clicked()), SLOT(moveDownSlot())); QObject::connect(m_ui.NameComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(nameChanged(const QString&))); QObject::connect(m_ui.NameComboBox, SIGNAL(activated(const QString &)), SLOT(loadSlot(const QString&))); QObject::connect(m_ui.SysexTextEdit, SIGNAL(textChanged()), SLOT(textChanged())); QObject::connect(m_ui.OpenButton, SIGNAL(clicked()), SLOT(openSlot())); QObject::connect(m_ui.SaveButton, SIGNAL(clicked()), SLOT(saveSlot())); QObject::connect(m_ui.DeleteButton, SIGNAL(clicked()), SLOT(deleteSlot())); QObject::connect(m_ui.AddButton, SIGNAL(clicked()), SLOT(addSlot())); QObject::connect(m_ui.UpdateButton, SIGNAL(clicked()), SLOT(updateSlot())); QObject::connect(m_ui.RemoveButton, SIGNAL(clicked()), SLOT(removeSlot())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(clicked(QAbstractButton *)), SLOT(click(QAbstractButton *))); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); } // Destructor. qtractorMidiSysexForm::~qtractorMidiSysexForm (void) { } // SysEx list accessors. void qtractorMidiSysexForm::setSysexList ( qtractorMidiSysexList *pSysexList ) { m_pSysexList = pSysexList; refreshForm(); stabilizeForm(); } qtractorMidiSysexList *qtractorMidiSysexForm::sysexList (void) const { return m_pSysexList; } // Import new SysEx into listing. void qtractorMidiSysexForm::importSlot (void) { qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; QStringList files; const QString sExt("syx"); QStringList filters; filters.append(tr("SysEx files (*.%1)").arg(sExt)); filters.append(tr("MIDI files (*.mid *.smf *.midi)")); filters.append(tr("All files (*.*)")); const QString& sTitle = tr("Import SysEx Files") + " - " QTRACTOR_TITLE; const QString& sFilter = filters.join(";;"); #if 0//QT_VERSION < 0x040400 // Ask for the filename to open... files = QFileDialog::getOpenFileNames(this, sTitle, pOptions->sMidiSysexDir, sFilter); #else // Construct open-files dialog... QFileDialog fileDialog(this, sTitle, pOptions->sMidiSysexDir, sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::ExistingFiles); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(pOptions->sMidiSysexDir)); fileDialog.setSidebarUrls(urls); // Show dialog... if (fileDialog.exec()) files = fileDialog.selectedFiles(); #endif if (files.isEmpty()) return; // Tell that we may take some time... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); m_ui.SysexListView->setUpdatesEnabled(false); // Start inserting in the current selected or last item... QTreeWidgetItem *pItem = m_ui.SysexListView->currentItem(); if (pItem == NULL) { int iLastItem = m_ui.SysexListView->topLevelItemCount() - 1; if (iLastItem >= 0) pItem = m_ui.SysexListView->topLevelItem(iLastItem); } // For avery selected SysEx file to load... QList items; QStringListIterator ifile(files); while (ifile.hasNext()) { QApplication::processEvents(); // Merge the file contents into global container... const QString& sPath = ifile.next(); if (loadSysexItems(items, sPath)) { pOptions->sMidiSysexDir = QFileInfo(sPath).absolutePath(); ++m_iDirtyCount; } } m_ui.SysexListView->addTopLevelItems(items); // Done waiting. m_ui.SysexListView->setUpdatesEnabled(true); QApplication::restoreOverrideCursor(); stabilizeForm(); } // Export the whole state into a single SysEx file. void qtractorMidiSysexForm::exportSlot (void) { qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; QString sPath; const QString sExt("syx"); const QString& sTitle = tr("Export SysEx File") + " - " QTRACTOR_TITLE; const QString& sFilter = tr("SysEx files (*.%1)").arg(sExt); #if 0// QT_VERSION < 0x040400 // Ask for the filename to open... sPath = QFileDialog::getSaveFileName(this, sTitle, pOptions->sMidiSysexDir, sFilter); #else // Construct open-files dialog... QFileDialog fileDialog(this, sTitle, pOptions->sMidiSysexDir, sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptSave); fileDialog.setFileMode(QFileDialog::AnyFile); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(pOptions->sMidiSysexDir)); fileDialog.setSidebarUrls(urls); // Show dialog... if (fileDialog.exec()) sPath = fileDialog.selectedFiles().first(); #endif if (sPath.isEmpty()) return; // Enforce .ins extension... if (QFileInfo(sPath).suffix().isEmpty()) { sPath += '.' + sExt; // Check if already exists... if (QFileInfo(sPath).exists()) { if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("The SysEx file already exists:\n\n" "\"%1\"\n\n" "Do you want to replace it?") .arg(sPath), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; } } // Tell that we may take some time... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // Just save the whole bunch... QList items; int iItemCount = m_ui.SysexListView->topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) items.append(m_ui.SysexListView->topLevelItem(iItem)); QApplication::processEvents(); if (saveSysexItems(items, sPath)) pOptions->sMidiSysexDir = QFileInfo(sPath).absolutePath(); // Done with export. QApplication::restoreOverrideCursor(); } // Move a SysEx item up on the list. void qtractorMidiSysexForm::moveUpSlot (void) { QTreeWidgetItem *pItem = m_ui.SysexListView->currentItem(); if (pItem) { int iItem = m_ui.SysexListView->indexOfTopLevelItem(pItem); if (iItem > 0) { pItem = m_ui.SysexListView->takeTopLevelItem(iItem); m_ui.SysexListView->insertTopLevelItem(iItem - 1, pItem); m_ui.SysexListView->setCurrentItem(pItem); ++m_iDirtyCount; } } stabilizeForm(); } // Move a SysEx item down on the list. void qtractorMidiSysexForm::moveDownSlot (void) { QTreeWidgetItem *pItem = m_ui.SysexListView->currentItem(); if (pItem) { int iItem = m_ui.SysexListView->indexOfTopLevelItem(pItem); if (iItem < m_ui.SysexListView->topLevelItemCount() - 1) { pItem = m_ui.SysexListView->takeTopLevelItem(iItem); m_ui.SysexListView->insertTopLevelItem(iItem + 1, pItem); m_ui.SysexListView->setCurrentItem(pItem); ++m_iDirtyCount; } } stabilizeForm(); } // Load a SysEx item. void qtractorMidiSysexForm::loadSlot ( const QString& sName ) { if (m_iUpdateSysex > 0 || sName.isEmpty()) return; // We'll need this, sure. qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; ++m_iUpdateSysex; QSettings& settings = pOptions->settings(); settings.beginGroup(sysexGroup()); loadSysexFile(settings.value(sName).toString()); settings.endGroup(); --m_iUpdateSysex; refreshSysex(); stabilizeForm(); } // Open a SysEx item. void qtractorMidiSysexForm::openSlot (void) { // We'll need this, sure. qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; // We'll assume that there's an external file... QString sFilename; // Prompt if file does not currently exist... const QString sExt("syx"); const QString& sTitle = tr("Open SysEx") + " - " QTRACTOR_TITLE; const QString& sFilter = tr("SysEx files (*.%1)").arg(sExt); #if 0//QT_VERSION < 0x040400 // Ask for the filename to save... sFilename = QFileDialog::getOpenFileName(this, sTitle, pOptions->sMidiSysexDir, sFilter); #else // Construct save-file dialog... QFileDialog fileDialog(this, sTitle, pOptions->sMidiSysexDir, sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::ExistingFile); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(pOptions->sMidiSysexDir)); fileDialog.setSidebarUrls(urls); // Show dialog... if (fileDialog.exec()) sFilename = fileDialog.selectedFiles().first(); #endif // Have we a filename to load a preset from? if (!sFilename.isEmpty()) { QFileInfo fi(sFilename); if (fi.exists()) { // Get it loaded alright... ++m_iUpdateSysex; loadSysexFile(sFilename); m_ui.NameComboBox->setEditText(fi.baseName()); pOptions->sMidiSysexDir = fi.absolutePath(); ++m_iDirtyItem; --m_iUpdateSysex; } } refreshSysex(); stabilizeForm(); } // Save a SysEx item. void qtractorMidiSysexForm::saveSlot (void) { const QString& sName = m_ui.NameComboBox->currentText(); if (sName.isEmpty()) return; // We'll need this, sure. qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; // The current state preset is about to be saved... // this is where we'll make it... QSettings& settings = pOptions->settings(); settings.beginGroup(sysexGroup()); // Sure, we'll have something complex enough // to make it save into an external file... const QString sExt("syx"); QFileInfo fi(QDir(pOptions->sMidiSysexDir), sName + '.' + sExt); QString sFilename = fi.absoluteFilePath(); // Prompt if file does not currently exist... if (!fi.exists()) { const QString& sTitle = tr("Save SysEx") + " - " QTRACTOR_TITLE; const QString& sFilter = tr("Sysex files (*.%1)").arg(sExt); #if 0//QT_VERSION < 0x040400 // Ask for the filename to save... sFilename = QFileDialog::getSaveFileName(this, sTitle, sFilename, sFilter); #else // Construct save-file dialog... QFileDialog fileDialog(this, sTitle, sFilename, sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptSave); fileDialog.setFileMode(QFileDialog::AnyFile); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(pOptions->sMidiSysexDir)); fileDialog.setSidebarUrls(urls); // Show dialog... if (fileDialog.exec()) sFilename = fileDialog.selectedFiles().first(); else sFilename.clear(); #endif } else if (pOptions->bConfirmRemove) { if (QMessageBox::warning(parentWidget(), tr("Warning") + " - " QTRACTOR_TITLE, tr("About to replace SysEx:\n\n" "\"%1\"\n\n" "Are you sure?") .arg(sName), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) { sFilename.clear(); } } // We've a filename to save the preset if (!sFilename.isEmpty()) { if (QFileInfo(sFilename).suffix().isEmpty()) sFilename += '.' + sExt; // Get it saved alright... ++m_iUpdateSysex; saveSysexFile(sFilename); settings.setValue(sName, sFilename); --m_iUpdateSysex; pOptions->sMidiSysexDir = QFileInfo(sFilename).absolutePath(); } settings.endGroup(); refreshSysex(); stabilizeForm(); } // Delete a SysEx item. void qtractorMidiSysexForm::deleteSlot (void) { const QString& sName = m_ui.NameComboBox->currentText(); if (sName.isEmpty()) return; // We'll need this, sure. qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; // A preset entry is about to be removed; // prompt user if he/she's sure about this... if (pOptions->bConfirmRemove) { if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("About to delete SysEx:\n\n" "\"%1\"\n\n" "Are you sure?") .arg(sName), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; } // Go ahead... ++m_iUpdateSysex; QSettings& settings = pOptions->settings(); settings.beginGroup(sysexGroup()); #ifdef QTRACTOR_REMOVE_PRESET_FILES const QString& sFilename = settings.value(sName).toString(); if (QFileInfo(sFilename).exists()) QFile(sFilename).remove(); #endif settings.remove(sName); settings.endGroup(); --m_iUpdateSysex; refreshSysex(); stabilizeForm(); } // Add a SysEx item to list. void qtractorMidiSysexForm::addSlot (void) { // Start inserting in the current selected or last item... QTreeWidgetItem *pItem = m_ui.SysexListView->currentItem(); if (pItem == NULL) { int iLastItem = m_ui.SysexListView->topLevelItemCount() - 1; if (iLastItem >= 0) pItem = m_ui.SysexListView->topLevelItem(iLastItem); } // Add item... pItem = new qtractorMidiSysexItem( m_ui.SysexListView, pItem, new qtractorMidiSysex( m_ui.NameComboBox->currentText(), m_ui.SysexTextEdit->toPlainText()) ); m_ui.SysexListView->setCurrentItem(pItem); ++m_iDirtyCount; m_iDirtyItem = 0; stabilizeForm(); } // Update a SysEx item from list. void qtractorMidiSysexForm::updateSlot (void) { QTreeWidgetItem *pItem = m_ui.SysexListView->currentItem(); if (pItem == NULL) return; // Update item... qtractorMidiSysexItem *pSysexItem = static_cast (pItem); qtractorMidiSysex *pSysex = pSysexItem->sysex(); pSysex->setName(m_ui.NameComboBox->currentText()); pSysex->setText(m_ui.SysexTextEdit->toPlainText()); pSysexItem->update(); m_ui.SysexListView->setCurrentItem(pItem); ++m_iDirtyCount; m_iDirtyItem = 0; stabilizeForm(); } // Remove a SysEx item from list. void qtractorMidiSysexForm::removeSlot (void) { QTreeWidgetItem *pItem = m_ui.SysexListView->currentItem(); if (pItem) { delete pItem; ++m_iDirtyCount; m_iDirtyItem = 0; } stabilizeForm(); } // Clear all SysEx items from list. void qtractorMidiSysexForm::clearSlot (void) { ++m_iUpdateSysex; m_ui.SysexListView->clear(); m_ui.NameComboBox->lineEdit()->clear(); m_ui.SysexTextEdit->clear(); --m_iUpdateSysex; ++m_iDirtyCount; m_iDirtyItem = 0; stabilizeForm(); } // SysEx item name change. void qtractorMidiSysexForm::nameChanged ( const QString& sName ) { if (m_iUpdateSysex > 0) return; if (!sName.isEmpty() && m_ui.NameComboBox->findText(sName) >= 0) ++m_iDirtySysex; ++m_iDirtyItem; stabilizeForm(); } void qtractorMidiSysexForm::textChanged (void) { if (m_iUpdateSysex > 0) return; ++m_iDirtySysex; ++m_iDirtyItem; stabilizeForm(); } // Reset settings (action button slot). void qtractorMidiSysexForm::click ( QAbstractButton *pButton ) { QDialogButtonBox::ButtonRole role = m_ui.DialogButtonBox->buttonRole(pButton); if ((role & QDialogButtonBox::ResetRole) == QDialogButtonBox::ResetRole) clearSlot(); } // Accept settings (OK button slot). void qtractorMidiSysexForm::accept (void) { if (m_iDirtyCount == 0) return; if (m_pSysexList == NULL) return; // Just reload the whole bunch... m_pSysexList->clear(); int iItemCount = m_ui.SysexListView->topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { qtractorMidiSysexItem *pSysexItem = static_cast ( m_ui.SysexListView->topLevelItem(iItem)); if (pSysexItem) { m_pSysexList->append( new qtractorMidiSysex(*(pSysexItem->sysex()))); } } // AG: Reset the controllers so that changes take effect immediately... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession && pSession->midiEngine()) pSession->midiEngine()->resetAllControllers(true); // Just go with dialog acceptance. QDialog::accept(); } // Reject settings (Cancel button slot). void qtractorMidiSysexForm::reject (void) { bool bReject = true; // Check if there's any pending changes... if (m_iDirtyCount > 0) { QMessageBox::StandardButtons buttons = QMessageBox::Discard | QMessageBox::Cancel; if (m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->isEnabled()) buttons |= QMessageBox::Apply; switch (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("SysEx settings have been changed.\n\n" "Do you want to apply the changes?"), buttons)) { case QMessageBox::Apply: accept(); return; case QMessageBox::Discard: break; default: // Cancel. bReject = false; } } if (bReject) QDialog::reject(); } // Stabilize form status. void qtractorMidiSysexForm::stabilizeForm (void) { int iItemCount = m_ui.SysexListView->topLevelItemCount(); m_ui.ExportButton->setEnabled(iItemCount > 0); QTreeWidgetItem *pItem = m_ui.SysexListView->currentItem(); if (pItem) { if (m_iDirtyItem == 0) { ++m_iUpdateSysex; qtractorMidiSysex *pSysex = static_cast (pItem)->sysex(); m_ui.NameComboBox->setEditText(pSysex->name()); m_ui.SysexTextEdit->setText(pSysex->text()); --m_iUpdateSysex; m_iDirtyItem = 0; } int iItem = m_ui.SysexListView->indexOfTopLevelItem(pItem); m_ui.MoveUpButton->setEnabled(iItem > 0); m_ui.MoveDownButton->setEnabled(iItem < iItemCount - 1); m_ui.RemoveButton->setEnabled(true); } else { m_ui.MoveUpButton->setEnabled(false); m_ui.MoveDownButton->setEnabled(false); m_ui.RemoveButton->setEnabled(false); } const QString& sName = m_ui.NameComboBox->currentText(); bool bEnabled = (!sName.isEmpty()); bool bExists = (m_ui.NameComboBox->findText(sName) >= 0); if (bEnabled && m_iDirtyItem > 0) { qtractorMidiSysex sysex(sName, m_ui.SysexTextEdit->toPlainText()); bEnabled = (sysex.size() > 0); } m_ui.SaveButton->setEnabled(bEnabled && (!bExists || m_iDirtySysex > 0)); m_ui.DeleteButton->setEnabled(bEnabled && bExists); m_ui.AddButton->setEnabled(bEnabled); m_ui.UpdateButton->setEnabled(bEnabled && pItem != NULL); m_ui.DialogButtonBox->button(QDialogButtonBox::Reset)->setEnabled( bEnabled || iItemCount > 0); m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled( m_iDirtyCount > 0 && m_iDirtyItem == 0); } // Refresh all SysEx definition views. void qtractorMidiSysexForm::refreshForm (void) { if (m_pSysexList == NULL) return; // Freeze... m_ui.SysexListView->setUpdatesEnabled(false); // Files list view... m_ui.SysexListView->clear(); qtractorMidiSysexItem *pItem = NULL; QListIterator iter(*m_pSysexList); while (iter.hasNext()) { pItem = new qtractorMidiSysexItem( m_ui.SysexListView, pItem, new qtractorMidiSysex(*iter.next()) ); } // Bail out... m_ui.SysexListView->setUpdatesEnabled(true); // Clean. m_iDirtyCount = 0; m_iDirtyItem = 0; } // Refresh SysEx names (presets). void qtractorMidiSysexForm::refreshSysex (void) { if (m_iUpdateSysex > 0) return; ++m_iUpdateSysex; const QString sOldName = m_ui.NameComboBox->currentText(); m_ui.NameComboBox->clear(); qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { pOptions->settings().beginGroup(sysexGroup()); m_ui.NameComboBox->insertItems(0, pOptions->settings().childKeys()); pOptions->settings().endGroup(); } m_ui.NameComboBox->setEditText(sOldName); m_iDirtySysex = 0; --m_iUpdateSysex; } // SysEx file i/o methods. bool qtractorMidiSysexForm::loadSysexItems ( QList& items, const QString& sFilename ) { int iSysex = 0; QFileInfo info(sFilename); // Try on SMF files first... qtractorMidiFile midifile; if (midifile.open(sFilename)) { unsigned short iTracks = midifile.tracks(); for (unsigned int iTrack = 0; iTrack < iTracks; ++iTrack) { qtractorMidiSequence seq; if (midifile.readTrack(&seq, iTrack)) { qtractorMidiEvent *pEvent = seq.events().first(); while (pEvent) { if (pEvent->type() == qtractorMidiEvent::SYSEX) { items.append(new qtractorMidiSysexItem( new qtractorMidiSysex( info.baseName() + '-' + QString::number(iTrack) + '.' + QString::number(++iSysex), pEvent->sysex(), pEvent->sysex_len()))); } pEvent = pEvent->next(); } } } midifile.close(); return (iSysex > 0); } // Should be a SysEx file then... QFile file(sFilename); if (!file.open(QIODevice::ReadOnly)) return false; unsigned short iBuff = 0; unsigned char *pBuff = NULL; unsigned short i = 0; // Read the file.... while (!file.atEnd()) { // (Re)allocate buffer... if (i >= iBuff) { unsigned char *pTemp = pBuff; iBuff += 1024; pBuff = new unsigned char [iBuff]; if (pTemp) { ::memcpy(pBuff, pTemp, i); delete [] pTemp; } } // Read the next chunk... unsigned short iRead = file.read((char *) pBuff + i, iBuff - i) + i; while (i < iRead) { if (pBuff[i++] == 0xf7) { QString sName = info.baseName(); if (++iSysex > 1 || i < iRead) { sName += '-'; sName += QString::number(iSysex); } items.append(new qtractorMidiSysexItem( new qtractorMidiSysex(sName, pBuff, i))); if (i < iRead) { ::memmove(pBuff, pBuff + i, iRead -= i); i = 0; } } } } // Cleanup... if (pBuff) delete [] pBuff; file.close(); return (iSysex > 0); } bool qtractorMidiSysexForm::saveSysexItems ( const QList& items, const QString& sFilename ) const { QFile file(sFilename); if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) return false; QListIterator iter(items); while (iter.hasNext()) { qtractorMidiSysexItem *pSysexItem = static_cast (iter.next()); if (pSysexItem) { qtractorMidiSysex *pSysex = pSysexItem->sysex(); file.write((const char *) pSysex->data(), pSysex->size()); } } file.close(); return true; } // Preset file handlers. void qtractorMidiSysexForm::loadSysexFile ( const QString& sFilename ) { // Open the source file... QFile file(sFilename); if (!file.open(QIODevice::ReadOnly)) return; // Tell the world we'll take some time... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); bool bResult = false; unsigned short iBuff = 0; unsigned char *pBuff = NULL; unsigned short i = 0; // Read the file.... while (!file.atEnd()) { // (Re)allocate buffer... if (i >= iBuff) { unsigned char *pTemp = pBuff; iBuff += 1024; pBuff = new unsigned char [iBuff]; if (pTemp) { ::memcpy(pBuff, pTemp, i); delete [] pTemp; } } // Read the next chunk... unsigned short iRead = file.read((char *) pBuff + i, iBuff - i) + i; while (i < iRead) { if (pBuff[i++] == 0xf7) { QFileInfo info(sFilename); qtractorMidiSysex sysex(info.baseName(), pBuff, i); m_ui.NameComboBox->setEditText(sysex.name()); m_ui.SysexTextEdit->setText(sysex.text()); bResult = true; break; } } } // Cleanup... if (pBuff) delete [] pBuff; file.close(); // We're formerly done. QApplication::restoreOverrideCursor(); // Any late warning? if (!bResult) { // Failure (maybe wrong preset)... QMessageBox::critical(this, tr("Error") + " - " QTRACTOR_TITLE, tr("SysEx could not be loaded:\n\n" "\"%1\".\n\n" "Sorry.").arg(sFilename), QMessageBox::Cancel); } } void qtractorMidiSysexForm::saveSysexFile ( const QString& sFilename ) { // Open the target file... QFile file(sFilename); if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) return; // Tell the world we'll take some time... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // Parse the data... qtractorMidiSysex sysex( m_ui.NameComboBox->currentText(), m_ui.SysexTextEdit->toPlainText()); file.write((const char *) sysex.data(), sysex.size()); file.close(); // We're formerly done. QApplication::restoreOverrideCursor(); } // Preset group path name. QString qtractorMidiSysexForm::sysexGroup (void) { return "/Midi/Sysex/"; } // end of qtractorMidiSysexForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorSessionDocument.h0000644000175000001440000000012311514076275022326 xustar000000000000000027 mtime=1295023293.370359 26 atime=1381134669.66808 30 ctime=1381134669.668080091 qtractor-0.5.11/src/qtractorSessionDocument.h0000644000175000001440000000361211514076275021617 0ustar00rncbcusers00000000000000// qtractorSessionDocument.h // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorSessionDocument_h #define __qtractorSessionDocument_h #include "qtractorDocument.h" // Forward declarations. class qtractorSession; class qtractorFiles; //------------------------------------------------------------------------- // qtractorSessionDocument -- Session file import/export helper class. // class qtractorSessionDocument : public qtractorDocument { public: // Constructor. qtractorSessionDocument(QDomDocument *pDocument, qtractorSession *pSession, qtractorFiles *pFiles); // Default destructor. ~qtractorSessionDocument(); // Property accessors. qtractorSession *session() const; qtractorFiles *files() const; // Elemental loader/savers... bool loadElement(QDomElement *pElement); bool saveElement(QDomElement *pElement); private: // Instance variables. qtractorSession *m_pSession; qtractorFiles *m_pFiles; }; #endif // __qtractorSessionDocument_h // end of qtractorSessionDocument.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorClipForm.h0000644000175000001440000000012212166134117020710 xustar000000000000000027 mtime=1373157455.942698 26 atime=1381134667.69708 29 ctime=1381134667.69708006 qtractor-0.5.11/src/qtractorClipForm.h0000644000175000001440000000445012166134117020203 0ustar00rncbcusers00000000000000// qtractorClipForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorClipForm_h #define __qtractorClipForm_h #include "ui_qtractorClipForm.h" #include "qtractorClip.h" //---------------------------------------------------------------------------- // qtractorClipForm -- UI wrapper form. class qtractorClipForm : public QDialog { Q_OBJECT public: // Constructor. qtractorClipForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorClipForm(); void setClip(qtractorClip *pClip, bool bClipNew = false); qtractorClip *clip() const; protected slots: void accept(); void reject(); void changed(); void formatChanged(int); void stabilizeForm(); void browseFilename(); void filenameChanged(const QString& sFilename); void trackChannelChanged(int iTrackChannel); void clipStartChanged(unsigned long iClipStart); protected: qtractorClip::FadeType fadeTypeFromIndex(int iIndex) const; int indexFromFadeType(qtractorClip::FadeType fadeType) const; qtractorTrack::TrackType trackType() const; void fileChanged(const QString& sFilename, unsigned short iTrackChannel); private: // The Qt-designer UI struct... Ui::qtractorClipForm m_ui; // Instance variables... qtractorClip *m_pClip; bool m_bClipNew; qtractorTimeScale *m_pTimeScale; int m_iDirtyCount; int m_iDirtySetup; }; #endif // __qtractorClipForm_h // end of qtractorClipForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMessages.cpp0000644000175000001440000000012311563576072021312 xustar000000000000000027 mtime=1305410618.253123 26 atime=1381134667.63008 30 ctime=1381134667.630080059 qtractor-0.5.11/src/qtractorMessages.cpp0000644000175000001440000002174011563576072020605 0ustar00rncbcusers00000000000000// qtractorMessages.cpp // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMessages.h" #include "qtractorMainForm.h" #include #include #include #include #include #include #include #include #include #if !defined(WIN32) #include #endif // The default maximum number of message lines. #define QTRACTOR_MESSAGES_MAXLINES 1000 // Notification pipe descriptors #define QTRACTOR_MESSAGES_FDNIL -1 #define QTRACTOR_MESSAGES_FDREAD 0 #define QTRACTOR_MESSAGES_FDWRITE 1 //------------------------------------------------------------------------- // qtractorMessagesTextEdit - Messages log dockable child window. // class qtractorMessagesTextEdit : public QTextEdit { public: // Constructor. qtractorMessagesTextEdit(QWidget *pParent) : QTextEdit(pParent) {} protected: // Minimum recommended. QSize sizeHint() const { return QTextEdit::minimumSize(); } }; //------------------------------------------------------------------------- // qtractorMessages - Messages log dockable window. // // Constructor. qtractorMessages::qtractorMessages ( QWidget *pParent ) : QDockWidget(pParent) { // Surely a name is crucial (e.g.for storing geometry settings) QDockWidget::setObjectName("qtractorMessages"); // Intialize stdout capture stuff. m_pStdoutNotifier = NULL; m_fdStdout[QTRACTOR_MESSAGES_FDREAD] = QTRACTOR_MESSAGES_FDNIL; m_fdStdout[QTRACTOR_MESSAGES_FDWRITE] = QTRACTOR_MESSAGES_FDNIL; // Create local text view widget. m_pMessagesTextView = new qtractorMessagesTextEdit(this); // QFont font(m_pMessagesTextView->font()); // font.setFamily("Fixed"); // m_pMessagesTextView->setFont(font); m_pMessagesTextView->setLineWrapMode(QTextEdit::NoWrap); m_pMessagesTextView->setReadOnly(true); m_pMessagesTextView->setUndoRedoEnabled(false); // m_pMessagesTextView->setTextFormat(Qt::LogText); // Initialize default message limit. m_iMessagesLines = 0; setMessagesLimit(QTRACTOR_MESSAGES_MAXLINES); m_pMessagesLog = NULL; // Prepare the dockable window stuff. QDockWidget::setWidget(m_pMessagesTextView); QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures); QDockWidget::setAllowedAreas( Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); // Some specialties to this kind of dock window... QDockWidget::setMinimumHeight(120); // Finally set the default caption and tooltip. const QString& sCaption = tr("Messages"); QDockWidget::setWindowTitle(sCaption); QDockWidget::setWindowIcon(QIcon(":/images/viewMessages.png")); QDockWidget::setToolTip(sCaption); } // Destructor. qtractorMessages::~qtractorMessages (void) { // Turn off and close logging. setLogging(false); // No more notifications. if (m_pStdoutNotifier) delete m_pStdoutNotifier; // No need to delete child widgets, Qt does it all for us. } // Just about to notify main-window that we're closing. void qtractorMessages::closeEvent ( QCloseEvent * /*pCloseEvent*/ ) { QDockWidget::hide(); qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeForm(); } // Own stdout/stderr socket notifier slot. void qtractorMessages::stdoutNotify ( int fd ) { #if !defined(WIN32) char achBuffer[1024]; int cchBuffer = ::read(fd, achBuffer, sizeof(achBuffer) - 1); if (cchBuffer > 0) { achBuffer[cchBuffer] = (char) 0; appendStdoutBuffer(achBuffer); } #endif } // Stdout buffer handler -- now splitted by complete new-lines... void qtractorMessages::appendStdoutBuffer ( const QString& s ) { m_sStdoutBuffer.append(s); int iLength = m_sStdoutBuffer.lastIndexOf('\n') + 1; if (iLength > 0) { QString sTemp = m_sStdoutBuffer.left(iLength); m_sStdoutBuffer.remove(0, iLength); QStringList list = sTemp.split('\n'); QStringListIterator iter(list); while (iter.hasNext()) appendMessagesText(iter.next()); } } // Stdout flusher -- show up any unfinished line... void qtractorMessages::flushStdoutBuffer (void) { if (!m_sStdoutBuffer.isEmpty()) { appendMessagesText(m_sStdoutBuffer); m_sStdoutBuffer.truncate(0); } } // Stdout capture accessors. bool qtractorMessages::isCaptureEnabled (void) const { return (bool) (m_pStdoutNotifier != NULL); } void qtractorMessages::setCaptureEnabled ( bool bCapture ) { // Flush current buffer. flushStdoutBuffer(); #ifdef CONFIG_DEBUG bCapture = false; #endif #if !defined(WIN32) // Destroy if already enabled. if (!bCapture && m_pStdoutNotifier) { delete m_pStdoutNotifier; m_pStdoutNotifier = NULL; // Close the notification pipes. if (m_fdStdout[QTRACTOR_MESSAGES_FDREAD] != QTRACTOR_MESSAGES_FDNIL) { ::close(m_fdStdout[QTRACTOR_MESSAGES_FDREAD]); m_fdStdout[QTRACTOR_MESSAGES_FDREAD] = QTRACTOR_MESSAGES_FDNIL; } if (m_fdStdout[QTRACTOR_MESSAGES_FDREAD] != QTRACTOR_MESSAGES_FDNIL) { ::close(m_fdStdout[QTRACTOR_MESSAGES_FDREAD]); m_fdStdout[QTRACTOR_MESSAGES_FDREAD] = QTRACTOR_MESSAGES_FDNIL; } } // Are we going to make up the capture? if (bCapture && m_pStdoutNotifier == NULL && ::pipe(m_fdStdout) == 0) { ::dup2(m_fdStdout[QTRACTOR_MESSAGES_FDWRITE], STDOUT_FILENO); ::dup2(m_fdStdout[QTRACTOR_MESSAGES_FDWRITE], STDERR_FILENO); m_pStdoutNotifier = new QSocketNotifier( m_fdStdout[QTRACTOR_MESSAGES_FDREAD], QSocketNotifier::Read, this); QObject::connect(m_pStdoutNotifier, SIGNAL(activated(int)), SLOT(stdoutNotify(int))); } #endif } // Message font accessors. QFont qtractorMessages::messagesFont (void) const { return m_pMessagesTextView->font(); } void qtractorMessages::setMessagesFont( const QFont& font ) { m_pMessagesTextView->setFont(font); } // Maximum number of message lines accessors. int qtractorMessages::messagesLimit (void) const { return m_iMessagesLimit; } void qtractorMessages::setMessagesLimit ( int iMessagesLimit ) { m_iMessagesLimit = iMessagesLimit; m_iMessagesHigh = iMessagesLimit + (iMessagesLimit >> 2); } // Messages logging stuff. bool qtractorMessages::isLogging (void) const { return (m_pMessagesLog != NULL); } void qtractorMessages::setLogging ( bool bEnabled, const QString& sFilename ) { if (m_pMessagesLog) { appendMessages(tr("Logging stopped --- %1 ---") .arg(QDateTime::currentDateTime().toString())); m_pMessagesLog->close(); delete m_pMessagesLog; m_pMessagesLog = NULL; } if (bEnabled) { m_pMessagesLog = new QFile(sFilename); if (m_pMessagesLog->open(QIODevice::Text | QIODevice::Append)) { appendMessages(tr("Logging started --- %1 ---") .arg(QDateTime::currentDateTime().toString())); } else { delete m_pMessagesLog; m_pMessagesLog = NULL; } } } // Messages log output method. void qtractorMessages::appendMessagesLog ( const QString& s ) { if (m_pMessagesLog) { QTextStream(m_pMessagesLog) << s << endl; m_pMessagesLog->flush(); } } // Messages widget output method. void qtractorMessages::appendMessagesLine ( const QString& s ) { // Check for message line limit... if (m_iMessagesLines > m_iMessagesHigh) { m_pMessagesTextView->setUpdatesEnabled(false); QTextCursor textCursor(m_pMessagesTextView->document()->begin()); while (m_iMessagesLines > m_iMessagesLimit) { // Move cursor extending selection // from start to next line-block... textCursor.movePosition( QTextCursor::NextBlock, QTextCursor::KeepAnchor); --m_iMessagesLines; } // Remove the excessive line-blocks... textCursor.removeSelectedText(); m_pMessagesTextView->setUpdatesEnabled(true); } m_pMessagesTextView->append(s); ++m_iMessagesLines; } // The main utility methods. void qtractorMessages::appendMessages ( const QString& s ) { appendMessagesColor(s, "#999999"); } void qtractorMessages::appendMessagesColor ( const QString& s, const QString &c ) { QString sText = QTime::currentTime().toString("hh:mm:ss.zzz") + ' ' + s; appendMessagesLine("" + sText + ""); appendMessagesLog(sText); } void qtractorMessages::appendMessagesText ( const QString& s ) { appendMessagesLine(s); appendMessagesLog(s); } // History reset. void qtractorMessages::clear (void) { m_iMessagesLines = 0; m_pMessagesTextView->clear(); } // end of qtractorMessages.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTracks.h0000644000175000001440000000012312220605131020413 xustar000000000000000027 mtime=1380125273.121591 26 atime=1381134671.09208 30 ctime=1381134671.092080114 qtractor-0.5.11/src/qtractorTracks.h0000644000175000001440000001520712220605131017707 0ustar00rncbcusers00000000000000// qtractorTracks.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorTracks_h #define __qtractorTracks_h #include // Forward declarations. class qtractorInstrumentList; class qtractorTrackItemWidget; class qtractorTrackList; class qtractorTrackTime; class qtractorTrackView; class qtractorTrack; class qtractorSession; class qtractorClip; class qtractorClipCommand; class qtractorClipRangeCommand; class qtractorMidiClipCommand; class qtractorMidiToolsForm; //---------------------------------------------------------------------------- // qtractorTracks -- The main session track listview widget. class qtractorTracks : public QSplitter { Q_OBJECT public: // Constructor. qtractorTracks(QWidget *pParent); // Destructor. ~qtractorTracks(); // Child widgets accessors. qtractorTrackList *trackList() const; qtractorTrackTime *trackTime() const; qtractorTrackView *trackView() const; // Update/sync from session tracks. void updateContents(bool bRefresh = false); // Primordial track management methods. qtractorTrack *currentTrack() const; bool addTrack(); bool removeTrack(qtractorTrack *pTrack = NULL); bool editTrack(qtractorTrack *pTrack = NULL); // Import Audio/MIDI files into new tracks... bool addAudioTracks(QStringList files, unsigned long iClipStart = 0); bool addMidiTracks(QStringList files, unsigned long iClipStart = 0); bool addMidiTrackChannel(const QString& sPath, int iTrackChannel, unsigned long iClipStart = 0); // Track-list active maintenance update. void updateTrack(qtractorTrack *pTrack); // MIDI track/bus/channel alias active maintenance method. void updateMidiTrack(qtractorTrack *pMidiTrack); // Primordial clip management methods. qtractorClip *currentClip() const; bool newClip(); bool editClip(qtractorClip *pClip = NULL); bool unlinkClip(qtractorClip *pClip = NULL); bool splitClip(qtractorClip *pClip = NULL); bool normalizeClip(qtractorClip *pClip = NULL); bool rangeClip(qtractorClip *pClip = NULL); bool loopClip(qtractorClip *pClip = NULL); bool tempoClip(qtractorClip *pClip = NULL); bool executeClipTool(int iTool, qtractorClip *pClip = NULL); bool importClips(QStringList files, unsigned long iClipStart = 0); bool exportClips(); bool mergeClips(); // Whether there's anything currently selected. bool isSelected() const; // Whether there's any clip currently selected. bool isClipSelected() const; // Whether there's any curve/automation currently selected. bool isCurveSelected() const; // Whether there's a single track selection. qtractorTrack *singleTrackSelected(); // Retrieve actual clip selection range. void clipSelectedRange( unsigned long& iSelectStart, unsigned long& iSelectEnd) const; // Clipboard methods. void cutClipboard(); void copyClipboard(); void pasteClipboard(); // Special paste/repeat prompt. void pasteRepeatClipboard(); // Delete selection method. void deleteSelect(); // Split selection method. void splitSelect(); // Selection methods. void selectEditRange(bool bReset = false); void selectCurrentTrack(bool bReset = false); void selectCurrentTrackRange(bool bReset = false); void selectAll(); void selectNone(); void selectInvert(); // Insertion and removal methods. bool insertEditRange(qtractorTrack *pTrack = NULL); bool removeEditRange(qtractorTrack *pTrack = NULL); // Simple main-form redirectors. void selectionChangeNotify(); void contentsChangeNotify(); void dirtyChangeNotify(); // Overall selection reset. void clearSelect(); // Overall contents reset. void clear(); // Zoom (view) modes. enum { ZoomNone = 0, ZoomHorizontal = 1, ZoomVertical = 2, ZoomAll = 3 }; void setZoomMode(int iZoomMode); int zoomMode() const; // Zoom view actuators. void zoomIn(); void zoomOut(); void zoomReset(); // Track-list update (current track only). void updateTrackList(); protected: // Zoom factor constants. enum { ZoomMin = 10, ZoomBase = 100, ZoomMax = 1000, ZoomStep = 10 }; // Common zoom factor settlers. void horizontalZoomStep(int iZoomStep); void verticalZoomStep(int iZoomStep); // Zoom centering context. struct ZoomCenter { int x, y; unsigned long frame; }; // Zoom centering prepare and post methods. void zoomCenterPre(ZoomCenter& zc) const; void zoomCenterPost(const ZoomCenter& zc); // Multi-clip command builders. bool normalizeClipCommand( qtractorClipCommand *pClipCommand, qtractorClip *pClip); bool executeClipToolCommand( qtractorMidiClipCommand *pMidiClipCommand, qtractorClip *pClip, qtractorMidiToolsForm *pToolsForm); // Common clip-export/merge methods. bool mergeExportClips(qtractorClipCommand *pClipCommand); // Specialized clip-export/merge methods. bool mergeExportAudioClips(qtractorClipCommand *pClipCommand); bool mergeExportMidiClips(qtractorClipCommand *pClipCommand); bool rangeClipEx(qtractorClip *pClip, bool bLoopSet); // Insertion and removal methods (track). int insertEditRangeTrack( qtractorClipRangeCommand *pClipRangeCommand, qtractorTrack *pTrack, unsigned long iInsertStart, unsigned long iInsertEnd, unsigned int iInsertOptions) const; int removeEditRangeTrack( qtractorClipRangeCommand *pClipRangeCommand, qtractorTrack *pTrack, unsigned long iRemoveStart, unsigned long iRemoveEnd, unsigned int iRemoveOptions) const; public slots: // Track-view update (obviously a slot). void updateTrackView(); protected slots: // Zoom view slots. void horizontalZoomInSlot(); void horizontalZoomOutSlot(); void verticalZoomInSlot(); void verticalZoomOutSlot(); void viewZoomResetSlot(); private: // The main child widgets. qtractorTrackList *m_pTrackList; qtractorTrackTime *m_pTrackTime; qtractorTrackView *m_pTrackView; // Zoom mode flag. int m_iZoomMode; }; #endif // __qtractorTracks_h // end of qtractorTracks.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorBusForm.cpp0000644000175000001440000000012312166526620021112 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134667.10708 30 ctime=1381134667.107080051 qtractor-0.5.11/src/qtractorBusForm.cpp0000644000175000001440000006370412166526620020413 0ustar00rncbcusers00000000000000// qtractorBusForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorBusForm.h" #include "qtractorAbout.h" #include "qtractorOptions.h" #include "qtractorEngineCommand.h" #include "qtractorAudioEngine.h" #include "qtractorMidiEngine.h" #include "qtractorMidiBuffer.h" #include "qtractorSession.h" #include "qtractorMidiSysexForm.h" #include "qtractorMidiSysex.h" #include "qtractorInstrument.h" #include "qtractorPlugin.h" #include #include #include //---------------------------------------------------------------------- // class qtractorBusListItem -- Custom bus listview item. // class qtractorBusListItem : public QTreeWidgetItem { public: // Constructor. qtractorBusListItem(QTreeWidgetItem *pRootItem, qtractorBus *pBus) : QTreeWidgetItem(pRootItem), m_pBus(pBus) { switch (m_pBus->busType()) { case qtractorTrack::Audio: QTreeWidgetItem::setIcon(0, QIcon(":/images/trackAudio.png")); QTreeWidgetItem::setText(1, QString::number( static_cast (m_pBus)->channels())); break; case qtractorTrack::Midi: QTreeWidgetItem::setIcon(0, QIcon(":/images/trackMidi.png")); QTreeWidgetItem::setText(1, QString::number(16)); break; case qtractorTrack::None: default: break; } QTreeWidgetItem::setText(0, m_pBus->busName()); switch (m_pBus->busMode()) { case qtractorBus::Duplex: QTreeWidgetItem::setText(2, QObject::tr("Duplex")); break; case qtractorBus::Output: QTreeWidgetItem::setText(2, QObject::tr("Output")); break; case qtractorBus::Input: QTreeWidgetItem::setText(2, QObject::tr("Input")); break; case qtractorBus::None: default: QTreeWidgetItem::setText(2, QObject::tr("None")); break; } } // Bus accessors. qtractorBus *bus() const { return m_pBus; } private: // Instance variables. qtractorBus *m_pBus; }; //---------------------------------------------------------------------------- // qtractorBusForm -- UI wrapper form. // Constructor. qtractorBusForm::qtractorBusForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::WindowModal); // Initialize locals. m_pBus = NULL; m_pAudioRoot = NULL; m_pMidiRoot = NULL; m_iDirtySetup = 0; m_iDirtyCount = 0; m_iDirtyTotal = 0; QHeaderView *pHeader = m_ui.BusListView->header(); pHeader->setDefaultAlignment(Qt::AlignLeft); pHeader->resizeSection(0, 160); #if QT_VERSION >= 0x050000 // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionResizeMode(1, QHeaderView::ResizeToContents); pHeader->setSectionResizeMode(2, QHeaderView::ResizeToContents); pHeader->setSectionsMovable(false); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setResizeMode(1, QHeaderView::ResizeToContents); pHeader->setResizeMode(2, QHeaderView::ResizeToContents); pHeader->setMovable(false); #endif m_ui.BusListView->setContextMenuPolicy(Qt::CustomContextMenu); const QColor& rgbDark = palette().dark().color().darker(150); m_ui.BusTitleTextLabel->setPalette(QPalette(rgbDark)); m_ui.BusTitleTextLabel->setAutoFillBackground(true); // (Re)initial contents. refreshBuses(); // Try to restore normal window positioning. adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.BusListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(selectBus())); QObject::connect(m_ui.BusListView, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(contextMenu(const QPoint&))); QObject::connect(m_ui.BusNameLineEdit, SIGNAL(textChanged(const QString&)), SLOT(changed())); QObject::connect(m_ui.BusModeComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.MonitorCheckBox, SIGNAL(clicked()), SLOT(changed())); QObject::connect(m_ui.AudioChannelsSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.AudioAutoConnectCheckBox, SIGNAL(clicked()), SLOT(changed())); QObject::connect(m_ui.MidiInstrumentComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.MidiSysexPushButton, SIGNAL(clicked()), SLOT(midiSysex())); QObject::connect(m_ui.InputPluginListView, SIGNAL(currentRowChanged(int)), SLOT(stabilizeForm())); QObject::connect(m_ui.InputPluginListView, SIGNAL(contentsChanged()), SLOT(stabilizeForm())); QObject::connect(m_ui.AddInputPluginToolButton, SIGNAL(clicked()), SLOT(addInputPlugin())); QObject::connect(m_ui.RemoveInputPluginToolButton, SIGNAL(clicked()), SLOT(removeInputPlugin())); QObject::connect(m_ui.MoveUpInputPluginToolButton, SIGNAL(clicked()), SLOT(moveUpInputPlugin())); QObject::connect(m_ui.MoveDownInputPluginToolButton, SIGNAL(clicked()), SLOT(moveDownInputPlugin())); QObject::connect(m_ui.OutputPluginListView, SIGNAL(currentRowChanged(int)), SLOT(stabilizeForm())); QObject::connect(m_ui.OutputPluginListView, SIGNAL(contentsChanged()), SLOT(stabilizeForm())); QObject::connect(m_ui.AddOutputPluginToolButton, SIGNAL(clicked()), SLOT(addOutputPlugin())); QObject::connect(m_ui.RemoveOutputPluginToolButton, SIGNAL(clicked()), SLOT(removeOutputPlugin())); QObject::connect(m_ui.MoveUpOutputPluginToolButton, SIGNAL(clicked()), SLOT(moveUpOutputPlugin())); QObject::connect(m_ui.MoveDownOutputPluginToolButton, SIGNAL(clicked()), SLOT(moveDownOutputPlugin())); QObject::connect(m_ui.RefreshPushButton, SIGNAL(clicked()), SLOT(refreshBuses())); QObject::connect(m_ui.CreatePushButton, SIGNAL(clicked()), SLOT(createBus())); QObject::connect(m_ui.UpdatePushButton, SIGNAL(clicked()), SLOT(updateBus())); QObject::connect(m_ui.DeletePushButton, SIGNAL(clicked()), SLOT(deleteBus())); QObject::connect(m_ui.ClosePushButton, SIGNAL(clicked()), SLOT(reject())); stabilizeForm(); } // Set current bus. void qtractorBusForm::setBus ( qtractorBus *pBus ) { // Get the device view root item... QTreeWidgetItem *pRootItem = NULL; if (pBus) { switch (pBus->busType()) { case qtractorTrack::Audio: pRootItem = m_pAudioRoot; break; case qtractorTrack::Midi: pRootItem = m_pMidiRoot; break; default: break; } } // Is the root present? if (pRootItem == NULL) { stabilizeForm(); return; } // For each child, test for identity... int iChildCount = pRootItem->childCount(); for (int i = 0; i < iChildCount; ++i) { QTreeWidgetItem *pItem = pRootItem->child(i); // If identities match, select as current device item. qtractorBusListItem *pBusItem = static_cast (pItem); if (pBusItem && pBusItem->bus() == pBus) { m_ui.BusListView->setCurrentItem(pItem); break; } } } // Current bus accessor. qtractorBus *qtractorBusForm::bus (void) { return m_pBus; } // Current bus accessor. bool qtractorBusForm::isDirty (void) { return (m_iDirtyTotal > 0); } // Show current selected bus. void qtractorBusForm::showBus ( qtractorBus *pBus ) { ++m_iDirtySetup; // Reset plugin lists... resetPluginLists(); // Settle current bus reference... m_pBus = pBus; // Update some dependable specifics... updateMidiInstruments(); updateMidiSysex(); // Show bus properties into view pane... if (pBus) { QString sBusTitle = pBus->busName(); if (!sBusTitle.isEmpty()) sBusTitle += " - "; switch (pBus->busType()) { case qtractorTrack::Audio: { sBusTitle += tr("Audio"); qtractorAudioBus *pAudioBus = static_cast (pBus); if (pAudioBus) { // Audio bus specifics... m_ui.AudioChannelsSpinBox->setValue( pAudioBus->channels()); m_ui.AudioAutoConnectCheckBox->setChecked( pAudioBus->isAutoConnect()); // Set plugin lists... if (pAudioBus->busMode() & qtractorBus::Input) m_ui.InputPluginListView->setPluginList( pAudioBus->pluginList_in()); if (pAudioBus->busMode() & qtractorBus::Output) m_ui.OutputPluginListView->setPluginList( pAudioBus->pluginList_out()); } break; } case qtractorTrack::Midi: { sBusTitle += tr("MIDI"); qtractorMidiBus *pMidiBus = static_cast (pBus); if (pMidiBus) { // MIDI bus specifics... int iInstrumentIndex = m_ui.MidiInstrumentComboBox->findText( pMidiBus->instrumentName()); m_ui.MidiInstrumentComboBox->setCurrentIndex( iInstrumentIndex > 0 ? iInstrumentIndex : 0); // Set plugin lists... if (pMidiBus->busMode() & qtractorBus::Input) m_ui.InputPluginListView->setPluginList( pMidiBus->pluginList_in()); if (pMidiBus->busMode() & qtractorBus::Output) m_ui.OutputPluginListView->setPluginList( pMidiBus->pluginList_out()); } break; } case qtractorTrack::None: default: break; } if (!sBusTitle.isEmpty()) sBusTitle += ' '; m_ui.BusTitleTextLabel->setText(sBusTitle + tr("Bus")); m_ui.BusNameLineEdit->setText(pBus->busName()); m_ui.BusModeComboBox->setCurrentIndex(int(pBus->busMode()) - 1); m_ui.MonitorCheckBox->setChecked(pBus->isMonitor()); } // Reset dirty flag... m_iDirtyCount = 0; --m_iDirtySetup; // Done. stabilizeForm(); } // Refresh all buses list and views. void qtractorBusForm::refreshBuses (void) { // // (Re)Load complete bus listing ... // m_pAudioRoot = NULL; m_pMidiRoot = NULL; m_ui.BusListView->clear(); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Audio buses... qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine) { m_pAudioRoot = new QTreeWidgetItem(m_ui.BusListView); m_pAudioRoot->setText(0, ' ' + tr("Audio")); m_pAudioRoot->setFlags( // Audio root item is not selectable... m_pAudioRoot->flags() & ~Qt::ItemIsSelectable); for (qtractorBus *pBus = pAudioEngine->buses().first(); pBus; pBus = pBus->next()) new qtractorBusListItem(m_pAudioRoot, pBus); m_pAudioRoot->setExpanded(true); } // MIDI buses... qtractorMidiEngine *pMidiEngine = pSession->midiEngine(); if (pMidiEngine) { m_pMidiRoot = new QTreeWidgetItem(m_ui.BusListView); m_pMidiRoot->setText(0, ' ' + tr("MIDI")); m_pMidiRoot->setFlags( // MIDI root item is not selectable... m_pMidiRoot->flags() & ~Qt::ItemIsSelectable); for (qtractorBus *pBus = pMidiEngine->buses().first(); pBus; pBus = pBus->next()) new qtractorBusListItem(m_pMidiRoot, pBus); m_pMidiRoot->setExpanded(true); } } // Bus selection slot. void qtractorBusForm::selectBus (void) { // Get current selected item, must not be a root one... QTreeWidgetItem *pItem = m_ui.BusListView->currentItem(); if (pItem == NULL) return; if (pItem->parent() == NULL) return; // Just make it in current view... qtractorBusListItem *pBusItem = static_cast (pItem); if (pBusItem == NULL) return; // Check if we need an update?... qtractorBus *pBus = pBusItem->bus(); if (m_pBus && m_pBus != pBus && m_iDirtyCount > 0) { QMessageBox::StandardButtons buttons = QMessageBox::Discard | QMessageBox::Cancel; if (m_ui.UpdatePushButton->isEnabled()) buttons |= QMessageBox::Apply; switch (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Some settings have been changed.\n\n" "Do you want to apply the changes?"), buttons)) { case QMessageBox::Apply: if (updateBus(m_pBus)) { ++m_iDirtyTotal; refreshBuses(); } // Fall thru... case QMessageBox::Discard: break; default: // Cancel. return; } } // Get new one into view... showBus(pBus); } // Check whether the current view is elligible for action. unsigned int qtractorBusForm::flags (void) const { unsigned int iFlags = 0; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return iFlags; if (m_pBus == NULL) return iFlags; if (m_pBus->prev()) iFlags |= Delete; if (m_iDirtyCount == 0) return iFlags; const QString sBusName = m_ui.BusNameLineEdit->text().simplified(); if (sBusName.isEmpty()) return iFlags; // Get the device view root item... qtractorEngine *pEngine = NULL; switch (m_pBus->busType()) { case qtractorTrack::Audio: pEngine = pSession->audioEngine(); break; case qtractorTrack::Midi: pEngine = pSession->midiEngine(); break; default: break; } // Is it still valid? if (pEngine == NULL) return iFlags; // Is there one already? qtractorBus *pBus = pEngine->findBus(sBusName); qtractorBus *pBusEx = pEngine->findBusEx(sBusName); if (pBus == NULL && pBusEx == NULL) iFlags |= Create; if ((pBus == NULL || pBus == m_pBus) && (pBusEx == NULL) && (m_pBus->prev() || m_ui.BusModeComboBox->currentIndex() == 2)) iFlags |= Update; return iFlags; } // Update bus method. bool qtractorBusForm::updateBus ( qtractorBus *pBus ) { if (pBus == NULL) return false; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; const QString sBusName = m_ui.BusNameLineEdit->text().simplified(); if (sBusName.isEmpty()) return false; // Reset plugin lists... resetPluginLists(); qtractorBus::BusMode busMode = qtractorBus::None; switch (m_ui.BusModeComboBox->currentIndex()) { case 0: busMode = qtractorBus::Input; break; case 1: busMode = qtractorBus::Output; break; case 2: busMode = qtractorBus::Duplex; break; } // Make it as an unduable command... qtractorUpdateBusCommand *pUpdateBusCommand = new qtractorUpdateBusCommand(pBus); // Set all updated properties... qtractorTrack::TrackType busType = pBus->busType(); pUpdateBusCommand->setBusType(busType); pUpdateBusCommand->setBusName(sBusName); pUpdateBusCommand->setBusMode(busMode); pUpdateBusCommand->setMonitor( (busMode & qtractorBus::Duplex) == qtractorBus::Duplex && m_ui.MonitorCheckBox->isChecked()); // Specialties for bus types... switch (busType) { case qtractorTrack::Audio: pUpdateBusCommand->setChannels( m_ui.AudioChannelsSpinBox->value()); pUpdateBusCommand->setAutoConnect( m_ui.AudioAutoConnectCheckBox->isChecked()); break; case qtractorTrack::Midi: pUpdateBusCommand->setInstrumentName( m_ui.MidiInstrumentComboBox->currentIndex() > 0 ? m_ui.MidiInstrumentComboBox->currentText() : QString::null); // Fall thru... case qtractorTrack::None: default: break; } // Execute and refresh form... return pSession->execute(pUpdateBusCommand); } // Create a new bus from current view. void qtractorBusForm::createBus (void) { if (m_pBus == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; const QString sBusName = m_ui.BusNameLineEdit->text().simplified(); if (sBusName.isEmpty()) return; qtractorBus::BusMode busMode = qtractorBus::None; switch (m_ui.BusModeComboBox->currentIndex()) { case 0: busMode = qtractorBus::Input; break; case 1: busMode = qtractorBus::Output; break; case 2: busMode = qtractorBus::Duplex; break; } // Make it as an unduable command... qtractorCreateBusCommand *pCreateBusCommand = new qtractorCreateBusCommand(); // Set all creational properties... qtractorTrack::TrackType busType = m_pBus->busType(); pCreateBusCommand->setBusType(busType); pCreateBusCommand->setBusName(sBusName); pCreateBusCommand->setBusMode(busMode); pCreateBusCommand->setMonitor( (busMode & qtractorBus::Duplex) == qtractorBus::Duplex && m_ui.MonitorCheckBox->isChecked()); // Specialties for bus types... switch (busType) { case qtractorTrack::Audio: pCreateBusCommand->setChannels( m_ui.AudioChannelsSpinBox->value()); pCreateBusCommand->setAutoConnect( m_ui.AudioAutoConnectCheckBox->isChecked()); break; case qtractorTrack::Midi: pCreateBusCommand->setInstrumentName( m_ui.MidiInstrumentComboBox->currentIndex() > 0 ? m_ui.MidiInstrumentComboBox->currentText() : QString::null); // Fall thru... case qtractorTrack::None: default: break; } // Execute and refresh form... if (pSession->execute(pCreateBusCommand)) { ++m_iDirtyTotal; refreshBuses(); } // Reselect current bus... setBus(m_pBus); } // Update current bus in view. void qtractorBusForm::updateBus (void) { // That's it... if (updateBus(m_pBus)) { ++m_iDirtyTotal; refreshBuses(); } // Reselect current bus... setBus(m_pBus); } // Delete current bus in view. void qtractorBusForm::deleteBus (void) { if (m_pBus == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Prompt user if he/she's sure about this... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions && pOptions->bConfirmRemove) { // Get some textual type... QString sBusType; switch (m_pBus->busType()) { case qtractorTrack::Audio: sBusType = tr("Audio"); break; case qtractorTrack::Midi: sBusType = tr("MIDI"); break; default: break; } // Show the warning... if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("About to remove bus:\n\n" "\"%1\" (%2)\n\n" "Are you sure?") .arg(m_pBus->busName()) .arg(sBusType), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; } // Reset plugin lists... resetPluginLists(); // Make it as an unduable command... qtractorDeleteBusCommand *pDeleteBusCommand = new qtractorDeleteBusCommand(m_pBus); // Invalidade current bus... m_pBus = NULL; // Execute and refresh form... if (pSession->execute(pDeleteBusCommand)) { ++m_iDirtyTotal; refreshBuses(); } // Done. stabilizeForm(); } // Reset (stabilize) plugin lists... void qtractorBusForm::resetPluginLists (void) { m_ui.InputPluginListView->setPluginList(NULL); m_ui.OutputPluginListView->setPluginList(NULL); } // Make changes due. void qtractorBusForm::changed (void) { if (m_iDirtySetup > 0) return; ++m_iDirtyCount; stabilizeForm(); } // Reject settings (Close button slot). void qtractorBusForm::reject (void) { bool bReject = true; // Check if there's any pending changes... if (m_iDirtyCount > 0) { switch (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Some settings have been changed.\n\n" "Do you want to discard the changes?"), QMessageBox::Discard | QMessageBox::Cancel)) { case QMessageBox::Discard: break; default: // Cancel. bReject = false; break; } } if (bReject) QDialog::reject(); } // Stabilize current form state. void qtractorBusForm::stabilizeForm (void) { if (m_pBus) { m_ui.CommonBusGroup->setEnabled(true); m_ui.AudioBusGroup->setEnabled( m_pBus->busType() == qtractorTrack::Audio); m_ui.MidiBusGroup->setEnabled( m_pBus->busType() == qtractorTrack::Midi && (m_pBus->busMode() & qtractorBus::Output)); } else { m_ui.CommonBusGroup->setEnabled(false); m_ui.AudioBusGroup->setEnabled(false); m_ui.MidiBusGroup->setEnabled(false); } m_ui.MonitorCheckBox->setEnabled( m_pBus && m_ui.BusModeComboBox->currentIndex() == 2); unsigned int iFlags = flags(); m_ui.RefreshPushButton->setEnabled(m_iDirtyCount > 0); m_ui.CreatePushButton->setEnabled(iFlags & Create); m_ui.UpdatePushButton->setEnabled(iFlags & Update); m_ui.DeletePushButton->setEnabled(iFlags & Delete); // Stabilize current plugin lists state. bool bEnabled; int iItem, iItemCount; qtractorPlugin *pPlugin = NULL; qtractorPluginListItem *pItem = NULL; // Input plugin list... bEnabled = (m_ui.InputPluginListView->pluginList() != NULL); m_ui.BusTabWidget->setTabEnabled(1, bEnabled); if (bEnabled) { iItemCount = m_ui.InputPluginListView->count(); iItem = -1; pPlugin = NULL; pItem = static_cast ( m_ui.InputPluginListView->currentItem()); if (pItem) { iItem = m_ui.InputPluginListView->row(pItem); pPlugin = pItem->plugin(); } // m_ui.AddInputPluginToolButton->setEnabled(true); m_ui.RemoveInputPluginToolButton->setEnabled(pPlugin != NULL); m_ui.MoveUpInputPluginToolButton->setEnabled(pItem && iItem > 0); m_ui.MoveDownInputPluginToolButton->setEnabled( pItem && iItem < iItemCount - 1); } // Output plugin list... bEnabled = (m_ui.OutputPluginListView->pluginList() != NULL); m_ui.BusTabWidget->setTabEnabled(2, bEnabled); if (bEnabled) { iItemCount = m_ui.OutputPluginListView->count(); iItem = -1; pPlugin = NULL; pItem = static_cast ( m_ui.OutputPluginListView->currentItem()); if (pItem) { iItem = m_ui.OutputPluginListView->row(pItem); pPlugin = pItem->plugin(); } // m_ui.AddOutputPluginToolButton->setEnabled(true); m_ui.RemoveOutputPluginToolButton->setEnabled(pPlugin != NULL); m_ui.MoveUpOutputPluginToolButton->setEnabled(pItem && iItem > 0); m_ui.MoveDownOutputPluginToolButton->setEnabled( pItem && iItem < iItemCount - 1); } } // Bus list view context menu handler. void qtractorBusForm::contextMenu ( const QPoint& /*pos*/ ) { // Build the device context menu... QMenu menu(this); QAction *pAction; unsigned int iFlags = flags(); pAction = menu.addAction( QIcon(":/images/formCreate.png"), tr("&Create"), this, SLOT(createBus())); pAction->setEnabled(iFlags & Create); pAction = menu.addAction( QIcon(":/images/formAccept.png"), tr("&Update"), this, SLOT(updateBus())); pAction->setEnabled(iFlags & Update); pAction = menu.addAction( QIcon(":/images/formRemove.png"), tr("&Delete"), this, SLOT(deleteBus())); pAction->setEnabled(iFlags & Delete); menu.addSeparator(); pAction = menu.addAction( QIcon(":/images/formRefresh.png"), tr("&Refresh"), this, SLOT(refreshBuses())); pAction->setEnabled(m_iDirtyCount > 0); // menu.exec(m_ui.BusListView->mapToGlobal(pos)); menu.exec(QCursor::pos()); } // Show MIDI SysEx bank manager dialog... void qtractorBusForm::midiSysex (void) { // Care of MIDI output bus... if (m_pBus == NULL) return; if (m_pBus->busType() != qtractorTrack::Midi) return; if ((m_pBus->busMode() & qtractorBus::Output) == 0) return; qtractorMidiBus *pMidiBus = static_cast (m_pBus); if (pMidiBus == NULL) return; if (pMidiBus->sysexList() == NULL) return; qtractorMidiSysexForm form(this); form.setSysexList(pMidiBus->sysexList()); form.exec(); updateMidiSysex(); } // Refresh instrument list. void qtractorBusForm::updateMidiInstruments (void) { m_ui.MidiInstrumentComboBox->clear(); m_ui.MidiInstrumentComboBox->addItem(tr("(No instrument)")); // Care of MIDI output bus... if (m_pBus == NULL) return; if (m_pBus->busType() != qtractorTrack::Midi) return; if ((m_pBus->busMode() & qtractorBus::Output) == 0) return; qtractorMidiBus *pMidiBus = static_cast (m_pBus); if (pMidiBus == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorInstrumentList *pInstruments = pSession->instruments(); if (pInstruments == NULL) return; // Avoid superfluous change notifications... ++m_iDirtySetup; const QIcon& icon = QIcon(":/images/itemInstrument.png"); if (pMidiBus->pluginList_out()) { qtractorMidiManager *pMidiManager = (pMidiBus->pluginList_out())->midiManager(); if (pMidiManager) { pMidiManager->updateInstruments(); const qtractorMidiManager::Instruments& list = pMidiManager->instruments(); qtractorMidiManager::Instruments::ConstIterator iter = list.constBegin(); const qtractorMidiManager::Instruments::ConstIterator& iter_end = list.constEnd(); for ( ; iter != iter_end; ++iter) m_ui.MidiInstrumentComboBox->addItem(icon, iter.key()); } } // Regular instrument names... qtractorInstrumentList::ConstIterator iter = pInstruments->constBegin(); const qtractorInstrumentList::ConstIterator& iter_end = pInstruments->constEnd(); for ( ; iter != iter_end; ++iter) m_ui.MidiInstrumentComboBox->addItem(icon, iter.value().instrumentName()); // Done. --m_iDirtySetup; } // Update SysEx status. void qtractorBusForm::updateMidiSysex (void) { m_ui.MidiSysexTextLabel->clear(); // Care of MIDI output bus... if (m_pBus == NULL) return; if (m_pBus->busType() != qtractorTrack::Midi) return; if ((m_pBus->busMode() & qtractorBus::Output) == 0) return; qtractorMidiBus *pMidiBus = static_cast (m_pBus); if (pMidiBus == NULL) return; if (pMidiBus->sysexList() == NULL) return; // Show proper count status... int iSysexCount = (pMidiBus->sysexList())->count(); switch (iSysexCount) { case 0: m_ui.MidiSysexTextLabel->setText(tr("(none)")); break; case 1: m_ui.MidiSysexTextLabel->setText(tr("(1 item)")); break; default: m_ui.MidiSysexTextLabel->setText(tr("(%1 items)").arg(iSysexCount)); break; } } // Input plugin list slots. void qtractorBusForm::addInputPlugin (void) { m_ui.InputPluginListView->addPlugin(); } void qtractorBusForm::removeInputPlugin (void) { m_ui.InputPluginListView->removePlugin(); } void qtractorBusForm::moveUpInputPlugin (void) { m_ui.InputPluginListView->moveUpPlugin(); } void qtractorBusForm::moveDownInputPlugin (void) { m_ui.InputPluginListView->moveDownPlugin(); } // Output plugin list slots. void qtractorBusForm::addOutputPlugin (void) { m_ui.OutputPluginListView->addPlugin(); } void qtractorBusForm::removeOutputPlugin (void) { m_ui.OutputPluginListView->removePlugin(); } void qtractorBusForm::moveUpOutputPlugin (void) { m_ui.OutputPluginListView->moveUpPlugin(); } void qtractorBusForm::moveDownOutputPlugin (void) { m_ui.OutputPluginListView->moveDownPlugin(); } // end of qtractorBusForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorZipFile.cpp0000644000175000001440000000012312073104061021063 xustar000000000000000027 mtime=1357678641.548312 26 atime=1381134671.09208 30 ctime=1381134671.093080114 qtractor-0.5.11/src/qtractorZipFile.cpp0000644000175000001440000006607412073104061020367 0ustar00rncbcusers00000000000000// qtractorZipFile.cpp // /**************************************************************************** Copyright (C) 2010-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #ifdef CONFIG_LIBZ /* Most of this code was originally borrowed, stirred, mangled * and finally adapted from the Qt 4.6 source code (LGPL). * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(ies). * All rights reserved. * Contact: Nokia Corporation (qt-info@nokia.com) */ #include "qtractorZipFile.h" #define QTRACTOR_PROGRESS_BAR #ifdef QTRACTOR_PROGRESS_BAR #include "qtractorMainForm.h" #include #endif #include #include #include #include #include #if defined(Q_OS_WIN) # undef S_IFREG # undef S_ISDIR # undef S_ISREG # undef S_IRUSR # undef S_IWUSR # undef S_IXUSR # define S_IFREG 0100000 # define S_ISDIR(x) ((x) & 0040000) > 0 # define S_ISREG(x) ((x) & 0170000) == S_IFREG # define S_IFLNK 020000 # define S_ISLNK(x) ((x) & S_IFLNK) > 0 # define S_IRUSR 0400 # define S_IWUSR 0200 # define S_IXUSR 0100 # define S_IRGRP 0040 # define S_IWGRP 0020 # define S_IXGRP 0010 # define S_IROTH 0004 # define S_IWOTH 0002 # define S_IXOTH 0001 #endif #include #define BUFF_SIZE 16384 static inline unsigned int read_uint ( const unsigned char *data ) { return data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24); } static inline unsigned short read_ushort ( const unsigned char *data ) { return data[0] + (data[1] << 8); } static inline void write_uint ( unsigned char *data, unsigned int i ) { data[0] = i & 0xff; data[1] = (i >> 8) & 0xff; data[2] = (i >> 16) & 0xff; data[3] = (i >> 24) & 0xff; } static inline void write_ushort ( unsigned char *data, ushort i ) { data[0] = i & 0xff; data[1] = (i >> 8) & 0xff; } static inline void copy_uint ( unsigned char *dest, const unsigned char *src ) { dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[2]; dest[3] = src[3]; } static inline void copy_ushort ( unsigned char *dest, const unsigned char *src ) { dest[0] = src[0]; dest[1] = src[1]; } static void write_msdos_date ( unsigned char *data, const QDateTime& dt ) { if (dt.isValid()) { unsigned short time = (dt.time().hour() << 11) // 5 bit hour | (dt.time().minute() << 5) // 6 bit minute | (dt.time().second() >> 1); // 5 bit double seconds data[0] = time & 0xff; data[1] = time >> 8; unsigned short date = ((dt.date().year() - 1980) << 9) // 7 bit year 1980-based | (dt.date().month() << 5) // 4 bit month | (dt.date().day()); // 5 bit day data[2] = date & 0xff; data[3] = date >> 8; } else { data[0] = 0; data[1] = 0; data[2] = 0; data[3] = 0; } } static QDateTime read_msdos_date ( unsigned char *data ) { unsigned short time = data[0] + (data[1] << 8); unsigned short date = data[2] + (data[3] << 8); unsigned int year = (date >> 9) + 1980; // 7 bit year 1980-based. unsigned int mon = (date >> 5) & 0x0f; // 4 bit month. unsigned int day = (date & 0x1f); // 5 bit day. unsigned int hh = (time >> 11); // 5 bit hour unsigned int mm = (time >> 5) & 0x3f; // 6 bit minute unsigned int ss = (time & 0x1f) << 1; // 5 bit double (m)seconds. return QDateTime(QDate(year, mon, day), QTime(hh, mm, ss)); } static unsigned int mode_from_permissions ( QFile::Permissions perms ) { unsigned int mode = 0; if (perms & QFile::ReadOwner) mode |= S_IRUSR; if (perms & QFile::WriteOwner) mode |= S_IWUSR; if (perms & QFile::ExeOwner) mode |= S_IXUSR; if (perms & QFile::ReadUser) mode |= S_IRUSR; if (perms & QFile::WriteUser) mode |= S_IWUSR; if (perms & QFile::ExeUser) mode |= S_IXUSR; if (perms & QFile::ReadGroup) mode |= S_IRGRP; if (perms & QFile::WriteGroup) mode |= S_IWGRP; if (perms & QFile::ExeGroup) mode |= S_IXGRP; if (perms & QFile::ReadOther) mode |= S_IROTH; if (perms & QFile::WriteOther) mode |= S_IWOTH; if (perms & QFile::ExeOther) mode |= S_IXOTH; return mode; } static QFile::Permissions permissions_from_mode ( unsigned int mode ) { QFile::Permissions perms; if (mode & S_IRUSR) perms |= QFile::ReadOwner; if (mode & S_IWUSR) perms |= QFile::WriteOwner; if (mode & S_IXUSR) perms |= QFile::ExeOwner; if (mode & S_IRUSR) perms |= QFile::ReadUser; if (mode & S_IWUSR) perms |= QFile::WriteUser; if (mode & S_IXUSR) perms |= QFile::ExeUser; if (mode & S_IRGRP) perms |= QFile::ReadGroup; if (mode & S_IWGRP) perms |= QFile::WriteGroup; if (mode & S_IXGRP) perms |= QFile::ExeGroup; if (mode & S_IROTH) perms |= QFile::ReadOther; if (mode & S_IWOTH) perms |= QFile::WriteOther; if (mode & S_IXOTH) perms |= QFile::ExeOther; return perms; } struct LocalFileHeader { unsigned char signature[4]; // 0x04034b50 unsigned char version_needed[2]; unsigned char general_purpose_bits[2]; unsigned char compression_method[2]; unsigned char last_mod_file[4]; unsigned char crc_32[4]; unsigned char compressed_size[4]; unsigned char uncompressed_size[4]; unsigned char file_name_length[2]; unsigned char extra_field_length[2]; }; struct CentralFileHeader { unsigned char signature[4]; // 0x02014b50 unsigned char version_made[2]; unsigned char version_needed[2]; unsigned char general_purpose_bits[2]; unsigned char compression_method[2]; unsigned char last_mod_file[4]; unsigned char crc_32[4]; unsigned char compressed_size[4]; unsigned char uncompressed_size[4]; unsigned char file_name_length[2]; unsigned char extra_field_length[2]; unsigned char file_comment_length[2]; unsigned char disk_start[2]; unsigned char internal_file_attributes[2]; unsigned char external_file_attributes[4]; unsigned char offset_local_header[4]; }; struct EndOfDirectory { unsigned char signature[4]; // 0x06054b50 unsigned char this_disk[2]; unsigned char start_of_directory_disk[2]; unsigned char num_dir_entries_this_disk[2]; unsigned char num_dir_entries[2]; unsigned char directory_size[4]; unsigned char dir_start_offset[4]; unsigned char comment_length[2]; }; struct FileHeader { CentralFileHeader h; QByteArray file_name; QByteArray extra_field; QByteArray file_comment; }; static void copy_header ( LocalFileHeader& lfh, const CentralFileHeader& h ) { write_uint(lfh.signature, 0x04034b50); copy_ushort(lfh.version_needed, h.version_needed); copy_ushort(lfh.general_purpose_bits, h.general_purpose_bits); copy_ushort(lfh.compression_method, h.compression_method); copy_uint(lfh.last_mod_file, h.last_mod_file); copy_uint(lfh.crc_32, h.crc_32); copy_uint(lfh.compressed_size, h.compressed_size); copy_uint(lfh.uncompressed_size, h.uncompressed_size); copy_ushort(lfh.file_name_length, h.file_name_length); copy_ushort(lfh.extra_field_length, h.extra_field_length); } //---------------------------------------------------------------------------- // qtractorZipDevice -- Common ZIP I/O device class. // class qtractorZipDevice { public: qtractorZipDevice (QIODevice *pDevice, bool bOwnDevice) : device(pDevice), own_device(bOwnDevice), status(qtractorZipFile::NoError), dirty_contents(true), total_uncompressed(0), total_compressed(0), total_processed(0), buff_read(new unsigned char [BUFF_SIZE]), buff_write(new unsigned char [BUFF_SIZE]), write_offset(0) { #ifdef QTRACTOR_PROGRESS_BAR qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); progress_bar = (pMainForm ? pMainForm->progressBar() : NULL); #endif } ~qtractorZipDevice() { delete [] buff_read; delete [] buff_write; if (own_device) delete device; } void scanFiles(); bool extractEntry(const QString& sFilename, const FileHeader& fh); bool extractAll(); QString alias(const QString& sFilename, const QString& sPrefix = QString()) const; enum EntryType { File = 0, Directory, SymLink }; bool addEntry(EntryType type, const QString& sFilename, const QString& sAlias = QString()); bool processEntry(const QString& sFilename, FileHeader& fh); bool processAll(); QIODevice *device; bool own_device; qtractorZipFile::Status status; bool dirty_contents; QHash file_headers; QHash file_aliases; QByteArray comment; unsigned int total_uncompressed; unsigned int total_compressed; unsigned int total_processed; unsigned char *buff_read; unsigned char *buff_write; unsigned int write_offset; #ifdef QTRACTOR_PROGRESS_BAR QProgressBar *progress_bar; #endif }; //---------------------------------------------------------------------------- // qtractorZipDevice -- Common ZIP I/O device class. // // Scans and reads zip archive entry directory (read-only). void qtractorZipDevice::scanFiles (void) { if (!dirty_contents) return; if (!(device->isOpen() || device->open(QIODevice::ReadOnly))) { status = qtractorZipFile::FileOpenError; return; } if (!(device->openMode() & QIODevice::ReadOnly)) { status = qtractorZipFile::FileReadError; return; } total_uncompressed = 0; total_compressed = 0; total_processed = 0; file_headers.clear(); dirty_contents = false; unsigned char tmp[4]; device->read((char *) tmp, 4); if (read_uint(tmp) != 0x04034b50) { qWarning("qtractorZipDevice::scanFiles: not a zip file."); return; } // Find EndOfDirectory header... int i = 0; int dir_start_offset = -1; int num_dir_entries = 0; EndOfDirectory eod; while (dir_start_offset == -1) { int pos = device->size() - sizeof(EndOfDirectory) - i; if (pos < 0 || i > 65535) { qWarning("qtractorZipDevice::scanFiles: " "end-of-directory not found."); return; } device->seek(pos); device->read((char *) &eod, sizeof(EndOfDirectory)); if (read_uint(eod.signature) == 0x06054b50) break; ++i; } // Have the eod... dir_start_offset = read_uint(eod.dir_start_offset); num_dir_entries = read_ushort(eod.num_dir_entries); int comment_length = read_ushort(eod.comment_length); if (comment_length != i) qWarning("qtractorZipDevice::scanFiles: failed to parse zip file."); comment = device->read(qMin(comment_length, i)); device->seek(dir_start_offset); for (i = 0; i < num_dir_entries; ++i) { FileHeader fh; int read = device->read((char *) &fh.h, sizeof(CentralFileHeader)); if (read < (int) sizeof(CentralFileHeader)) { qWarning("qtractorZipDevice::scanFiles: " "failed to read complete header, " "index may be incomplete."); break; } if (read_uint(fh.h.signature) != 0x02014b50) { qWarning("qtractorZipDevice::scanFiles: " "invalid header signature, " "zip index may be incomplete."); break; } int l = read_ushort(fh.h.file_name_length); fh.file_name = device->read(l); if (fh.file_name.length() != l) { qWarning("qtractorZipDevice::scanFiles: " "failed to read filename, " "zip index may be incomplete."); break; } l = read_ushort(fh.h.extra_field_length); fh.extra_field = device->read(l); if (fh.extra_field.length() != l) { qWarning("qtractorZipDevice::scanFiles: " "failed to read extra field, skipping, " "zip index may be incomplete"); break; } l = read_ushort(fh.h.file_comment_length); fh.file_comment = device->read(l); if (fh.file_comment.length() != l) { qWarning("qtractorZipDevice::scanFiles: " "failed to read file comment, " "index may be incomplete"); break; } total_uncompressed += read_uint(fh.h.uncompressed_size); total_compressed += read_uint(fh.h.compressed_size); file_headers.insert(QString::fromLocal8Bit(fh.file_name), fh); } } // Extract contents of a zip archive file entry (read-only). bool qtractorZipDevice::extractEntry ( const QString& sFilename, const FileHeader& fh ) { if (!(device->isOpen() || device->open(QIODevice::ReadOnly))) { status = qtractorZipFile::FileOpenError; return false; } if (!(device->openMode() & QIODevice::ReadOnly)) { status = qtractorZipFile::FileReadError; return false; } QFileInfo info(sFilename); if (!info.dir().exists()) QDir().mkpath(info.dir().path()); QFile *pFile = NULL; const unsigned int mode = read_uint(fh.h.external_file_attributes) >> 16; if (S_ISREG(mode)) { pFile = new QFile(info.filePath()); if (!pFile->open(QIODevice::WriteOnly)) { status = qtractorZipFile::FileError; delete pFile; return false; } } else if (S_ISDIR(mode)) return QDir().mkpath(info.filePath()); else if (pFile == NULL) return false; unsigned int uncompressed_size = read_uint(fh.h.uncompressed_size); unsigned int compressed_size = read_uint(fh.h.compressed_size); if (uncompressed_size == 0 || compressed_size == 0) return false; device->seek(read_uint(fh.h.offset_local_header)); LocalFileHeader lfh; device->read((char *) &lfh, sizeof(LocalFileHeader)); unsigned int skip = read_ushort(lfh.file_name_length) + read_ushort(lfh.extra_field_length); device->seek(device->pos() + skip); ushort compression_method = read_ushort(lfh.compression_method); if (compression_method == 8) { unsigned int n_file_read = 0; unsigned int n_file_write = 0; z_stream zstream; memset(&zstream, 0, sizeof(zstream)); unsigned int crc_32 = ::crc32(0, 0, 0); int zrc = ::inflateInit2(&zstream, -MAX_WBITS); while (zrc != Z_STREAM_END) { unsigned int n_buff_read = BUFF_SIZE; if (n_file_read + BUFF_SIZE > compressed_size) n_buff_read = compressed_size - n_file_read; device->read((char *) buff_read, n_buff_read); n_file_read += n_buff_read; zstream.next_in = (uchar *) buff_read; zstream.avail_in = (uint) n_buff_read; do { unsigned int n_buff_write = BUFF_SIZE; zstream.next_out = (uchar *) buff_write; zstream.avail_out = (uint) n_buff_write; zrc = ::inflate(&zstream, Z_NO_FLUSH); if (zrc != Z_STREAM_ERROR) { n_buff_write -= zstream.avail_out; if (n_buff_write > 0) { pFile->write((const char *) buff_write, n_buff_write); crc_32 = ::crc32(crc_32, (const uchar *) buff_write, (ulong) n_buff_write); n_file_write += n_buff_write; total_processed += n_buff_write; } } } while (zstream.avail_out == 0); #ifdef QTRACTOR_PROGRESS_BAR if (progress_bar) progress_bar->setValue( (100.0f * float(total_processed)) / float(total_uncompressed)); #endif } // uncompressed_size = n_file_write; ::inflateEnd(&zstream); if (crc_32 != read_uint(lfh.crc_32)) qWarning("qtractorZipDevice::extractEntry: bad CRC32!"); } else { // No compression... QByteArray data = device->read(compressed_size); data.truncate(uncompressed_size); pFile->write(data); } pFile->setPermissions(permissions_from_mode(S_IRUSR | S_IWUSR | mode)); pFile->close(); delete pFile; // Set file time using utime... struct utimbuf utb; long tse = read_msdos_date(lfh.last_mod_file).toTime_t(); utb.actime = tse; utb.modtime = tse; if (::utime(fh.file_name.data(), &utb)) qWarning("qtractorZipDevice::extractEntry: failed to set file time."); #ifdef CONFIG_DEBUG qDebug("qtractorZipDevice::inflate(%3.0f%%) %s", (100.0f * float(total_processed)) / float(total_uncompressed), fh.file_name.data()); #endif return true; } // Extract the full contents of the zip file (read-only). bool qtractorZipDevice::extractAll (void) { scanFiles(); #ifdef QTRACTOR_PROGRESS_BAR if (progress_bar) { progress_bar->setRange(0, 100); progress_bar->reset(); progress_bar->show(); } #endif int iExtracted = 0; QHash::ConstIterator iter = file_headers.constBegin(); const QHash::ConstIterator& iter_end = file_headers.constEnd(); for ( ; iter != iter_end; ++iter) { if (extractEntry(iter.key(), iter.value())) ++iExtracted; } #ifdef QTRACTOR_PROGRESS_BAR if (progress_bar) progress_bar->hide(); #endif return (iExtracted == file_headers.count()); } // Returns an zip archive entry alias name avoiding duplicates (write-only). QString qtractorZipDevice::alias ( const QString& sFilename, const QString& sPrefix ) const { QFileInfo info(sFilename); QString sAliasPrefix = sPrefix; if (!sAliasPrefix.isEmpty() && !sAliasPrefix.endsWith('/')) sAliasPrefix.append('/'); sAliasPrefix.append(info.baseName()); QString sAliasExt; const QString& sAliasSuffix = info.completeSuffix(); if (!sAliasSuffix.isEmpty()) sAliasExt = '.' + sAliasSuffix; QString sAlias = sAliasPrefix + sAliasExt; if (!file_headers.contains(info.canonicalFilePath())) { int i = 0; while (file_aliases.contains(sAlias)) { if (i == 0) sAliasPrefix.remove(QRegExp("\\-[0-9]+$")); sAlias = sAliasPrefix + '-' + QString::number(++i) + sAliasExt; } } return sAlias; } // Add an entry to a zip archive (write-only). bool qtractorZipDevice::addEntry ( EntryType type, const QString& sFilename, const QString& sAlias ) { QFileInfo info(sFilename); if (info.isDir()) type = Directory; else if (info.isSymLink()) type = File; /* OVERRIDE */ if (type == File && !info.exists()) return false; const QString& sFilepath = info.canonicalFilePath(); if (file_headers.contains(sFilepath)) return true; FileHeader fh; memset(&fh.h, 0, sizeof(CentralFileHeader)); write_uint(fh.h.signature, 0x02014b50); write_ushort(fh.h.version_needed, 0x14); write_uint(fh.h.uncompressed_size, info.size()); write_msdos_date(fh.h.last_mod_file, info.lastModified()); total_uncompressed += info.size(); QString sFakename = sAlias; if (sFakename.isEmpty()) { if (info.isAbsolute()) { sFakename = sFilepath; sFakename.remove(QRegExp('^' + QDir::rootPath())); } else { sFakename = info.filePath(); sFakename.remove(QRegExp("^[\\./]+")); } } fh.file_name = sFakename.toLocal8Bit(); write_ushort(fh.h.file_name_length, fh.file_name.length()); write_ushort(fh.h.version_made, 3 << 8); unsigned int mode = mode_from_permissions(info.permissions()); switch (type) { case File: mode |= S_IFREG; break; case Directory: mode |= S_IFDIR; break; case SymLink: mode |= S_IFLNK; break; } write_uint(fh.h.external_file_attributes, mode << 16); write_uint(fh.h.offset_local_header, 0); /* DEFERRED (write_offset) */ write_ushort(fh.h.compression_method, 0); /* DEFERRED */ file_headers.insert(sFilepath, fh); file_aliases.insert(sFakename, file_aliases.count()); dirty_contents = true; return true; } // Process contents of zip archive entry (write-only). bool qtractorZipDevice::processEntry ( const QString& sFilename, FileHeader& fh ) { if (!(device->isOpen() || device->open(QIODevice::WriteOnly))) { status = qtractorZipFile::FileOpenError; return false; } if (!(device->openMode() & QIODevice::WriteOnly)) { status = qtractorZipFile::FileWriteError; return false; } QFile *pFile = NULL; const unsigned int mode = read_uint(fh.h.external_file_attributes) >> 16; if (S_ISREG(mode)) { pFile = new QFile(sFilename); if (!pFile->open(QIODevice::ReadOnly)) { status = qtractorZipFile::FileError; delete pFile; return false; } } unsigned int uncompressed_size = read_uint(fh.h.uncompressed_size); unsigned int compressed_size = 0; device->seek(write_offset); LocalFileHeader lfh; copy_header(lfh, fh.h); device->write((char *) &lfh, sizeof(LocalFileHeader)); device->write(fh.file_name); unsigned int crc_32 = ::crc32(0, 0, 0); if (pFile) { write_ushort(fh.h.compression_method, 8); /* DEFERRED */ unsigned int n_file_read = 0; unsigned int n_file_write = 0; z_stream zstream; memset(&zstream, 0, sizeof(zstream)); int zrc = ::deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY); while (zrc != Z_STREAM_END) { unsigned int n_buff_read = BUFF_SIZE; if (n_file_read + BUFF_SIZE > uncompressed_size) n_buff_read =uncompressed_size - n_file_read; int zflush = (n_buff_read < BUFF_SIZE ? Z_FINISH : Z_NO_FLUSH); pFile->read((char *) buff_read, n_buff_read); crc_32 = ::crc32(crc_32, (const uchar *) buff_read, (ulong) n_buff_read); n_file_read += n_buff_read; total_processed += n_buff_read; zstream.next_in = (uchar *) buff_read; zstream.avail_in = (uint) n_buff_read; do { unsigned int n_buff_write = BUFF_SIZE; zstream.next_out = (uchar *) buff_write; zstream.avail_out = (uint) n_buff_write; zrc = ::deflate(&zstream, zflush); if (zrc != Z_STREAM_ERROR) { n_buff_write -= zstream.avail_out; if (n_buff_write > 0) { device->write((const char *) buff_write, n_buff_write); n_file_write += n_buff_write; } } } while (zstream.avail_out == 0); #ifdef QTRACTOR_PROGRESS_BAR if (progress_bar) progress_bar->setValue( (100.0f * float(total_processed)) / float(total_uncompressed)); #endif } compressed_size = n_file_write; ::deflateEnd(&zstream); pFile->close(); delete pFile; } unsigned int last_offset = device->pos(); // Rewrite updated header... total_compressed += compressed_size; write_uint(fh.h.compressed_size, compressed_size); write_uint(fh.h.crc_32, crc_32); device->seek(write_offset); copy_header(lfh, fh.h); device->write((char *) &lfh, sizeof(LocalFileHeader)); write_uint(fh.h.offset_local_header, write_offset); /* DEFERRED */ // Done for next item so far... write_offset = last_offset; #ifdef CONFIG_DEBUG qDebug("qtractorZipDevice::deflate(%3.0f%%) %s.", (100.0f * float(total_processed)) / float(total_uncompressed), fh.file_name.data()); #endif return true; } // Process the full contents of the zip file (write-only). bool qtractorZipDevice::processAll (void) { #ifdef QTRACTOR_PROGRESS_BAR if (progress_bar) { progress_bar->setRange(0, 100); progress_bar->reset(); progress_bar->show(); } #endif int iProcessed = 0; QHash::Iterator iter = file_headers.begin(); const QHash::Iterator& iter_end = file_headers.end(); for ( ; iter != iter_end; ++iter) { if (!processEntry(iter.key(), iter.value())) break; ++iProcessed; } #ifdef QTRACTOR_PROGRESS_BAR if (progress_bar) progress_bar->hide(); #endif return (iProcessed == file_headers.count()); } //---------------------------------------------------------------------------- // qtractorZipFile -- Custom ZIP file archive class. // // Constructors. qtractorZipFile::qtractorZipFile ( const QString& sFilename, QIODevice::OpenMode mode ) { QFile *pFile = new QFile(sFilename); pFile->open(mode); qtractorZipFile::Status status; if (pFile->error() == QFile::NoError) status = NoError; else if (pFile->error() == QFile::ReadError) status = FileReadError; else if (pFile->error() == QFile::WriteError) status = FileWriteError; else if (pFile->error() == QFile::OpenError) status = FileOpenError; else if (pFile->error() == QFile::PermissionsError) status = FilePermissionsError; else status = FileError; m_pZip = new qtractorZipDevice(pFile, /*bOwnDevice=*/true); m_pZip->status = status; } qtractorZipFile::qtractorZipFile ( QIODevice *pDevice ) : m_pZip(new qtractorZipDevice(pDevice, /*bOwnDevice=*/false)) { Q_ASSERT(pDevice); } // Desctructor qtractorZipFile::~qtractorZipFile (void) { close(); delete m_pZip; } // Returns a status code indicating the first error met. qtractorZipFile::Status qtractorZipFile::status (void) const { return m_pZip->status; } // Returns true if the user can read the file; // otherwise returns false. bool qtractorZipFile::isReadable (void) const { return (m_pZip->status == NoError) && m_pZip->device->isReadable(); } // Returns true if the user can write the file; // otherwise returns false. bool qtractorZipFile::isWritable (void) const { return (m_pZip->status == NoError) && m_pZip->device->isWritable(); } // Returns true if the file exists; otherwise returns false. bool qtractorZipFile::exists (void) const { QFile *pFile = qobject_cast (m_pZip->device); return (pFile ? pFile->exists() : false); } // Extract file contents from the zip archive (read-only). bool qtractorZipFile::extractFile ( const QString& sFilename ) { m_pZip->scanFiles(); if (!m_pZip->file_headers.contains(sFilename)) return false; return m_pZip->extractEntry(sFilename, m_pZip->file_headers.value(sFilename)); } // Extracts the full contents of the zip archive (read-only). bool qtractorZipFile::extractAll (void) { return m_pZip->extractAll(); } // Returns the possible alias name avoiding file entry duplicates (write-only). QString qtractorZipFile::alias ( const QString& sFilename, const QString& sPrefix ) const { return m_pZip->alias(sFilename, sPrefix); } // Add a file in the zip archive (write-only). bool qtractorZipFile::addFile ( const QString& sFilename, const QString& sAlias ) { return m_pZip->addEntry(qtractorZipDevice::File, sFilename, sAlias); } // Add a directory in the zip archive (write-only). bool qtractorZipFile::addDirectory ( const QString& sDirectory ) { QString sFilename = sDirectory; if (!sFilename.endsWith('/')) sFilename.append('/'); return m_pZip->addEntry(qtractorZipDevice::Directory, sFilename); } // Process the full contents of the zip archive (write-only). bool qtractorZipFile::processAll (void) { return m_pZip->processAll(); } // Closes the zip file. void qtractorZipFile::close (void) { if (!(m_pZip->device->openMode() & QIODevice::WriteOnly)) { m_pZip->device->close(); return; } m_pZip->device->seek(m_pZip->write_offset); // Write new directory... QHash::ConstIterator iter = m_pZip->file_headers.constBegin(); const QHash::ConstIterator iter_end = m_pZip->file_headers.constEnd(); for ( ; iter != iter_end; ++iter) { const FileHeader& fh = iter.value(); m_pZip->device->write((const char *) &fh.h, sizeof(CentralFileHeader)); m_pZip->device->write(fh.file_name); m_pZip->device->write(fh.extra_field); m_pZip->device->write(fh.file_comment); } int dir_size = m_pZip->device->pos() - m_pZip->write_offset; // Write end of directory... EndOfDirectory eod; memset(&eod, 0, sizeof(EndOfDirectory)); write_uint(eod.signature, 0x06054b50); write_ushort(eod.num_dir_entries_this_disk, m_pZip->file_headers.size()); write_ushort(eod.num_dir_entries, m_pZip->file_headers.size()); write_uint(eod.directory_size, dir_size); write_uint(eod.dir_start_offset, m_pZip->write_offset); write_ushort(eod.comment_length, m_pZip->comment.length()); m_pZip->device->write((const char *) &eod, sizeof(EndOfDirectory)); m_pZip->device->write(m_pZip->comment); m_pZip->device->close(); } // Statistical accessors. unsigned int qtractorZipFile::totalUncompressed (void) const { return m_pZip->total_uncompressed; } unsigned int qtractorZipFile::totalCompressed (void) const { return m_pZip->total_compressed; } unsigned int qtractorZipFile::totalProcessed (void) const { return m_pZip->total_processed; } #endif // CONFIG_LIBZ // end of qtractorZipFile.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorAtomic.h0000644000175000001440000000012312166526620020416 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134670.76808 30 ctime=1381134670.768080109 qtractor-0.5.11/src/qtractorAtomic.h0000644000175000001440000001005212166526620017703 0ustar00rncbcusers00000000000000// qtractorAtomic.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorAtomic_h #define __qtractorAtomic_h #define HAVE_QATOMIC_H #if defined(HAVE_QATOMIC_H) # include #endif #if defined(__cplusplus) extern "C" { #endif #if defined(__GNUC__) #if defined(powerpc) || defined(__ppc__) static inline int ATOMIC_CAS1 ( volatile int *pAddr, int iOldValue, int iNewValue ) { register int result; asm volatile ( "# ATOMIC_CAS1 \n" " lwarx r0, 0, %1 \n" " cmpw r0, %2 \n" " bne- 1f \n" " sync \n" " stwcx. %3, 0, %1 \n" " bne- 1f \n" " li %0, 1 \n" " b 2f \n" "1: \n" " li %0, 0 \n" "2: \n" : "=r" (result) : "r" (pValue), "r" (iOldValue), "r" (iNewValue) : "r0" ); return result; } #elif defined(__i386__) || defined(__x86_64__) static inline int ATOMIC_CAS1 ( volatile int *pValue, int iOldValue, int iNewValue ) { register char result; asm volatile ( "# ATOMIC_CAS1 \n" "lock ; cmpxchgl %2, %3 \n" "sete %1 \n" : "=a" (iNewValue), "=qm" (result) : "r" (iNewValue), "m" (*pValue), "0" (iOldValue) : "memory" ); return result; } #else # error "qtractorAtomic.h: unsupported target compiler processor (GNUC)." #endif #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) static inline int ATOMIC_CAS1 ( volatile int *pValue, int iOldValue, int iNewValue ) { register char result; __asm { push ebx push esi mov esi, pValue mov eax, iOldValue mov ebx, iNewValue lock cmpxchg dword ptr [esi], ebx sete result pop esi pop ebx } return result; } #else # error "qtractorAtomic.h: unsupported target compiler processor (WIN32)." #endif #if defined(HAVE_QATOMIC_H) typedef QAtomicInt qtractorAtomic; #if QT_VERSION >= 0x050000 #define ATOMIC_GET(a) ((a)->load()) #define ATOMIC_SET(a,v) ((a)->store(v)) #else #define ATOMIC_GET(a) ((int) *(a)) #define ATOMIC_SET(a,v) (*(a) = (v)) #endif static inline int ATOMIC_CAS ( qtractorAtomic *pVal, int iOldValue, int iNewValue ) { return pVal->testAndSetOrdered(iOldValue, iNewValue); } #else typedef struct { volatile int value; } qtractorAtomic; #define ATOMIC_GET(a) ((a)->value) #define ATOMIC_SET(a,v) ((a)->value = (v)) static inline int ATOMIC_CAS ( qtractorAtomic *pVal, int iOldValue, int iNewValue ) { return ATOMIC_CAS1(&(pVal->value), iOldValue, iNewValue); } #endif // Strict test-and-set primite. static inline int ATOMIC_TAS ( qtractorAtomic *pVal ) { return ATOMIC_CAS(pVal, 0, 1); } // Strict test-and-add primitive. static inline int ATOMIC_ADD ( qtractorAtomic *pVal, int iAddValue ) { volatile int iOldValue, iNewValue; do { iOldValue = ATOMIC_GET(pVal); iNewValue = iOldValue + iAddValue; } while (!ATOMIC_CAS(pVal, iOldValue, iNewValue)); return iNewValue; } #define ATOMIC_INC(a) ATOMIC_ADD((a), (+1)) #define ATOMIC_DEC(a) ATOMIC_ADD((a), (-1)) // Special test-and-zero primitive (invented here:) static inline int ATOMIC_TAZ ( qtractorAtomic *pVal ) { volatile int iOldValue; do { iOldValue = ATOMIC_GET(pVal); } while (iOldValue && !ATOMIC_CAS(pVal, iOldValue, 0)); return iOldValue; } #if defined(__cplusplus) } #endif #endif // __qtractorAtomic_h // end of qtractorAtomic.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiSequence.h0000644000175000001440000000012312141244677021557 xustar000000000000000027 mtime=1367689663.484158 26 atime=1381134667.66208 30 ctime=1381134667.662080059 qtractor-0.5.11/src/qtractorMidiSequence.h0000644000175000001440000001147512141244677021056 0ustar00rncbcusers00000000000000// qtractorMidiSequence.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiSequence_h #define __qtractorMidiSequence_h #include "qtractorMidiEvent.h" #include #include // typedef unsigned long long uint64_t; #include //---------------------------------------------------------------------- // class qtractorMidiSequence -- The generic MIDI event sequence buffer. // class qtractorMidiSequence { public: // Constructor. qtractorMidiSequence(const QString& sName = QString(), unsigned short iChannel = 0, unsigned short iTicksPerBeat = 960); // Destructor. ~qtractorMidiSequence(); // Sequencer reset method. void clear(); // Sequence/track name accessors. void setName(const QString& sName) { m_sName = sName; } const QString& name() const { return m_sName; } // Sequence/track channel accessors. void setChannel(unsigned short iChannel) { m_iChannel = (iChannel & 0x0f); } unsigned short channel() const { return m_iChannel; } // Sequence/track bank accessors (optional). void setBank(int iBank) { m_iBank = iBank; } int bank() const { return m_iBank; } // Sequence/track prog accessors (optional). void setProg(int iProg) { m_iProg = iProg; } int prog() const { return m_iProg; } // Sequence/track resolution accessors. void setTicksPerBeat(unsigned short iTicksPerBeat) { m_iTicksPerBeat = iTicksPerBeat; } unsigned short ticksPerBeat() const { return m_iTicksPerBeat; } // Sequence time-offset parameter accessors. void setTimeOffset(unsigned long iTimeOffset) { m_iTimeOffset = iTimeOffset; } unsigned long timeOffset() const { return m_iTimeOffset; } // Sequence duration parameter accessors. void setTimeLength(unsigned long iTimeLength) { m_iTimeLength = iTimeLength; } unsigned long timeLength() const { return m_iTimeLength; } void setDuration(unsigned long iDuration) { m_duration = iDuration; } unsigned long duration() const { return m_duration; } // Statiscal helper accessors. void setNoteMin(unsigned char note) { if (m_noteMin > note || m_noteMin == 0) m_noteMin = note; } void setNoteMax(unsigned char note) { if (m_noteMax < note || m_noteMax == 0) m_noteMax = note; } unsigned char noteMin() const { return m_noteMin; } unsigned char noteMax() const { return m_noteMax; } // Event list accessor. const qtractorList& events() const { return m_events; } // Event list management methods. void addEvent (qtractorMidiEvent *pEvent); void insertEvent (qtractorMidiEvent *pEvent); void unlinkEvent (qtractorMidiEvent *pEvent); void removeEvent (qtractorMidiEvent *pEvent); // Adjust time resolutions (64bit). unsigned long timep(unsigned long iTime, unsigned short p) const { return uint64_t(iTime) * p / m_iTicksPerBeat; } unsigned long timeq(unsigned long iTime, unsigned short q) const { return uint64_t(iTime) * m_iTicksPerBeat / q; } // Replace events from another sequence in given range. void replaceEvents(qtractorMidiSequence *pSeq, unsigned long iTimeOffset = 0, unsigned long iTimeLength = 0); // Clopy all events from another sequence (raw-copy). void copyEvents(qtractorMidiSequence *pSeq); // Sequence closure method. void close(); // Typed hash table to track note-ons. typedef QMultiHash NoteMap; private: // Sequence/track properties. QString m_sName; unsigned short m_iChannel; unsigned short m_iTicksPerBeat; // Sequence time-offset/duration parameters. unsigned long m_iTimeOffset; unsigned long m_iTimeLength; // Sequence/track optional properties. int m_iBank; int m_iProg; // Statistical helper variables. unsigned char m_noteMin; unsigned char m_noteMax; unsigned long m_duration; // Sequence instance event list (all same MIDI channel). qtractorList m_events; // Local hash table to track note-ons. NoteMap m_notes; }; #endif // __qtractorMidiSequence_h // end of qtractorMidiSequence.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMmcEvent.cpp0000644000175000001440000000012312146231030021235 xustar000000000000000027 mtime=1368994328.053655 26 atime=1381134671.09408 30 ctime=1381134671.095080114 qtractor-0.5.11/src/qtractorMmcEvent.cpp0000644000175000001440000000676012146231030020535 0ustar00rncbcusers00000000000000// qtractorMmcEvent.cpp // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorMmcEvent.h" //---------------------------------------------------------------------- // qtractorMmcEvent - MMC custom event. // // Retrieve MMC time-code and standard frame position (SMPTE?). unsigned long qtractorMmcEvent::locate (void) const { unsigned long iLocate = 0; unsigned char *data = (unsigned char *) m_data.constData(); if (m_cmd == LOCATE && m_data.length() > 4 && data[0] == 0x01) { iLocate = (3600 * 30) * int(data[1] & 0x1f) // hh - hours [0..23] + ( 60 * 30) * int(data[2]) // mm - minutes [0..59] + ( 30) * int(data[3]) // ss - seconds [0..59] + int(data[4]); // ff - frames [0..29] } return iLocate; } // Retrieve MMC shuttle-speed and direction. float qtractorMmcEvent::shuttle (void) const { float fShuttle = 0.0f; unsigned char *data = (unsigned char *) m_data.constData(); if (m_cmd == SHUTTLE && m_data.length() > 2) { unsigned char sh = data[0]; unsigned char sm = data[1]; unsigned char sl = data[2]; unsigned int n = (sh & 0x38); unsigned int p = ((sh & 0x07) << n) | (sm >> (7 - n)); unsigned int q = ((sm << n) << 7) | sl; fShuttle = float(p) + float(q) / (1 << (14 - n)); if (sh & 0x40) fShuttle = -(fShuttle); } return fShuttle; } // Retrieve MMC step and direction. int qtractorMmcEvent::step (void) const { int iStep = 0; unsigned char *data = (unsigned char *) m_data.constData(); if (m_cmd == STEP && m_data.length() > 0) { iStep = (data[0] & 0x3f); if (data[0] & 0x40) iStep = -(iStep); } return iStep; } // Retrieve MMC masked-write sub-command data. qtractorMmcEvent::SubCommand qtractorMmcEvent::scmd (void) const { SubCommand scmd = TRACK_NONE; unsigned char *data = (unsigned char *) m_data.constData(); if (m_cmd == MASKED_WRITE && m_data.length() > 3) scmd = SubCommand(data[0]); return scmd; } int qtractorMmcEvent::track (void) const { int iTrack = 0; unsigned char *data = (unsigned char *) m_data.constData(); if (m_cmd == MASKED_WRITE && m_data.length() > 3) { iTrack = (data[1] > 0 ? (data[1] * 7) : 0) - 5; for (int i = 0; i < 7; ++i) { int iMask = (1 << i); if (data[2] & iMask) break; ++iTrack; } } return iTrack; } bool qtractorMmcEvent::isOn (void) const { bool bOn = false; unsigned char *data = (unsigned char *) m_data.constData(); if (m_cmd == MASKED_WRITE && m_data.length() > 3) { for (int i = 0; i < 7; ++i) { int iMask = (1 << i); if (data[2] & iMask) { bOn = (data[3] & iMask); break; } } } return bOn; } // end of qtractorMmcEvent.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTracks.cpp0000644000175000001440000000012312221411230020742 xustar000000000000000027 mtime=1380323992.023236 26 atime=1381134667.54808 30 ctime=1381134667.549080058 qtractor-0.5.11/src/qtractorTracks.cpp0000644000175000001440000024030712221411230020237 0ustar00rncbcusers00000000000000// qtractorTracks.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorTracks.h" #include "qtractorTrackView.h" #include "qtractorTrackList.h" #include "qtractorTrackTime.h" #include "qtractorSession.h" #include "qtractorSessionCursor.h" #include "qtractorSessionCommand.h" #include "qtractorTrackCommand.h" #include "qtractorClipCommand.h" #include "qtractorCurveCommand.h" #include "qtractorMidiEditCommand.h" #include "qtractorTimeScaleCommand.h" #include "qtractorTrackButton.h" #include "qtractorAudioEngine.h" #include "qtractorAudioBuffer.h" #include "qtractorAudioClip.h" #include "qtractorMidiEngine.h" #include "qtractorMidiClip.h" #include "qtractorClipSelect.h" #include "qtractorOptions.h" #include "qtractorMainForm.h" #include "qtractorTrackForm.h" #include "qtractorClipForm.h" #include "qtractorPasteRepeatForm.h" #include "qtractorTempoAdjustForm.h" #include "qtractorEditRangeForm.h" #include "qtractorMidiEditorForm.h" #include "qtractorMidiToolsForm.h" #include "qtractorMidiEditSelect.h" #include "qtractorFileList.h" #include #include #include #include #include #include #include #include //---------------------------------------------------------------------------- // qtractorTracks -- The main session track listview widget. // Constructor. qtractorTracks::qtractorTracks ( QWidget *pParent ) : QSplitter(Qt::Horizontal, pParent) { // Surely a name is crucial (e.g. for storing geometry settings) QSplitter::setObjectName("qtractorTracks"); // Create child widgets... m_pTrackList = new qtractorTrackList(this, this); QWidget *pVBox = new QWidget(this); m_pTrackTime = new qtractorTrackTime(this, pVBox); m_pTrackView = new qtractorTrackView(this, pVBox); // Zoom mode flag. m_iZoomMode = ZoomAll; // Create child box layouts... QVBoxLayout *pVBoxLayout = new QVBoxLayout(pVBox); pVBoxLayout->setMargin(0); pVBoxLayout->setSpacing(0); pVBoxLayout->addWidget(m_pTrackTime); pVBoxLayout->addWidget(m_pTrackView); pVBox->setLayout(pVBoxLayout); // QSplitter::setOpaqueResize(false); QSplitter::setStretchFactor(QSplitter::indexOf(m_pTrackList), 0); QSplitter::setHandleWidth(2); QSplitter::setWindowTitle(tr("Tracks")); QSplitter::setWindowIcon(QIcon(":/images/qtractorTracks.png")); // Get previously saved splitter sizes, // (with some fair default...) qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { QList sizes; sizes.append(160); sizes.append(480); pOptions->loadSplitterSizes(this, sizes); } // Early track list stabilization. m_pTrackTime->setFixedHeight( (m_pTrackList->header())->sizeHint().height()); // To have all views in positional sync. QObject::connect(m_pTrackList, SIGNAL(contentsMoving(int,int)), m_pTrackView, SLOT(contentsYMovingSlot(int,int))); QObject::connect(m_pTrackView, SIGNAL(contentsMoving(int,int)), m_pTrackTime, SLOT(contentsXMovingSlot(int,int))); QObject::connect(m_pTrackView, SIGNAL(contentsMoving(int,int)), m_pTrackList, SLOT(contentsYMovingSlot(int,int))); } // Destructor. qtractorTracks::~qtractorTracks (void) { // Save splitter sizes... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) pOptions->saveSplitterSizes(this); } // Child widgets accessors. qtractorTrackList *qtractorTracks::trackList (void) const { return m_pTrackList; } qtractorTrackTime *qtractorTracks::trackTime (void) const { return m_pTrackTime; } qtractorTrackView *qtractorTracks::trackView (void) const { return m_pTrackView; } // Horizontal zoom factor. void qtractorTracks::horizontalZoomStep ( int iZoomStep ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; int iHorizontalZoom = pSession->horizontalZoom() + iZoomStep; if (iHorizontalZoom < ZoomMin) iHorizontalZoom = ZoomMin; else if (iHorizontalZoom > ZoomMax) iHorizontalZoom = ZoomMax; if (iHorizontalZoom == pSession->horizontalZoom()) return; // Fix the ssession time scale zoom determinant. pSession->setHorizontalZoom(iHorizontalZoom); pSession->updateTimeScale(); pSession->updateSession(); } // Vertical zoom factor. void qtractorTracks::verticalZoomStep ( int iZoomStep ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; int iVerticalZoom = pSession->verticalZoom() + iZoomStep; if (iVerticalZoom < ZoomMin) iVerticalZoom = ZoomMin; else if (iVerticalZoom > ZoomMax) iVerticalZoom = ZoomMax; if (iVerticalZoom == pSession->verticalZoom()) return; // Fix the session vertical view zoom. pSession->setVerticalZoom(iVerticalZoom); } // Zoom (view) mode. void qtractorTracks::setZoomMode ( int iZoomMode ) { m_iZoomMode = iZoomMode; } int qtractorTracks::zoomMode (void) const { return m_iZoomMode; } // Zoom view actuators. void qtractorTracks::zoomIn (void) { ZoomCenter zc; zoomCenterPre(zc); if (m_iZoomMode & ZoomHorizontal) horizontalZoomStep(+ ZoomStep); if (m_iZoomMode & ZoomVertical) verticalZoomStep(+ ZoomStep); zoomCenterPost(zc); } void qtractorTracks::zoomOut (void) { ZoomCenter zc; zoomCenterPre(zc); if (m_iZoomMode & ZoomHorizontal) horizontalZoomStep(- ZoomStep); if (m_iZoomMode & ZoomVertical) verticalZoomStep(- ZoomStep); zoomCenterPost(zc); } void qtractorTracks::zoomReset (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; ZoomCenter zc; zoomCenterPre(zc); if (m_iZoomMode & ZoomHorizontal) horizontalZoomStep(ZoomBase - pSession->horizontalZoom()); if (m_iZoomMode & ZoomVertical) verticalZoomStep(ZoomBase - pSession->verticalZoom()); zoomCenterPost(zc); } void qtractorTracks::horizontalZoomInSlot (void) { ZoomCenter zc; zoomCenterPre(zc); horizontalZoomStep(+ ZoomStep); zoomCenterPost(zc); } void qtractorTracks::horizontalZoomOutSlot (void) { ZoomCenter zc; zoomCenterPre(zc); horizontalZoomStep(- ZoomStep); zoomCenterPost(zc); } void qtractorTracks::verticalZoomInSlot (void) { ZoomCenter zc; zoomCenterPre(zc); verticalZoomStep(+ ZoomStep); zoomCenterPost(zc); } void qtractorTracks::verticalZoomOutSlot (void) { ZoomCenter zc; zoomCenterPre(zc); verticalZoomStep(- ZoomStep); zoomCenterPost(zc); } void qtractorTracks::viewZoomResetSlot (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; ZoomCenter zc; zoomCenterPre(zc); // All zoom base are belong to us :) verticalZoomStep(ZoomBase - pSession->verticalZoom()); horizontalZoomStep(ZoomBase - pSession->horizontalZoom()); zoomCenterPost(zc); } // Zoom centering prepare method. // (usually before zoom change) void qtractorTracks::zoomCenterPre ( ZoomCenter& zc ) const { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; QWidget *pViewport = m_pTrackView->viewport(); const QRect& rect = pViewport->rect(); const QPoint& pos = pViewport->mapFromGlobal(QCursor::pos()); if (rect.contains(pos)) { zc.x = pos.x(); zc.y = 0; // pos.y(); } else { #if 0 zc.x = 0; zc.y = 0; #else zc.x = (rect.width() >> 1); zc.y = 0; // (rect.height() >> 1); #endif } int cx = m_pTrackView->contentsX(); zc.frame = pSession->frameFromPixel(cx + zc.x); } // Zoom centering post methods. // (usually after zoom change) void qtractorTracks::zoomCenterPost ( const ZoomCenter& zc ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; int cx = pSession->pixelFromFrame(zc.frame); int cy = m_pTrackView->contentsY(); if (cx > zc.x) cx -= zc.x; else cx = 0; if (cy > zc.y) cy -= zc.y; else cy = 0; // Update the dependant views... m_pTrackList->updateContentsHeight(); m_pTrackView->updateContentsWidth(); m_pTrackView->setContentsPos(cx, cy); m_pTrackView->updateContents(); // Make its due... selectionChangeNotify(); } // Update/sync integral contents from session tracks. void qtractorTracks::updateContents ( bool bRefresh ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; #ifdef CONFIG_DEBUG_0 qDebug("qtractorTracks::updateContents(%d)\n", int(bRefresh)); #endif // Update/sync from session tracks. int iRefresh = 0; if (bRefresh) ++iRefresh; int iTrack = 0; qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack) { // Check if item is already on list if (m_pTrackList->trackRow(pTrack) < 0) { m_pTrackList->insertTrack(iTrack, pTrack); ++iRefresh; } pTrack = pTrack->next(); ++iTrack; } // Update dependant views. if (iRefresh > 0) { m_pTrackView->updateContentsWidth(); m_pTrackList->updateContentsHeight(); // m_pTrackView->setFocus(); } } // Retrieves current (selected) track reference. qtractorTrack *qtractorTracks::currentTrack (void) const { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return NULL; qtractorTrack *pTrack = m_pTrackList->currentTrack(); if (pTrack == NULL) { qtractorClip *pClip = m_pTrackView->currentClip(); if (pClip) pTrack = pClip->track(); } return pTrack; } // Retrieves current selected clip reference. qtractorClip *qtractorTracks::currentClip (void) const { return m_pTrackView->currentClip(); } // Edit/create a brand new clip. bool qtractorTracks::newClip (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return false; // Create on current track, or take the first... qtractorTrack *pTrack = currentTrack(); if (pTrack == NULL) pTrack = pSession->tracks().first(); if (pTrack == NULL) return false; // Create the clip prototype... qtractorClip *pClip = NULL; switch (pTrack->trackType()) { case qtractorTrack::Audio: pClip = new qtractorAudioClip(pTrack); break; case qtractorTrack::Midi: pClip = new qtractorMidiClip(pTrack); break; case qtractorTrack::None: default: break; } // Correct so far? if (pClip == NULL) return false; // Set initial default clip parameters... const unsigned long iClipStart = pSession->editHead(); pClip->setClipStart(iClipStart); m_pTrackView->ensureVisibleFrame(iClipStart); // Special for MIDI clips, which already have it's own editor, // we'll add and start a blank one right-away... if (pTrack->trackType() == qtractorTrack::Midi) { // Set initial clip length... if (pSession->editTail() > pSession->editHead()) { pClip->setClipLength(pSession->editTail() - pSession->editHead()); } else { pClip->setClipLength(pSession->frameFromTick( pSession->ticksPerBeat() * pSession->beatsPerBar())); } // Proceed to setup the MDII clip properly... qtractorMidiClip *pMidiClip = static_cast (pClip); if (pMidiClip) { // Create a clip filename from scratch... const QString& sFilename = pSession->createFilePath(pTrack->trackName(), "mid"); // Create the SMF for good... if (pMidiClip->createMidiFile(sFilename)) { // Add that to regular files... pMainForm->addMidiFile(pClip->filename()); // Insert the clip right away... qtractorClipCommand *pClipCommand = new qtractorClipCommand(tr("new clip")); pClipCommand->addClip(pClip, pTrack); pSession->execute(pClipCommand); // Just start the MIDI editor on it... return pClip->startEditor(pMainForm); } } } // Then ask user to refine clip properties... qtractorClipForm clipForm(pMainForm); clipForm.setClip(pClip, true); if (!clipForm.exec()) { delete pClip; return false; } // Done. return true; } // Edit given(current) clip. bool qtractorTracks::editClip ( qtractorClip *pClip ) { if (pClip == NULL) pClip = m_pTrackView->currentClip(); if (pClip == NULL) return false; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return false; // All else hasn't fail. return pClip->startEditor(pMainForm); } // Unlink given(current) clip. bool qtractorTracks::unlinkClip ( qtractorClip *pClip ) { if (pClip == NULL) pClip = m_pTrackView->currentClip(); if (pClip == NULL) return false; qtractorMidiClip *pMidiClip = static_cast (pClip); if (pMidiClip == NULL) return false; if (!pMidiClip->isHashLinked()) return false; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // Have a new filename revision... const QString& sFilename = pMidiClip->createFilePathRevision(true); // Save/replace the clip track... qtractorMidiFile::saveCopyFile(sFilename, pMidiClip->filename(), pMidiClip->trackChannel(), pMidiClip->format(), pMidiClip->sequence(), pSession->timeScale(), pSession->tickFromFrame(pMidiClip->clipStart())); // Now, we avoid the linked/ref-counted instances... pSession->files()->removeClipItem(qtractorFileList::Midi, pMidiClip); pMidiClip->setFilename(sFilename); pMidiClip->setDirty(false); pMidiClip->unlinkHashData(); pMidiClip->updateEditor(true); pSession->files()->addClipItem(qtractorFileList::Midi, pMidiClip, true); // HACK: This operation is so important that // it surely deserves being in the front page... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->addMidiFile(sFilename); return true; } // Split given(current) clip. bool qtractorTracks::splitClip ( qtractorClip *pClip ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; const unsigned long iPlayHead = pSession->playHead(); if (pClip == NULL) pClip = m_pTrackView->currentClip(); if (pClip == NULL) { qtractorTrack *pTrack = m_pTrackList->currentTrack(); if (pTrack) { pClip = pTrack->clips().first(); while (pClip && iPlayHead > pClip->clipStart() + pClip->clipLength()) pClip = pClip->next(); } } if (pClip == NULL) return false; if (!pClip->queryEditor()) return false; const unsigned long iClipStart = pClip->clipStart(); const unsigned long iClipEnd = iClipStart + pClip->clipLength(); if (iClipStart >= iPlayHead || iPlayHead >= iClipEnd) return false; m_pTrackView->ensureVisibleFrame(iPlayHead); qtractorClipCommand *pClipCommand = new qtractorClipCommand(tr("split clip")); // Shorten old right... const unsigned long iClipOffset = pClip->clipOffset(); pClipCommand->resizeClip(pClip, iClipStart, iClipOffset, iPlayHead - iClipStart); // Add left clone... qtractorClip *pNewClip = m_pTrackView->cloneClip(pClip); if (pNewClip) { pNewClip->setClipStart(iPlayHead); pNewClip->setClipOffset(iClipOffset + iPlayHead - iClipStart); pNewClip->setClipLength(iClipEnd - iPlayHead); pNewClip->setFadeOutLength(pClip->fadeOutLength()); pClipCommand->addClip(pNewClip, pNewClip->track()); } // That's it... return pSession->execute(pClipCommand); } // Audio clip normalize callback. struct audioClipNormalizeData { // Ctor. audioClipNormalizeData(unsigned short iChannels) : count(0), channels(iChannels), max(0.0f) {}; // Members. unsigned int count; unsigned short channels; float max; }; static void audioClipNormalize ( float **ppFrames, unsigned int iFrames, void *pvArg ) { audioClipNormalizeData *pData = static_cast (pvArg); for (unsigned short i = 0; i < pData->channels; ++i) { float *pFrames = ppFrames[i]; for (unsigned int n = 0; n < iFrames; ++n) { float fSample = *pFrames++; if (fSample < 0.0f) // Take absolute value... fSample = -(fSample); if (pData->max < fSample) pData->max = fSample; } } if (++(pData->count) > 100) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) { QProgressBar *pProgressBar = pMainForm->progressBar(); pProgressBar->setValue(pProgressBar->value() + iFrames); } qtractorSession::stabilize(); pData->count = 0; } } // MIDI clip normalize callback. static void midiClipNormalize ( qtractorMidiSequence *pSeq, void *pvArg ) { unsigned char *pMax = (unsigned char *) (pvArg); for (qtractorMidiEvent *pEvent = pSeq->events().first(); pEvent; pEvent = pEvent->next()) { if (pEvent->type() == qtractorMidiEvent::NOTEON && *pMax < pEvent->velocity()) { *pMax = pEvent->velocity(); } } } // Normalize given(current) clip. bool qtractorTracks::normalizeClip ( qtractorClip *pClip ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // Make it as an undoable command... qtractorClipCommand *pClipCommand = new qtractorClipCommand(tr("clip normalize")); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // Multiple clip selection... if (isClipSelected()) { qtractorClipSelect *pClipSelect = m_pTrackView->clipSelect(); const qtractorClipSelect::ItemList& items = pClipSelect->items(); qtractorClipSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorClipSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { // Make sure it's legal selection... pClip = iter.key(); if (pClip->track() && pClip->isClipSelected()) normalizeClipCommand(pClipCommand, pClip); } } // Single, current clip instead? else normalizeClipCommand(pClipCommand, pClip); QApplication::restoreOverrideCursor(); // Check if valid... if (pClipCommand->isEmpty()) { delete pClipCommand; return false; } // That's it... return pSession->execute(pClipCommand); } bool qtractorTracks::normalizeClipCommand ( qtractorClipCommand *pClipCommand, qtractorClip *pClip ) { if (pClip == NULL) pClip = m_pTrackView->currentClip(); if (pClip == NULL) return false; qtractorTrack *pTrack = pClip->track(); if (pTrack == NULL) return false; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); unsigned long iOffset = 0; unsigned long iLength = pClip->clipLength(); if (pClip->isClipSelected()) { iOffset = pClip->clipSelectStart() - pClip->clipStart(); iLength = pClip->clipSelectEnd() - pClip->clipSelectStart(); } // Default non-normalized setting... float fGain = pClip->clipGain(); if (pTrack->trackType() == qtractorTrack::Audio) { // Normalize audio clip... qtractorAudioClip *pAudioClip = static_cast (pClip); if (pAudioClip == NULL) return false; qtractorAudioBus *pAudioBus = static_cast (pTrack->outputBus()); if (pAudioBus == NULL) return false; QProgressBar *pProgressBar = NULL; if (pMainForm) pProgressBar = pMainForm->progressBar(); if (pProgressBar) { pProgressBar->setRange(0, iLength / 100); pProgressBar->reset(); pProgressBar->show(); } audioClipNormalizeData data(pAudioBus->channels()); pAudioClip->clipExport(audioClipNormalize, &data, iOffset, iLength); if (data.max > 0.01f && data.max < 1.1f) fGain /= data.max; if (pProgressBar) pProgressBar->hide(); } else if (pTrack->trackType() == qtractorTrack::Midi) { // Normalize MIDI clip... qtractorMidiClip *pMidiClip = static_cast (pClip); if (pMidiClip == NULL) return false; unsigned char max = 0; pMidiClip->clipExport(midiClipNormalize, &max, iOffset, iLength); if (max > 0x0c && max < 0x7f) fGain *= (127.0f / float(max)); } // Make it as an undoable command... pClipCommand->gainClip(pClip, fGain); // That's it... return true; } // Execute tool on a given(current) MIDI clip. bool qtractorTracks::executeClipTool ( int iTool, qtractorClip *pClip ) { qtractorMidiToolsForm toolsForm(this); toolsForm.setToolIndex(iTool); if (!toolsForm.exec()) return false; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // Make it as an undoable named command... QString sTool; switch (iTool) { case 0: sTool = tr("quantize"); break; case 1: sTool = tr("transpose"); break; case 2: sTool = tr("normalize"); break; case 3: sTool = tr("randomize"); break; case 4: sTool = tr("resize"); break; case 5: sTool = tr("rescale"); break; case 6: sTool = tr("timeshift"); break; } qtractorMidiClipCommand *pMidiClipCommand = new qtractorMidiClipCommand(tr("clip tool %1").arg(sTool)); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // Multiple clip selection... if (isClipSelected()) { qtractorClipSelect *pClipSelect = m_pTrackView->clipSelect(); const qtractorClipSelect::ItemList& items = pClipSelect->items(); qtractorClipSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorClipSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { // Make sure it's legal selection... qtractorClip *pClip = iter.key(); if (pClip->track() && pClip->isClipSelected()) executeClipToolCommand(pMidiClipCommand, pClip, &toolsForm); } } // Single, current clip instead? else executeClipToolCommand(pMidiClipCommand, pClip, &toolsForm); QApplication::restoreOverrideCursor(); // Check if valid... if (pMidiClipCommand->isEmpty()) { delete pMidiClipCommand; return false; } // That's it... return pSession->execute(pMidiClipCommand); } bool qtractorTracks::executeClipToolCommand ( qtractorMidiClipCommand *pMidiClipCommand, qtractorClip *pClip, qtractorMidiToolsForm *pToolsForm ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; if (pClip == NULL) pClip = m_pTrackView->currentClip(); if (pClip == NULL) return false; qtractorTrack *pTrack = pClip->track(); if (pTrack == NULL) return false; if (pTrack->trackType() != qtractorTrack::Midi) return false; qtractorMidiClip *pMidiClip = static_cast (pClip); if (pMidiClip == NULL) return false; unsigned long iOffset = 0; unsigned long iLength = pClip->clipLength(); if (pClip->isClipSelected()) { iOffset = pClip->clipSelectStart() - pClip->clipStart(); iLength = pClip->clipSelectEnd() - pClip->clipSelectStart(); } qtractorMidiSequence *pSeq = pMidiClip->sequence(); const unsigned long iTimeOffset = pSeq->timeOffset(); qtractorTimeScale::Cursor cursor(pSession->timeScale()); qtractorTimeScale::Node *pNode = cursor.seekFrame(pClip->clipStart()); const unsigned long t0 = pNode->tickFromFrame(pClip->clipStart()); unsigned long f1 = pClip->clipStart() + pClip->clipOffset() + iOffset; pNode = cursor.seekFrame(f1); const unsigned long t1 = pNode->tickFromFrame(f1); unsigned long iTimeStart = t1 - t0; iTimeStart = (iTimeStart > iTimeOffset ? iTimeStart - iTimeOffset : 0); pNode = cursor.seekFrame(f1 += iLength); const unsigned long iTimeEnd = iTimeStart + pNode->tickFromFrame(f1) - t1; // Emulate an user-made selection... qtractorMidiEditSelect select; const QRect rect; // Dummy event rectangle. for (qtractorMidiEvent *pEvent = pSeq->events().first(); pEvent; pEvent = pEvent->next()) { const unsigned long iTime = pEvent->time(); if (iTime >= iTimeStart && iTime < iTimeEnd) { select.addItem(pEvent, rect, rect); } } // Add new edit command from tool... pMidiClipCommand->addEditCommand( pToolsForm->editCommand(pMidiClip, &select, pSession->tickFromFrame(pClip->clipStart()))); // Must be brand new revision... pMidiClip->setRevision(0); // That's it... return true; } // Import (audio) clip(s) into current track... bool qtractorTracks::importClips ( QStringList files, unsigned long iClipStart ) { // Have we some? if (files.isEmpty()) return false; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // Create on current track, or take the first... qtractorTrack *pTrack = currentTrack(); if (pTrack == NULL) pTrack = pSession->tracks().first(); if (pTrack == NULL) // || pTrack->trackType() != qtractorTrack::Audio) return addAudioTracks(files, iClipStart); // To log this import into session description. QString sDescription = pSession->description().trimmed(); if (!sDescription.isEmpty()) sDescription += '\n'; qtractorClipCommand *pImportClipCommand = new qtractorClipCommand(tr("clip import")); // For each one of those files... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); QStringListIterator iter(files); while (iter.hasNext()) { // This is one of the selected filenames.... const QString& sPath = iter.next(); switch (pTrack->trackType()) { case qtractorTrack::Audio: { // Add the audio clip at once... qtractorAudioClip *pAudioClip = new qtractorAudioClip(pTrack); pAudioClip->setFilename(sPath); pAudioClip->setClipStart(iClipStart); // Redundant but necessary for multi-clip // concatenation, as we only know the actual // audio clip length after opening it... if (iter.hasNext()) { pAudioClip->open(); iClipStart += pAudioClip->clipLength(); } // Will add the new clip into session on command execute... pImportClipCommand->addClip(pAudioClip, pTrack); // Don't forget to add this one to local repository. if (pMainForm) { pMainForm->addAudioFile(sPath); // Log this successful import operation... sDescription += tr("Audio file import \"%1\" on %2 %3.\n") .arg(QFileInfo(sPath).fileName()) .arg(QDate::currentDate().toString("MMM dd yyyy")) .arg(QTime::currentTime().toString("hh:mm:ss")); pMainForm->appendMessages( tr("Audio file import: \"%1\".").arg(sPath)); } break; } case qtractorTrack::Midi: { // We'll be careful and pre-open the SMF header here... qtractorMidiFile file; if (file.open(sPath)) { // Depending of SMF format... int iTrackChannel = pTrack->midiChannel(); if (file.format() == 1) ++iTrackChannel; // Add the MIDI clip at once... qtractorMidiClip *pMidiClip = new qtractorMidiClip(pTrack); pMidiClip->setFilename(sPath); pMidiClip->setTrackChannel(iTrackChannel); pMidiClip->setClipStart(iClipStart); // Redundant but necessary for multi-clip // concatenation, as we only know the actual // MIDI clip length after opening it... if (iter.hasNext()) { pMidiClip->open(); iClipStart += pMidiClip->clipLength(); } // Will add the new clip into session on command execute... pImportClipCommand->addClip(pMidiClip, pTrack); // Don't forget to add this one to local repository. if (pMainForm) { pMainForm->addMidiFile(sPath); // Log this successful import operation... sDescription += tr("MIDI file import \"%1\"" " track-channel %2 on %3 %4.\n") .arg(QFileInfo(sPath).fileName()).arg(iTrackChannel) .arg(QDate::currentDate().toString("MMM dd yyyy")) .arg(QTime::currentTime().toString("hh:mm:ss")); pMainForm->appendMessages( tr("MIDI file import: \"%1\", track-channel: %2.") .arg(sPath).arg(iTrackChannel)); } } break; } default: break; } } // Log to session (undoable by import-track command)... pSession->setDescription(sDescription); // Done. return pSession->execute(pImportClipCommand); } // Export selected clips. bool qtractorTracks::exportClips (void) { return mergeExportClips(NULL); } // Merge selected clips. bool qtractorTracks::mergeClips (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // Make it as an undoable command... qtractorClipCommand *pClipCommand = new qtractorClipCommand(tr("clip merge")); const bool bResult = mergeExportClips(pClipCommand); // Have we failed the command prospect? if (!bResult || pClipCommand->isEmpty()) { delete pClipCommand; return false; } return pSession->execute(pClipCommand); } // Merge/export selected clips. bool qtractorTracks::mergeExportClips ( qtractorClipCommand *pClipCommand ) { // Multiple clip selection: // - make sure we have at least 2 clips to merge... qtractorClipSelect *pClipSelect = m_pTrackView->clipSelect(); if (pClipSelect->items().count() < 1) return false; // Should be one single track... qtractorTrack *pTrack = pClipSelect->singleTrack(); if (pTrack == NULL) return false; // Dispatch to specialized method... bool bResult = false; switch (pTrack->trackType()) { case qtractorTrack::Audio: bResult = mergeExportAudioClips(pClipCommand); break; case qtractorTrack::Midi: bResult = mergeExportMidiClips(pClipCommand); break; case qtractorTrack::None: default: break; } // Done most. return bResult; } // Audio clip buffer merge/export item. struct audioClipBufferItem { // Constructor. audioClipBufferItem(qtractorClip *pClip, qtractorAudioBufferThread *pSyncThread, unsigned short iChannels, unsigned int iSampleRate) : clip(static_cast (pClip)) { buff = new qtractorAudioBuffer(pSyncThread, iChannels, iSampleRate); buff->setOffset(clip->clipOffset()); buff->setLength(clip->clipLength()); buff->setTimeStretch(clip->timeStretch()); buff->setPitchShift(clip->pitchShift()); buff->open(clip->filename()); buff->syncExport(); } // Destructor. ~audioClipBufferItem() { if (buff) delete buff; } // Members. qtractorAudioClip *clip; qtractorAudioBuffer *buff; }; // Merge/export selected(audio) clips. bool qtractorTracks::mergeExportAudioClips ( qtractorClipCommand *pClipCommand ) { // Should be one single MIDI track... qtractorClipSelect *pClipSelect = m_pTrackView->clipSelect(); qtractorTrack *pTrack = pClipSelect->singleTrack(); if (pTrack == NULL) return false; if (pTrack->trackType() != qtractorTrack::Audio) return false; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; qtractorAudioBus *pAudioBus = static_cast (pTrack->outputBus()); if (pAudioBus == NULL) return false; const QString& sExt = qtractorAudioFileFactory::defaultExt(); const QString& sTitle = tr("Merge/Export Audio Clip") + " - " QTRACTOR_TITLE; const QString& sFilter = tr("Audio files (*.%1)").arg(sExt); #if 0//QT_VERSION < 0x040400 // Ask for the filename to save... QString sFilename = QFileDialog::getSaveFileName(this, sTitle, pSession->createFilePath(pTrack->trackName(), 0, sExt), sFilter); #else // Construct save-file dialog... QFileDialog fileDialog(this, sTitle, pSession->createFilePath(pTrack->trackName(), sExt), sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptSave); fileDialog.setFileMode(QFileDialog::AnyFile); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(pOptions->sAudioDir)); fileDialog.setSidebarUrls(urls); } // Show dialog... if (!fileDialog.exec()) return false; QString sFilename = fileDialog.selectedFiles().first(); #endif if (sFilename.isEmpty()) return false; if (QFileInfo(sFilename).suffix().isEmpty()) sFilename += '.' + sExt; // Should take sometime... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); qtractorAudioFile *pAudioFile = qtractorAudioFileFactory::createAudioFile(sFilename, pAudioBus->channels(), pSession->sampleRate()); if (pAudioFile == NULL) { QApplication::restoreOverrideCursor(); return false; } // Open the file for writing... if (!pAudioFile->open(sFilename, qtractorAudioFile::Write)) { QApplication::restoreOverrideCursor(); delete pAudioFile; return false; } // Start logging... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) { pMainForm->appendMessages( tr("Audio clip merge/export: \"%1\" started...") .arg(sFilename)); } // Multiple clip selection... const qtractorClipSelect::ItemList& items = pClipSelect->items(); qtractorClipSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorClipSelect::ItemList::ConstIterator& iter_end = items.constEnd(); const unsigned short iChannels = pAudioBus->channels(); const unsigned int iSampleRate = pSession->sampleRate(); // Multi-selection extents (in frames)... QList list; unsigned long iSelectStart = pSession->sessionEnd(); unsigned long iSelectEnd = pSession->sessionStart(); for ( ; iter != iter_end; ++iter) { qtractorClip *pClip = iter.key(); qtractorTrack *pTrack = pClip->track(); // Make sure it's a legal selection... if (pTrack && pClip->isClipSelected()) { qtractorAudioBufferThread *pSyncThread = pTrack->syncThread(); if (iSelectStart > pClip->clipSelectStart()) iSelectStart = pClip->clipSelectStart(); if (iSelectEnd < pClip->clipSelectEnd()) iSelectEnd = pClip->clipSelectEnd(); list.append(new audioClipBufferItem( pClip, pSyncThread, iChannels, iSampleRate)); } } // A progress indication might be friendly... QProgressBar *pProgressBar = NULL; if (pMainForm) pProgressBar = pMainForm->progressBar(); if (pProgressBar) { pProgressBar->setRange(0, (iSelectEnd - iSelectStart) / 100); pProgressBar->reset(); pProgressBar->show(); } // Allocate merge audio scratch buffer... const unsigned int iBufferSize = pSession->audioEngine()->bufferSize(); unsigned short i; float **ppFrames = new float * [iChannels]; for (i = 0; i < iChannels; ++i) ppFrames[i] = new float[iBufferSize]; // Setup clip buffers... QListIterator it(list); while (it.hasNext()) { audioClipBufferItem *pItem = it.next(); qtractorAudioClip *pClip = pItem->clip; qtractorAudioBuffer *pBuff = pItem->buff; // Almost similar to qtractorAudioClip::process(0)... const unsigned long iClipStart = pClip->clipStart(); const unsigned long iClipEnd = iClipStart + pClip->clipLength(); unsigned long iOffset = 0; if (iSelectStart > iClipStart && iSelectStart < iClipEnd) iOffset = iSelectStart - iClipStart; // Make it initially filled... pBuff->seek(iOffset); // pBuff->syncExport(); } // Loop-merge audio clips... unsigned long iFrameStart = iSelectStart; unsigned long iFrameEnd = iFrameStart + iBufferSize; int count = 0; // Loop until EOF... while (iFrameStart < iSelectEnd && iFrameEnd > iSelectStart) { // Zero-silence on scratch buffers... for (i = 0; i < iChannels; ++i) ::memset(ppFrames[i], 0, iBufferSize * sizeof(float)); // Merge clips in window... it.toFront(); while (it.hasNext()) { audioClipBufferItem *pItem = it.next(); qtractorAudioClip *pClip = pItem->clip; qtractorAudioBuffer *pBuff = pItem->buff; // Should force sync now and then... if ((count % 33) == 0) pBuff->syncExport(); // Quite similar to qtractorAudioClip::process()... const unsigned long iClipStart = pClip->clipStart(); const unsigned long iClipEnd = iClipStart + pClip->clipLength();; if (iFrameStart < iClipStart && iFrameEnd > iClipStart) { unsigned long iOffset = iFrameEnd - iClipStart; while (!pBuff->inSync(iClipStart - iFrameStart, iOffset)) pBuff->syncExport(); pBuff->readMix(ppFrames, iOffset, iChannels, iClipStart - iFrameStart, pClip->gain(iOffset)); } else if (iFrameStart >= iClipStart && iFrameStart < iClipEnd) { const unsigned long iOffset = iFrameEnd - iClipStart; while (!pBuff->inSync(iFrameStart - iClipStart, iOffset)) pBuff->syncExport(); pBuff->readMix(ppFrames, iFrameEnd - iFrameStart, iChannels, 0, pClip->gain(iOffset)); } } // Actually write to merge audio file; // - check for last incomplete block... if (iFrameEnd > iSelectEnd) pAudioFile->write(ppFrames, iBufferSize - (iFrameEnd - iSelectEnd)); else pAudioFile->write(ppFrames, iBufferSize); // Advance to next buffer... iFrameStart = iFrameEnd; iFrameEnd = iFrameStart + iBufferSize; if (++count > 100 && pProgressBar) { pProgressBar->setValue(pProgressBar->value() + iBufferSize); qtractorSession::stabilize(); count = 0; } } for (i = 0; i < iChannels; ++i) delete ppFrames[i]; delete [] ppFrames; qDeleteAll(list); list.clear(); // Close and free it up... pAudioFile->close(); delete pAudioFile; if (pProgressBar) pProgressBar->hide(); // Stop logging... if (pMainForm) { pMainForm->addAudioFile(sFilename, true); pMainForm->appendMessages( tr("Audio clip merge/export: \"%1\" complete.") .arg(sFilename)); } // The resulting merge comands, if any... if (pClipCommand) { iter = items.constBegin(); for ( ; iter != iter_end; ++iter) { qtractorClip *pClip = iter.key(); // Clip parameters. const unsigned long iClipStart = pClip->clipStart(); const unsigned long iClipOffset = pClip->clipOffset(); const unsigned long iClipLength = pClip->clipLength(); const unsigned long iClipEnd = iClipStart + iClipLength; // Determine and keep clip regions... if (iSelectStart > iClipStart) { // -- Left clip... pClipCommand->resizeClip(pClip, iClipStart, iClipOffset, iSelectStart - iClipStart); // Done, left clip. } else if (iSelectEnd < iClipEnd) { // -- Right clip... pClipCommand->resizeClip(pClip, iSelectEnd, iClipOffset + (iSelectEnd - iClipStart), iClipEnd - iSelectEnd); // Done, right clip. } else { // -- Inner clip... pClipCommand->removeClip(pClip); // Done, inner clip. } } // Set the resulting clip command... qtractorAudioClip *pNewClip = new qtractorAudioClip(pTrack); pNewClip->setClipStart(iSelectStart); pNewClip->setClipLength(iSelectEnd - iSelectStart); pNewClip->setFilename(sFilename); pClipCommand->addClip(pNewClip, pTrack); } // Almost done with it... QApplication::restoreOverrideCursor(); // That's it... return true; } // Merge/export selected(MIDI) clips. bool qtractorTracks::mergeExportMidiClips ( qtractorClipCommand *pClipCommand ) { // Should be one single MIDI track... qtractorClipSelect *pClipSelect = m_pTrackView->clipSelect(); qtractorTrack *pTrack = pClipSelect->singleTrack(); if (pTrack == NULL) return false; if (pTrack->trackType() != qtractorTrack::Midi) return false; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // Merge MIDI Clip filename requester... const QString sExt("mid"); const QString& sTitle = tr("Merge/Export MIDI Clip") + " - " QTRACTOR_TITLE; const QString& sFilter = tr("MIDI files (*.%1 *.smf *.midi)").arg(sExt); #if 0//QT_VERSION < 0x040400 // Ask for the filename to save... QString sFilename = QFileDialog::getSaveFileName(this, sTitle, pSession->createFilePath(pTrack->trackName(), 0, sExt), sFilter); #else // Construct save-file dialog... QFileDialog fileDialog(this, sTitle, pSession->createFilePath(pTrack->trackName(), sExt), sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptSave); fileDialog.setFileMode(QFileDialog::AnyFile); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(pOptions->sMidiDir)); fileDialog.setSidebarUrls(urls); } // Show dialog... if (!fileDialog.exec()) return false; QString sFilename = fileDialog.selectedFiles().first(); #endif if (sFilename.isEmpty()) return false; if (QFileInfo(sFilename).suffix().isEmpty()) sFilename += '.' + sExt; // Should take sometime... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // Create SMF... qtractorMidiFile file; if (!file.open(sFilename, qtractorMidiFile::Write)) { QApplication::restoreOverrideCursor(); return false; } // Write SMF header... const unsigned short iTicksPerBeat = pSession->ticksPerBeat(); const unsigned short iFormat = qtractorMidiClip::defaultFormat(); const unsigned short iTracks = (iFormat == 0 ? 1 : 2); if (!file.writeHeader(iFormat, iTracks, iTicksPerBeat)) { QApplication::restoreOverrideCursor(); return false; } // Start logging... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) { pMainForm->appendMessages( tr("MIDI clip merge/export: \"%1\" started...") .arg(sFilename)); } // Multiple clip selection... const qtractorClipSelect::ItemList& items = pClipSelect->items(); qtractorClipSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorClipSelect::ItemList::ConstIterator& iter_end = items.constEnd(); // Multi-selection extents (in frames)... unsigned long iSelectStart = pSession->sessionEnd(); unsigned long iSelectEnd = pSession->sessionStart(); for ( ; iter != iter_end; ++iter) { qtractorClip *pClip = iter.key(); // Make sure it's a legal selection... if (pClip->track() && pClip->isClipSelected()) { if (iSelectStart > pClip->clipSelectStart()) iSelectStart = pClip->clipSelectStart(); if (iSelectEnd < pClip->clipSelectEnd()) iSelectEnd = pClip->clipSelectEnd(); } } // Multi-selection extents (in ticks)... const unsigned long iTimeStart = pSession->tickFromFrame(iSelectStart); const unsigned long iTimeEnd = pSession->tickFromFrame(iSelectEnd); // Set proper tempo map... if (file.tempoMap()) { file.tempoMap()->fromTimeScale( pSession->timeScale(), pSession->tickFromFrame(iTimeStart)); } // Setup track (SMF format 1). if (iFormat == 1) file.writeTrack(NULL); // Setup merge sequence... qtractorMidiSequence seq(pTrack->trackName(), 1, iTicksPerBeat); seq.setChannel(pTrack->midiChannel()); seq.setBank(pTrack->midiBank()); seq.setProg(pTrack->midiProg()); // The merge... iter = items.constBegin(); for ( ; iter != iter_end; ++iter) { qtractorClip *pClip = iter.key(); // Make sure it's a legal selection... if (pClip->track() && pClip->isClipSelected()) { // Clip parameters. const unsigned long iClipStart = pClip->clipStart(); const unsigned long iClipOffset = pClip->clipOffset(); const unsigned long iClipLength = pClip->clipLength(); const unsigned long iClipEnd = iClipStart + iClipLength; // Determine and keep clip regions... if (pClipCommand) { if (iSelectStart > iClipStart) { // -- Left clip... pClipCommand->resizeClip(pClip, iClipStart, iClipOffset, iSelectStart - iClipStart); // Done, left clip. } else if (iSelectEnd < iClipEnd) { // -- Right clip... pClipCommand->resizeClip(pClip, iSelectEnd, iClipOffset + (iSelectEnd - iClipStart), iClipEnd - iSelectEnd); // Done, right clip. } else { // -- Inner clip... pClipCommand->removeClip(pClip); // Done, inner clip. } } // Do the MIDI merge, itself... qtractorMidiClip *pMidiClip = static_cast (pClip); if (pMidiClip) { const unsigned long iTimeClip = pSession->tickFromFrame(pClip->clipStart()); const unsigned long iTimeOffset = iTimeClip - iTimeStart; // For each event... qtractorMidiEvent *pEvent = pMidiClip->sequence()->events().first(); while (pEvent && iTimeClip + pEvent->time() < iTimeStart) pEvent = pEvent->next(); while (pEvent && iTimeClip + pEvent->time() < iTimeEnd) { qtractorMidiEvent *pNewEvent = new qtractorMidiEvent(*pEvent); pNewEvent->setTime(iTimeOffset + pEvent->time()); if (pNewEvent->type() == qtractorMidiEvent::NOTEON) { const unsigned long iTimeEvent = iTimeClip + pEvent->time(); const float fGain = pMidiClip->gain( pSession->frameFromTick(iTimeEvent) - pClip->clipStart()); pNewEvent->setVelocity((unsigned char) (fGain * float(pEvent->velocity())) & 0x7f); if (iTimeEvent + pEvent->duration() > iTimeEnd) pNewEvent->setDuration(iTimeEnd - iTimeEvent); } seq.insertEvent(pNewEvent); pEvent = pEvent->next(); } } } } // Write the track and close SMF... file.writeTrack(&seq); file.close(); // Stop logging... if (pMainForm) { pMainForm->addMidiFile(sFilename, true); pMainForm->appendMessages( tr("MIDI clip merge/export: \"%1\" complete.") .arg(sFilename)); } // Set the resulting clip command... if (pClipCommand) { qtractorMidiClip *pNewClip = new qtractorMidiClip(pTrack); pNewClip->setClipStart(iSelectStart); pNewClip->setClipLength(iSelectEnd - iSelectStart); pNewClip->setFilename(sFilename); pNewClip->setTrackChannel(1); pClipCommand->addClip(pNewClip, pTrack); } // Almost done with it... QApplication::restoreOverrideCursor(); // That's it... return true; } // Edit/loop-range from current clip settlers. bool qtractorTracks::rangeClip ( qtractorClip *pClip ) { return rangeClipEx(pClip, false); } bool qtractorTracks::loopClip ( qtractorClip *pClip ) { return rangeClipEx(pClip, true); } bool qtractorTracks::rangeClipEx ( qtractorClip *pClip, bool bLoopSet ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; unsigned long iEditHead = 0; unsigned long iEditTail = 0; // Multiple clip selection... if (pClip == NULL && isClipSelected()) { // Multi-selection extents (in frames)... iEditHead = pSession->sessionEnd(); iEditTail = pSession->sessionStart(); qtractorClipSelect *pClipSelect = m_pTrackView->clipSelect(); const qtractorClipSelect::ItemList& items = pClipSelect->items(); qtractorClipSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorClipSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { pClip = iter.key(); // Make sure it's a legal selection... if (pClip->isClipSelected()) { const unsigned long iClipStart = pClip->clipStart(); const unsigned long iClipEnd = iClipStart + pClip->clipLength(); if (iEditHead > iClipStart) iEditHead = iClipStart; if (iEditTail < iClipEnd) iEditTail = iClipEnd; } } } else { if (pClip == NULL) pClip = m_pTrackView->currentClip(); if (pClip) { iEditHead = pClip->clipStart(); iEditTail = iEditHead + pClip->clipLength(); } } pSession->setEditHead(iEditHead); pSession->setEditTail(iEditTail); if (bLoopSet) { return pSession->execute( new qtractorSessionLoopCommand(pSession, iEditHead, iEditTail)); } selectionChangeNotify(); return true; } // Adjust current tempo from clip selection or interactive tapping... bool qtractorTracks::tempoClip ( qtractorClip *pClip ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; unsigned long iRangeStart = pSession->editHead(); unsigned long iRangeLength = pSession->editTail() - iRangeStart; if (pClip == NULL) pClip = currentClip(); if (pClip) { if (pClip->isClipSelected()) { iRangeStart = pClip->clipSelectStart(); iRangeLength = pClip->clipSelectEnd() - iRangeStart; } else { iRangeStart = pClip->clipStart(); iRangeLength = pClip->clipLength(); } } qtractorTempoAdjustForm form(this); form.setRangeStart(iRangeStart); form.setRangeLength(iRangeLength); if (!form.exec()) return false; // Avoid automatic time stretching option for audio clips... const bool bAutoTimeStretch = pSession->isAutoTimeStretch(); pSession->setAutoTimeStretch(false); // Find appropriate node... qtractorTimeScale *pTimeScale = pSession->timeScale(); qtractorTimeScale::Cursor& cursor = pTimeScale->cursor(); qtractorTimeScale::Node *pNode = cursor.seekFrame(form.rangeStart()); // Now, express the change as a undoable command... pSession->execute( new qtractorTimeScaleUpdateNodeCommand(pTimeScale, pNode->frame, form.tempo(), 2, form.beatsPerBar(), form.beatDivisor())); // Done. pSession->setAutoTimeStretch(bAutoTimeStretch); pSession->setEditTail(pSession->editHead() + form.rangeLength()); selectionChangeNotify(); return true; } // Whether there's anything currently selected. bool qtractorTracks::isSelected (void) const { return isClipSelected() || isCurveSelected(); } // Whether there's any clip currently selected. bool qtractorTracks::isClipSelected (void) const { return m_pTrackView->isClipSelected(); } // Whether there's any curve/automation currently selected. bool qtractorTracks::isCurveSelected (void) const { return m_pTrackView->isCurveSelected(); } // Whether there's a single track selection. qtractorTrack *qtractorTracks::singleTrackSelected (void) { return m_pTrackView->singleTrackSelected(); } // Retrieve actual clip selection range. void qtractorTracks::clipSelectedRange ( unsigned long& iSelectStart, unsigned long& iSelectEnd ) const { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; iSelectStart = pSession->sessionEnd(); iSelectEnd = pSession->sessionStart(); qtractorClipSelect *pClipSelect = m_pTrackView->clipSelect(); const qtractorClipSelect::ItemList& items = pClipSelect->items(); qtractorClipSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorClipSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorClip *pClip = iter.key(); qtractorTrack *pTrack = pClip->track(); // Make sure it's a legal selection... if (pTrack && pClip->isClipSelected()) { if (iSelectStart > pClip->clipSelectStart()) iSelectStart = pClip->clipSelectStart(); if (iSelectEnd < pClip->clipSelectEnd()) iSelectEnd = pClip->clipSelectEnd(); } } } // Clipboard methods. void qtractorTracks::cutClipboard (void) { if (m_pTrackView->isCurveEdit()) m_pTrackView->executeCurveSelect(qtractorTrackView::Cut); else m_pTrackView->executeClipSelect(qtractorTrackView::Cut); } void qtractorTracks::copyClipboard (void) { if (m_pTrackView->isCurveEdit()) m_pTrackView->executeCurveSelect(qtractorTrackView::Copy); else m_pTrackView->executeClipSelect(qtractorTrackView::Copy); } void qtractorTracks::pasteClipboard (void) { m_pTrackView->pasteClipboard(); } // Special paste/repeat prompt. void qtractorTracks::pasteRepeatClipboard (void) { qtractorPasteRepeatForm pasteForm(this); pasteForm.setRepeatPeriod(m_pTrackView->pastePeriod()); if (pasteForm.exec()) { m_pTrackView->pasteClipboard( pasteForm.repeatCount(), pasteForm.repeatPeriod()); } } // Delete current selection. void qtractorTracks::deleteSelect (void) { if (m_pTrackView->isCurveEdit()) m_pTrackView->executeCurveSelect(qtractorTrackView::Delete); else m_pTrackView->executeClipSelect(qtractorTrackView::Delete); } // Split selection method. void qtractorTracks::splitSelect (void) { m_pTrackView->executeClipSelect(qtractorTrackView::Split); } // Select range interval between edit head and tail. void qtractorTracks::selectEditRange ( bool bReset ) { if (m_pTrackView->isCurveEdit()) m_pTrackView->selectCurveTrackRange(NULL, bReset); else m_pTrackView->selectClipTrackRange(NULL, bReset); } // Select all clips on current track. void qtractorTracks::selectCurrentTrack ( bool bReset ) { qtractorTrack *pTrack = currentTrack(); if (pTrack == NULL) return; if (m_pTrackView->isCurveEdit()) m_pTrackView->selectCurveTrack(pTrack, bReset); else m_pTrackView->selectClipTrack(pTrack, bReset); } // Select all clips on current track range. void qtractorTracks::selectCurrentTrackRange ( bool bReset ) { qtractorTrack *pTrack = currentTrack(); if (pTrack == NULL) return; if (m_pTrackView->isCurveEdit()) m_pTrackView->selectCurveTrackRange(pTrack, bReset); else m_pTrackView->selectClipTrackRange(pTrack, bReset); } // Select everything on all tracks. void qtractorTracks::selectAll (void) { if (m_pTrackView->isCurveEdit()) m_pTrackView->selectCurveAll(); else m_pTrackView->selectClipAll(); } // Select nothing on all tracks. void qtractorTracks::selectNone (void) { m_pTrackView->clearSelect(); selectionChangeNotify(); } // Invert selection on all tracks and clips. void qtractorTracks::selectInvert (void) { if (m_pTrackView->isCurveEdit()) m_pTrackView->selectCurveInvert(); else m_pTrackView->selectClipInvert(); } // Insertion method. bool qtractorTracks::insertEditRange ( qtractorTrack *pTrack ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; qtractorTimeScale *pTimeScale = pSession->timeScale(); if (pTimeScale == NULL) return false; unsigned long iInsertStart = pSession->editHead(); unsigned long iInsertEnd = pSession->editTail(); if (iInsertStart >= iInsertEnd) { unsigned short iBar = pTimeScale->barFromFrame(iInsertStart); iInsertEnd = pTimeScale->frameFromBar(iBar + 1); } unsigned int iInsertOptions = qtractorEditRangeForm::None; iInsertOptions |= qtractorEditRangeForm::Clips; iInsertOptions |= qtractorEditRangeForm::Automation; if (pTrack == NULL) { qtractorEditRangeForm rangeForm(this); rangeForm.setWindowTitle(tr("Insert Range") + " - " QTRACTOR_TITLE); if (isClipSelected()) clipSelectedRange(iInsertStart, iInsertEnd); rangeForm.setSelectionRange(iInsertStart, iInsertEnd); if (!rangeForm.exec()) return false; iInsertStart = rangeForm.rangeStart(); iInsertEnd = rangeForm.rangeEnd(); iInsertOptions = rangeForm.rangeOptions(); } if (iInsertStart >= iInsertEnd) return false; const unsigned long iInsertLength = iInsertEnd - iInsertStart; int iUpdate = 0; qtractorClipRangeCommand *pClipRangeCommand = new qtractorClipRangeCommand(pTrack == NULL ? tr("insert range") : tr("insert track range")); if (pTrack) { iUpdate += insertEditRangeTrack(pClipRangeCommand, pTrack, iInsertStart, iInsertEnd, iInsertOptions); } else { // Clips & Automation... pTrack = pSession->tracks().first(); while (pTrack) { iUpdate += insertEditRangeTrack(pClipRangeCommand, pTrack, iInsertStart, iInsertEnd, iInsertOptions); pTrack = pTrack->next(); } // Loop... if (iInsertOptions & qtractorEditRangeForm::Loop) { unsigned long iLoopStart = pSession->loopStart(); unsigned long iLoopEnd = pSession->loopEnd(); if (iLoopStart < iLoopEnd) { int iLoopUpdate = 0; if (iLoopStart > iInsertStart) { iLoopStart += iInsertLength; ++iLoopUpdate; } if (iLoopEnd > iInsertStart) { iLoopEnd += iInsertLength; ++iLoopUpdate; } if (iLoopUpdate > 0) { pClipRangeCommand->addSessionCommand( new qtractorSessionLoopCommand(pSession, iLoopStart, iLoopEnd)); ++iUpdate; } } } // Punch In/Out... if (iInsertOptions & qtractorEditRangeForm::Punch) { unsigned long iPunchIn = pSession->punchOut(); unsigned long iPunchOut = pSession->punchIn(); if (iPunchIn < iPunchOut) { int iPunchUpdate = 0; if (iPunchIn > iInsertStart) { iPunchIn += iInsertLength; ++iPunchUpdate; } if (iPunchOut > iInsertStart) { iPunchOut += iInsertLength; ++iPunchUpdate; } if (iPunchUpdate > 0) { pClipRangeCommand->addSessionCommand( new qtractorSessionPunchCommand(pSession, iPunchIn, iPunchOut)); ++iUpdate; } } } // Markers... if (iInsertOptions & qtractorEditRangeForm::Markers) { qtractorTimeScale::Marker *pMarker = pTimeScale->markers().last(); while (pMarker && pMarker->frame > iInsertStart) { pClipRangeCommand->addTimeScaleMarkerCommand( new qtractorTimeScaleMoveMarkerCommand(pTimeScale, pMarker, pMarker->frame + iInsertLength)); pMarker = pMarker->prev(); ++iUpdate; } } // Tempo-map... if (iInsertOptions & qtractorEditRangeForm::TempoMap) { qtractorTimeScale::Cursor cursor(pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(pSession->sessionEnd()); while (pNode && pNode->frame > iInsertStart) { pClipRangeCommand->addTimeScaleNodeCommand( new qtractorTimeScaleMoveNodeCommand(pTimeScale, pNode, pNode->frame + iInsertLength)); pNode = pNode->prev(); ++iUpdate; } } } if (iUpdate < 1) { delete pClipRangeCommand; return false; } return pSession->execute(pClipRangeCommand); } // Insertion method (track). int qtractorTracks::insertEditRangeTrack ( qtractorClipRangeCommand *pClipRangeCommand, qtractorTrack *pTrack, unsigned long iInsertStart, unsigned long iInsertEnd, unsigned int iInsertOptions ) const { const unsigned long iInsertLength = iInsertEnd - iInsertStart; int iUpdate = 0; if (iInsertOptions & qtractorEditRangeForm::Clips) { qtractorClip *pClip = pTrack->clips().first(); while (pClip) { const unsigned long iClipStart = pClip->clipStart(); const unsigned long iClipOffset = pClip->clipOffset(); const unsigned long iClipLength = pClip->clipLength(); const unsigned long iClipEnd = iClipStart + iClipLength; if (iClipEnd > iInsertStart) { // Slip/move clip... if (iClipStart < iInsertStart) { // Left-clip... pClipRangeCommand->resizeClip(pClip, iClipStart, iClipOffset, iInsertStart - iClipStart); // Right-clip... qtractorClip *pClipEx = m_pTrackView->cloneClip(pClip); if (pClipEx) { const unsigned long iClipOffset2 = iClipOffset + iInsertStart - iClipStart; pClipEx->setClipStart(iInsertEnd); pClipEx->setClipOffset(iClipOffset2); pClipEx->setClipLength(iClipEnd - iInsertStart); pClipEx->setFadeOutLength(pClip->fadeOutLength()); pClipRangeCommand->addClip(pClipEx, pTrack); } } else { // Whole-clip... pClipRangeCommand->moveClip(pClip, pTrack, iClipStart + iInsertLength, iClipOffset, iClipLength); } ++iUpdate; } pClip = pClip->next(); } } if (iInsertOptions & qtractorEditRangeForm::Automation) { qtractorCurveList *pCurveList = pTrack->curveList(); if (pCurveList) { qtractorCurve *pCurve = pCurveList->first(); while (pCurve) { int iCurveEditUpdate = 0; qtractorCurveEditCommand *pCurveEditCommand = new qtractorCurveEditCommand(QString(), pCurve); qtractorCurve::Node *pNode = pCurve->seek(iInsertStart); while (pNode) { pCurveEditCommand->moveNode(pNode, pNode->frame + iInsertLength); ++iCurveEditUpdate; pNode = pNode->next(); } if (iCurveEditUpdate > 0) { pClipRangeCommand->addCurveEditCommand(pCurveEditCommand); iUpdate += iCurveEditUpdate; } else delete pCurveEditCommand; pCurve = pCurve->next(); } } } return iUpdate; } // Removal method. bool qtractorTracks::removeEditRange ( qtractorTrack *pTrack ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; qtractorTimeScale *pTimeScale = pSession->timeScale(); if (pTimeScale == NULL) return false; unsigned long iRemoveStart = pSession->editHead(); unsigned long iRemoveEnd = pSession->editTail(); if (iRemoveStart >= iRemoveEnd) { unsigned short iBar = pTimeScale->barFromFrame(iRemoveStart); iRemoveEnd = pTimeScale->frameFromBar(iBar + 1); } unsigned int iRemoveOptions = qtractorEditRangeForm::None; iRemoveOptions |= qtractorEditRangeForm::Clips; iRemoveOptions |= qtractorEditRangeForm::Automation; if (pTrack == NULL) { qtractorEditRangeForm rangeForm(this); rangeForm.setWindowTitle(tr("Remove Range") + " - " QTRACTOR_TITLE); if (isClipSelected()) clipSelectedRange(iRemoveStart, iRemoveEnd); rangeForm.setSelectionRange(iRemoveStart, iRemoveEnd); if (!rangeForm.exec()) return false; iRemoveStart = rangeForm.rangeStart(); iRemoveEnd = rangeForm.rangeEnd(); iRemoveOptions = rangeForm.rangeOptions(); } if (iRemoveStart >= iRemoveEnd) return false; const unsigned long iRemoveLength = iRemoveEnd - iRemoveStart; int iUpdate = 0; qtractorClipRangeCommand *pClipRangeCommand = new qtractorClipRangeCommand(pTrack == NULL ? tr("remove range") : tr("remove track range")); if (pTrack) { iUpdate += removeEditRangeTrack(pClipRangeCommand, pTrack, iRemoveStart, iRemoveEnd, iRemoveOptions); } else { // Clips & Automation... pTrack = pSession->tracks().first(); while (pTrack) { iUpdate += removeEditRangeTrack(pClipRangeCommand, pTrack, iRemoveStart, iRemoveEnd, iRemoveOptions); pTrack = pTrack->next(); } // Loop... if (iRemoveOptions & qtractorEditRangeForm::Loop) { unsigned long iLoopStart = pSession->loopStart(); unsigned long iLoopEnd = pSession->loopEnd(); if (iLoopStart < iLoopEnd) { int iLoopUpdate = 0; if (iLoopStart > iRemoveStart) { if (iLoopStart > iRemoveEnd) iLoopStart = iRemoveStart; else iLoopStart -= iRemoveLength; ++iLoopUpdate; } if (iLoopEnd > iRemoveStart) { if (iLoopEnd > iRemoveEnd) iLoopEnd -= iRemoveLength; else iLoopEnd = iRemoveEnd; ++iLoopUpdate; } if (iLoopUpdate > 0) { pClipRangeCommand->addSessionCommand( new qtractorSessionLoopCommand(pSession, iLoopStart, iLoopEnd)); ++iUpdate; } } } // Punch In/Out... if (iRemoveOptions & qtractorEditRangeForm::Punch) { unsigned long iPunchIn = pSession->punchOut(); unsigned long iPunchOut = pSession->punchIn(); if (iPunchIn < iPunchOut) { int iPunchUpdate = 0; if (iPunchIn > iRemoveStart) { if (iPunchIn > iRemoveEnd) iPunchIn = iRemoveStart; else iPunchIn -= iRemoveLength; ++iPunchUpdate; } if (iPunchOut > iRemoveStart) { if (iPunchOut > iRemoveEnd) iPunchOut -= iRemoveLength; else iPunchOut = iRemoveEnd; ++iPunchUpdate; } if (iPunchUpdate > 0) { pClipRangeCommand->addSessionCommand( new qtractorSessionPunchCommand(pSession, iPunchIn, iPunchOut)); ++iUpdate; } } } // Markers... if (iRemoveOptions & qtractorEditRangeForm::Markers) { qtractorTimeScale::Marker *pMarker = pTimeScale->markers().seekFrame(iRemoveStart); while (pMarker) { if (pMarker->frame > iRemoveStart) { if (pMarker->frame < iRemoveEnd) { pClipRangeCommand->addTimeScaleMarkerCommand( new qtractorTimeScaleRemoveMarkerCommand( pTimeScale, pMarker)); ++iUpdate; } else if (pMarker->frame > iRemoveEnd) { pClipRangeCommand->addTimeScaleMarkerCommand( new qtractorTimeScaleMoveMarkerCommand(pTimeScale, pMarker, pMarker->frame - iRemoveLength)); ++iUpdate; } } pMarker = pMarker->next(); } } // Tempo-map... if (iRemoveOptions & qtractorEditRangeForm::TempoMap) { qtractorTimeScale::Cursor cursor(pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(iRemoveStart); while (pNode) { if (pNode->frame > iRemoveStart) { if (pNode->frame < iRemoveEnd) { pClipRangeCommand->addTimeScaleNodeCommand( new qtractorTimeScaleRemoveNodeCommand( pTimeScale, pNode)); ++iUpdate; } else if (pNode->frame > iRemoveEnd) { pClipRangeCommand->addTimeScaleNodeCommand( new qtractorTimeScaleMoveNodeCommand(pTimeScale, pNode, pNode->frame - iRemoveLength)); ++iUpdate; } } pNode = pNode->next(); } } } if (iUpdate < 1) { delete pClipRangeCommand; return false; } clearSelect(); return pSession->execute(pClipRangeCommand); } // Removal method (track). int qtractorTracks::removeEditRangeTrack ( qtractorClipRangeCommand *pClipRangeCommand, qtractorTrack *pTrack, unsigned long iRemoveStart, unsigned long iRemoveEnd, unsigned int iRemoveOptions ) const { const unsigned long iRemoveLength = iRemoveEnd - iRemoveStart; int iUpdate = 0; if (iRemoveOptions & qtractorEditRangeForm::Clips) { qtractorClip *pClip = pTrack->clips().first(); while (pClip) { const unsigned long iClipStart = pClip->clipStart(); const unsigned long iClipOffset = pClip->clipOffset(); const unsigned long iClipLength = pClip->clipLength(); const unsigned long iClipEnd = iClipStart + iClipLength; if (iClipEnd > iRemoveStart) { // Slip/move clip... if (iClipStart < iRemoveEnd) { // Left-clip... if (iClipStart < iRemoveStart) { pClipRangeCommand->resizeClip(pClip, iClipStart, iClipOffset, iRemoveStart - iClipStart); // Right-clip... if (iClipEnd > iRemoveEnd) { qtractorClip *pClipEx = m_pTrackView->cloneClip(pClip); if (pClipEx) { const unsigned long iClipOffset2 = iClipOffset + iRemoveEnd - iClipStart; pClipEx->setClipStart(iRemoveStart); pClipEx->setClipOffset(iClipOffset2); pClipEx->setClipLength(iClipEnd - iRemoveEnd); pClipEx->setFadeOutLength(pClip->fadeOutLength()); pClipRangeCommand->addClip(pClipEx, pTrack); } } } else if (iClipEnd > iRemoveEnd) { pClipRangeCommand->resizeClip(pClip, iRemoveStart, iClipOffset + iRemoveEnd - iClipStart, iClipEnd - iRemoveEnd); } else { pClipRangeCommand->removeClip(pClip); } } else { // Whole-clip... pClipRangeCommand->moveClip(pClip, pTrack, iClipStart - iRemoveLength, iClipOffset, iClipLength); } ++iUpdate; } pClip = pClip->next(); } } if (iRemoveOptions & qtractorEditRangeForm::Automation) { qtractorCurveList *pCurveList = pTrack->curveList(); if (pCurveList) { qtractorCurve *pCurve = pCurveList->first(); while (pCurve) { int iCurveEditUpdate = 0; qtractorCurveEditCommand *pCurveEditCommand = new qtractorCurveEditCommand(QString(), pCurve); qtractorCurve::Node *pNode = pCurve->seek(iRemoveStart); while (pNode) { if (pNode->frame < iRemoveEnd) pCurveEditCommand->removeNode(pNode); else pCurveEditCommand->moveNode(pNode, pNode->frame - iRemoveLength); ++iCurveEditUpdate; pNode = pNode->next(); } if (iCurveEditUpdate > 0) { pClipRangeCommand->addCurveEditCommand(pCurveEditCommand); iUpdate += iCurveEditUpdate; } else delete pCurveEditCommand; pCurve = pCurve->next(); } } } return iUpdate; } // Adds a new track into session. bool qtractorTracks::addTrack (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return false; // Create a new track right away... const int iTrack = pSession->tracks().count() + 1; const QColor& color = qtractorTrack::trackColor(iTrack); qtractorTrack *pTrack = new qtractorTrack(pSession); pTrack->setTrackName(QString("Track %1").arg(iTrack)); pTrack->setMidiChannel(pSession->midiTag() % 16); pTrack->setBackground(color); pTrack->setForeground(color.darker()); // Open dialog for settings... qtractorTrackForm trackForm(pMainForm); trackForm.setTrack(pTrack); if (!trackForm.exec()) { delete pTrack; return false; } // Take care of user supplied properties... pTrack->properties() = trackForm.properties(); // Put it in the form of an undoable command... return pSession->execute( new qtractorAddTrackCommand(pTrack, currentTrack())); } // Remove given(current) track from session. bool qtractorTracks::removeTrack ( qtractorTrack *pTrack ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // Get the list view item reference of the intended track... if (pTrack == NULL) pTrack = currentTrack(); if (pTrack == NULL) return false; // Don't remove tracks engaged in recording... if (pTrack->isRecord() && pSession->isRecording() && pSession->isPlaying()) return false; // Prompt user if he/she's sure about this... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions && pOptions->bConfirmRemove) { if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("About to remove track:\n\n" "\"%1\"\n\n" "Are you sure?") .arg(pTrack->trackName()), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return false; } // Put it in the form of an undoable command... return pSession->execute( new qtractorRemoveTrackCommand(pTrack)); } // Edit given(current) track properties. bool qtractorTracks::editTrack ( qtractorTrack *pTrack ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return false; // Get the list view item reference of the intended track... if (pTrack == NULL) pTrack = currentTrack(); if (pTrack == NULL) return false; // Don't edit tracks engaged in recording... if (pTrack->isRecord() && pSession->isRecording() && pSession->isPlaying()) return false; // Open dialog for settings... qtractorTrackForm trackForm(pMainForm); trackForm.setTrack(pTrack); if (!trackForm.exec()) return false; // Put it in the form of an undoable command... return pSession->execute( new qtractorEditTrackCommand(pTrack, trackForm.properties())); } // Import Audio files into new tracks... bool qtractorTracks::addAudioTracks ( QStringList files, unsigned long iClipStart ) { // Have we some? if (files.isEmpty()) return false; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // pSession->lock(); // Account for actual updates... int iUpdate = 0; // We'll build a composite command... qtractorImportTrackCommand *pImportTrackCommand = new qtractorImportTrackCommand(currentTrack()); // Increment this for suggestive track coloring... int iTrack = pSession->tracks().count(); // To log this import into session description. QString sDescription = pSession->description().trimmed(); if (!sDescription.isEmpty()) sDescription += '\n'; // Needed whether we'll span to one single track // or will have each clip intto several tracks... const bool bDropSpan = m_pTrackView->isDropSpan(); qtractorTrack *pTrack = NULL; int iTrackClip = 0; // For each one of those files... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); QStringListIterator iter(files); while (iter.hasNext()) { // This is one of the selected filenames.... const QString& sPath = iter.next(); // Create a new track right away... if (pTrack == NULL || !bDropSpan) { const QColor& color = qtractorTrack::trackColor(++iTrack); pTrack = new qtractorTrack(pSession, qtractorTrack::Audio); pTrack->setBackground(color); pTrack->setForeground(color.darker()); pImportTrackCommand->addTrack(pTrack); iTrackClip = 0; } // Add the clip at once... qtractorAudioClip *pAudioClip = new qtractorAudioClip(pTrack); pAudioClip->setFilename(sPath); pAudioClip->setClipStart(iClipStart); // Time to add the new track/clip into session; // actuallly, this is when the given audio file gets open... pTrack->addClip(pAudioClip); if (iTrackClip == 0) pTrack->setTrackName(pAudioClip->clipName()); ++iTrackClip; // Add the new track to composite command... if (bDropSpan) iClipStart += pAudioClip->clipLength(); ++iUpdate; // Don't forget to add this one to local repository. if (pMainForm) { pMainForm->addAudioFile(sPath); // Log this successful import operation... sDescription += tr("Audio file import \"%1\" on %2 %3.\n") .arg(QFileInfo(sPath).fileName()) .arg(QDate::currentDate().toString("MMM dd yyyy")) .arg(QTime::currentTime().toString("hh:mm:ss")); pMainForm->appendMessages( tr("Audio file import: \"%1\".").arg(sPath)); } } // Have we changed anything? bool bResult = false; if (iUpdate > 0) { // Log to session (undoable by import-track command)... pSession->setDescription(sDescription); // Put it in the form of an undoable command... bResult = pSession->execute(pImportTrackCommand); } else { delete pImportTrackCommand; } // pSession->unlock(); return bResult; } // Import MIDI files into new tracks... bool qtractorTracks::addMidiTracks ( QStringList files, unsigned long iClipStart ) { // Have we some? if (files.isEmpty()) return false; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // pSession->lock(); // Account for actual updates... int iUpdate = 0; // We'll build a composite command... qtractorImportTrackCommand *pImportTrackCommand = new qtractorImportTrackCommand(currentTrack()); // Increment this for suggestive track coloring... int iTrack = pSession->tracks().count(); // Needed to help on setting whole session properties // from the first imported MIDI file... int iImport = iTrack; const unsigned long iTimeStart = pSession->tickFromFrame(iClipStart); // To log this import into session description. QString sDescription = pSession->description().trimmed(); if (!sDescription.isEmpty()) sDescription += '\n'; // For each one of those files... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); QStringListIterator iter(files); while (iter.hasNext()) { // This is one of the selected filenames.... const QString& sPath = iter.next(); // We'll be careful and pre-open the SMF header here... qtractorMidiFile file; if (!file.open(sPath)) continue; // It all depends on the format... int iTracks = (file.format() == 1 ? file.tracks() : 16); for (int iTrackChannel = 0; iTrackChannel < iTracks; ++iTrackChannel) { // Create a new track right away... const QColor& color = qtractorTrack::trackColor(++iTrack); qtractorTrack *pTrack = new qtractorTrack(pSession, qtractorTrack::Midi); // pTrack->setTrackName(QFileInfo(sPath).baseName()); pTrack->setBackground(color); pTrack->setForeground(color.darker()); // Add the clip at once... qtractorMidiClip *pMidiClip = new qtractorMidiClip(pTrack); pMidiClip->setFilename(sPath); pMidiClip->setTrackChannel(iTrackChannel); pMidiClip->setClipStart(iClipStart); if (iTrackChannel == 0 && iImport == 0) pMidiClip->setSessionFlag(true); // Time to add the new track/clip into session; // actuallly, this is when the given MIDI file and // track-channel gets open and read into the clip! pTrack->addClip(pMidiClip); // As far the standards goes,from which we'll strictly follow, // only the first track/channel has some tempo/time signature... if (iTrackChannel == 0) { // Some adjustment required... ++iImport; iClipStart = pSession->frameFromTick(iTimeStart); pMidiClip->setClipStart(iClipStart); } // Time to check whether there is actual data on track... if (pMidiClip->clipLength() > 0) { // Add the new track to composite command... pTrack->setTrackName(pMidiClip->clipName()); pTrack->setMidiChannel(pMidiClip->channel()); pImportTrackCommand->addTrack(pTrack); ++iUpdate; // Don't forget to add this one to local repository. if (pMainForm) pMainForm->addMidiFile(sPath); } else { // Get rid of these, now... pTrack->unlinkClip(pMidiClip); delete pMidiClip; delete pTrack; } } // Log this successful import operation... if (iUpdate > 0 && pMainForm) { sDescription += tr("MIDI file import \"%1\" on %2 %3.\n") .arg(QFileInfo(sPath).fileName()) .arg(QDate::currentDate().toString("MMM dd yyyy")) .arg(QTime::currentTime().toString("hh:mm:ss")); pMainForm->appendMessages( tr("MIDI file import: \"%1\".").arg(sPath)); } } // Have we changed anything? bool bResult = false; if (iUpdate > 0) { // Log to session (undoable by import-track command)... pSession->setDescription(sDescription); // Put it in the form of an undoable command... bResult = pSession->execute(pImportTrackCommand); } else { delete pImportTrackCommand; } // pSession->unlock(); return bResult; } // Import MIDI file track-channel into new track... bool qtractorTracks::addMidiTrackChannel ( const QString& sPath, int iTrackChannel, unsigned long iClipStart ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // To log this import into session description. QString sDescription = pSession->description().trimmed(); if (!sDescription.isEmpty()) sDescription += '\n'; // We'll build a composite command... qtractorImportTrackCommand *pImportTrackCommand = new qtractorImportTrackCommand(currentTrack()); // Increment this for suggestive track coloring... int iTrack = pSession->tracks().count(); // Create a new track right away... const QColor& color = qtractorTrack::trackColor(++iTrack); qtractorTrack *pTrack = new qtractorTrack(pSession, qtractorTrack::Midi); // pTrack->setTrackName(QFileInfo(sPath).baseName()); pTrack->setBackground(color); pTrack->setForeground(color.darker()); // Add the clip at once... qtractorMidiClip *pMidiClip = new qtractorMidiClip(pTrack); pMidiClip->setFilename(sPath); pMidiClip->setTrackChannel(iTrackChannel); pMidiClip->setClipStart(iClipStart); // Time to add the new track/clip into session... pTrack->addClip(pMidiClip); pTrack->setTrackName(pMidiClip->clipName()); pTrack->setMidiChannel(pMidiClip->channel()); // Add the new track to composite command... pImportTrackCommand->addTrack(pTrack); // Don't forget to add this one to local repository. qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) { pMainForm->addMidiFile(sPath); // Log this successful import operation... sDescription += tr("MIDI file import \"%1\"" " track-channel %2 on %3 %4.\n") .arg(QFileInfo(sPath).fileName()).arg(iTrackChannel) .arg(QDate::currentDate().toString("MMM dd yyyy")) .arg(QTime::currentTime().toString("hh:mm:ss")); pMainForm->appendMessages( tr("MIDI file import: \"%1\", track-channel: %2.") .arg(sPath).arg(iTrackChannel)); } // Log to session (undoable by import-track command)... pSession->setDescription(sDescription); // Put it in the form of an undoable command... return pSession->execute(pImportTrackCommand); } // Track-list active maintenance update. void qtractorTracks::updateTrack ( qtractorTrack *pTrack ) { m_pTrackList->updateTrack(pTrack); if (pTrack->trackType() == qtractorTrack::Midi) updateMidiTrack(pTrack); } // MIDI track/bus/channel alias active maintenance method. void qtractorTracks::updateMidiTrack ( qtractorTrack *pMidiTrack ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; const QString& sBusName = pMidiTrack->outputBusName(); const unsigned short iChannel = pMidiTrack->midiChannel(); for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { // If same channel, force same bank/program stuff... if (pTrack != pMidiTrack && pTrack->trackType() == qtractorTrack::Midi && pTrack->outputBusName() == sBusName && pTrack->midiChannel() == iChannel) { // Make else tracks MIDI attributes the same.... pTrack->setMidiBankSelMethod(pMidiTrack->midiBankSelMethod()); pTrack->setMidiBank(pMidiTrack->midiBank()); pTrack->setMidiProg(pMidiTrack->midiProg()); // Update the track list view, immediately... m_pTrackList->updateTrack(pTrack); } } #if 0 // Re-open all MIDI clips (channel might have changed?)... qtractorClip *pClip = pMidiTrack->clips().first(); for ( ; pClip; pClip = pClip->next()) pClip->open(); #endif // Update MIDI bus patch... qtractorMidiEngine *pMidiEngine = pSession->midiEngine(); if (pMidiEngine == NULL) return; qtractorMidiBus *pMidiBus = static_cast (pMidiTrack->outputBus()); if (pMidiBus == NULL) return; const qtractorMidiBus::Patch& patch = pMidiBus->patch(iChannel); pMidiBus->setPatch(iChannel, patch.instrumentName, pMidiTrack->midiBankSelMethod(), pMidiTrack->midiBank(), pMidiTrack->midiProg(), pMidiTrack); } // Simple main-form stabilizer redirector. void qtractorTracks::selectionChangeNotify (void) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->selectionNotifySlot(NULL); } // Simple main-form dirty-flag redirectors. void qtractorTracks::contentsChangeNotify (void) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->changeNotifySlot(NULL); } void qtractorTracks::dirtyChangeNotify (void) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->dirtyNotifySlot(); } // Track-list update (current track only). void qtractorTracks::updateTrackList (void) { m_pTrackList->updateTrack(currentTrack()); } // Track-view update (obviously a slot). void qtractorTracks::updateTrackView (void) { m_pTrackView->update(); } // Overall selection reset. void qtractorTracks::clearSelect (void) { m_pTrackView->clearSelect(); } // Overall contents reset. void qtractorTracks::clear (void) { m_pTrackList->clear(); m_pTrackView->clear(); updateContents(true); } // end of qtractorTracks.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorFiles.cpp0000644000175000001440000000012312166526620020577 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134671.13908 30 ctime=1381134671.198080115 qtractor-0.5.11/src/qtractorFiles.cpp0000644000175000001440000003447412166526620020102 0ustar00rncbcusers00000000000000// qtractorFiles.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorFiles.h" #include "qtractorMainForm.h" #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #include #endif //------------------------------------------------------------------------- // qtractorFilesTabWidget - File/Groups dockable child window. // class qtractorFilesTabWidget : public QTabWidget { public: // Constructor. qtractorFilesTabWidget(QWidget *pParent) : QTabWidget(pParent) {} protected: // Minimum recommended. QSize sizeHint() const { return QTabWidget::minimumSize(); } }; //------------------------------------------------------------------------- // qtractorFiles - File/Groups dockable window. // // Constructor. qtractorFiles::qtractorFiles ( QWidget *pParent ) : QDockWidget(pParent) { // Surely a name is crucial (e.g.for storing geometry settings) QDockWidget::setObjectName("qtractorFiles"); // Create file type selection tab widget. const QFont& font = QDockWidget::font(); m_pTabWidget = new qtractorFilesTabWidget(this); m_pTabWidget->setFont(QFont(font.family(), font.pointSize() - 1)); m_pTabWidget->setTabPosition(QTabWidget::South); // Create local tabs. m_pAudioListView = new qtractorAudioListView(); m_pMidiListView = new qtractorMidiListView(); // Add respective... m_pTabWidget->addTab(m_pAudioListView, tr("Audio")); m_pTabWidget->addTab(m_pMidiListView, tr("MIDI")); // Icons... m_pTabWidget->setTabIcon(qtractorFiles::Audio, QIcon(":/images/trackAudio.png")); m_pTabWidget->setTabIcon(qtractorFiles::Midi, QIcon(":/images/trackMidi.png")); m_pTabWidget->setUsesScrollButtons(false); // Player button (initially disabled)... m_pPlayWidget = new QWidget(m_pTabWidget); m_pPlayLayout = new QHBoxLayout(/*m_pPlayWidget*/); m_pPlayLayout->setMargin(2); m_pPlayLayout->setSpacing(2); m_pPlayWidget->setLayout(m_pPlayLayout); m_iPlayUpdate = 0; m_pPlayButton = new QToolButton(m_pPlayWidget); m_pPlayButton->setIcon(QIcon(":/images/transportPlay.png")); m_pPlayButton->setToolTip(tr("Play file")); m_pPlayButton->setCheckable(true); m_pPlayButton->setEnabled(false); m_pPlayLayout->addWidget(m_pPlayButton); m_pTabWidget->setCornerWidget(m_pPlayWidget, Qt::BottomRightCorner); // Common file list-view actions... m_pNewGroupAction = new QAction( QIcon(":/images/itemGroup.png"), tr("New &Group..."), this); m_pOpenFileAction = new QAction( QIcon(":/images/itemFile.png"), tr("Add &Files..."), this); m_pCutItemAction = new QAction( QIcon(":/images/editCut.png"), tr("Cu&t"), NULL); m_pCopyItemAction = new QAction( QIcon(":/images/editCopy.png"), tr("&Copy"), NULL); m_pPasteItemAction = new QAction( QIcon(":/images/editPaste.png"), tr("&Paste"), NULL); m_pRenameItemAction = new QAction( QIcon(":/images/formEdit.png"), tr("Re&name"), this); m_pRemoveItemAction = new QAction( QIcon(":/images/formRemove.png"), tr("&Remove"), NULL); m_pPlayItemAction = new QAction( QIcon(":/images/transportPlay.png"), tr("Pla&y"), this); m_pPlayItemAction->setCheckable(true); m_pCleanupAction = new QAction(tr("Cl&eanup"), this); // m_pNewGroupAction->setShortcut(tr("Ctrl+G")); // m_pOpenFileAction->setShortcut(tr("Ctrl+F")); m_pCutItemAction->setShortcut(tr("Ctrl+X")); m_pCopyItemAction->setShortcut(tr("Ctrl+C")); m_pPasteItemAction->setShortcut(tr("Ctrl+V")); // m_pRenameItemAction->setShortcut(tr("Ctrl+N")); m_pRemoveItemAction->setShortcut(tr("Del")); // m_pPlayItemAction->setShortcut(tr("Ctrl+Y")); // m_pCleanupAction->setShortcut(tr("Ctrl+E")); // Some actions surely need those // shortcuts firmly attached... #if 0 QDockWidget::addAction(m_pNewGroupAction); QDockWidget::addAction(m_pOpenFileAction); QDockWidget::addAction(m_pCutItemAction); QDockWidget::addAction(m_pCopyItemAction); QDockWidget::addAction(m_pPasteItemAction); QDockWidget::addAction(m_pRenameItemAction); QDockWidget::addAction(m_pRemoveItemAction); QDockWidget::addAction(m_pPlayItemAction); QDockWidget::addAction(m_pCleanupAction); #endif // Prepare the dockable window stuff. QDockWidget::setWidget(m_pTabWidget); QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures); QDockWidget::setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); // Some specialties to this kind of dock window... QDockWidget::setMinimumWidth(160); // Finally set the default caption and tooltip. const QString& sCaption = tr("Files"); QDockWidget::setWindowTitle(sCaption); QDockWidget::setWindowIcon(QIcon(":/images/viewFiles.png")); QDockWidget::setToolTip(sCaption); // Make it initially stable... stabilizeSlot(); // Child widgets signal/slots... QObject::connect(m_pTabWidget, SIGNAL(currentChanged(int)), SLOT(stabilizeSlot())); QObject::connect(m_pAudioListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(stabilizeSlot())); QObject::connect(m_pAudioListView, SIGNAL(itemClicked(QTreeWidgetItem*,int)), SLOT(stabilizeSlot())); QObject::connect(m_pMidiListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(stabilizeSlot())); QObject::connect(m_pMidiListView, SIGNAL(itemClicked(QTreeWidgetItem*,int)), SLOT(stabilizeSlot())); QObject::connect(m_pNewGroupAction, SIGNAL(triggered(bool)), SLOT(newGroupSlot())); QObject::connect(m_pOpenFileAction, SIGNAL(triggered(bool)), SLOT(openFileSlot())); QObject::connect(m_pCutItemAction, SIGNAL(triggered(bool)), SLOT(cutItemSlot())); QObject::connect(m_pCopyItemAction, SIGNAL(triggered(bool)), SLOT(copyItemSlot())); QObject::connect(m_pPasteItemAction, SIGNAL(triggered(bool)), SLOT(pasteItemSlot())); QObject::connect(m_pRenameItemAction, SIGNAL(triggered(bool)), SLOT(renameItemSlot())); QObject::connect(m_pRemoveItemAction, SIGNAL(triggered(bool)), SLOT(removeItemSlot())); QObject::connect(m_pPlayItemAction, SIGNAL(triggered(bool)), SLOT(playSlot(bool))); QObject::connect(m_pCleanupAction, SIGNAL(triggered(bool)), SLOT(cleanupSlot())); QObject::connect(m_pPlayButton, SIGNAL(toggled(bool)), SLOT(playSlot(bool))); QObject::connect(QApplication::clipboard(), SIGNAL(dataChanged()), SLOT(stabilizeSlot())); } // Destructor. qtractorFiles::~qtractorFiles (void) { delete m_pNewGroupAction; delete m_pOpenFileAction; delete m_pCutItemAction; delete m_pCopyItemAction; delete m_pPasteItemAction; delete m_pRenameItemAction; delete m_pRemoveItemAction; delete m_pCleanupAction; delete m_pPlayItemAction; // No need to delete child widgets, Qt does it all for us. } // Just about to notify main-window that we're closing. void qtractorFiles::closeEvent ( QCloseEvent * /*pCloseEvent*/ ) { QDockWidget::hide(); qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeForm(); } // Audio file list view accessor. qtractorAudioListView *qtractorFiles::audioListView (void) const { return m_pAudioListView; } // MIDI file list view accessor. qtractorMidiListView *qtractorFiles::midiListView (void) const { return m_pMidiListView; } // Clear everything on sight. void qtractorFiles::clear (void) { m_pAudioListView->clear(); m_pMidiListView->clear(); setPlayState(false); } // Check whether one of the widgets has focus (oveerride method) bool qtractorFiles::hasFocus (void) const { if (m_pAudioListView->hasFocus() || m_pMidiListView->hasFocus()) return true; return QDockWidget::hasFocus(); } // Tell whether a file item is currently selected. bool qtractorFiles::isFileSelected (void) const { qtractorFileListView *pFileListView = currentFileListView(); if (pFileListView) { QTreeWidgetItem *pItem = pFileListView->currentItem(); return (pItem && pItem->type() == qtractorFileListView::FileItem); } return false; } // Audio file addition convenience method. void qtractorFiles::addAudioFile ( const QString& sFilename, bool bAutoRemove ) { m_pTabWidget->setCurrentIndex(qtractorFiles::Audio); m_pAudioListView->addFileItem(sFilename, bAutoRemove); } // MIDI file addition convenience method. void qtractorFiles::addMidiFile ( const QString& sFilename, bool bAutoRemove ) { m_pTabWidget->setCurrentIndex(qtractorFiles::Midi); m_pMidiListView->addFileItem(sFilename, bAutoRemove); } // Audio file selection convenience method. void qtractorFiles::selectAudioFile ( const QString& sFilename ) { m_pTabWidget->setCurrentIndex(qtractorFiles::Audio); m_pAudioListView->selectFileItem(sFilename); } // MIDI file selection convenience method. void qtractorFiles::selectMidiFile ( const QString& sFilename, int iTrackChannel ) { m_pTabWidget->setCurrentIndex(qtractorFiles::Midi); m_pMidiListView->selectFileItem(sFilename, iTrackChannel); } // Audition/pre-listening player methods. void qtractorFiles::setPlayState ( bool bOn ) { ++m_iPlayUpdate; m_pPlayItemAction->setChecked(bOn); m_pPlayButton->setChecked(bOn); --m_iPlayUpdate; } bool qtractorFiles::isPlayState (void) const { return m_pPlayItemAction->isChecked(); } // Retrieve current selected file list view. qtractorFileListView *qtractorFiles::currentFileListView (void) const { switch (m_pTabWidget->currentIndex()) { case qtractorFiles::Audio: return m_pAudioListView; case qtractorFiles::Midi: return m_pMidiListView; default: return NULL; } } // Open and add a new file item below the current group one. void qtractorFiles::openFileSlot (void) { qtractorFileListView *pFileListView = currentFileListView(); if (pFileListView) pFileListView->openFile(); } // Add a new group item below the current one. void qtractorFiles::newGroupSlot (void) { qtractorFileListView *pFileListView = currentFileListView(); if (pFileListView) pFileListView->newGroup(); } // Cut current file item(s) to clipboard. void qtractorFiles::cutItemSlot (void) { qtractorFileListView *pFileListView = currentFileListView(); if (pFileListView) pFileListView->copyItem(true); } // Copy current file item(s) to clipboard. void qtractorFiles::copyItemSlot (void) { qtractorFileListView *pFileListView = currentFileListView(); if (pFileListView) pFileListView->copyItem(false); } // Paste file item(s) from clipboard. void qtractorFiles::pasteItemSlot (void) { qtractorFileListView *pFileListView = currentFileListView(); if (pFileListView) pFileListView->pasteItem(); } // Rename current group/file item. void qtractorFiles::renameItemSlot (void) { qtractorFileListView *pFileListView = currentFileListView(); if (pFileListView) pFileListView->renameItem(); } // Remove current group/file item. void qtractorFiles::removeItemSlot (void) { qtractorFileListView *pFileListView = currentFileListView(); if (pFileListView) pFileListView->removeItem(); } // Current item change slots. void qtractorFiles::stabilizeSlot (void) { qtractorFileListView *pFileListView = currentFileListView(); if (pFileListView) { QTreeWidgetItem *pItem = pFileListView->currentItem(); m_pCutItemAction->setEnabled( pItem && pItem->type() == qtractorFileListView::FileItem); m_pCopyItemAction->setEnabled( pItem && pItem->type() == qtractorFileListView::FileItem); m_pPasteItemAction->setEnabled( (QApplication::clipboard()->mimeData())->hasUrls()); m_pRenameItemAction->setEnabled( pItem && pItem->type() == qtractorFileListView::GroupItem); m_pRemoveItemAction->setEnabled( pItem && pItem->type() != qtractorFileListView::ChannelItem); m_pCleanupAction->setEnabled(pFileListView->topLevelItemCount() > 0); bool bPlayEnabled = ( pItem && pItem->type() != qtractorFileListView::GroupItem); m_pPlayItemAction->setEnabled(bPlayEnabled); m_pPlayButton->setEnabled(bPlayEnabled); } // Stabilize main form as well... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeForm(); } // Audition/pre-listening player slot. void qtractorFiles::playSlot ( bool bOn ) { if (m_iPlayUpdate > 0) return; setPlayState(bOn); if (bOn) { qtractorFileListView *pFileListView = currentFileListView(); if (pFileListView) pFileListView->activateItem(); } } // Clean-up unused file items. void qtractorFiles::cleanupSlot (void) { qtractorFileListView *pFileListView = currentFileListView(); if (pFileListView) pFileListView->cleanup(); } // Tab page switch slots. void qtractorFiles::pageAudioSlot (void) { m_pTabWidget->setCurrentIndex(qtractorFiles::Audio); } void qtractorFiles::pageMidiSlot (void) { m_pTabWidget->setCurrentIndex(qtractorFiles::Midi); } // Context menu request event handler. void qtractorFiles::contextMenuEvent ( QContextMenuEvent *pContextMenuEvent ) { QMenu menu(this); // Construct context menu. menu.addAction(m_pNewGroupAction); menu.addAction(m_pOpenFileAction); menu.addSeparator(); menu.addAction(m_pCutItemAction); menu.addAction(m_pCopyItemAction); menu.addAction(m_pPasteItemAction); menu.addSeparator(); menu.addAction(m_pRenameItemAction); menu.addSeparator(); menu.addAction(m_pRemoveItemAction); menu.addAction(m_pCleanupAction); menu.addSeparator(); menu.addAction(m_pPlayItemAction); menu.addSeparator(); // Switch page options... switch (m_pTabWidget->currentIndex()) { case qtractorFiles::Audio: menu.addAction(QIcon(":/images/trackMidi.png"), tr("MIDI Files"), this, SLOT(pageMidiSlot())); break; case qtractorFiles::Midi: menu.addAction(QIcon(":/images/trackAudio.png"), tr("Audio Files"), this, SLOT(pageAudioSlot())); break; default: break; } menu.exec(pContextMenuEvent->globalPos()); } // end of qtractorFiles.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditEvent.cpp0000644000175000001440000000012312166526620022227 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134670.60408 30 ctime=1381134670.604080106 qtractor-0.5.11/src/qtractorMidiEditEvent.cpp0000644000175000001440000004253412166526620021526 0ustar00rncbcusers00000000000000// qtractorMidiEditEvent.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiEditEvent.h" #include "qtractorMidiEditor.h" #include "qtractorMidiEditView.h" #include "qtractorMidiSequence.h" #include "qtractorSession.h" #include #include #include #include #include #include #include //---------------------------------------------------------------------------- // qtractorMidiEditEventScale -- MIDI event scale widget. // Constructor. qtractorMidiEditEventScale::qtractorMidiEditEventScale ( qtractorMidiEditor *pEditor, QWidget *pParent ) : QWidget(pParent) { m_pEditor = pEditor; QWidget::setMinimumWidth(22); // QWidget::setBackgroundRole(QPalette::Mid); const QFont& font = QWidget::font(); QWidget::setFont(QFont(font.family(), font.pointSize() - 2)); } // Default destructor. qtractorMidiEditEventScale::~qtractorMidiEditEventScale (void) { } // Paint event handler. void qtractorMidiEditEventScale::paintEvent ( QPaintEvent * ) { QPainter p(this); p.setPen(Qt::darkGray); // Draw scale line labels... qtractorMidiEditEvent *pEditEvent = m_pEditor->editEvent(); const QFontMetrics& fm = p.fontMetrics(); int h = (pEditEvent->viewport())->height(); int w = QWidget::width(); int h2 = (fm.height() >> 1); int dy = (h >> 3); // Account for event view widget frame... h += 4; int y = 2; int y0 = y + 1; int n = 128; int dn = (n >> 3); if (pEditEvent->eventType() == qtractorMidiEvent::PITCHBEND) { n = 8192; dn = (n >> 2); } while (y < h) { const QString& sLabel = QString::number(n); if (fm.width(sLabel) < w - 6) p.drawLine(w - 4, y, w - 1, y); if (y > y0 + (h2 << 1) && y < h - (h2 << 1)) { p.drawText(2, y - h2, w - 8, fm.height(), Qt::AlignRight | Qt::AlignVCenter, sLabel); y0 = y + 1; } y += dy; n -= dn; } } //---------------------------------------------------------------------------- // qtractorMidiEditEvent -- MIDI sequence event view widget. // Constructor. qtractorMidiEditEvent::qtractorMidiEditEvent ( qtractorMidiEditor *pEditor, QWidget *pParent ) : qtractorScrollView(pParent) { m_pEditor = pEditor; m_eventType = qtractorMidiEvent::NOTEON; m_controller = 0; // Zoom tool widgets m_pHzoomOut = new QToolButton(this); m_pHzoomIn = new QToolButton(this); m_pHzoomReset = new QToolButton(this); m_pHzoomOut->setIcon(QIcon(":/images/viewZoomOut.png")); m_pHzoomIn->setIcon(QIcon(":/images/viewZoomIn.png")); m_pHzoomReset->setIcon(QIcon(":/images/viewZoomTool.png")); int iScrollBarExtent = qtractorScrollView::style()->pixelMetric(QStyle::PM_ScrollBarExtent); m_pHzoomReset->setFixedWidth(iScrollBarExtent); m_pHzoomIn->setFixedWidth(iScrollBarExtent); m_pHzoomOut->setFixedWidth(iScrollBarExtent); qtractorScrollView::addScrollBarWidget(m_pHzoomReset, Qt::AlignRight); qtractorScrollView::addScrollBarWidget(m_pHzoomIn, Qt::AlignRight); qtractorScrollView::addScrollBarWidget(m_pHzoomOut, Qt::AlignRight); m_pHzoomIn->setAutoRepeat(true); m_pHzoomOut->setAutoRepeat(true); m_pHzoomIn->setToolTip(tr("Zoom in (horizontal)")); m_pHzoomOut->setToolTip(tr("Zoom out (horizontal)")); m_pHzoomReset->setToolTip(tr("Zoom reset (horizontal)")); QObject::connect(m_pHzoomIn, SIGNAL(clicked()), m_pEditor, SLOT(horizontalZoomInSlot())); QObject::connect(m_pHzoomOut, SIGNAL(clicked()), m_pEditor, SLOT(horizontalZoomOutSlot())); QObject::connect(m_pHzoomReset, SIGNAL(clicked()), m_pEditor, SLOT(horizontalZoomResetSlot())); qtractorScrollView::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); qtractorScrollView::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); qtractorScrollView::viewport()->setFocusPolicy(Qt::ClickFocus); // qtractorScrollView::viewport()->setFocusProxy(this); // qtractorScrollView::viewport()->setAcceptDrops(true); // qtractorScrollView::setDragAutoScroll(false); qtractorScrollView::setMouseTracking(true); const QFont& font = qtractorScrollView::font(); qtractorScrollView::setFont(QFont(font.family(), font.pointSize() - 1)); // QObject::connect(this, SIGNAL(contentsMoving(int,int)), // this, SLOT(updatePixmap(int,int))); // Trap for help/tool-tips and leave events. qtractorScrollView::viewport()->installEventFilter(this); } // Destructor. qtractorMidiEditEvent::~qtractorMidiEditEvent (void) { } // Rectangular contents update. void qtractorMidiEditEvent::updateContents ( const QRect& rect ) { updatePixmap( qtractorScrollView::contentsX(), qtractorScrollView::contentsY()); qtractorScrollView::updateContents(rect); } // Overall contents update. void qtractorMidiEditEvent::updateContents (void) { updatePixmap( qtractorScrollView::contentsX(), qtractorScrollView::contentsY()); qtractorScrollView::updateContents(); } // Current event selection accessors. void qtractorMidiEditEvent::setEventType ( qtractorMidiEvent::EventType eventType ) { m_eventType = eventType; m_pEditor->selectAll(this, false); // m_pEditor->updateContents(); } qtractorMidiEvent::EventType qtractorMidiEditEvent::eventType (void) const { return m_eventType; } void qtractorMidiEditEvent::setController ( unsigned char controller ) { m_controller = controller; m_pEditor->selectAll(this, false); // m_pEditor->updateContents(); } unsigned char qtractorMidiEditEvent::controller (void) const { return m_controller; } // Resize event handler. void qtractorMidiEditEvent::resizeEvent ( QResizeEvent *pResizeEvent ) { qtractorScrollView::resizeEvent(pResizeEvent); // FIXME: Prevent any overlay selection during resizing this, // as the overlay rectangles will certainly be wrong... if (m_pEditor->isSelected()) { m_pEditor->updateContents(); } else { updateContents(); } } // (Re)create the complete view pixmap. void qtractorMidiEditEvent::updatePixmap ( int cx, int /*cy*/ ) { QWidget *pViewport = qtractorScrollView::viewport(); const int w = pViewport->width(); const int h = pViewport->height() & ~1; // always even. if (w < 1 || h < 1) return; const QPalette& pal = qtractorScrollView::palette(); const QColor& rgbBase = pal.base().color(); const QColor& rgbFore = m_pEditor->foreground(); const QColor& rgbBack = m_pEditor->background(); const QColor& rgbDark = pal.mid().color(); const QColor& rgbLight = pal.midlight().color(); m_pixmap = QPixmap(w, h); m_pixmap.fill(rgbBase); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorTimeScale *pTimeScale = m_pEditor->timeScale(); if (pTimeScale == NULL) return; QPainter p(&m_pixmap); p.initFrom(this); // Show that we may have clip limits... if (m_pEditor->length() > 0) { int x1 = pTimeScale->pixelFromFrame(m_pEditor->length()) - cx; if (x1 < 0) x1 = 0; if (x1 < w) p.fillRect(x1, 0, w - x1, h, rgbBase.darker(105)); } // Draw horizontal lines... p.setPen(rgbLight); int dy = (h >> 3); int y = 0; while (y < h) { p.drawLine(0, y, w, y); y += dy; } // Account for the editing offset: qtractorTimeScale::Cursor cursor(pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(m_pEditor->offset()); unsigned long t0 = pNode->tickFromFrame(m_pEditor->offset()); int x0 = pTimeScale->pixelFromFrame(m_pEditor->offset()); int dx = x0 + cx; // Draw vertical grid lines... const QBrush zebra(QColor(0, 0, 0, 20)); pNode = cursor.seekPixel(dx); unsigned short iSnapPerBeat = (m_pEditor->isSnapGrid() ? pTimeScale->snapPerBeat() : 0); unsigned short iPixelsPerBeat = pNode->pixelsPerBeat(); unsigned int iBeat = pNode->beatFromPixel(dx); unsigned short iBar = (m_pEditor->isSnapZebra() ? pNode->barFromBeat(iBeat) : 0); int x = pNode->pixelFromBeat(iBeat) - dx; int x2 = x; while (x < w) { bool bBeatIsBar = pNode->beatIsBar(iBeat); if (bBeatIsBar) { p.setPen(rgbDark); p.drawLine(x - 1, 0, x - 1, h); if (m_pEditor->isSnapZebra() && (x > x2) && (++iBar & 1)) p.fillRect(QRect(x2, 0, x - x2 + 1, h), zebra); x2 = x; if (iBeat == pNode->beat) iPixelsPerBeat = pNode->pixelsPerBeat(); } if (bBeatIsBar || iPixelsPerBeat > 8) { p.setPen(rgbLight); p.drawLine(x, 0, x, h); } if (iSnapPerBeat > 1) { int q = iPixelsPerBeat / iSnapPerBeat; if (q > 4) { p.setPen(rgbBase.value() < 0x7f ? rgbLight.darker(105) : rgbLight.lighter(120)); for (int i = 1; i < iSnapPerBeat; ++i) { x = pTimeScale->pixelSnap(x + dx + q) - dx - 1; p.drawLine(x, 0, x, h); } } } pNode = cursor.seekBeat(++iBeat); x = pNode->pixelFromBeat(iBeat) - dx; } if (m_pEditor->isSnapZebra() && (x > x2) && (++iBar & 1)) p.fillRect(QRect(x2, 0, x - x2 + 1, h), zebra); // Draw location marker lines... qtractorTimeScale::Marker *pMarker = pTimeScale->markers().seekPixel(dx); while (pMarker) { x = pTimeScale->pixelFromFrame(pMarker->frame) - dx; if (x > w) break; p.setPen(pMarker->color); p.drawLine(x, 0, x, h); pMarker = pMarker->next(); } // // Draw the sequence events... // qtractorMidiSequence *pSeq = m_pEditor->sequence(); if (pSeq == NULL) return; pNode = cursor.seekPixel(x = dx); unsigned long iTickStart = pNode->tickFromPixel(x); pNode = cursor.seekPixel(x += w); unsigned long iTickEnd = pNode->tickFromPixel(x); // This is the zero-line... const int y0 = (m_eventType == qtractorMidiEvent::PITCHBEND ? h >> 1 : h); p.setPen(rgbLight); p.drawLine(0, y0 - 1, w, y0 - 1); p.setPen(rgbDark); p.drawLine(0, y0, w, y0); // p.setPen(rgbFore); // p.setBrush(rgbBack); QColor rgbValue(rgbBack); int hue, sat, val; rgbValue.getHsv(&hue, &sat, &val); sat = 86; bool bController = (m_eventType == qtractorMidiEvent::CONTROLLER); qtractorMidiEvent *pEvent = m_pEditor->seekEvent(iTickStart > t0 ? iTickStart - t0 : 0); while (pEvent) { unsigned long t1 = t0 + pEvent->time(); if (t1 >= iTickEnd) break; unsigned long t2 = t1 + pEvent->duration(); // Filter event type!... if (pEvent->type() == m_eventType && t2 >= iTickStart && (!bController || pEvent->controller() == m_controller)) { if (m_eventType == qtractorMidiEvent::PITCHBEND) y = y0 - (y0 * pEvent->pitchBend()) / 8192; else y = y0 - (y0 * pEvent->value()) / 128; pNode = cursor.seekTick(t1); x = pNode->pixelFromTick(t1) - x0 - cx; int w1 = pNode->pixelFromTick(t2) - x0 - cx - x; if (w1 < 5 || !m_pEditor->isNoteDuration()) w1 = 5; if (m_eventType == qtractorMidiEvent::NOTEON || m_eventType == qtractorMidiEvent::KEYPRESS) { if (m_pEditor->isNoteColor()) { hue = (128 - int(pEvent->note())) << 4; if (m_pEditor->isValueColor()) sat = 64 + (int(pEvent->velocity()) >> 1); rgbValue.setHsv(hue, sat, val); } else if (m_pEditor->isValueColor()) { hue = (128 - int(pEvent->velocity())) << 1; rgbValue.setHsv(hue, sat, val); } } if (y < y0) { p.fillRect(x, y, w1, y0 - y, rgbFore); p.fillRect(x + 1, y + 1, w1 - 4, y0 - y - 2, rgbValue); } else if (y > y0) { p.fillRect(x, y0, w1, y - y0, rgbFore); p.fillRect(x + 1, y0 + 1, w1 - 4, y - y0 - 2, rgbValue); } else { p.fillRect(x, y0 - 2, w1, 4, rgbFore); p.fillRect(x + 1, y0 - 1, w1 - 4, 2, rgbValue); } } pEvent = pEvent->next(); } // Draw loop boundaries, if applicable... if (pSession->isLooping()) { const QBrush shade(QColor(0, 0, 0, 60)); p.setPen(Qt::darkCyan); x = pTimeScale->pixelFromFrame(pSession->loopStart()) - dx; if (x >= w) p.fillRect(QRect(0, 0, w, h), shade); else if (x >= 0) { p.fillRect(QRect(0, 0, x, h), shade); p.drawLine(x, 0, x, h); } x = pTimeScale->pixelFromFrame(pSession->loopEnd()) - dx; if (x < 0) p.fillRect(QRect(0, 0, w, h), shade); else if (x < w) { p.fillRect(QRect(x, 0, w - x, h), shade); p.drawLine(x, 0, x, h); } } // Draw punch boundaries, if applicable... if (pSession->isPunching()) { const QBrush shade(QColor(0, 0, 0, 60)); p.setPen(Qt::darkMagenta); x = pTimeScale->pixelFromFrame(pSession->punchIn()) - dx; if (x >= w) p.fillRect(QRect(0, 0, w, h), shade); else if (x >= 0) { p.fillRect(QRect(0, 0, x, h), shade); p.drawLine(x, 0, x, h); } x = pTimeScale->pixelFromFrame(pSession->punchOut()) - dx; if (x < 0) p.fillRect(QRect(0, 0, w, h), shade); else if (x < w) { p.fillRect(QRect(x, 0, w - x, h), shade); p.drawLine(x, 0, x, h); } } } // Draw the time scale. void qtractorMidiEditEvent::drawContents ( QPainter *pPainter, const QRect& rect ) { pPainter->drawPixmap(rect, m_pixmap, rect); m_pEditor->paintDragState(this, pPainter); // Draw special play-head line... int cx = qtractorScrollView::contentsX(); int x = m_pEditor->playHeadX() - cx; if (x >= rect.left() && x <= rect.right()) { pPainter->setPen(Qt::red); pPainter->drawLine(x, rect.top(), x, rect.bottom()); } // Draw edit-head line... x = m_pEditor->editHeadX() - cx; if (x >= rect.left() && x <= rect.right()) { pPainter->setPen(Qt::blue); pPainter->drawLine(x, rect.top(), x, rect.bottom()); } // Draw edit-tail line... x = m_pEditor->editTailX() - cx; if (x >= rect.left() && x <= rect.right()) { pPainter->setPen(Qt::blue); pPainter->drawLine(x, rect.top(), x, rect.bottom()); } } // To have event view in h-sync with main view. void qtractorMidiEditEvent::contentsXMovingSlot ( int cx, int /*cy*/ ) { if (qtractorScrollView::contentsX() != cx) qtractorScrollView::setContentsPos(cx, qtractorScrollView::contentsY()); } // Focus lost event. void qtractorMidiEditEvent::focusOutEvent ( QFocusEvent *pFocusEvent ) { m_pEditor->focusOut(this); qtractorScrollView::focusOutEvent(pFocusEvent); } // Keyboard event handler. void qtractorMidiEditEvent::keyPressEvent ( QKeyEvent *pKeyEvent ) { if (!m_pEditor->keyPress(this, pKeyEvent->key(), pKeyEvent->modifiers())) qtractorScrollView::keyPressEvent(pKeyEvent); } // Handle item selection/dragging -- mouse button press. void qtractorMidiEditEvent::mousePressEvent ( QMouseEvent *pMouseEvent ) { // Process mouse press... // qtractorScrollView::mousePressEvent(pMouseEvent); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Which mouse state? const bool bModifier = (pMouseEvent->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)); // Maybe start the drag-move-selection dance? const QPoint& pos = qtractorScrollView::viewportToContents(pMouseEvent->pos()); qtractorTimeScale *pTimeScale = m_pEditor->timeScale(); unsigned long iFrame = pTimeScale->frameSnap(m_pEditor->offset() + pTimeScale->frameFromPixel(pos.x() > 0 ? pos.x() : 0)); switch (pMouseEvent->button()) { case Qt::LeftButton: // Only the left-mouse-button was meaningful... break; case Qt::MidButton: // Mid-button direct positioning... m_pEditor->selectAll(this, false); // Which mouse state? if (bModifier) { // Play-head positioning commit... m_pEditor->setPlayHead(iFrame); pSession->setPlayHead(m_pEditor->playHead()); } else { // Edit cursor (merge) positioning... m_pEditor->setEditHead(iFrame); m_pEditor->setEditTail(iFrame); } // Logical contents changed, just for visual feedback... m_pEditor->selectionChangeNotify(); // Fall thru... default: return; } // Remember what and where we'll be dragging/selecting... m_pEditor->dragMoveStart(this, pos, pMouseEvent->modifiers()); } // Handle item selection/dragging -- mouse pointer move. void qtractorMidiEditEvent::mouseMoveEvent ( QMouseEvent *pMouseEvent ) { // Process mouse move... // qtractorScrollView::mouseMoveEvent(pMouseEvent); // Are we already moving/dragging something? const QPoint& pos = qtractorScrollView::viewportToContents(pMouseEvent->pos()); m_pEditor->dragMoveUpdate(this, pos, pMouseEvent->modifiers()); } // Handle item selection/dragging -- mouse button release. void qtractorMidiEditEvent::mouseReleaseEvent ( QMouseEvent *pMouseEvent ) { // Were we moving/dragging something? const QPoint& pos = qtractorScrollView::viewportToContents(pMouseEvent->pos()); m_pEditor->dragMoveCommit(this, pos, pMouseEvent->modifiers()); } // Handle zoom with mouse wheel. void qtractorMidiEditEvent::wheelEvent ( QWheelEvent *pWheelEvent ) { if (pWheelEvent->modifiers() & Qt::ControlModifier) { int delta = pWheelEvent->delta(); if (delta > 0) m_pEditor->zoomIn(); else m_pEditor->zoomOut(); } else qtractorScrollView::wheelEvent(pWheelEvent); } // Trap for help/tool-tip and leave events. bool qtractorMidiEditEvent::eventFilter ( QObject *pObject, QEvent *pEvent ) { if (m_pEditor->dragMoveFilter(this, pObject, pEvent)) return true; // Not handled here. return qtractorScrollView::eventFilter(pObject, pEvent); } // end of qtractorMidiEditEvent.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorPluginForm.ui0000644000175000001440000000012311723216126021445 xustar000000000000000027 mtime=1330453590.950629 26 atime=1381134671.09408 30 ctime=1381134671.094080114 qtractor-0.5.11/src/qtractorPluginForm.ui0000644000175000001440000002347011723216126020742 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorPluginForm 0 0 480 120 Sans Serif 8 50 false false false false qtractorPluginForm :/images/trackProperties.png 4 4 Qt::TabFocus Open preset :/images/formOpen.png 160 0 Preset name true Qt::TabFocus Save preset :/images/formSave.png Qt::TabFocus Delete preset :/images/formRemove.png Qt::Horizontal QSizePolicy::Expanding 20 20 Qt::TabFocus Plugin parameters Params :/images/formParamsOff.png true Qt::ToolButtonTextBesideIcon Qt::TabFocus Edit plugin Edit :/images/formEdit.png true Qt::ToolButtonTextBesideIcon Qt::TabFocus Activate plugin Active :/images/itemLedOff.png true Qt::ToolButtonTextBesideIcon Qt::TabFocus Outputs (Sends) Sends :/images/itemAudioPortOut.png Qt::ToolButtonTextBesideIcon Qt::TabFocus Inputs (Returns) Returns :/images/itemAudioPortIn.png Qt::ToolButtonTextBesideIcon Aux Send Bus: 22 22 24 24 Qt::TabFocus Manage buses ... Qt::Horizontal QSizePolicy::Expanding 20 0 80 22 120 24 Qt::TabFocus Direct Access Parameter Direct Access PresetComboBox OpenPresetToolButton SavePresetToolButton DeletePresetToolButton ParamsToolButton EditToolButton ActivateToolButton SendsToolButton ReturnsToolButton AudioBusNameComboBox AudioBusNameToolButton DirectAccessParamPushButton qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioClip.h0000644000175000001440000000012312106025301021033 xustar000000000000000027 mtime=1360538305.788922 26 atime=1381134666.49208 30 ctime=1381134666.492080041 qtractor-0.5.11/src/qtractorAudioClip.h0000644000175000001440000001266012106025301020327 0ustar00rncbcusers00000000000000// qtractorAudioClip.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorAudioClip_h #define __qtractorAudioClip_h #include "qtractorClip.h" #include "qtractorAudioBuffer.h" // Forward declarations. class qtractorAudioPeak; //---------------------------------------------------------------------- // class qtractorAudioClip -- Audio file/buffer clip. // class qtractorAudioClip : public qtractorClip { public: // Constructor. qtractorAudioClip(qtractorTrack *pTrack); // Copy constructor. qtractorAudioClip(const qtractorAudioClip& clip); // Destructor. ~qtractorAudioClip(); // Time-stretching. void setTimeStretch(float fTimeStretch); float timeStretch() const; // Pitch-shifting. void setPitchShift(float fPitchShift); float pitchShift() const; // Alternating overlap tag. unsigned int overlap() const; // Clip (re)open method. void open(); // The main use method. bool openAudioFile(const QString& sFilename, int iMode = qtractorAudioFile::Read); // Sequence properties accessors. qtractorAudioBuffer *buffer() const { return (m_pData ? m_pData->buffer() : NULL); } // Direct write method. void write(float **ppBuffer, unsigned int iFrames, unsigned short iChannels = 0, unsigned int iOffset = 0); // Export-mode sync method. void syncExport(); // Intra-clip frame positioning. void seek(unsigned long iFrame); // Reset clip state. void reset(bool bLooping); // Loop positioning. void setLoop(unsigned long iLoopStart, unsigned long iLoopEnd); // Clip close-commit (record specific) void close(); // Audio clip special process cycle executive. void process(unsigned long iFrameStart, unsigned long iFrameEnd); // Clip paint method. void draw(QPainter *pPainter, const QRect& clipRect, unsigned long iClipOffset); // Audio clip tool-tip. QString toolTip() const; // Audio clip export method. typedef void (*ClipExport)(float **, unsigned int, void *); bool clipExport(ClipExport pfnClipExport, void *pvArg, unsigned long iOffset = 0, unsigned long iLength = 0) const; // Most interesting key/data (ref-counted?)... class Key; class Data { public: // Constructor. Data(qtractorTrack *pTrack, unsigned short iChannels, unsigned int iSampleRate) : m_pBuff(new qtractorAudioBuffer(pTrack->syncThread(), iChannels, iSampleRate)) {} // Destructor. ~Data() { clear(); delete m_pBuff; } // Buffer accessor. qtractorAudioBuffer *buffer() const { return m_pBuff; } // Direct write method. void write (float **ppBuffer, unsigned int iFrames, unsigned short iChannels, unsigned int iOffset) { m_pBuff->write(ppBuffer, iFrames, iChannels, iOffset); } // Direct sync method. void syncExport() { m_pBuff->syncExport(); } // Intra-clip frame positioning. void seek(unsigned long iFrame) { m_pBuff->seek(iFrame); } // Reset buffer state. void reset(bool bLooping) { m_pBuff->reset(bLooping); } // Loop positioning. void setLoop(unsigned long iLoopStart, unsigned long iLoopEnd) { m_pBuff->setLoop(iLoopStart, iLoopEnd); } // Ref-counting related methods. void attach(qtractorAudioClip *pAudioClip) { m_clips.append(pAudioClip); } void detach(qtractorAudioClip *pAudioClip) { m_clips.removeAll(pAudioClip); } unsigned short count() const { return m_clips.count(); } const QList& clips() const { return m_clips; } void clear() { m_clips.clear(); } private: // Interesting variables. qtractorAudioBuffer *m_pBuff; // Ref-counting related stuff. QList m_clips; }; typedef QHash Hash; // Manage local hash key. void insertHashKey(); void updateHashKey(); void removeHashKey(); // Un/relink (de/clone) local hash data. void unlinkHashData(); void relinkHashData(); // Whether local hash is being shared. bool isHashLinked() const; // Make sure the clip hash-table gets reset. static void clearHashTable(); protected: // Virtual document element methods. bool loadClipElement(qtractorDocument *pDocument, QDomElement *pElement); bool saveClipElement(qtractorDocument *pDocument, QDomElement *pElement) const; // Private cleanup. void closeAudioFile(); // Alternating overlap test. bool isOverlap(unsigned int iOverlapSize) const; private: // Instance variables. qtractorAudioPeak *m_pPeak; float m_fTimeStretch; float m_fPitchShift; // Alternate overlap tag. unsigned int m_iOverlap; // Most interesting key/data (ref-counted?)... Key *m_pKey; Data *m_pData; static Hash g_hashTable; }; #endif // __qtractorAudioClip_h // end of qtractorAudioClip.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorOptionsForm.cpp0000644000175000001440000000012112203713015021776 xustar000000000000000025 mtime=1376753165.6215 26 atime=1381134669.06008 30 ctime=1381134669.060080082 qtractor-0.5.11/src/qtractorOptionsForm.cpp0000644000175000001440000014231112203713015021271 0ustar00rncbcusers00000000000000// qtractorOptionsForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorOptionsForm.h" #include "qtractorAbout.h" #include "qtractorOptions.h" #include "qtractorAudioFile.h" #include "qtractorMidiTimer.h" #include "qtractorMidiEditor.h" #include "qtractorTimeScale.h" #include "qtractorPlugin.h" #include "qtractorAudioMeter.h" #include "qtractorMidiMeter.h" #include #include #include #include #include #include #include // Needed for fabs(), logf() and powf() #include static inline float log10f2 ( float x ) { return (x > 0.0f ? 20.0f * ::log10f(x) : -60.0f); } static inline float pow10f2 ( float x ) { return ::powf(10.0f, 0.05f * x); } // Translatable macro contextualizer. #undef _TR #define _TR(x) QT_TR_NOOP(x) // Available session formats/ext-suffixes. static struct { const char *name; const char *ext; } g_aSessionFormats[] = { { _TR("XML Default (*.%1)"), "qtr" }, { _TR("XML Regular (*.%1)"), "qts" }, { _TR("ZIP Archive (*.%1)"), "qtz" }, { NULL, NULL } }; //---------------------------------------------------------------------------- // qtractorOptionsForm -- UI wrapper form. // Constructor. qtractorOptionsForm::qtractorOptionsForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::ApplicationModal); // No settings descriptor initially (the caller will set it). m_pOptions = NULL; // Populate the session format combo-box. m_ui.SessionFormatComboBox->clear(); for (int i = 0; g_aSessionFormats[i].ext; ++i) { m_ui.SessionFormatComboBox->addItem( tr(g_aSessionFormats[i].name).arg(g_aSessionFormats[i].ext)); } // Populate the capture file type combo-box. m_ui.AudioCaptureTypeComboBox->clear(); int iFormat = 0; const qtractorAudioFileFactory::FileFormats& list = qtractorAudioFileFactory::formats(); QListIterator iter(list); while (iter.hasNext()) { qtractorAudioFileFactory::FileFormat *pFormat = iter.next(); if (pFormat->type != qtractorAudioFileFactory::MadFile) m_ui.AudioCaptureTypeComboBox->addItem(pFormat->name, iFormat); ++iFormat; } // Populate the audio capture sample format combo-box. m_ui.AudioCaptureFormatComboBox->clear(); m_ui.AudioCaptureFormatComboBox->addItem(tr("Signed 16-Bit")); m_ui.AudioCaptureFormatComboBox->addItem(tr("Signed 24-Bit")); m_ui.AudioCaptureFormatComboBox->addItem(tr("Signed 32-Bit")); m_ui.AudioCaptureFormatComboBox->addItem(tr("Float 32-Bit")); m_ui.AudioCaptureFormatComboBox->addItem(tr("Float 64-Bit")); // Populate the MIDI capture file format combo-box. m_ui.MidiCaptureFormatComboBox->clear(); m_ui.MidiCaptureFormatComboBox->addItem(tr("SMF Format 0")); m_ui.MidiCaptureFormatComboBox->addItem(tr("SMF Format 1")); // Populate the MIDI capture quantize combo-box. QStringList items = qtractorTimeScale::snapItems(0); m_ui.MidiCaptureQuantizeComboBox->clear(); m_ui.MidiCaptureQuantizeComboBox->insertItems(0, items); // Populate the MMC device combo-box. m_ui.MidiMmcDeviceComboBox->clear(); for (unsigned char mmcDevice = 0; mmcDevice < 0x7f; ++mmcDevice) m_ui.MidiMmcDeviceComboBox->addItem(QString::number(int(mmcDevice))); m_ui.MidiMmcDeviceComboBox->addItem(tr("(Any)")); // updateMetroNoteNames(); // Plugin path types... m_ui.PluginTypeComboBox->clear(); #ifdef CONFIG_LADSPA m_ui.PluginTypeComboBox->addItem( qtractorPluginType::textFromHint(qtractorPluginType::Ladspa)); #endif #ifdef CONFIG_DSSI m_ui.PluginTypeComboBox->addItem( qtractorPluginType::textFromHint(qtractorPluginType::Dssi)); #endif #ifdef CONFIG_VST m_ui.PluginTypeComboBox->addItem( qtractorPluginType::textFromHint(qtractorPluginType::Vst)); #else m_ui.PluginExperimentalGroupBox->hide(); #endif #ifdef CONFIG_LV2 m_ui.PluginTypeComboBox->addItem( qtractorPluginType::textFromHint(qtractorPluginType::Lv2)); #endif #ifndef CONFIG_LV2_PRESETS m_ui.Lv2PresetDirLabel->hide(); m_ui.Lv2PresetDirComboBox->hide(); m_ui.Lv2PresetDirToolButton->hide(); #endif // Initialize dirty control state. m_iDirtyCount = 0; // Try to restore old window positioning. adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.AudioCaptureTypeComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.AudioCaptureFormatComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.AudioCaptureQualitySpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.AudioResampleTypeComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.TransportModeComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.AudioAutoTimeStretchCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.AudioWsolaTimeStretchCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.AudioWsolaQuickSeekCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.AudioPlayerBusCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.AudioPlayerAutoConnectCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.AudioMetronomeCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.MetroBarFilenameComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(changed())); QObject::connect(m_ui.MetroBarFilenameToolButton, SIGNAL(clicked()), SLOT(chooseMetroBarFilename())); QObject::connect(m_ui.MetroBarGainSpinBox, SIGNAL(valueChanged(double)), SLOT(changed())); QObject::connect(m_ui.MetroBeatFilenameComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(changed())); QObject::connect(m_ui.MetroBeatFilenameToolButton, SIGNAL(clicked()), SLOT(chooseMetroBeatFilename())); QObject::connect(m_ui.MetroBeatGainSpinBox, SIGNAL(valueChanged(double)), SLOT(changed())); QObject::connect(m_ui.AudioMetroBusCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.AudioMetroAutoConnectCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.MidiCaptureFormatComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.MidiCaptureQuantizeComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.MidiQueueTimerComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.MidiPlayerBusCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.MidiMmcModeComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.MidiMmcDeviceComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.MidiSppModeComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.MidiClockModeComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.MidiControlBusCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.MidiMetronomeCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.MetroChannelSpinBox, SIGNAL(valueChanged(int)), SLOT(updateMetroNoteNames())); QObject::connect(m_ui.MetroBarNoteComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.MetroBarVelocitySpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.MetroBarDurationSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.MetroBeatNoteComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.MetroBeatVelocitySpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.MetroBeatDurationSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.MidiMetroBusCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.ConfirmRemoveCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.StdoutCaptureCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.CompletePathCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.PeakAutoRemoveCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.KeepToolsOnTopCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.TrackViewDropSpanCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.MidButtonModifierCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.LoopRecordingModeComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.DisplayFormatComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.MaxRecentFilesSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.BaseFontSizeComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(changed())); QObject::connect(m_ui.SessionFormatComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.SessionTemplateCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.SessionTemplatePathComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(changed())); QObject::connect(m_ui.SessionTemplatePathToolButton, SIGNAL(clicked()), SLOT(chooseSessionTemplatePath())); QObject::connect(m_ui.SessionBackupCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.SessionBackupModeComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.AudioMeterLevelComboBox, SIGNAL(activated(int)), SLOT(changeAudioMeterLevel(int))); QObject::connect(m_ui.MidiMeterLevelComboBox, SIGNAL(activated(int)), SLOT(changeMidiMeterLevel(int))); QObject::connect(m_ui.AudioMeterColorLineEdit, SIGNAL(textChanged(const QString&)), SLOT(changeAudioMeterColor(const QString&))); QObject::connect(m_ui.MidiMeterColorLineEdit, SIGNAL(textChanged(const QString&)), SLOT(changeMidiMeterColor(const QString&))); QObject::connect(m_ui.AudioMeterColorToolButton, SIGNAL(clicked()), SLOT(chooseAudioMeterColor())); QObject::connect(m_ui.MidiMeterColorToolButton, SIGNAL(clicked()), SLOT(chooseMidiMeterColor())); QObject::connect(m_ui.ResetMeterColorsPushButton, SIGNAL(clicked()), SLOT(resetMeterColors())); QObject::connect(m_ui.PluginTypeComboBox, SIGNAL(activated(int)), SLOT(choosePluginType(int))); QObject::connect(m_ui.PluginPathComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(changePluginPath(const QString&))); QObject::connect(m_ui.PluginPathBrowseToolButton, SIGNAL(clicked()), SLOT(choosePluginPath())); QObject::connect(m_ui.PluginPathAddToolButton, SIGNAL(clicked()), SLOT(addPluginPath())); QObject::connect(m_ui.PluginPathListWidget, SIGNAL(itemSelectionChanged()), SLOT(selectPluginPath())); QObject::connect(m_ui.PluginPathRemoveToolButton, SIGNAL(clicked()), SLOT(removePluginPath())); QObject::connect(m_ui.PluginPathUpToolButton, SIGNAL(clicked()), SLOT(moveUpPluginPath())); QObject::connect(m_ui.PluginPathDownToolButton, SIGNAL(clicked()), SLOT(moveDownPluginPath())); QObject::connect(m_ui.Lv2PresetDirComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(changed())); QObject::connect(m_ui.Lv2PresetDirToolButton, SIGNAL(clicked()), SLOT(chooseLv2PresetDir())); QObject::connect(m_ui.AudioOutputBusCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.AudioOutputAutoConnectCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.OpenEditorCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.DummyVstScanCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.MessagesFontPushButton, SIGNAL(clicked()), SLOT(chooseMessagesFont())); QObject::connect(m_ui.MessagesLimitCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.MessagesLimitLinesSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.MessagesLogCheckBox, SIGNAL(stateChanged(int)), SLOT(changed())); QObject::connect(m_ui.MessagesLogPathComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(changed())); QObject::connect(m_ui.MessagesLogPathToolButton, SIGNAL(clicked()), SLOT(chooseMessagesLogPath())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); } // Destructor. qtractorOptionsForm::~qtractorOptionsForm (void) { } // Populate (setup) dialog controls from settings descriptors. void qtractorOptionsForm::setOptions ( qtractorOptions *pOptions ) { // Set reference descriptor. m_pOptions = pOptions; // Initialize conveniency options... m_pOptions->loadComboBoxHistory(m_ui.MetroBarFilenameComboBox); m_pOptions->loadComboBoxHistory(m_ui.MetroBeatFilenameComboBox); m_pOptions->loadComboBoxHistory(m_ui.PluginPathComboBox); m_pOptions->loadComboBoxHistory(m_ui.MessagesLogPathComboBox); m_pOptions->loadComboBoxHistory(m_ui.SessionTemplatePathComboBox); m_pOptions->loadComboBoxHistory(m_ui.Lv2PresetDirComboBox); // Audio options. int iIndex = 0; int iFormat = 0; const qtractorAudioFileFactory::FileFormats& list = qtractorAudioFileFactory::formats(); QListIterator iter(list); while (iter.hasNext()) { qtractorAudioFileFactory::FileFormat *pFormat = iter.next(); if (m_pOptions->sAudioCaptureExt == pFormat->ext && m_pOptions->iAudioCaptureType == pFormat->data) { iIndex = m_ui.AudioCaptureTypeComboBox->findData(iFormat); break; } ++iFormat; } m_ui.AudioCaptureTypeComboBox->setCurrentIndex(iIndex); m_ui.AudioCaptureFormatComboBox->setCurrentIndex(m_pOptions->iAudioCaptureFormat); m_ui.AudioCaptureQualitySpinBox->setValue(m_pOptions->iAudioCaptureQuality); m_ui.AudioResampleTypeComboBox->setCurrentIndex(m_pOptions->iAudioResampleType); m_ui.TransportModeComboBox->setCurrentIndex(m_pOptions->iTransportMode); m_ui.AudioAutoTimeStretchCheckBox->setChecked(m_pOptions->bAudioAutoTimeStretch); #ifdef CONFIG_LIBRUBBERBAND m_ui.AudioWsolaTimeStretchCheckBox->setChecked(m_pOptions->bAudioWsolaTimeStretch); #else m_ui.AudioWsolaTimeStretchCheckBox->setChecked(true); m_ui.AudioWsolaTimeStretchCheckBox->setEnabled(false); #endif m_ui.AudioWsolaQuickSeekCheckBox->setChecked(m_pOptions->bAudioWsolaQuickSeek); m_ui.AudioPlayerBusCheckBox->setChecked(m_pOptions->bAudioPlayerBus); m_ui.AudioPlayerAutoConnectCheckBox->setChecked(m_pOptions->bAudioPlayerAutoConnect); #ifndef CONFIG_LIBSAMPLERATE m_ui.AudioResampleTypeTextLabel->setEnabled(false); m_ui.AudioResampleTypeComboBox->setEnabled(false); #endif // Audio metronome options. m_ui.AudioMetronomeCheckBox->setChecked(m_pOptions->bAudioMetronome); m_ui.MetroBarFilenameComboBox->setEditText(m_pOptions->sMetroBarFilename); m_ui.MetroBarGainSpinBox->setValue(log10f2(m_pOptions->fMetroBarGain)); m_ui.MetroBeatFilenameComboBox->setEditText(m_pOptions->sMetroBeatFilename); m_ui.MetroBeatGainSpinBox->setValue(log10f2(m_pOptions->fMetroBeatGain)); m_ui.AudioMetroBusCheckBox->setChecked(m_pOptions->bAudioMetroBus); m_ui.AudioMetroAutoConnectCheckBox->setChecked(m_pOptions->bAudioMetroAutoConnect); // MIDI capture/export options. m_ui.MidiCaptureFormatComboBox->setCurrentIndex(m_pOptions->iMidiCaptureFormat); m_ui.MidiCaptureQuantizeComboBox->setCurrentIndex(m_pOptions->iMidiCaptureQuantize); // MIDI playback options. qtractorMidiTimer timer; m_ui.MidiQueueTimerComboBox->clear(); for (int i = 0; i < timer.count(); ++i) m_ui.MidiQueueTimerComboBox->addItem(timer.name(i), timer.key(i)); m_ui.MidiQueueTimerComboBox->setCurrentIndex( timer.indexOf(m_pOptions->iMidiQueueTimer)); m_ui.MidiPlayerBusCheckBox->setChecked(m_pOptions->bMidiPlayerBus); // MIDI control options. m_ui.MidiMmcModeComboBox->setCurrentIndex(m_pOptions->iMidiMmcMode); m_ui.MidiMmcDeviceComboBox->setCurrentIndex(m_pOptions->iMidiMmcDevice); m_ui.MidiSppModeComboBox->setCurrentIndex(m_pOptions->iMidiSppMode); m_ui.MidiClockModeComboBox->setCurrentIndex(m_pOptions->iMidiClockMode); m_ui.MidiControlBusCheckBox->setChecked(m_pOptions->bMidiControlBus); // MIDI metronome options. m_ui.MidiMetronomeCheckBox->setChecked(m_pOptions->bMidiMetronome); m_ui.MetroChannelSpinBox->setValue(m_pOptions->iMetroChannel + 1); updateMetroNoteNames(); m_ui.MetroBarNoteComboBox->setCurrentIndex(m_pOptions->iMetroBarNote); m_ui.MetroBarVelocitySpinBox->setValue(m_pOptions->iMetroBarVelocity); m_ui.MetroBarDurationSpinBox->setValue(m_pOptions->iMetroBarDuration); m_ui.MetroBeatNoteComboBox->setCurrentIndex(m_pOptions->iMetroBeatNote); m_ui.MetroBeatVelocitySpinBox->setValue(m_pOptions->iMetroBeatVelocity); m_ui.MetroBeatDurationSpinBox->setValue(m_pOptions->iMetroBeatDuration); m_ui.MidiMetroBusCheckBox->setChecked(m_pOptions->bMidiMetroBus); // Custom colors. int iColor; for (iColor = 0; iColor < AudioMeterColors; ++iColor) m_audioMeterColors[iColor] = qtractorAudioMeter::color(iColor); for (iColor = 0; iColor < MidiMeterColors; ++iColor) m_midiMeterColors[iColor] = qtractorMidiMeter::color(iColor); // Default meter color levels shown... m_ui.AudioMeterLevelComboBox->setCurrentIndex(AudioMeterColors - 1); m_ui.MidiMeterLevelComboBox->setCurrentIndex(MidiMeterColors - 1); changeAudioMeterLevel(m_ui.AudioMeterLevelComboBox->currentIndex()); changeMidiMeterLevel(m_ui.MidiMeterLevelComboBox->currentIndex()); // Load Display options... QFont font; // Messages font. if (m_pOptions->sMessagesFont.isEmpty() || !font.fromString(m_pOptions->sMessagesFont)) font = QFont("Monospace", 8); QPalette pal(m_ui.MessagesFontTextLabel->palette()); pal.setColor(QPalette::Background, pal.base().color()); m_ui.MessagesFontTextLabel->setPalette(pal); m_ui.MessagesFontTextLabel->setFont(font); m_ui.MessagesFontTextLabel->setText( font.family() + " " + QString::number(font.pointSize())); // Messages limit option. m_ui.MessagesLimitCheckBox->setChecked(m_pOptions->bMessagesLimit); m_ui.MessagesLimitLinesSpinBox->setValue(m_pOptions->iMessagesLimitLines); // Logging options... m_ui.MessagesLogCheckBox->setChecked(m_pOptions->bMessagesLog); m_ui.MessagesLogPathComboBox->setEditText(m_pOptions->sMessagesLogPath); // Other options finally. m_ui.ConfirmRemoveCheckBox->setChecked(m_pOptions->bConfirmRemove); m_ui.StdoutCaptureCheckBox->setChecked(m_pOptions->bStdoutCapture); m_ui.CompletePathCheckBox->setChecked(m_pOptions->bCompletePath); m_ui.PeakAutoRemoveCheckBox->setChecked(m_pOptions->bPeakAutoRemove); m_ui.KeepToolsOnTopCheckBox->setChecked(m_pOptions->bKeepToolsOnTop); m_ui.TrackViewDropSpanCheckBox->setChecked(m_pOptions->bTrackViewDropSpan); m_ui.MidButtonModifierCheckBox->setChecked(m_pOptions->bMidButtonModifier); m_ui.MaxRecentFilesSpinBox->setValue(m_pOptions->iMaxRecentFiles); m_ui.LoopRecordingModeComboBox->setCurrentIndex(m_pOptions->iLoopRecordingMode); m_ui.DisplayFormatComboBox->setCurrentIndex(m_pOptions->iDisplayFormat); if (m_pOptions->iBaseFontSize > 0) m_ui.BaseFontSizeComboBox->setEditText(QString::number(m_pOptions->iBaseFontSize)); else m_ui.BaseFontSizeComboBox->setCurrentIndex(0); // Session options... m_ui.SessionFormatComboBox->setCurrentIndex( sessionFormatFromExt(m_pOptions->sSessionExt)); m_ui.SessionTemplateCheckBox->setChecked(m_pOptions->bSessionTemplate); m_ui.SessionTemplatePathComboBox->setEditText(m_pOptions->sSessionTemplatePath); m_ui.SessionBackupCheckBox->setChecked(m_pOptions->bSessionBackup); m_ui.SessionBackupModeComboBox->setCurrentIndex(m_pOptions->iSessionBackupMode); // Plugin path initialization... m_ladspaPaths = m_pOptions->ladspaPaths; m_dssiPaths = m_pOptions->dssiPaths; m_vstPaths = m_pOptions->vstPaths; m_lv2Paths = m_pOptions->lv2Paths; m_ui.Lv2PresetDirComboBox->setEditText(m_pOptions->sLv2PresetDir); // Plugin instruments options. m_ui.AudioOutputBusCheckBox->setChecked(m_pOptions->bAudioOutputBus); m_ui.AudioOutputAutoConnectCheckBox->setChecked(m_pOptions->bAudioOutputAutoConnect); m_ui.OpenEditorCheckBox->setChecked(m_pOptions->bOpenEditor); m_ui.DummyVstScanCheckBox->setChecked(m_pOptions->bDummyVstScan); int iPluginType = m_pOptions->iPluginType - 1; if (iPluginType < 0) iPluginType = 0; m_ui.PluginTypeComboBox->setCurrentIndex(iPluginType); m_ui.PluginPathComboBox->setEditText(QString()); choosePluginType(iPluginType); #ifdef CONFIG_DEBUG m_ui.StdoutCaptureCheckBox->setEnabled(false); #endif // Done. Restart clean. m_iDirtyCount = 0; stabilizeForm(); } // Retrieve the editing options, if the case arises. qtractorOptions *qtractorOptionsForm::options (void) const { return m_pOptions; } // Accept settings (OK button slot). void qtractorOptionsForm::accept (void) { // Save options... if (m_iDirtyCount > 0) { // Audio options... int iFormat = m_ui.AudioCaptureTypeComboBox->itemData( m_ui.AudioCaptureTypeComboBox->currentIndex()).toInt(); const qtractorAudioFileFactory::FileFormat *pFormat = qtractorAudioFileFactory::formats().at(iFormat); m_pOptions->sAudioCaptureExt = pFormat->ext; m_pOptions->iAudioCaptureType = pFormat->data; m_pOptions->iAudioCaptureFormat = m_ui.AudioCaptureFormatComboBox->currentIndex(); m_pOptions->iAudioCaptureQuality = m_ui.AudioCaptureQualitySpinBox->value(); m_pOptions->iAudioResampleType = m_ui.AudioResampleTypeComboBox->currentIndex(); m_pOptions->iTransportMode = m_ui.TransportModeComboBox->currentIndex(); m_pOptions->bAudioAutoTimeStretch = m_ui.AudioAutoTimeStretchCheckBox->isChecked(); m_pOptions->bAudioWsolaTimeStretch = m_ui.AudioWsolaTimeStretchCheckBox->isChecked(); m_pOptions->bAudioWsolaQuickSeek = m_ui.AudioWsolaQuickSeekCheckBox->isChecked(); m_pOptions->bAudioPlayerBus = m_ui.AudioPlayerBusCheckBox->isChecked(); m_pOptions->bAudioPlayerAutoConnect = m_ui.AudioPlayerAutoConnectCheckBox->isChecked(); // Audio metronome options. m_pOptions->bAudioMetronome = m_ui.AudioMetronomeCheckBox->isChecked(); m_pOptions->sMetroBarFilename = m_ui.MetroBarFilenameComboBox->currentText(); m_pOptions->fMetroBarGain = pow10f2(m_ui.MetroBarGainSpinBox->value()); m_pOptions->sMetroBeatFilename = m_ui.MetroBeatFilenameComboBox->currentText(); m_pOptions->fMetroBeatGain = pow10f2(m_ui.MetroBeatGainSpinBox->value()); m_pOptions->bAudioMetroBus = m_ui.AudioMetroBusCheckBox->isChecked(); m_pOptions->bAudioMetroAutoConnect = m_ui.AudioMetroAutoConnectCheckBox->isChecked(); // MIDI options... m_pOptions->iMidiCaptureFormat = m_ui.MidiCaptureFormatComboBox->currentIndex(); m_pOptions->iMidiCaptureQuantize = m_ui.MidiCaptureQuantizeComboBox->currentIndex(); m_pOptions->iMidiQueueTimer = m_ui.MidiQueueTimerComboBox->itemData( m_ui.MidiQueueTimerComboBox->currentIndex()).toInt(); m_pOptions->bMidiPlayerBus = m_ui.MidiPlayerBusCheckBox->isChecked(); m_pOptions->iMidiMmcMode = m_ui.MidiMmcModeComboBox->currentIndex(); m_pOptions->iMidiMmcDevice = m_ui.MidiMmcDeviceComboBox->currentIndex(); m_pOptions->iMidiSppMode = m_ui.MidiSppModeComboBox->currentIndex(); m_pOptions->iMidiClockMode = m_ui.MidiClockModeComboBox->currentIndex(); m_pOptions->bMidiControlBus = m_ui.MidiControlBusCheckBox->isChecked(); // MIDI metronome options. m_pOptions->bMidiMetronome = m_ui.MidiMetronomeCheckBox->isChecked(); m_pOptions->iMetroChannel = m_ui.MetroChannelSpinBox->value() - 1; m_pOptions->iMetroBarNote = m_ui.MetroBarNoteComboBox->currentIndex(); m_pOptions->iMetroBarVelocity = m_ui.MetroBarVelocitySpinBox->value(); m_pOptions->iMetroBarDuration = m_ui.MetroBarDurationSpinBox->value(); m_pOptions->iMetroBeatNote = m_ui.MetroBeatNoteComboBox->currentIndex(); m_pOptions->iMetroBeatVelocity = m_ui.MetroBeatVelocitySpinBox->value(); m_pOptions->iMetroBeatDuration = m_ui.MetroBeatDurationSpinBox->value(); m_pOptions->bMidiMetroBus = m_ui.MidiMetroBusCheckBox->isChecked(); // Display options... m_pOptions->bConfirmRemove = m_ui.ConfirmRemoveCheckBox->isChecked(); m_pOptions->bStdoutCapture = m_ui.StdoutCaptureCheckBox->isChecked(); m_pOptions->bCompletePath = m_ui.CompletePathCheckBox->isChecked(); m_pOptions->bPeakAutoRemove = m_ui.PeakAutoRemoveCheckBox->isChecked(); m_pOptions->bKeepToolsOnTop = m_ui.KeepToolsOnTopCheckBox->isChecked(); m_pOptions->bTrackViewDropSpan = m_ui.TrackViewDropSpanCheckBox->isChecked(); m_pOptions->bMidButtonModifier = m_ui.MidButtonModifierCheckBox->isChecked(); m_pOptions->iMaxRecentFiles = m_ui.MaxRecentFilesSpinBox->value(); m_pOptions->iLoopRecordingMode = m_ui.LoopRecordingModeComboBox->currentIndex(); m_pOptions->iDisplayFormat = m_ui.DisplayFormatComboBox->currentIndex(); m_pOptions->iBaseFontSize = m_ui.BaseFontSizeComboBox->currentText().toInt(); // Plugin paths... m_pOptions->iPluginType = m_ui.PluginTypeComboBox->currentIndex() + 1; m_pOptions->ladspaPaths = m_ladspaPaths; m_pOptions->dssiPaths = m_dssiPaths; m_pOptions->vstPaths = m_vstPaths; m_pOptions->lv2Paths = m_lv2Paths; m_pOptions->sLv2PresetDir = m_ui.Lv2PresetDirComboBox->currentText(); // Plugin instruments options. m_pOptions->bAudioOutputBus = m_ui.AudioOutputBusCheckBox->isChecked(); m_pOptions->bAudioOutputAutoConnect = m_ui.AudioOutputAutoConnectCheckBox->isChecked(); m_pOptions->bOpenEditor = m_ui.OpenEditorCheckBox->isChecked(); m_pOptions->bDummyVstScan = m_ui.DummyVstScanCheckBox->isChecked(); // Messages options... m_pOptions->sMessagesFont = m_ui.MessagesFontTextLabel->font().toString(); m_pOptions->bMessagesLimit = m_ui.MessagesLimitCheckBox->isChecked(); m_pOptions->iMessagesLimitLines = m_ui.MessagesLimitLinesSpinBox->value(); // Logging options... m_pOptions->bMessagesLog = m_ui.MessagesLogCheckBox->isChecked(); m_pOptions->sMessagesLogPath = m_ui.MessagesLogPathComboBox->currentText(); // Session options... m_pOptions->bSessionTemplate = m_ui.SessionTemplateCheckBox->isChecked(); m_pOptions->sSessionTemplatePath = m_ui.SessionTemplatePathComboBox->currentText(); m_pOptions->sSessionExt = sessionExtFromFormat( m_ui.SessionFormatComboBox->currentIndex()); m_pOptions->bSessionBackup = m_ui.SessionBackupCheckBox->isChecked(); m_pOptions->iSessionBackupMode = m_ui.SessionBackupModeComboBox->currentIndex(); // Custom colors. int iColor; for (iColor = 0; iColor < AudioMeterColors; ++iColor) qtractorAudioMeter::setColor(iColor, m_audioMeterColors[iColor]); for (iColor = 0; iColor < MidiMeterColors; ++iColor) qtractorMidiMeter::setColor(iColor, m_midiMeterColors[iColor]); // Reset dirty flag. m_iDirtyCount = 0; } // Save other conveniency options... m_pOptions->saveComboBoxHistory(m_ui.MetroBarFilenameComboBox); m_pOptions->saveComboBoxHistory(m_ui.MetroBeatFilenameComboBox); m_pOptions->saveComboBoxHistory(m_ui.PluginPathComboBox); m_pOptions->saveComboBoxHistory(m_ui.MessagesLogPathComboBox); m_pOptions->saveComboBoxHistory(m_ui.SessionTemplatePathComboBox); m_pOptions->saveComboBoxHistory(m_ui.Lv2PresetDirComboBox); // Save/commit to disk. m_pOptions->saveOptions(); // Just go with dialog acceptance QDialog::accept(); } // Reject settings (Cancel button slot). void qtractorOptionsForm::reject (void) { bool bReject = true; // Check if there's any pending changes... if (m_iDirtyCount > 0) { QMessageBox::StandardButtons buttons = QMessageBox::Discard | QMessageBox::Cancel; if (m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->isEnabled()) buttons |= QMessageBox::Apply; switch (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Some settings have been changed.\n\n" "Do you want to apply the changes?"), buttons)) { case QMessageBox::Apply: accept(); return; case QMessageBox::Discard: break; default: // Cancel. bReject = false; } } if (bReject) QDialog::reject(); } // Dirty up settings. void qtractorOptionsForm::changed (void) { ++m_iDirtyCount; stabilizeForm(); } // Choose audio metronome filenames. void qtractorOptionsForm::chooseMetroBarFilename (void) { QString sFilename = getOpenAudioFileName( tr("Metronome Bar Audio File") + " - " QTRACTOR_TITLE, m_ui.MetroBarFilenameComboBox->currentText()); if (sFilename.isEmpty()) return; m_ui.MetroBarFilenameComboBox->setEditText(sFilename); changed(); } void qtractorOptionsForm::chooseMetroBeatFilename (void) { QString sFilename = getOpenAudioFileName( tr("Metronome Beat Audio File") + " - " QTRACTOR_TITLE, m_ui.MetroBeatFilenameComboBox->currentText()); if (sFilename.isEmpty()) return; m_ui.MetroBeatFilenameComboBox->setEditText(sFilename); changed(); } // The metronome note names changer. void qtractorOptionsForm::updateMetroNoteNames (void) { // Save current selection... int iOldBarNote = m_ui.MetroBarNoteComboBox->currentIndex(); int iOldBeatNote = m_ui.MetroBeatNoteComboBox->currentIndex(); // Populate the Metronome notes. m_ui.MetroBarNoteComboBox->clear(); m_ui.MetroBeatNoteComboBox->clear(); bool bDrums = (m_ui.MetroChannelSpinBox->value() == 10); QStringList items; const QString sItem("%1 (%2)"); for (int i = 0; i < 128; ++i) { items.append(sItem .arg(qtractorMidiEditor::defaultNoteName(i, bDrums)).arg(i)); } m_ui.MetroBarNoteComboBox->insertItems(0, items); m_ui.MetroBeatNoteComboBox->insertItems(0, items); // Restore old selection... m_ui.MetroBarNoteComboBox->setCurrentIndex(iOldBarNote); m_ui.MetroBeatNoteComboBox->setCurrentIndex(iOldBeatNote); changed(); } // Audio meter level index change. void qtractorOptionsForm::changeAudioMeterLevel ( int iColor ) { const QColor& color = m_audioMeterColors[iColor]; m_ui.AudioMeterColorLineEdit->setText(color.name()); } // MIDI meter level index change. void qtractorOptionsForm::changeMidiMeterLevel ( int iColor ) { const QColor& color = m_midiMeterColors[iColor]; m_ui.MidiMeterColorLineEdit->setText(color.name()); } // Audio meter color change. void qtractorOptionsForm::changeAudioMeterColor ( const QString& sColor ) { const QColor& color = QColor(sColor); if (color.isValid()) { updateColorText(m_ui.AudioMeterColorLineEdit, color); m_audioMeterColors[m_ui.AudioMeterLevelComboBox->currentIndex()] = color; changed(); } } // MIDI meter color change. void qtractorOptionsForm::changeMidiMeterColor ( const QString& sColor ) { const QColor& color = QColor(sColor); if (color.isValid()) { updateColorText(m_ui.MidiMeterColorLineEdit, color); m_midiMeterColors[m_ui.MidiMeterLevelComboBox->currentIndex()] = color; changed(); } } // Audio meter color selection. void qtractorOptionsForm::chooseAudioMeterColor (void) { const QColor& color = QColorDialog::getColor( QColor(m_ui.AudioMeterColorLineEdit->text()), this); if (color.isValid()) m_ui.AudioMeterColorLineEdit->setText(color.name()); } // Midi meter color selection. void qtractorOptionsForm::chooseMidiMeterColor (void) { const QColor& color = QColorDialog::getColor( QColor(m_ui.MidiMeterColorLineEdit->text()), this); if (color.isValid()) m_ui.MidiMeterColorLineEdit->setText(color.name()); } // Reset all meter colors from default. void qtractorOptionsForm::resetMeterColors (void) { // Reset colors. int iColor; for (iColor = 0; iColor < AudioMeterColors; ++iColor) m_audioMeterColors[iColor] = qtractorAudioMeter::defaultColor(iColor); for (iColor = 0; iColor < MidiMeterColors; ++iColor) m_midiMeterColors[iColor] = qtractorMidiMeter::defaultColor(iColor); // Update current display... changeAudioMeterLevel(m_ui.AudioMeterLevelComboBox->currentIndex()); changeMidiMeterLevel(m_ui.MidiMeterLevelComboBox->currentIndex()); } // Update color item visual text. void qtractorOptionsForm::updateColorText ( QLineEdit *pLineEdit, const QColor& color ) { QPalette pal(color); pal.setColor(QPalette::Base, color); pLineEdit->setPalette(pal); } // Change plugin type. void qtractorOptionsForm::choosePluginType ( int iPluginType ) { if (m_pOptions == NULL) return; QStringList paths; qtractorPluginType::Hint typeHint = qtractorPluginType::hintFromText( m_ui.PluginTypeComboBox->itemText(iPluginType)); #ifdef CONFIG_LV2_PRESETS bool bLv2Enabled = false; #endif switch (typeHint) { case qtractorPluginType::Ladspa: paths = m_ladspaPaths; break; case qtractorPluginType::Dssi: paths = m_dssiPaths; break; case qtractorPluginType::Vst: paths = m_vstPaths; break; case qtractorPluginType::Lv2: paths = m_lv2Paths; #ifdef CONFIG_LV2_PRESETS bLv2Enabled = true; #endif break; default: break; } m_ui.PluginPathListWidget->clear(); QStringListIterator iter(paths); while (iter.hasNext()) m_ui.PluginPathListWidget->addItem(iter.next()); #ifdef CONFIG_LV2_PRESETS m_ui.Lv2PresetDirLabel->setEnabled(bLv2Enabled); m_ui.Lv2PresetDirComboBox->setEnabled(bLv2Enabled); m_ui.Lv2PresetDirToolButton->setEnabled(bLv2Enabled); #endif selectPluginPath(); stabilizeForm(); } // Change plugin path. void qtractorOptionsForm::changePluginPath ( const QString& /*sPluginPath*/ ) { selectPluginPath(); stabilizeForm(); } // Browse for plugin path. void qtractorOptionsForm::choosePluginPath (void) { QString sPluginPath; const QString& sTitle = tr("Plug-in Directory") + " - " QTRACTOR_TITLE; #if 1//QT_VERSION < 0x040400 // Ask for the directory... sPluginPath = QFileDialog::getExistingDirectory(this, sTitle, m_ui.PluginPathComboBox->currentText()); #else // Construct open-directory dialog... QFileDialog fileDialog(this, sTitle, m_ui.PluginPathComboBox->currentText()); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::DirectoryOnly); // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(m_pOptions->sSessionDir)); fileDialog.setSidebarUrls(urls); // Show dialog... if (fileDialog.exec()) sPluginPath = fileDialog.selectedFiles().first(); #endif if (!sPluginPath.isEmpty()) { m_ui.PluginPathComboBox->setEditText(sPluginPath); m_ui.PluginPathComboBox->setFocus(); } selectPluginPath(); stabilizeForm(); } // Add chosen plugin path. void qtractorOptionsForm::addPluginPath (void) { const QString& sPluginPath = m_ui.PluginPathComboBox->currentText(); if (sPluginPath.isEmpty()) return; if (!QDir(sPluginPath).exists()) return; qtractorPluginType::Hint typeHint = qtractorPluginType::hintFromText( m_ui.PluginTypeComboBox->currentText()); switch (typeHint) { case qtractorPluginType::Ladspa: m_ladspaPaths.append(sPluginPath); break; case qtractorPluginType::Dssi: m_dssiPaths.append(sPluginPath); break; case qtractorPluginType::Vst: m_vstPaths.append(sPluginPath); break; case qtractorPluginType::Lv2: m_lv2Paths.append(sPluginPath); break; default: return; } m_ui.PluginPathListWidget->addItem(sPluginPath); m_ui.PluginPathListWidget->setCurrentRow( m_ui.PluginPathListWidget->count() - 1); int i = m_ui.PluginPathComboBox->findText(sPluginPath); if (i >= 0) m_ui.PluginPathComboBox->removeItem(i); m_ui.PluginPathComboBox->insertItem(0, sPluginPath); m_ui.PluginPathComboBox->setEditText(QString()); m_ui.PluginPathListWidget->setFocus(); selectPluginPath(); changed(); } // Select current plugin path. void qtractorOptionsForm::selectPluginPath (void) { int iPluginPath = m_ui.PluginPathListWidget->currentRow(); m_ui.PluginPathRemoveToolButton->setEnabled(iPluginPath >= 0); m_ui.PluginPathUpToolButton->setEnabled(iPluginPath > 0); m_ui.PluginPathDownToolButton->setEnabled(iPluginPath >= 0 && iPluginPath < m_ui.PluginPathListWidget->count() - 1); } // Remove current plugin path. void qtractorOptionsForm::removePluginPath (void) { int iPluginPath = m_ui.PluginPathListWidget->currentRow(); if (iPluginPath < 0) return; qtractorPluginType::Hint typeHint = qtractorPluginType::hintFromText( m_ui.PluginTypeComboBox->currentText()); switch (typeHint) { case qtractorPluginType::Ladspa: m_ladspaPaths.removeAt(iPluginPath); break; case qtractorPluginType::Dssi: m_dssiPaths.removeAt(iPluginPath); break; case qtractorPluginType::Vst: m_vstPaths.removeAt(iPluginPath); break; case qtractorPluginType::Lv2: m_lv2Paths.removeAt(iPluginPath); break; default: return; } QListWidgetItem *pItem = m_ui.PluginPathListWidget->takeItem(iPluginPath); if (pItem) delete pItem; selectPluginPath(); changed(); } // Move up plugin path on search order. void qtractorOptionsForm::moveUpPluginPath (void) { int iPluginPath = m_ui.PluginPathListWidget->currentRow(); if (iPluginPath < 1) return; QString sPluginPath; qtractorPluginType::Hint typeHint = qtractorPluginType::hintFromText( m_ui.PluginTypeComboBox->currentText()); switch (typeHint) { case qtractorPluginType::Ladspa: sPluginPath = m_ladspaPaths.takeAt(iPluginPath); m_ladspaPaths.insert(iPluginPath - 1, sPluginPath); break; case qtractorPluginType::Dssi: sPluginPath = m_dssiPaths.takeAt(iPluginPath); m_dssiPaths.insert(iPluginPath - 1, sPluginPath); break; case qtractorPluginType::Vst: sPluginPath = m_vstPaths.takeAt(iPluginPath); m_vstPaths.insert(iPluginPath - 1, sPluginPath); break; case qtractorPluginType::Lv2: sPluginPath = m_lv2Paths.takeAt(iPluginPath); m_lv2Paths.insert(iPluginPath - 1, sPluginPath); break; default: return; } QListWidgetItem *pItem = m_ui.PluginPathListWidget->takeItem(iPluginPath); if (pItem) { pItem->setSelected(false); m_ui.PluginPathListWidget->insertItem(iPluginPath - 1, pItem); pItem->setSelected(true); m_ui.PluginPathListWidget->setCurrentItem(pItem); } selectPluginPath(); changed(); } // Move down plugin path on search order. void qtractorOptionsForm::moveDownPluginPath (void) { int iPluginPath = m_ui.PluginPathListWidget->currentRow(); if (iPluginPath >= m_ui.PluginPathListWidget->count() - 1) return; QString sPluginPath; qtractorPluginType::Hint typeHint = qtractorPluginType::hintFromText( m_ui.PluginTypeComboBox->currentText()); switch (typeHint) { case qtractorPluginType::Ladspa: sPluginPath = m_ladspaPaths.takeAt(iPluginPath); m_ladspaPaths.insert(iPluginPath + 1, sPluginPath); break; case qtractorPluginType::Dssi: sPluginPath = m_dssiPaths.takeAt(iPluginPath); m_dssiPaths.insert(iPluginPath + 1, sPluginPath); break; case qtractorPluginType::Vst: sPluginPath = m_vstPaths.takeAt(iPluginPath); m_vstPaths.insert(iPluginPath + 1, sPluginPath); break; case qtractorPluginType::Lv2: sPluginPath = m_lv2Paths.takeAt(iPluginPath); m_lv2Paths.insert(iPluginPath + 1, sPluginPath); break; default: return; } QListWidgetItem *pItem = m_ui.PluginPathListWidget->takeItem(iPluginPath); if (pItem) { pItem->setSelected(false); m_ui.PluginPathListWidget->insertItem(iPluginPath + 1, pItem); pItem->setSelected(true); m_ui.PluginPathListWidget->setCurrentItem(pItem); } selectPluginPath(); changed(); } // Browse for LV2 Presets directory. void qtractorOptionsForm::chooseLv2PresetDir (void) { QString sLv2PresetDir = m_ui.Lv2PresetDirComboBox->currentText(); if (sLv2PresetDir.isEmpty()) sLv2PresetDir = QDir::homePath() + QDir::separator() + ".lv2"; const QString& sTitle = tr("LV2 Presets Directory") + " - " QTRACTOR_TITLE; #if 1// QT_VERSION < 0x040400 // Ask for the directory... sLv2PresetDir = QFileDialog::getExistingDirectory(this, sTitle, sLv2PresetDir); #else // Construct open-directory dialog... QFileDialog fileDialog(this, sTitle, sLv2PresetDir); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::DirectoryOnly); // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(m_pOptions->sLv2PresetDir)); fileDialog.setSidebarUrls(urls); // Show dialog... if (fileDialog.exec()) sLv2PresetDir = fileDialog.selectedFiles().first(); #endif if (!sLv2PresetDir.isEmpty()) { m_ui.Lv2PresetDirComboBox->setEditText(sLv2PresetDir); m_ui.Lv2PresetDirComboBox->setFocus(); } changed(); } // The messages font selection dialog. void qtractorOptionsForm::chooseMessagesFont (void) { bool bOk = false; QFont font = QFontDialog::getFont(&bOk, m_ui.MessagesFontTextLabel->font(), this); if (bOk) { m_ui.MessagesFontTextLabel->setFont(font); m_ui.MessagesFontTextLabel->setText( font.family() + " " + QString::number(font.pointSize())); changed(); } } // Messages log path browse slot. void qtractorOptionsForm::chooseMessagesLogPath (void) { QString sFilename; const QString sExt("log"); const QString& sTitle = tr("Messages Log") + " - " QTRACTOR_TITLE; const QString& sFilter = tr("Log files (*.%1)").arg(sExt); #if 0//QT_VERSION < 0x040400 // Ask for the filename to open... sFilename = QFileDialog::getSaveFileName(this, sTitle, m_ui.MessagesLogPathComboBox->currentText(), sFilter); #else // Construct open-file dialog... QFileDialog fileDialog(this, sTitle, m_ui.MessagesLogPathComboBox->currentText(), sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptSave); fileDialog.setFileMode(QFileDialog::AnyFile); fileDialog.setDefaultSuffix(sExt); // Show dialog... if (fileDialog.exec()) sFilename = fileDialog.selectedFiles().first(); #endif if (!sFilename.isEmpty()) { m_ui.MessagesLogPathComboBox->setEditText(sFilename); m_ui.MessagesLogPathComboBox->setFocus(); changed(); } } // Session template path browse slot. void qtractorOptionsForm::chooseSessionTemplatePath (void) { QString sFilename; const QString sExt("qtt"); const QString& sTitle = tr("Session Template") + " - " QTRACTOR_TITLE; const QString& sFilter = tr("Session template files (*.qtr *.qts *.%1)").arg(sExt); #if 0//QT_VERSION < 0x040400 // Ask for the filename to open... sFilename = QFileDialog::getOpenFileName(this, sTitle, m_ui.SessionTemplatePathComboBox->currentText(), sFilter); #else // Construct open-files dialog... QFileDialog fileDialog(this, sTitle, m_ui.SessionTemplatePathComboBox->currentText(), sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::ExistingFile); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(m_pOptions->sSessionDir)); fileDialog.setSidebarUrls(urls); // Show dialog... if (fileDialog.exec()) sFilename = fileDialog.selectedFiles().first(); #endif if (sFilename.isEmpty()) return; m_ui.SessionTemplatePathComboBox->setEditText(sFilename); m_ui.SessionTemplatePathComboBox->setFocus(); changed(); } // Stabilize current form state. void qtractorOptionsForm::stabilizeForm (void) { m_ui.MessagesLimitLinesSpinBox->setEnabled( m_ui.MessagesLimitCheckBox->isChecked()); // Audio options validy check... int iIndex = m_ui.AudioCaptureTypeComboBox->currentIndex(); int iFormat = m_ui.AudioCaptureTypeComboBox->itemData(iIndex).toInt(); const qtractorAudioFileFactory::FileFormat *pFormat = qtractorAudioFileFactory::formats().at(iFormat); bool bSndFile = (pFormat && pFormat->type == qtractorAudioFileFactory::SndFile); m_ui.AudioCaptureFormatTextLabel->setEnabled(bSndFile); m_ui.AudioCaptureFormatComboBox->setEnabled(bSndFile); bool bVorbisFile = (pFormat && pFormat->type == qtractorAudioFileFactory::VorbisFile); m_ui.AudioCaptureQualityTextLabel->setEnabled(bVorbisFile); m_ui.AudioCaptureQualitySpinBox->setEnabled(bVorbisFile); bool bValid = (m_iDirtyCount > 0); if (bValid) { iFormat = m_ui.AudioCaptureFormatComboBox->currentIndex(); bValid = qtractorAudioFileFactory::isValidFormat(pFormat, iFormat); } m_ui.AudioWsolaQuickSeekCheckBox->setEnabled( m_ui.AudioWsolaTimeStretchCheckBox->isChecked()); m_ui.AudioPlayerAutoConnectCheckBox->setEnabled( m_ui.AudioPlayerBusCheckBox->isChecked()); bool bAudioMetronome = m_ui.AudioMetronomeCheckBox->isChecked(); m_ui.MetroBarFilenameTextLabel->setEnabled(bAudioMetronome); m_ui.MetroBarFilenameComboBox->setEnabled(bAudioMetronome); m_ui.MetroBarFilenameToolButton->setEnabled(bAudioMetronome); m_ui.MetroBarGainTextLabel->setEnabled(bAudioMetronome); m_ui.MetroBarGainSpinBox->setEnabled(bAudioMetronome); m_ui.MetroBeatFilenameTextLabel->setEnabled(bAudioMetronome); m_ui.MetroBeatFilenameComboBox->setEnabled(bAudioMetronome); m_ui.MetroBeatFilenameToolButton->setEnabled(bAudioMetronome); m_ui.MetroBeatGainTextLabel->setEnabled(bAudioMetronome); m_ui.MetroBeatGainSpinBox->setEnabled(bAudioMetronome); m_ui.AudioMetroBusCheckBox->setEnabled(bAudioMetronome); m_ui.AudioMetroAutoConnectCheckBox->setEnabled( bAudioMetronome && m_ui.AudioMetroBusCheckBox->isChecked()); bool bMmcMode =(m_ui.MidiMmcModeComboBox->currentIndex() > 0); m_ui.MidiMmcDeviceTextLabel->setEnabled(bMmcMode); m_ui.MidiMmcDeviceComboBox->setEnabled(bMmcMode); bool bMidiMetronome = m_ui.MidiMetronomeCheckBox->isChecked(); m_ui.MetroChannelTextLabel->setEnabled(bMidiMetronome); m_ui.MetroChannelSpinBox->setEnabled(bMidiMetronome); m_ui.MetroBarNoteTextLabel->setEnabled(bMidiMetronome); m_ui.MetroBarNoteComboBox->setEnabled(bMidiMetronome); m_ui.MetroBarVelocityTextLabel->setEnabled(bMidiMetronome); m_ui.MetroBarVelocitySpinBox->setEnabled(bMidiMetronome); m_ui.MetroBarDurationTextLabel->setEnabled(bMidiMetronome); m_ui.MetroBarDurationSpinBox->setEnabled(bMidiMetronome); m_ui.MetroBeatNoteTextLabel->setEnabled(bMidiMetronome); m_ui.MetroBeatNoteComboBox->setEnabled(bMidiMetronome); m_ui.MetroBeatVelocityTextLabel->setEnabled(bMidiMetronome); m_ui.MetroBeatVelocitySpinBox->setEnabled(bMidiMetronome); m_ui.MetroBeatDurationTextLabel->setEnabled(bMidiMetronome); m_ui.MetroBeatDurationSpinBox->setEnabled(bMidiMetronome); m_ui.MidiMetroBusCheckBox->setEnabled(bMidiMetronome); bool bMessagesLog = m_ui.MessagesLogCheckBox->isChecked(); m_ui.MessagesLogPathComboBox->setEnabled(bMessagesLog); m_ui.MessagesLogPathToolButton->setEnabled(bMessagesLog); if (bMessagesLog && bValid) { const QString& sPath = m_ui.MessagesLogPathComboBox->currentText(); bValid = !sPath.isEmpty(); } bool bSessionTemplate = m_ui.SessionTemplateCheckBox->isChecked(); m_ui.SessionTemplatePathComboBox->setEnabled(bSessionTemplate); m_ui.SessionTemplatePathToolButton->setEnabled(bSessionTemplate); if (bSessionTemplate && bValid) { const QString& sPath = m_ui.SessionTemplatePathComboBox->currentText(); bValid = !sPath.isEmpty() && QFileInfo(sPath).exists(); } m_ui.SessionBackupModeComboBox->setEnabled( m_ui.SessionBackupCheckBox->isChecked()); const QString& sPluginPath = m_ui.PluginPathComboBox->currentText(); m_ui.PluginPathAddToolButton->setEnabled( !sPluginPath.isEmpty() && QDir(sPluginPath).exists() && m_ui.PluginPathListWidget->findItems( sPluginPath, Qt::MatchExactly).isEmpty()); if (bValid) { const QString& sLv2PresetDir = m_ui.Lv2PresetDirComboBox->currentText(); bValid = sLv2PresetDir.isEmpty() || QDir(sLv2PresetDir).exists(); } m_ui.AudioOutputAutoConnectCheckBox->setEnabled( m_ui.AudioOutputBusCheckBox->isChecked()); m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(bValid); } // Browse for an existing audio filename. QString qtractorOptionsForm::getOpenAudioFileName ( const QString& sTitle, const QString& sFilename ) { QString sAudioFile; #if 0//QT_VERSION < 0x040400 // Ask for the filename to open... sAudioFile = QFileDialog::getOpenFileName(this, sTitle, sFilename, qtractorAudioFileFactory::filters()); #else // Construct open-file dialog... QFileDialog fileDialog(this, sTitle, sFilename, qtractorAudioFileFactory::filters()); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::ExistingFile); fileDialog.setDefaultSuffix(qtractorAudioFileFactory::defaultExt()); // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(m_pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(m_pOptions->sAudioDir)); fileDialog.setSidebarUrls(urls); // Show dialog... if (fileDialog.exec()) sAudioFile = fileDialog.selectedFiles().first(); #endif return sAudioFile; } // Session format ext/suffix helpers. int qtractorOptionsForm::sessionFormatFromExt ( const QString& sSessionExt ) const { int iSessionFormat = 0; for (int i = 1; g_aSessionFormats[i].ext; ++i) { if (g_aSessionFormats[i].ext == sSessionExt) { iSessionFormat = i; break; } } return iSessionFormat; } QString qtractorOptionsForm::sessionExtFromFormat ( int iSessionFormat ) const { if (iSessionFormat < 0 || iSessionFormat > 2) iSessionFormat = 0; return g_aSessionFormats[iSessionFormat].ext; } // end of qtractorOptionsForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiToolsForm.h0000644000175000001440000000012312073012112021710 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134668.01708 30 ctime=1381134668.017080065 qtractor-0.5.11/src/qtractorMidiToolsForm.h0000644000175000001440000000512212073012112021177 0ustar00rncbcusers00000000000000// qtractorMidiToolsForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiToolsForm_h #define __qtractorMidiToolsForm_h #include "ui_qtractorMidiToolsForm.h" // Forward declarations. class qtractorMidiClip; class qtractorMidiEditSelect; class qtractorMidiEditCommand; class qtractorTimeScale; //---------------------------------------------------------------------------- // qtractorMidiToolsForm -- UI wrapper form. class qtractorMidiToolsForm : public QDialog { Q_OBJECT public: // Constructor. qtractorMidiToolsForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorMidiToolsForm(); // Tool page accessors. void setToolIndex(int iToolIndex); int toolIndex() const; // Create edit command based on given selection. qtractorMidiEditCommand *editCommand( qtractorMidiClip *pMidiClip, qtractorMidiEditSelect *pSelect, unsigned long iTimeOffset); protected slots: // Preset management slots... void presetChanged(const QString& sPreset); void presetActivated(const QString& sPreset); void presetSave(); void presetDelete(); void timeshiftSpinBoxChanged(double p); void timeshiftSliderChanged(int i); void formatChanged(int); void changed(); void accept(); void reject(); void stabilizeForm(); protected: // Preset management methods... void loadPreset(const QString& sPreset); void savePreset(const QString& sPreset); void refreshPresets(); private: // The Qt-designer UI struct... Ui::qtractorMidiToolsForm m_ui; // Instance variables... qtractorTimeScale *m_pTimeScale; int m_iDirtyCount; int m_iUpdate; class TimeshiftCurve *m_pTimeshiftCurve; }; #endif // __qtractorMidiToolsForm_h // end of qtractorMidiToolsForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorTimeScaleCommand.cpp0000644000175000001440000000012312165037037022700 xustar000000000000000027 mtime=1372864031.847614 26 atime=1381134671.20008 30 ctime=1381134671.200080115 qtractor-0.5.11/src/qtractorTimeScaleCommand.cpp0000644000175000001440000004116212165037037022173 0ustar00rncbcusers00000000000000// qtractorTimeScaleCommand.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorTimeScaleCommand.h" #include "qtractorClipCommand.h" #include "qtractorSession.h" #include "qtractorAudioEngine.h" #include "qtractorMidiEngine.h" #include "qtractorAudioClip.h" //---------------------------------------------------------------------- // class qtractorTimeScaleNodeCommand - implementation. // // Constructor. qtractorTimeScaleNodeCommand::qtractorTimeScaleNodeCommand ( const QString& sName, qtractorTimeScale *pTimeScale, unsigned long iFrame, float fTempo, unsigned short iBeatType, unsigned short iBeatsPerBar, unsigned short iBeatDivisor) : qtractorCommand(sName), m_pTimeScale(pTimeScale), m_iFrame(iFrame), m_fTempo(fTempo), m_iBeatType(iBeatType), m_iBeatsPerBar(iBeatsPerBar), m_iBeatDivisor(iBeatDivisor), m_pClipCommand(NULL), m_bAutoTimeStretch(false) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) m_bAutoTimeStretch = pSession->isAutoTimeStretch(); setClearSelect(true); } // Destructor. qtractorTimeScaleNodeCommand::~qtractorTimeScaleNodeCommand (void) { if (m_pClipCommand) delete m_pClipCommand; } // Add time-scale node command method. bool qtractorTimeScaleNodeCommand::addNode (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // If currently playing, we need to do a stop and go... bool bPlaying = pSession->isPlaying(); if (bPlaying) pSession->lock(); if (m_pClipCommand) m_pClipCommand->undo(); qtractorTimeScale::Node *pNode = m_pTimeScale->addNode( m_iFrame, m_fTempo, m_iBeatType, m_iBeatsPerBar, m_iBeatDivisor); if (m_pClipCommand) { delete m_pClipCommand; m_pClipCommand = NULL; } else { qtractorTimeScale::Node *pPrev = pNode->prev(); float fOldTempo = (pPrev ? pPrev->tempo : m_pTimeScale->tempo()); float fNewTempo = pNode->tempo; m_pClipCommand = createClipCommand(name(), pNode, fNewTempo, fOldTempo); if (m_pClipCommand) m_pClipCommand->redo(); } // Restore playback state, if needed... if (bPlaying) { // The Audio engine too... if (pSession->audioEngine()) pSession->audioEngine()->resetMetro(); // The MIDI engine queue needs a reset... if (pSession->midiEngine()) pSession->midiEngine()->resetTempo(); pSession->unlock(); } return true; } // Update time-scale node command method. bool qtractorTimeScaleNodeCommand::updateNode (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(m_iFrame); if (pNode == NULL) return false; if (pNode->frame != m_iFrame) return false; // If currently playing, we need to do a stop and go... bool bPlaying = pSession->isPlaying(); if (bPlaying) pSession->lock(); float fTempo = pNode->tempo; unsigned short iBeatType = pNode->beatType; unsigned short iBeatsPerBar = pNode->beatsPerBar; unsigned short iBeatDivisor = pNode->beatDivisor; if (m_pClipCommand) { m_pClipCommand->undo(); delete m_pClipCommand; m_pClipCommand = NULL; } else { float fOldTempo = pNode->tempo; float fNewTempo = m_fTempo; m_pClipCommand = createClipCommand(name(), pNode, fNewTempo, fOldTempo); } pNode->tempo = m_fTempo; pNode->beatType = m_iBeatType; pNode->beatsPerBar = m_iBeatsPerBar; pNode->beatDivisor = m_iBeatDivisor; m_pTimeScale->updateNode(pNode); m_fTempo = fTempo; m_iBeatType = iBeatType; m_iBeatsPerBar = iBeatsPerBar; m_iBeatDivisor = iBeatDivisor; if (m_pClipCommand) m_pClipCommand->redo(); // Restore playback state, if needed... if (bPlaying) { // The Audio engine too... if (pSession->audioEngine()) pSession->audioEngine()->resetMetro(); // The MIDI engine queue needs a reset... if (pSession->midiEngine()) pSession->midiEngine()->resetTempo(); pSession->unlock(); } return true; } // Remove time-scale node command method. bool qtractorTimeScaleNodeCommand::removeNode (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(m_iFrame); if (pNode == NULL) return false; if (pNode->frame != m_iFrame) return false; // If currently playing, we need to do a stop and go... bool bPlaying = pSession->isPlaying(); if (bPlaying) pSession->lock(); if (m_pClipCommand) { m_pClipCommand->undo(); delete m_pClipCommand; m_pClipCommand = NULL; } else { qtractorTimeScale::Node *pPrev = pNode->prev(); float fOldTempo = pNode->tempo; float fNewTempo = (pPrev ? pPrev->tempo : m_pTimeScale->tempo()); m_pClipCommand = createClipCommand(name(), pNode, fNewTempo, fOldTempo); } // m_iFrame = pNode->frame; m_fTempo = pNode->tempo; m_iBeatType = pNode->beatType; m_iBeatsPerBar = pNode->beatsPerBar; m_iBeatDivisor = pNode->beatDivisor; m_pTimeScale->removeNode(pNode); if (m_pClipCommand) m_pClipCommand->redo(); // Restore playback state, if needed... if (bPlaying) { // The Audio engine too... if (pSession->audioEngine()) pSession->audioEngine()->resetMetro(); // The MIDI engine queue needs a reset... if (pSession->midiEngine()) pSession->midiEngine()->resetTempo(); pSession->unlock(); } return true; } // Make it automatic clip time-stretching command (static). qtractorClipCommand *qtractorTimeScaleNodeCommand::createClipCommand ( const QString& sName, qtractorTimeScale::Node *pNode, float fNewTempo, float fOldTempo ) { if (pNode == NULL) return NULL; if (fNewTempo == fOldTempo) return NULL; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return NULL; qtractorTimeScale::Node *pNext = pNode->next(); unsigned long iFrameStart = pNode->frame; unsigned long iFrameEnd = (pNext ? pNext->frame : pSession->sessionEnd()); qtractorClipCommand *pClipCommand = NULL; for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { for (qtractorClip *pClip = pTrack->clips().first(); pClip; pClip = pClip->next()) { if (pClip->clipStart() < iFrameStart || pClip->clipStart() >= iFrameEnd) continue; if (pTrack->trackType() == qtractorTrack::Audio) { qtractorAudioClip *pAudioClip = static_cast (pClip); if (pAudioClip) { if (pClipCommand == NULL) pClipCommand = new qtractorClipCommand(sName); if (m_bAutoTimeStretch) { float fTimeStretch = (fOldTempo * pAudioClip->timeStretch()) / fNewTempo; pClipCommand->timeStretchClip(pClip, fTimeStretch); } else { pClipCommand->resetClip(pClip); } } } } } // Take care of possible empty commands... if (pClipCommand && pClipCommand->isEmpty()) { delete pClipCommand; pClipCommand = NULL; } return pClipCommand; } //---------------------------------------------------------------------- // class qtractorTimeScaleAddNodeCommand - implementation. // // Constructor. qtractorTimeScaleAddNodeCommand::qtractorTimeScaleAddNodeCommand ( qtractorTimeScale *pTimeScale, unsigned long iFrame, float fTempo, unsigned short iBeatType, unsigned short iBeatsPerBar, unsigned short iBeatDivisor ) : qtractorTimeScaleNodeCommand( QObject::tr("add tempo node"), pTimeScale, iFrame, fTempo, iBeatType, iBeatsPerBar, iBeatDivisor) { } // Time-scale node command methods. bool qtractorTimeScaleAddNodeCommand::redo (void) { return addNode(); } bool qtractorTimeScaleAddNodeCommand::undo (void) { return removeNode(); } //---------------------------------------------------------------------- // class qtractorTimeScaleUpdateNodeCommand - implementation. // // Constructor. qtractorTimeScaleUpdateNodeCommand::qtractorTimeScaleUpdateNodeCommand ( qtractorTimeScale *pTimeScale, unsigned long iFrame, float fTempo, unsigned short iBeatType, unsigned short iBeatsPerBar, unsigned short iBeatDivisor) : qtractorTimeScaleNodeCommand( QObject::tr("update tempo node"), pTimeScale, iFrame, fTempo, iBeatType, iBeatsPerBar, iBeatDivisor) { } // Time-scale node command methods. bool qtractorTimeScaleUpdateNodeCommand::redo (void) { return updateNode(); } bool qtractorTimeScaleUpdateNodeCommand::undo (void) { return redo(); } //---------------------------------------------------------------------- // class qtractorTimeScaleRemoveNodeCommand - implementation. // // Constructor. qtractorTimeScaleRemoveNodeCommand::qtractorTimeScaleRemoveNodeCommand ( qtractorTimeScale *pTimeScale, qtractorTimeScale::Node *pNode ) : qtractorTimeScaleNodeCommand( QObject::tr("remove tempo node"), pTimeScale, pNode->frame) { } // Time-scale node command methods. bool qtractorTimeScaleRemoveNodeCommand::redo (void) { return removeNode(); } bool qtractorTimeScaleRemoveNodeCommand::undo (void) { return addNode(); } //---------------------------------------------------------------------- // class qtractorTimeScaleMoveNodeCommand - implementation. // // Constructor. qtractorTimeScaleMoveNodeCommand::qtractorTimeScaleMoveNodeCommand ( qtractorTimeScale *pTimeScale, qtractorTimeScale::Node *pNode, unsigned long iFrame ) : qtractorTimeScaleNodeCommand( QObject::tr("move tempo node"), pTimeScale, pNode->frame, pNode->tempo, pNode->beatType, pNode->beatsPerBar, pNode->beatDivisor) { // The new location. m_iNewFrame = pTimeScale->frameFromBar(pTimeScale->barFromFrame(iFrame)); m_iOldFrame = frame(); // Replaced node salvage. qtractorTimeScale::Cursor cursor(pTimeScale); pNode = cursor.seekFrame(m_iNewFrame); if (pNode && pNode->frame == m_iNewFrame) { m_bOldNode = true; m_fOldTempo = pNode->tempo; m_iOldBeatType = pNode->beatType; m_iOldBeatsPerBar = pNode->beatsPerBar; m_iOldBeatDivisor = pNode->beatDivisor; } else { m_bOldNode = false; } } // Time-scale node command methods. bool qtractorTimeScaleMoveNodeCommand::redo (void) { qtractorTimeScale *pTimeScale = timeScale(); if (pTimeScale == NULL) return false; unsigned long iNewFrame = m_iNewFrame; unsigned long iOldFrame = m_iOldFrame; qtractorTimeScale::Cursor cursor(pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(iOldFrame); if (pNode && pNode->frame == iOldFrame) pTimeScale->removeNode(pNode); pTimeScale->addNode(iNewFrame, tempo(), beatType(), beatsPerBar(), beatDivisor()); m_iNewFrame = iOldFrame; m_iOldFrame = iNewFrame; return true; } bool qtractorTimeScaleMoveNodeCommand::undo (void) { qtractorTimeScale *pTimeScale = timeScale(); if (pTimeScale == NULL) return false; bool bResult = redo(); if (bResult && m_bOldNode) { pTimeScale->addNode(m_iNewFrame, m_fOldTempo, m_iOldBeatType, m_iOldBeatsPerBar, m_iOldBeatDivisor); } return bResult; } //---------------------------------------------------------------------- // class qtractorTimeScaleMarkerCommand - implementation. // // Constructor. qtractorTimeScaleMarkerCommand::qtractorTimeScaleMarkerCommand ( const QString& sName, qtractorTimeScale *pTimeScale, unsigned long iFrame, const QString& sText, const QColor& rgbColor ) : qtractorCommand(sName), m_pTimeScale(pTimeScale), m_iFrame(iFrame), m_sText(sText), m_rgbColor(rgbColor) { } // Add time-scale marker command method. bool qtractorTimeScaleMarkerCommand::addMarker (void) { return (m_pTimeScale->addMarker(m_iFrame, m_sText, m_rgbColor) != NULL); } // Update time-scale marker command method. bool qtractorTimeScaleMarkerCommand::updateMarker (void) { qtractorTimeScale::Marker *pMarker = m_pTimeScale->markers().seekFrame(m_iFrame); if (pMarker == NULL) return false; if (pMarker->frame != m_iFrame) return false; QString sText = pMarker->text; QColor rgbColor = pMarker->color; pMarker->text = m_sText; pMarker->color = m_rgbColor; m_pTimeScale->updateMarker(pMarker); m_sText = sText; m_rgbColor = rgbColor; return true; } // Remove time-scale marker command method. bool qtractorTimeScaleMarkerCommand::removeMarker (void) { qtractorTimeScale::Marker *pMarker = m_pTimeScale->markers().seekFrame(m_iFrame); if (pMarker == NULL) return false; if (pMarker->frame != m_iFrame) return false; // m_iFrame = pMarker->frame; m_sText = pMarker->text; m_rgbColor = pMarker->color; m_pTimeScale->removeMarker(pMarker); return true; } //---------------------------------------------------------------------- // class qtractorTimeScaleAddMarkerCommand - implementation. // // Constructor. qtractorTimeScaleAddMarkerCommand::qtractorTimeScaleAddMarkerCommand ( qtractorTimeScale *pTimeScale, unsigned long iFrame, const QString& sText, const QColor& rgbColor ) : qtractorTimeScaleMarkerCommand( QObject::tr("add marker"), pTimeScale, iFrame, sText, rgbColor) { } // Time-scale marker command methods. bool qtractorTimeScaleAddMarkerCommand::redo (void) { return addMarker(); } bool qtractorTimeScaleAddMarkerCommand::undo (void) { return removeMarker(); } //---------------------------------------------------------------------- // class qtractorTimeScaleUpdateMarkerCommand - implementation. // // Constructor. qtractorTimeScaleUpdateMarkerCommand::qtractorTimeScaleUpdateMarkerCommand ( qtractorTimeScale *pTimeScale, unsigned long iFrame, const QString& sText, const QColor& rgbColor ) : qtractorTimeScaleMarkerCommand( QObject::tr("update marker"), pTimeScale, iFrame, sText, rgbColor) { } // Time-scale marker command methods. bool qtractorTimeScaleUpdateMarkerCommand::redo (void) { return updateMarker(); } bool qtractorTimeScaleUpdateMarkerCommand::undo (void) { return redo(); } //---------------------------------------------------------------------- // class qtractorTimeScaleRemoveMarkerCommand - implementation. // // Constructor. qtractorTimeScaleRemoveMarkerCommand::qtractorTimeScaleRemoveMarkerCommand ( qtractorTimeScale *pTimeScale, qtractorTimeScale::Marker *pMarker ) : qtractorTimeScaleMarkerCommand( QObject::tr("remove marker"), pTimeScale, pMarker->frame) { } // Time-scale marker command methods. bool qtractorTimeScaleRemoveMarkerCommand::redo (void) { return removeMarker(); } bool qtractorTimeScaleRemoveMarkerCommand::undo (void) { return addMarker(); } //---------------------------------------------------------------------- // class qtractorTimeScaleMoveMarkerCommand - implementation. // // Constructor. qtractorTimeScaleMoveMarkerCommand::qtractorTimeScaleMoveMarkerCommand ( qtractorTimeScale *pTimeScale, qtractorTimeScale::Marker *pMarker, unsigned long iFrame ) : qtractorTimeScaleMarkerCommand( QObject::tr("move marker"), pTimeScale, pMarker->frame, pMarker->text, pMarker->color) { // The new location. m_iNewFrame = pTimeScale->frameFromBar(pTimeScale->barFromFrame(iFrame)); m_iOldFrame = frame(); // Replaced marker salvage. pMarker = pTimeScale->markers().seekFrame(m_iNewFrame); if (pMarker && pMarker->frame == m_iNewFrame) { m_bOldMarker = true; m_sOldText = pMarker->text; m_rgbOldColor = pMarker->color; } else { m_bOldMarker = false; } } // Time-scale marker command methods. bool qtractorTimeScaleMoveMarkerCommand::redo (void) { qtractorTimeScale *pTimeScale = timeScale(); if (pTimeScale == NULL) return false; unsigned long iNewFrame = m_iNewFrame; unsigned long iOldFrame = m_iOldFrame; qtractorTimeScale::Marker *pMarker = pTimeScale->markers().seekFrame(iOldFrame); if (pMarker && pMarker->frame == iOldFrame) pTimeScale->removeMarker(pMarker); pTimeScale->addMarker(iNewFrame, text(), color()); m_iNewFrame = iOldFrame; m_iOldFrame = iNewFrame; return true; } bool qtractorTimeScaleMoveMarkerCommand::undo (void) { qtractorTimeScale *pTimeScale = timeScale(); if (pTimeScale == NULL) return false; bool bResult = redo(); if (bResult && m_bOldMarker) pTimeScale->addMarker(m_iNewFrame, m_sOldText, m_rgbOldColor); return bResult; } // end of qtractorTimeScaleCommand.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioPeak.cpp0000644000175000001440000000012312116671426021377 xustar000000000000000027 mtime=1362850582.597247 26 atime=1381134666.67508 30 ctime=1381134666.676080044 qtractor-0.5.11/src/qtractorAudioPeak.cpp0000644000175000001440000005232112116671426020671 0ustar00rncbcusers00000000000000// qtractorAudioPeak.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorAudioPeak.h" #include "qtractorAudioFile.h" #include "qtractorSession.h" #include #include #include #include #include #include #include #include // Audio file buffer size in frames per channel. static const unsigned int c_iAudioFrames = (32 * 1024); // Peak file buffer size in frames per channel. static const unsigned int c_iPeakFrames = (8 * 1024); // Default peak period as a digest representation in frames per channel. static const unsigned short c_iPeakPeriod = 1024; // Default peak filename extension. static const QString c_sPeakFileExt = ".peak"; //---------------------------------------------------------------------- // class qtractorAudioPeakThread -- Audio Peak file thread. // class qtractorAudioPeakThread : public QThread { public: // Constructor. qtractorAudioPeakThread(unsigned int iSyncSize = 128); // Destructor. ~qtractorAudioPeakThread(); // Thread run state accessors. void setRunState(bool bRunState); bool runState() const; // Wake from executive wait condition. void sync(qtractorAudioPeakFile *pPeakFile = NULL); protected: // The main thread executive. void run(); // Actual peak file creation methods. // (this is just about to be used internally) bool openPeakFile(); bool writePeakFile(); void closePeakFile(); void notifyPeakEvent() const; private: // The peak file queue instance reference. unsigned int m_iSyncSize; unsigned int m_iSyncMask; qtractorAudioPeak **m_ppSyncItems; volatile unsigned int m_iSyncRead; volatile unsigned int m_iSyncWrite; // Whether the thread is logically running. volatile bool m_bRunState; // Thread synchronization objects. QMutex m_mutex; QWaitCondition m_cond; // Current audio peak file instance. qtractorAudioPeakFile *m_pPeakFile; // Current audio file instance. qtractorAudioFile *m_pAudioFile; // Current audio file buffer. float **m_ppAudioFrames; }; // Constructor. qtractorAudioPeakThread::qtractorAudioPeakThread ( unsigned int iSyncSize ) { m_iSyncSize = (64 << 1); while (m_iSyncSize < iSyncSize) m_iSyncSize <<= 1; m_iSyncMask = (m_iSyncSize - 1); m_ppSyncItems = new qtractorAudioPeak * [m_iSyncSize]; m_iSyncRead = 0; m_iSyncWrite = 0; ::memset(m_ppSyncItems, 0, m_iSyncSize * sizeof(qtractorAudioPeak *)); m_bRunState = false; m_pPeakFile = NULL; m_pAudioFile = NULL; m_ppAudioFrames = NULL; } // Destructor. qtractorAudioPeakThread::~qtractorAudioPeakThread (void) { delete [] m_ppSyncItems; } // Run state accessor. void qtractorAudioPeakThread::setRunState ( bool bRunState ) { QMutexLocker locker(&m_mutex); m_bRunState = bRunState; } bool qtractorAudioPeakThread::runState (void) const { return m_bRunState; } // Wake from executive wait condition. void qtractorAudioPeakThread::sync ( qtractorAudioPeakFile *pPeakFile ) { if (pPeakFile == NULL) { unsigned int r = m_iSyncRead; unsigned int w = m_iSyncWrite; while (r != w) { qtractorAudioPeak *pSyncItem = m_ppSyncItems[r]; if (pSyncItem) pSyncItem->peakFile()->setWaitSync(false); ++r &= m_iSyncMask; w = m_iSyncWrite; } // m_iSyncRead = r; } else { // !pPeakFile->isWaitSync() unsigned int n; unsigned int r = m_iSyncRead; unsigned int w = m_iSyncWrite; if (w > r) { n = ((r - w + m_iSyncSize) & m_iSyncMask) - 1; } else if (r > w) { n = (r - w) - 1; } else { n = m_iSyncSize - 1; } if (n > 0) { pPeakFile->setWaitSync(true); m_ppSyncItems[w] = new qtractorAudioPeak(pPeakFile); m_iSyncWrite = (w + 1) & m_iSyncMask; } } if (m_mutex.tryLock()) { m_cond.wakeAll(); m_mutex.unlock(); } #ifdef CONFIG_DEBUG_0 else qDebug("qtractorAudioPeakThread[%p]::sync(): tryLock() failed.", this); #endif } // The main thread executive cycle. void qtractorAudioPeakThread::run (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioPeakThread[%p]::run(): started...", this); #endif m_mutex.lock(); m_bRunState = true; while (m_bRunState) { // Do whatever we must, then wait for more... unsigned int r = m_iSyncRead; unsigned int w = m_iSyncWrite; while (r != w) { qtractorAudioPeak *pSyncItem = m_ppSyncItems[r]; m_pPeakFile = pSyncItem->peakFile(); if (m_pPeakFile->isWaitSync()) { if (openPeakFile()) { // Go ahead with the whole bunch... while (writePeakFile()) /* empty loop */; // We're done. closePeakFile(); } m_pPeakFile->setWaitSync(false); } delete pSyncItem; m_ppSyncItems[r] = NULL; ++r &= m_iSyncMask; w = m_iSyncWrite; } m_iSyncRead = r; // Send notification event, anyway... notifyPeakEvent(); // Wait for sync... m_cond.wait(&m_mutex); } m_mutex.unlock(); #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioPeakThread[%p]::run(): stopped.\n", this); #endif } // Open the peak file for create. bool qtractorAudioPeakThread::openPeakFile (void) { m_pAudioFile = qtractorAudioFileFactory::createAudioFile(m_pPeakFile->filename()); if (m_pAudioFile == NULL) return false; if (!m_pAudioFile->open(m_pPeakFile->filename())) { delete m_pAudioFile; m_pAudioFile = NULL; return false; } unsigned short iChannels = m_pAudioFile->channels(); unsigned int iSampleRate = m_pAudioFile->sampleRate(); if (!m_pPeakFile->openWrite(iChannels, iSampleRate)) { delete m_pAudioFile; m_pAudioFile = NULL; return false; } #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioPeakThread::openPeakFile(%p)", m_pPeakFile); #endif // Allocate audio file frame buffer // and peak period accumulators. m_ppAudioFrames = new float* [iChannels]; for (unsigned short i = 0; i < iChannels; ++i) m_ppAudioFrames[i] = new float [c_iAudioFrames]; return true; } // Create the peak file chunk. bool qtractorAudioPeakThread::writePeakFile (void) { if (!m_bRunState) return false; if (m_ppAudioFrames == NULL) return false; #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioPeakThread::writePeakFile(%p)", m_pPeakFile); #endif // Read another bunch of frames from the physical audio file... int nread = m_pAudioFile->read(m_ppAudioFrames, c_iAudioFrames); if (nread > 0) m_pPeakFile->write(m_ppAudioFrames, nread); return (nread > 0); } // Close the (hopefully) created peak file. void qtractorAudioPeakThread::closePeakFile (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioPeakThread::closePeakFile(%p)", m_pPeakFile); #endif // Always force target file close. m_pPeakFile->closeWrite(); // Get rid of physical used stuff. if (m_ppAudioFrames) { unsigned short iChannels = m_pAudioFile->channels(); for (unsigned short i = 0; i < iChannels; ++i) delete [] m_ppAudioFrames[i]; delete [] m_ppAudioFrames; m_ppAudioFrames = NULL; } // Finally the source file too. if (m_pAudioFile) { delete m_pAudioFile; m_pAudioFile = NULL; } // Send notification event, someway... notifyPeakEvent(); } // Send notification event, someway... void qtractorAudioPeakThread::notifyPeakEvent (void) const { if (!m_bRunState) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { qtractorAudioPeakFactory *pPeakFactory = pSession->audioPeakFactory(); if (pPeakFactory) pPeakFactory->notifyPeakEvent(); } } //---------------------------------------------------------------------- // class qtractorAudioPeakFile -- Audio peak file (ref'counted) // // Constructor. qtractorAudioPeakFile::qtractorAudioPeakFile ( const QString& sFilename, float fTimeStretch ) { // Initialize instance variables. m_sFilename = sFilename; m_fTimeStretch = fTimeStretch; m_openMode = None; m_peakHeader.period = c_iPeakPeriod; m_peakHeader.channels = 0; m_pBuffer = NULL; m_iBuffSize = 0; m_iBuffLength = 0; m_iBuffOffset = 0; m_iWriteOffset = 0; m_peakMax = NULL; m_peakMin = NULL; m_peakRms = NULL; m_iPeakPeriod = 0; m_iPeak = 0; m_bWaitSync = false; m_iRefCount = 0; // Set peak filename... QDir dir; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) dir.setPath(pSession->sessionDir()); const QString sPeakFilePrefix = QFileInfo(dir, QFileInfo(sFilename).fileName()).filePath() + '_' + QString::number(fTimeStretch); QFileInfo peakInfo(sPeakFilePrefix + c_sPeakFileExt); // Avoid duplicates, as much as psssible... for (int i = 1; peakInfo.exists(); ++i) { peakInfo.setFile(sPeakFilePrefix + '-' + QString::number(i) + c_sPeakFileExt); } m_peakFile.setFileName(peakInfo.absoluteFilePath()); } // Default destructor. qtractorAudioPeakFile::~qtractorAudioPeakFile (void) { // Check if it's aborting (ought to be atomic)... bool bAborted = m_bWaitSync; m_bWaitSync = false; // Close the file, anyway now. closeWrite(); closeRead(); // Tell master-factory that we're out. qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { qtractorAudioPeakFactory *pPeakFactory = pSession->audioPeakFactory(); if (pPeakFactory) { pPeakFactory->removePeak(this); // Do we get rid from the filesystem too? if (pPeakFactory->isAutoRemove() || bAborted) m_peakFile.remove(); } } } // Open an existing peak file cache. bool qtractorAudioPeakFile::openRead (void) { // If it's already open, just tell the news. if (m_openMode != None) return true; // Are we still waiting for its creation? if (m_bWaitSync) return false; // Need some preliminary file information... QFileInfo fileInfo(m_sFilename); QFileInfo peakInfo(m_peakFile.fileName()); // Have we a peak file up-to-date, // or must the peak file be (re)created? if (!peakInfo.exists() || peakInfo.created() < fileInfo.created()) { // || peakInfo.lastModified() < fileInfo.lastModified()) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { qtractorAudioPeakFactory *pPeakFactory = pSession->audioPeakFactory(); if (pPeakFactory) pPeakFactory->sync(this); } return false; } // Make things critical... QMutexLocker locker(&m_mutex); // Just open and go ahead with first bunch... if (!m_peakFile.open(QIODevice::ReadOnly)) return false; if (m_peakFile.read((char *) &m_peakHeader, sizeof(Header)) != (qint64) sizeof(Header)) { m_peakFile.close(); return false; } // Set open mode... m_openMode = Read; #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioPeakFile[%p]::openRead() ---", this); qDebug("name = %s", m_peakFile.fileName().toUtf8().constData()); qDebug("filename = %s", m_sFilename.toUtf8().constData()); qDebug("timeStretch = %g", m_fTimeStretch); qDebug("header = %lu", sizeof(Header)); qDebug("frame = %lu", sizeof(Frame)); qDebug("period = %d", m_peakHeader.period); qDebug("channels = %d", m_peakHeader.channels); qDebug("---"); #endif // Its a certain success... return true; } // Free all attended resources for this peak file. void qtractorAudioPeakFile::closeRead (void) { // Make things critical... QMutexLocker locker(&m_mutex); // Close file. if (m_openMode == Read) { m_peakFile.close(); m_openMode = None; } if (m_pBuffer) delete [] m_pBuffer; m_pBuffer = NULL; m_iBuffSize = 0; m_iBuffLength = 0; m_iBuffOffset = 0; } // Audio properties accessors. const QString& qtractorAudioPeakFile::filename (void) const { return m_sFilename; } float qtractorAudioPeakFile::timeStretch (void) const { return m_fTimeStretch; } // Peak cache properties accessors. QString qtractorAudioPeakFile::name (void) const { return m_peakFile.fileName(); } unsigned short qtractorAudioPeakFile::period (void) { return m_peakHeader.period; } unsigned short qtractorAudioPeakFile::channels (void) { return m_peakHeader.channels; } // Read frames from peak file. qtractorAudioPeakFile::Frame *qtractorAudioPeakFile::read ( unsigned long iPeakOffset, unsigned int iPeakFrames ) { // Must be open for something... if (m_openMode == None) return NULL; // Make things critical... QMutexLocker locker(&m_mutex); #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioPeakFile[%p]::read(%lu, %u) [%lu, %u, %u]", this, iPeakOffset, iPeakFrames, m_iBuffOffset, m_iBuffLength, m_iBuffSize); #endif // Cache effect, only valid if we're really reading... unsigned long iPeakEnd = iPeakOffset + iPeakFrames; if (iPeakOffset >= m_iBuffOffset && m_iBuffOffset < iPeakEnd) { unsigned long iBuffEnd = m_iBuffOffset + m_iBuffLength; if (iBuffEnd >= iPeakEnd) return m_pBuffer + m_peakHeader.channels * (iPeakOffset - m_iBuffOffset); if (m_iBuffOffset + m_iBuffSize >= iPeakEnd) { m_iBuffLength += readBuffer(m_iBuffLength, iBuffEnd, iPeakEnd - iBuffEnd); return m_pBuffer + m_peakHeader.channels * (iPeakOffset - m_iBuffOffset); } } // Read peak data as requested... m_iBuffLength = readBuffer(0, iPeakOffset, iPeakFrames); m_iBuffOffset = iPeakOffset; return m_pBuffer; } // Read frames from peak file into local buffer cache. unsigned int qtractorAudioPeakFile::readBuffer ( unsigned int iBuffOffset, unsigned long iPeakOffset, unsigned int iPeakFrames ) { // Shall we reallocate? if (iBuffOffset + iPeakFrames > m_iBuffSize) { Frame *pOldBuffer = m_pBuffer; m_iBuffSize += (iPeakFrames << 1); m_pBuffer = new Frame [m_peakHeader.channels * m_iBuffSize]; if (pOldBuffer) { ::memcpy(m_pBuffer, pOldBuffer, m_peakHeader.channels * m_iBuffLength * sizeof(Frame)); delete [] pOldBuffer; } } #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioPeakFile[%p]::readBuffer(%u, %lu, %u) [%lu, %u, %u]", this, iBuffOffset, iPeakOffset, iPeakFrames, m_iBuffOffset, m_iBuffLength, m_iBuffSize); #endif // Grab new contents from peak file... char *pBuffer = (char *) (m_pBuffer + m_peakHeader.channels * iBuffOffset); unsigned long iOffset = iPeakOffset * m_peakHeader.channels * sizeof(Frame); unsigned int iLength = iPeakFrames * m_peakHeader.channels * sizeof(Frame); int nread = 0; if (m_peakFile.seek(sizeof(Header) + iOffset)) nread = (int) m_peakFile.read(&pBuffer[0], iLength); // Zero the remaining... if (nread < (int) iLength) ::memset(&pBuffer[nread], 0, iLength - nread); return nread / (m_peakHeader.channels * sizeof(Frame)); } // Open an new peak file for writing. bool qtractorAudioPeakFile::openWrite ( unsigned short iChannels, unsigned int iSampleRate ) { // If it's already open, just tell the news. if (m_openMode == Write) return true; // Make things critical... QMutexLocker locker(&m_mutex); // We'll force (re)open if already reading (duh?) if (m_openMode == Read) { m_peakFile.close(); m_openMode = None; } // Just open and go ahead with it... if (!m_peakFile.open(QIODevice::ReadWrite | QIODevice::Truncate)) return false; // Set open mode... m_openMode = Write; // Initialize header... m_peakHeader.period = c_iPeakPeriod; m_peakHeader.channels = iChannels; // Write peak file header. if (m_peakFile.write((const char *) &m_peakHeader, sizeof(Header)) != (qint64) sizeof(Header)) { m_peakFile.close(); return false; } #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioPeakFile[%p]::openWrite() ---", this); qDebug("name = %s", m_peakFile.fileName().toUtf8().constData()); qDebug("filename = %s", m_sFilename.toUtf8().constData()); qDebug("timeStretch = %g", m_fTimeStretch); qDebug("header = %u", sizeof(Header)); qDebug("frame = %u", sizeof(Frame)); qDebug("period = %d", m_peakHeader.period); qDebug("channels = %d", m_peakHeader.channels); qDebug("---"); #endif // Go ahead, it's already open. m_iWriteOffset = 0; m_peakMax = new float [m_peakHeader.channels]; m_peakMin = new float [m_peakHeader.channels]; m_peakRms = new float [m_peakHeader.channels]; for (unsigned short i = 0; i < m_peakHeader.channels; ++i) m_peakMax[i] = m_peakMin[i] = m_peakRms[i] = 0.0f; m_iPeakPeriod = c_iPeakPeriod; m_iPeak = 0; // Get running sample-rate... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { // The resample/timestretch-aware internal peak period... m_iPeakPeriod = (unsigned short) ::lroundf( (float(c_iPeakPeriod * iSampleRate)) / (float(pSession->sampleRate()) * m_fTimeStretch)); } // Its a certain success... return true; } // Close the (hopefully) created peak file. void qtractorAudioPeakFile::closeWrite (void) { // Make things critical... QMutexLocker locker(&m_mutex); // Flush and close... if (m_openMode == Write) { if (m_iPeak > 0) writeFrame(); m_peakFile.close(); m_openMode = None; } if (m_peakMax) delete [] m_peakMax; m_peakMax = NULL; if (m_peakMin) delete [] m_peakMin; m_peakMin = NULL; if (m_peakRms) delete [] m_peakRms; m_peakRms = NULL; m_iPeakPeriod = 0; m_iPeak = 0; } // Write peak from audio frame methods. void qtractorAudioPeakFile::write ( float **ppAudioFrames, unsigned int iAudioFrames ) { if (m_openMode != Write) return; // Make things critical... QMutexLocker locker(&m_mutex); for (unsigned int n = 0; n < iAudioFrames; ++n) { // Accumulate for this sample frame... for (unsigned short i = 0; i < m_peakHeader.channels; ++i) { float fSample = ppAudioFrames[i][n]; if (m_peakMax[i] < fSample) m_peakMax[i] = fSample; if (m_peakMin[i] > fSample) m_peakMin[i] = fSample; m_peakRms[i] += (fSample * fSample); } // Have we reached the peak accumulative period? if (++m_iPeak >= m_iPeakPeriod) writeFrame(); } } void qtractorAudioPeakFile::writeFrame (void) { if (!m_peakFile.seek(sizeof(Header) + m_iWriteOffset)) return; for (unsigned short i = 0; i < m_peakHeader.channels; ++i) { Frame frame; // Write the denormalized peak values... m_peakMax[i] = 255.0f * ::fabs(m_peakMax[i]); m_peakMin[i] = 255.0f * ::fabs(m_peakMin[i]); m_peakRms[i] = 255.0f * ::sqrtf(m_peakRms[i] / float(m_iPeak)); frame.max = (unsigned char) (m_peakMax[i] > 255.0f ? 255 : m_peakMax[i]); frame.min = (unsigned char) (m_peakMin[i] > 255.0f ? 255 : m_peakMin[i]); frame.rms = (unsigned char) (m_peakRms[i] > 255.0f ? 255 : m_peakRms[i]); // Reset peak period accumulators... m_peakMax[i] = m_peakMin[i] = m_peakRms[i] = 0.0f; // Bail out?... m_iWriteOffset += m_peakFile.write((const char *) &frame, sizeof(Frame)); } // We'll reset. m_iPeak = 0; } // Reference count methods. void qtractorAudioPeakFile::addRef (void) { ++m_iRefCount; } void qtractorAudioPeakFile::removeRef (void) { if (--m_iRefCount == 0) delete this; } // Sync thread state flags accessors. void qtractorAudioPeakFile::setWaitSync ( bool bWaitSync ) { m_bWaitSync = bWaitSync; } bool qtractorAudioPeakFile::isWaitSync (void) const { return m_bWaitSync; } //---------------------------------------------------------------------- // class qtractorAudioPeakFactory -- Audio peak file factory (singleton). // // Constructor. qtractorAudioPeakFactory::qtractorAudioPeakFactory ( QObject *pParent ) : QObject(pParent), m_bAutoRemove(false), m_pPeakThread(NULL) { } // Default destructor. qtractorAudioPeakFactory::~qtractorAudioPeakFactory (void) { if (m_pPeakThread) { if (m_pPeakThread->isRunning()) do { m_pPeakThread->setRunState(false); // m_pPeakThread->terminate(); m_pPeakThread->sync(); } while (!m_pPeakThread->wait(100)); delete m_pPeakThread; m_pPeakThread = NULL; } qDeleteAll(m_peaks); m_peaks.clear(); } // The peak file factory-methods. qtractorAudioPeak* qtractorAudioPeakFactory::createPeak ( const QString& sFilename, float fTimeStretch ) { QMutexLocker locker(&m_mutex); if (m_pPeakThread == NULL) { m_pPeakThread = new qtractorAudioPeakThread(); m_pPeakThread->start(); } const QString sKey = sFilename + '_' + QString::number(fTimeStretch); qtractorAudioPeakFile *pPeakFile = m_peaks.value(sKey, NULL); if (pPeakFile == NULL) { pPeakFile = new qtractorAudioPeakFile(sFilename, fTimeStretch); m_peaks.insert(sKey, pPeakFile); } return new qtractorAudioPeak(pPeakFile); } void qtractorAudioPeakFactory::removePeak ( qtractorAudioPeakFile *pPeakFile ) { QMutexLocker locker(&m_mutex); m_peaks.remove(pPeakFile->filename() + '_' + QString::number(pPeakFile->timeStretch())); } // Auto-delete property. void qtractorAudioPeakFactory::setAutoRemove ( bool bAutoRemove ) { m_bAutoRemove = bAutoRemove; } bool qtractorAudioPeakFactory::isAutoRemove (void) const { return m_bAutoRemove; } // Event notifier. void qtractorAudioPeakFactory::notifyPeakEvent (void) { emit peakEvent(); } // Base sync method. void qtractorAudioPeakFactory::sync ( qtractorAudioPeakFile *pPeakFile ) { if (m_pPeakThread) m_pPeakThread->sync(pPeakFile); } // end of qtractorAudioPeak.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorPluginListView.cpp0000644000175000001440000000012312166526620022462 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134668.01408 30 ctime=1381134668.015080065 qtractor-0.5.11/src/qtractorPluginListView.cpp0000644000175000001440000012365012166526620021760 0ustar00rncbcusers00000000000000// qtractorPluginListView.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorPluginListView.h" #include "qtractorPluginCommand.h" #include "qtractorPluginSelectForm.h" #include "qtractorPluginForm.h" #include "qtractorRubberBand.h" #include "qtractorSession.h" #include "qtractorMainForm.h" #include "qtractorAudioEngine.h" #include "qtractorMidiBuffer.h" #include "qtractorConnections.h" #include "qtractorInsertPlugin.h" #include "qtractorOptions.h" #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #include #endif //---------------------------------------------------------------------------- // qtractorTinyScrollBarStyle -- Custom style to have some tiny scrollbars // #if QT_VERSION < 0x050000 #include #else #include class QCDEStyle : public QCommonStyle {}; #endif class qtractorTinyScrollBarStyle : public QCDEStyle { protected: // Custom virtual override. int pixelMetric( PixelMetric pm, const QStyleOption *option = 0, const QWidget *pWidget = 0 ) const { if (pm == QStyle::PM_ScrollBarExtent) return 8; return QCommonStyle::pixelMetric(pm, option, pWidget); } }; static qtractorTinyScrollBarStyle g_tinyScrollBarStyle; //---------------------------------------------------------------------------- // qtractorPluginListItemDelegate -- Plugin list view item delgate. class qtractorPluginListItemDelegate : public QItemDelegate { public: // Constructor. qtractorPluginListItemDelegate(QListWidget *pListWidget) : QItemDelegate(pListWidget), m_pListWidget(pListWidget) {} // Overridden paint method. void paint(QPainter *pPainter, const QStyleOptionViewItem& option, const QModelIndex& index) const { qtractorPluginListItem *pItem = static_cast ( m_pListWidget->item(index.row())); // nb. Unselectable items get special grayed out painting... if (pItem) { pPainter->save(); const QPalette& pal = option.palette; QColor rgbBack; QColor rgbFore; if (option.state & QStyle::State_HasFocus) { rgbBack = pal.highlight().color(); rgbFore = pal.highlightedText().color(); } else { rgbBack = pal.window().color(); rgbFore = pal.windowText().color(); } // Fill the background... pPainter->fillRect(option.rect, rgbBack); const QSize& iconSize = m_pListWidget->iconSize(); // Draw the direct access parameter value status... QPolygon polyg(3); qtractorPlugin *pPlugin = pItem->plugin(); qtractorPluginParam *pDirectAccessParam = NULL; qtractorMidiControlObserver *pDirectAccessObserver = NULL; if (pPlugin) pDirectAccessParam = pPlugin->directAccessParam(); if (pDirectAccessParam) pDirectAccessObserver = pDirectAccessParam->observer(); if (pDirectAccessObserver) { float fScale = pDirectAccessObserver->scaleFromValue( pDirectAccessParam->value(), pDirectAccessParam->isLogarithmic()); QRect rectValue = option.rect .adjusted(iconSize.width(), 1, -2, -2); const int iDirectAccessWidth = rectValue.width(); pItem->setDirectAccessWidth(iDirectAccessWidth); rectValue.setWidth(int(fScale * float(iDirectAccessWidth))); pPainter->fillRect(rectValue, rgbBack.lighter(140)); polyg.setPoint(0, rectValue.right(), rectValue.top() + 1); polyg.setPoint(1, rectValue.right() - 2, rectValue.bottom() + 1); polyg.setPoint(2, rectValue.right() + 2, rectValue.bottom() + 1); } // Draw the icon... QRect rect = option.rect; pPainter->drawPixmap(1, rect.top() + ((rect.height() - iconSize.height()) >> 1), pItem->icon().pixmap(iconSize)); // Draw the text... rect.setLeft(iconSize.width()); pPainter->setPen(rgbFore); pPainter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, pItem->text()); // Draw frame lines... pPainter->setPen(rgbBack.lighter(150)); pPainter->drawLine( option.rect.left(), option.rect.top(), option.rect.right(), option.rect.top()); pPainter->setPen(rgbBack.darker(150)); pPainter->drawLine( option.rect.left(), option.rect.bottom(), option.rect.right(), option.rect.bottom()); if (pDirectAccessObserver) { pPainter->setRenderHint(QPainter::Antialiasing, true); pPainter->setBrush(rgbBack.darker(160)); pPainter->drawPolygon(polyg); pPainter->setPen(rgbBack.lighter(180)); pPainter->drawLine(polyg.at(0), polyg.at(1)); pPainter->setRenderHint(QPainter::Antialiasing, false); } pPainter->restore(); // if (option.state & QStyle::State_HasFocus) // QItemDelegate::drawFocus(pPainter, option, option.rect); } else { // Others do as default... QItemDelegate::paint(pPainter, option, index); } } private: QListWidget *m_pListWidget; }; //---------------------------------------------------------------------------- // qtractorPluginListItem -- Plugins list item. // Constructors. qtractorPluginListItem::qtractorPluginListItem ( qtractorPlugin *pPlugin ) : QListWidgetItem(), m_pPlugin(pPlugin), m_iDirectAccessWidth(0) { m_pPlugin->addItem(this); QString sText; qtractorPluginType *pType = m_pPlugin->type(); if (pType->typeHint() == qtractorPluginType::AuxSend) { qtractorAuxSendPlugin *pAuxSendPlugin = static_cast (m_pPlugin); if (pAuxSendPlugin) sText = pAuxSendPlugin->audioBusName(); } QListWidgetItem::setText(sText.isEmpty() ? pType->name() : sText); updateActivated(); } // Destructor. qtractorPluginListItem::~qtractorPluginListItem (void) { m_pPlugin->removeItem(this); } // Plugin container accessor. qtractorPlugin *qtractorPluginListItem::plugin (void) const { return m_pPlugin; } // Activation methods. void qtractorPluginListItem::updateActivated (void) { QListWidgetItem::setIcon( *qtractorPluginListView::itemIcon( m_pPlugin && m_pPlugin->isActivated() ? 1 : 0)); } //---------------------------------------------------------------------------- // qtractorPluginListView -- Plugin chain list widget instance. // int qtractorPluginListView::g_iItemRefCount = 0; QIcon *qtractorPluginListView::g_pItemIcons[2] = { NULL, NULL }; // Construcctor. qtractorPluginListView::qtractorPluginListView ( QWidget *pParent ) : QListWidget(pParent), m_pPluginList(NULL), m_pClickedItem(NULL) { if (++g_iItemRefCount == 1) { g_pItemIcons[0] = new QIcon(":/images/itemLedOff.png"); g_pItemIcons[1] = new QIcon(":/images/itemLedOn.png"); } // Drag-and-drop stuff. m_dragCursor = DragNone; m_dragState = DragNone; m_pDragItem = NULL; m_pDropItem = NULL; m_pRubberBand = NULL; // QListWidget::setDragEnabled(true); QListWidget::setAcceptDrops(true); QListWidget::setDropIndicatorShown(true); QListWidget::setAutoScroll(true); QListWidget::setIconSize(QSize(10, 10)); QListWidget::setItemDelegate(new qtractorPluginListItemDelegate(this)); QListWidget::setSelectionMode(QAbstractItemView::SingleSelection); QListWidget::setMouseTracking(true); QListWidget::viewport()->setBackgroundRole(QPalette::Window); QListWidget::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // QListWidget::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QListWidget::setFrameShape(QFrame::Panel); QListWidget::setFrameShadow(QFrame::Sunken); // Trap for help/tool-tips events. QListWidget::viewport()->installEventFilter(this); // Double-click handling... QObject::connect(this, SIGNAL(itemDoubleClicked(QListWidgetItem*)), SLOT(itemDoubleClickedSlot(QListWidgetItem*))); #if 0 QObject::connect(this, SIGNAL(itemActivated(QListWidgetItem*)), SLOT(itemActivatedSlot(QListWidgetItem*))); #endif } // Destructor. qtractorPluginListView::~qtractorPluginListView (void) { // No need to delete child widgets, Qt does it all for us clear(); setPluginList(NULL); if (--g_iItemRefCount == 0) { for (int i = 0; i < 2; ++i) { delete g_pItemIcons[i]; g_pItemIcons[i] = NULL; } } } // Plugin list accessors. void qtractorPluginListView::setPluginList ( qtractorPluginList *pPluginList ) { if (m_pPluginList) m_pPluginList->removeView(this); m_pPluginList = pPluginList; if (m_pPluginList) m_pPluginList->addView(this); refresh(); } qtractorPluginList *qtractorPluginListView::pluginList (void) const { return m_pPluginList; } // Special scrollbar style accessors. void qtractorPluginListView::setTinyScrollBar ( bool bTinyScrollBar ) { if (bTinyScrollBar) { QListWidget::verticalScrollBar()->setStyle(&g_tinyScrollBarStyle); QListWidget::horizontalScrollBar()->setStyle(&g_tinyScrollBarStyle); } else { QListWidget::verticalScrollBar()->setStyle(NULL); QListWidget::horizontalScrollBar()->setStyle(NULL); } } bool qtractorPluginListView::isTinyScrollBar (void) const { return QListWidget::verticalScrollBar()->style() == &g_tinyScrollBarStyle && QListWidget::horizontalScrollBar()->style() == &g_tinyScrollBarStyle; } // Plugin list refreshner void qtractorPluginListView::refresh (void) { clear(); QListWidget::setUpdatesEnabled(false); if (m_pPluginList) { for (qtractorPlugin *pPlugin = m_pPluginList->first(); pPlugin; pPlugin = pPlugin->next()) { QListWidget::addItem(new qtractorPluginListItem(pPlugin)); } } QListWidget::setUpdatesEnabled(true); } // Master clean-up. void qtractorPluginListView::clear (void) { dragLeaveEvent(NULL); QListWidget::clear(); } // Get an item index, given the plugin reference... int qtractorPluginListView::pluginItem ( qtractorPlugin *pPlugin ) { int iItemCount = QListWidget::count(); for (int iItem = 0; iItem < iItemCount; ++iItem) { qtractorPluginListItem *pItem = static_cast (QListWidget::item(iItem)); if (pItem && pItem->plugin() == pPlugin) return iItem; } return -1; } // Move item on list. void qtractorPluginListView::moveItem ( qtractorPluginListItem *pItem, qtractorPluginListItem *pNextItem ) { if (pItem == NULL) return; if (m_pPluginList == NULL) return; // The plugin to be moved... qtractorPlugin *pPlugin = pItem->plugin(); if (pPlugin == NULL) return; // To be after this one... qtractorPlugin *pNextPlugin = NULL; if (pNextItem) pNextPlugin = pNextItem->plugin(); // Make it an undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; pSession->execute( new qtractorMovePluginCommand(pPlugin, pNextPlugin, m_pPluginList)); emit contentsChanged(); } // Copy item on list. void qtractorPluginListView::copyItem ( qtractorPluginListItem *pItem, qtractorPluginListItem *pNextItem ) { if (pItem == NULL) return; if (m_pPluginList == NULL) return; // The plugin to be moved... qtractorPlugin *pPlugin = pItem->plugin(); // Clone/copy the new plugin here... if (pPlugin) pPlugin = m_pPluginList->copyPlugin(pPlugin); if (pPlugin == NULL) return; // To be after this one... qtractorPlugin *pNextPlugin = NULL; if (pNextItem) pNextPlugin = pNextItem->plugin(); // Make it an undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; pSession->execute( new qtractorInsertPluginCommand( tr("copy plugin"), pPlugin, pNextPlugin)); emit contentsChanged(); } // Add a new plugin slot. void qtractorPluginListView::addPlugin (void) { if (m_pPluginList == NULL) return; qtractorPluginSelectForm selectForm(this); selectForm.setChannels(m_pPluginList->channels(), m_pPluginList->isMidi()); if (!selectForm.exec()) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; bool bOpenEditor = false; qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) bOpenEditor = pOptions->bOpenEditor; // Tell the world we'll take some time, iif... if (!bOpenEditor) QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // Make it a undoable command... qtractorAddPluginCommand *pAddPluginCommand = new qtractorAddPluginCommand(); for (int i = 0; i < selectForm.pluginCount(); ++i) { // Add an actual plugin item... qtractorPlugin *pPlugin = qtractorPluginFile::createPlugin(m_pPluginList, selectForm.pluginFilename(i), selectForm.pluginIndex(i), selectForm.pluginTypeHint(i)); if (pPlugin) { pPlugin->setActivated(selectForm.isPluginActivated()); pAddPluginCommand->addPlugin(pPlugin); // Show the plugin form right away... if (bOpenEditor && (pPlugin->type())->isEditor()) pPlugin->openEditor(this); else (pPlugin->form())->activateForm(); } } pSession->execute(pAddPluginCommand); // We're formerly done. if (!bOpenEditor) QApplication::restoreOverrideCursor(); emit contentsChanged(); } // Add an insert pseudo-plugin slot. void qtractorPluginListView::addInsertPlugin (void) { if (m_pPluginList == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Tell the world we'll take some time... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // Create our special pseudo-plugin type... qtractorPlugin *pPlugin = qtractorPluginFile::createPlugin(m_pPluginList, QString(), // Empty filename! m_pPluginList->channels(), qtractorPluginType::Insert); if (pPlugin) { // Show the plugin form right away... (pPlugin->form())->activateForm(); // Make it a undoable command... pSession->execute(new qtractorAddInsertPluginCommand(pPlugin)); } // We're formerly done. QApplication::restoreOverrideCursor(); emit contentsChanged(); } // Add an insert pseudo-plugin slot. void qtractorPluginListView::addAuxSendPlugin (void) { if (m_pPluginList == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Tell the world we'll take some time... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // Create our special pseudo-plugin type... qtractorPlugin *pPlugin = qtractorPluginFile::createPlugin(m_pPluginList, QString(), // Empty filename! m_pPluginList->channels(), qtractorPluginType::AuxSend); if (pPlugin) { // Show the plugin form right away... (pPlugin->form())->activateForm(); // Make it a undoable command... pSession->execute(new qtractorAddAuxSendPluginCommand(pPlugin)); } // We're formerly done. QApplication::restoreOverrideCursor(); emit contentsChanged(); } // Remove an existing plugin slot. void qtractorPluginListView::removePlugin (void) { if (m_pPluginList == NULL) return; qtractorPluginListItem *pItem = static_cast (QListWidget::currentItem()); if (pItem == NULL) return; qtractorPlugin *pPlugin = pItem->plugin(); if (pPlugin == NULL) return; // Make it a undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; pSession->execute(new qtractorRemovePluginCommand(pPlugin)); emit contentsChanged(); } // Activate existing plugin slot. void qtractorPluginListView::activatePlugin (void) { qtractorPluginListItem *pItem = static_cast (QListWidget::currentItem()); if (pItem == NULL) return; qtractorPlugin *pPlugin = pItem->plugin(); if (pPlugin == NULL) return; // Make it a undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; pSession->execute( new qtractorActivatePluginCommand(pPlugin, !pPlugin->isActivated())); emit contentsChanged(); } // Activate all plugins. void qtractorPluginListView::activateAllPlugins (void) { if (m_pPluginList == NULL) return; // Check whether everyone is already activated... if (m_pPluginList->count() < 1 || m_pPluginList->isActivatedAll()) return; // Make it an undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorActivatePluginCommand *pActivateAllCommand = new qtractorActivatePluginCommand(NULL, true); pActivateAllCommand->setName(tr("activate all plugins")); for (qtractorPlugin *pPlugin = m_pPluginList->first(); pPlugin; pPlugin = pPlugin->next()) { if (!pPlugin->isActivated()) pActivateAllCommand->addPlugin(pPlugin); } pSession->execute(pActivateAllCommand); emit contentsChanged(); } // Dectivate all plugins. void qtractorPluginListView::deactivateAllPlugins (void) { if (m_pPluginList == NULL) return; // Check whether everyone is already dectivated... if (m_pPluginList->activated() < 1) return; // Make it an undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorActivatePluginCommand *pDeactivateAllCommand = new qtractorActivatePluginCommand(NULL, false); pDeactivateAllCommand->setName(tr("deactivate all plugins")); for (qtractorPlugin *pPlugin = m_pPluginList->first(); pPlugin; pPlugin = pPlugin->next()) { if (pPlugin->isActivated()) pDeactivateAllCommand->addPlugin(pPlugin); } pSession->execute(pDeactivateAllCommand); emit contentsChanged(); } // Remove all plugins. void qtractorPluginListView::removeAllPlugins (void) { if (m_pPluginList == NULL) return; // Check whether there's any... if (m_pPluginList->count() < 1) return; // Make it an undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorRemovePluginCommand *pRemoveAllCommand = new qtractorRemovePluginCommand(); pRemoveAllCommand->setName(tr("remove all plugins")); for (qtractorPlugin *pPlugin = m_pPluginList->first(); pPlugin; pPlugin = pPlugin->next()) { pRemoveAllCommand->addPlugin(pPlugin); } pSession->execute(pRemoveAllCommand); emit contentsChanged(); } // Move an existing plugin upward slot. void qtractorPluginListView::moveUpPlugin (void) { if (m_pPluginList == NULL) return; qtractorPluginListItem *pItem = static_cast (QListWidget::currentItem()); if (pItem == NULL) return; int iNextItem = QListWidget::row(pItem) - 1; if (iNextItem < 0) return; qtractorPluginListItem *pNextItem = static_cast ( QListWidget::item(iNextItem)); if (pNextItem == NULL) return; moveItem(pItem, pNextItem); } // Move an existing plugin downward slot. void qtractorPluginListView::moveDownPlugin (void) { if (m_pPluginList == NULL) return; qtractorPluginListItem *pItem = static_cast (QListWidget::currentItem()); if (pItem == NULL) return; int iNextItem = QListWidget::row(pItem) + 1; if (iNextItem >= QListWidget::count()) return; qtractorPluginListItem *pNextItem = static_cast ( QListWidget::item(iNextItem + 1)); moveItem(pItem, pNextItem); } // Select a direct access parameter index. void qtractorPluginListView::directAccessPlugin (void) { if (m_pPluginList == NULL) return; qtractorPluginListItem *pItem = static_cast (QListWidget::currentItem()); if (pItem == NULL) return; qtractorPlugin *pPlugin = pItem->plugin(); if (pPlugin == NULL) return; // Retrieve direct access parameter index from action data... QAction *pAction = qobject_cast (sender()); if (pAction == NULL) return; int iDirectAccessParamIndex = pAction->data().toInt(); // Make it a undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; pSession->execute( new qtractorDirectAccessParamCommand(pPlugin, iDirectAccessParamIndex)); } // Show/hide an existing plugin form slot. void qtractorPluginListView::propertiesPlugin (void) { if (m_pPluginList == NULL) return; qtractorPluginListItem *pItem = static_cast (QListWidget::currentItem()); if (pItem == NULL) return; qtractorPlugin *pPlugin = pItem->plugin(); if (pPlugin == NULL) return; if (pPlugin->isFormVisible()) (pPlugin->form())->hide(); else (pPlugin->form())->activateForm(); } // Show/hide an existing plugin editor (GUI) slot. void qtractorPluginListView::editPlugin (void) { if (m_pPluginList == NULL) return; qtractorPluginListItem *pItem = static_cast (QListWidget::currentItem()); if (pItem == NULL) return; qtractorPlugin *pPlugin = pItem->plugin(); if (pPlugin == NULL) return; if (pPlugin->isEditorVisible()) pPlugin->closeEditor(); else pPlugin->openEditor(this); } // Insert specific slots. void qtractorPluginListView::insertPluginOutputs (void) { insertPluginBus(qtractorBus::Output); } void qtractorPluginListView::insertPluginInputs (void) { insertPluginBus(qtractorBus::Input); } // Show insert pseudo-plugin audio bus connections. void qtractorPluginListView::insertPluginBus ( int iBusMode ) { qtractorPluginListItem *pItem = static_cast (QListWidget::currentItem()); if (pItem == NULL) return; insertPluginBus(pItem->plugin(), iBusMode); } // Show insert pseudo-plugin audio bus connections (static) void qtractorPluginListView::insertPluginBus ( qtractorPlugin *pPlugin, int iBusMode ) { if (pPlugin == NULL) return; if ((pPlugin->type())->typeHint() == qtractorPluginType::Insert) { qtractorInsertPlugin *pInsertPlugin = static_cast (pPlugin); if (pInsertPlugin) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm && pMainForm->connections()) { (pMainForm->connections())->showBus( pInsertPlugin->audioBus(), qtractorBus::BusMode(iBusMode)); } } } } // Audio specific slots. void qtractorPluginListView::audioOutputs (void) { qtractorMidiManager *pMidiManager = m_pPluginList->midiManager(); if (pMidiManager && pMidiManager->audioOutputBus()) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm && pMainForm->connections()) { (pMainForm->connections())->showBus( pMidiManager->audioOutputBus(), qtractorBus::Output); } } } void qtractorPluginListView::audioOutputBus (void) { qtractorMidiManager *pMidiManager = m_pPluginList->midiManager(); if (pMidiManager == NULL) return; // Make it an undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; pSession->execute( new qtractorAudioOutputBusCommand(pMidiManager, !pMidiManager->isAudioOutputBus(), // Toggle! pMidiManager->isAudioOutputAutoConnect())); emit contentsChanged(); } void qtractorPluginListView::audioOutputAutoConnect (void) { qtractorMidiManager *pMidiManager = m_pPluginList->midiManager(); if (pMidiManager == NULL) return; // Make it an undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; pSession->execute( new qtractorAudioOutputBusCommand(pMidiManager, pMidiManager->isAudioOutputBus(), !pMidiManager->isAudioOutputAutoConnect())); // Toggle! emit contentsChanged(); } // Show an existing plugin form slot. void qtractorPluginListView::itemDoubleClickedSlot ( QListWidgetItem *item ) { itemActivatedSlot(item); } void qtractorPluginListView::itemActivatedSlot ( QListWidgetItem *item ) { if (m_pPluginList == NULL) return; qtractorPluginListItem *pItem = static_cast (item); if (pItem == NULL) return; qtractorPlugin *pPlugin = pItem->plugin(); if (pPlugin == NULL) return; bool bOpenEditor = false; qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) bOpenEditor = pOptions->bOpenEditor; if (bOpenEditor && (pPlugin->type())->isEditor()) pPlugin->openEditor(this); else (pPlugin->form())->activateForm(); } // Trap for help/tool-tip events. bool qtractorPluginListView::eventFilter ( QObject *pObject, QEvent *pEvent ) { QWidget *pViewport = QListWidget::viewport(); if (static_cast (pObject) == pViewport) { if (pEvent->type() == QEvent::ToolTip) { QHelpEvent *pHelpEvent = static_cast (pEvent); if (pHelpEvent) { qtractorPluginListItem *pItem = static_cast ( QListWidget::itemAt(pHelpEvent->pos())); qtractorPlugin *pPlugin = NULL; if (pItem) pPlugin = pItem->plugin(); if (pPlugin) { QString sToolTip = pItem->text(); // (pPlugin->type())->name(); if (pPlugin->isDirectAccessParam()) { qtractorPluginParam *pDirectAccessParam = pPlugin->directAccessParam(); if (pDirectAccessParam) { sToolTip.append(QString("\n(%1: %2)") .arg(pDirectAccessParam->name()) .arg(pDirectAccessParam->display())); } } QToolTip::showText(pHelpEvent->globalPos(), sToolTip, pViewport); return true; } } } else if (pEvent->type() == QEvent::Leave) { m_dragCursor = DragNone; QListWidget::unsetCursor(); return true; } } // Not handled here. return QListWidget::eventFilter(pObject, pEvent); } // trap the wheel event to change the value of the direcgAccessParameter void qtractorPluginListView::wheelEvent ( QWheelEvent *pWheelEvent ) { const QPoint& pos = pWheelEvent->pos(); qtractorPluginListItem *pItem = static_cast (QListWidget::itemAt(pos)); if (pItem) { qtractorPlugin *pPlugin = pItem->plugin(); qtractorPluginParam *pDirectAccessParam = NULL; qtractorMidiControlObserver *pDirectAccessObserver = NULL; if (pPlugin) pDirectAccessParam = pPlugin->directAccessParam(); if (pDirectAccessParam) pDirectAccessObserver = pDirectAccessParam->observer(); if (pDirectAccessObserver) { const bool bLogarithmic = pDirectAccessParam->isLogarithmic(); float fValue = pDirectAccessObserver->value(); float fScale = pDirectAccessObserver->scaleFromValue( fValue, bLogarithmic); float fDelta = (pWheelEvent->delta() < 0 ? -0.1f : +0.1f); if (!pDirectAccessParam->isInteger()) fDelta *= 0.5f; fValue = pDirectAccessObserver->valueFromScale( fScale + fDelta, bLogarithmic); pDirectAccessParam->updateValue(fValue, true); } } } // To get precize clicking for in-place (de)activation; // handle mouse events for drag-and-drop stuff. void qtractorPluginListView::mousePressEvent ( QMouseEvent *pMouseEvent ) { dragLeaveEvent(NULL); const QPoint& pos = pMouseEvent->pos(); qtractorPluginListItem *pItem = static_cast (QListWidget::itemAt(pos)); if (pItem && pos.x() > 0 && pos.x() < QListWidget::iconSize().width()) m_pClickedItem = pItem; if (pMouseEvent->button() == Qt::LeftButton) { m_posDrag = pos; m_pDragItem = pItem; dragDirectAccess(pos); } QListWidget::mousePressEvent(pMouseEvent); } void qtractorPluginListView::mouseMoveEvent ( QMouseEvent *pMouseEvent ) { QListWidget::mouseMoveEvent(pMouseEvent); const QPoint& pos = pMouseEvent->pos(); if ((pMouseEvent->buttons() & Qt::LeftButton) && m_pDragItem) { if (m_dragCursor != DragNone) m_dragState = m_dragCursor; if (m_dragState != DragNone) { dragDirectAccess(pos); return; } if ((pos - m_posDrag).manhattanLength() >= QApplication::startDragDistance()) { // We'll start dragging something alright... QMimeData *pMimeData = new QMimeData(); encodeItem(pMimeData, m_pDragItem); QDrag *pDrag = new QDrag(this); pDrag->setMimeData(pMimeData); pDrag->setPixmap(m_pDragItem->icon().pixmap(16)); pDrag->setHotSpot(QPoint(-4, -12)); pDrag->start(Qt::MoveAction); // We've dragged and maybe dropped it by now... m_pDragItem = NULL; } } else if (m_dragState == DragNone) dragDirectAccess(pos); } void qtractorPluginListView::mouseReleaseEvent ( QMouseEvent *pMouseEvent ) { QListWidget::mouseReleaseEvent(pMouseEvent); const QPoint& pos = pMouseEvent->pos(); qtractorPluginListItem *pItem = static_cast (QListWidget::itemAt(pos)); if (pItem && pos.x() > 0 && pos.x() < QListWidget::iconSize().width() && m_pClickedItem == pItem) { qtractorPlugin *pPlugin = pItem->plugin(); if (pPlugin) { // Make it a undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { pSession->execute( new qtractorActivatePluginCommand(pPlugin, !pPlugin->isActivated())); emit contentsChanged(); } } } dragLeaveEvent(NULL); } // Drag-n-drop stuff; // track on the current drop item position. bool qtractorPluginListView::canDropEvent ( QDropEvent *pDropEvent ) { if (m_pPluginList == NULL) return false; if (!canDecodeItem(pDropEvent->mimeData())) return false; if (m_pDragItem == NULL) m_pDragItem = decodeItem(pDropEvent->mimeData()); if (m_pDragItem == NULL) return false; qtractorPluginListItem *pDropItem = static_cast ( QListWidget::itemAt(pDropEvent->pos())); if (pDropItem && pDropItem != m_pDropItem) ensureVisibleItem(pDropItem); // Cannot drop onto itself or over the one below... qtractorPlugin *pPlugin = m_pDragItem->plugin(); if (pPlugin == NULL) return false; if (pDropItem) { if (pDropItem->plugin() == pPlugin || (pDropItem->plugin())->prev() == pPlugin) return false; } else if (m_pPluginList->last() == pPlugin) return false; // All that to check whether it will get properly instantiated. if ((pPlugin->type())->instances( m_pPluginList->channels(), m_pPluginList->isMidi()) < 1) return false; // This is the place we'll drop something // (append if null) m_pDropItem = pDropItem; return true; } bool qtractorPluginListView::canDropItem ( QDropEvent *pDropEvent ) { bool bCanDropItem = canDropEvent(pDropEvent); if (bCanDropItem) moveRubberBand(m_pDropItem); else if (m_pRubberBand && m_pRubberBand->isVisible()) m_pRubberBand->hide(); return bCanDropItem; } // Ensure given item is brought to viewport visibility... void qtractorPluginListView::ensureVisibleItem ( qtractorPluginListItem *pItem ) { int iItem = QListWidget::row(pItem); if (iItem > 0) { qtractorPluginListItem *pItemAbove = static_cast ( QListWidget::item(iItem - 1)); if (pItemAbove) QListWidget::scrollToItem(pItemAbove); } QListWidget::scrollToItem(pItem); } void qtractorPluginListView::dragEnterEvent ( QDragEnterEvent *pDragEnterEvent ) { #if 0 if (canDropItem(pDragEnterEvent)) { if (!pDragEnterEvent->isAccepted()) { pDragEnterEvent->setDropAction(Qt::MoveAction); pDragEnterEvent->accept(); } } else { pDragEnterEvent->ignore(); } #else // Always accept the drag-enter event, // so let we deal with it during move later... pDragEnterEvent->accept(); #endif } void qtractorPluginListView::dragMoveEvent ( QDragMoveEvent *pDragMoveEvent ) { if (canDropItem(pDragMoveEvent)) { if (!pDragMoveEvent->isAccepted()) { pDragMoveEvent->setDropAction(Qt::MoveAction); pDragMoveEvent->accept(); } } else { pDragMoveEvent->ignore(); } } void qtractorPluginListView::dragLeaveEvent ( QDragLeaveEvent * ) { if (m_pRubberBand) { delete m_pRubberBand; m_pRubberBand = NULL; } // Should fallback mouse cursor... if (m_dragCursor != DragNone) QListWidget::unsetCursor(); m_dragCursor = DragNone; m_dragState = DragNone; m_pClickedItem = NULL; m_pDragItem = NULL; m_pDropItem = NULL; } void qtractorPluginListView::dropEvent ( QDropEvent *pDropEvent ) { if (!canDropItem(pDropEvent)) { dragLeaveEvent(NULL); return; } // If we aren't in the same list, // or care for keyboard modifiers... if (((m_pDragItem->plugin())->list() == m_pPluginList) || (pDropEvent->keyboardModifiers() & Qt::ShiftModifier)) { dropMove(); } else if (pDropEvent->keyboardModifiers() & Qt::ControlModifier) { dropCopy(); } else { // We'll better have a drop menu... QMenu menu(this); menu.addAction(tr("&Move Here"), this, SLOT(dropMove())); menu.addAction(tr("&Copy Here"), this, SLOT(dropCopy())); menu.addSeparator(); menu.addAction(QIcon(":/images/formReject.png"), tr("C&ancel"), this, SLOT(dropCancel())); menu.exec(QListWidget::mapToGlobal(pDropEvent->pos())); } dragLeaveEvent(NULL); } // Drop item slots. void qtractorPluginListView::dropMove (void) { moveItem(m_pDragItem, m_pDropItem); QListWidget::setFocus(); } void qtractorPluginListView::dropCopy (void) { copyItem(m_pDragItem, m_pDropItem); QListWidget::setFocus(); } void qtractorPluginListView::dropCancel (void) { // Do nothing... } // Draw a dragging separator line. void qtractorPluginListView::moveRubberBand ( qtractorPluginListItem *pDropItem ) { // Create the rubber-band if there's none... if (m_pRubberBand == NULL) { m_pRubberBand = new qtractorRubberBand( QRubberBand::Line, QListWidget::viewport()); // QPalette pal(m_pRubberBand->palette()); // pal.setColor(m_pRubberBand->foregroundRole(), Qt::blue); // m_pRubberBand->setPalette(pal); // m_pRubberBand->setBackgroundRole(QPalette::NoRole); } // Just move it... QRect rect; if (pDropItem) { rect = QListWidget::visualItemRect(pDropItem); rect.setTop(rect.top() - 1); } else { pDropItem = static_cast ( QListWidget::item(QListWidget::count() - 1)); if (pDropItem) { rect = QListWidget::visualItemRect(pDropItem); rect.setTop(rect.bottom() - 1); } else { rect = QListWidget::viewport()->rect(); } } // Set always this height: rect.setHeight(2); m_pRubberBand->setGeometry(rect); // Ah, and make it visible, of course... if (!m_pRubberBand->isVisible()) m_pRubberBand->show(); } // Context menu event handler. void qtractorPluginListView::contextMenuEvent ( QContextMenuEvent *pContextMenuEvent ) { if (m_pPluginList == NULL) return; QMenu menu(this); QAction *pAction; int iItem = -1; int iItemCount = QListWidget::count(); bool bEnabled = (iItemCount > 0); qtractorPlugin *pPlugin = NULL; qtractorPluginListItem *pItem = static_cast (QListWidget::currentItem()); if (pItem) { iItem = QListWidget::row(pItem); pPlugin = pItem->plugin(); } pAction = menu.addAction( QIcon(":/images/formCreate.png"), tr("&Add Plugin..."), this, SLOT(addPlugin())); // pAction->setEnabled(true); QMenu *pInsertMenu = menu.addMenu("&Inserts"); pAction = pInsertMenu->addAction( QIcon(":/images/formAdd.png"), tr("Add &Insert"), this, SLOT(addInsertPlugin())); pAction->setEnabled(m_pPluginList->channels() > 0); pAction = pInsertMenu->addAction( QIcon(":/images/formAdd.png"), tr("Add &Aux Send"), this, SLOT(addAuxSendPlugin())); pAction->setEnabled(m_pPluginList->channels() > 0); pInsertMenu->addSeparator(); bool bInsertEnabled = (pPlugin && (pPlugin->type())->typeHint() == qtractorPluginType::Insert); pAction = pInsertMenu->addAction( QIcon(":/images/itemAudioPortOut.png"), tr("&Sends"), this, SLOT(insertPluginOutputs())); pAction->setEnabled(bInsertEnabled); pAction = pInsertMenu->addAction( QIcon(":/images/itemAudioPortIn.png"), tr("&Returns"), this, SLOT(insertPluginInputs())); pAction->setEnabled(bInsertEnabled); menu.addSeparator(); pAction = menu.addAction( tr("Ac&tivate"), this, SLOT(activatePlugin())); pAction->setCheckable(true); pAction->setChecked(pPlugin && pPlugin->isActivated()); pAction->setEnabled(pPlugin != NULL); bool bActivatedAll = m_pPluginList->isActivatedAll(); pAction = menu.addAction( tr("Acti&vate All"), this, SLOT(activateAllPlugins())); pAction->setCheckable(true); pAction->setChecked(bActivatedAll); pAction->setEnabled(bEnabled && !bActivatedAll); bool bDeactivatedAll = (m_pPluginList->activated() < 1); pAction = menu.addAction( tr("Deactivate Al&l"), this, SLOT(deactivateAllPlugins())); pAction->setCheckable(true); pAction->setChecked(bDeactivatedAll); pAction->setEnabled(bEnabled && !bDeactivatedAll); menu.addSeparator(); pAction = menu.addAction( QIcon(":/images/formRemove.png"), tr("&Remove"), this, SLOT(removePlugin())); pAction->setEnabled(pPlugin != NULL); pAction = menu.addAction( tr("Re&move All"), this, SLOT(removeAllPlugins())); pAction->setEnabled(bEnabled); menu.addSeparator(); pAction = menu.addAction( QIcon(":/images/formMoveUp.png"), tr("Move &Up"), this, SLOT(moveUpPlugin())); pAction->setEnabled(pItem && iItem > 0); pAction = menu.addAction( QIcon(":/images/formMoveDown.png"), tr("Move &Down"), this, SLOT(moveDownPlugin())); pAction->setEnabled(pItem && iItem < iItemCount - 1); menu.addSeparator(); QMenu *pDirectAccessParamMenu = menu.addMenu("Dire&ct Access"); if (pPlugin) { int iDirectAccessParamIndex = pPlugin->directAccessParamIndex(); const qtractorPlugin::Params& params = pPlugin->params(); qtractorPlugin::Params::ConstIterator param = params.constBegin(); const qtractorPlugin::Params::ConstIterator& param_end = params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); int iParamIndex = int(param.key()); pAction = pDirectAccessParamMenu->addAction( pParam->name(), this, SLOT(directAccessPlugin())); pAction->setCheckable(true); pAction->setChecked(iDirectAccessParamIndex == iParamIndex); pAction->setData(iParamIndex); } bool bParams = (params.count() > 0); if (bParams) { pDirectAccessParamMenu->addSeparator(); pAction = pDirectAccessParamMenu->addAction( tr("&None"), this, SLOT(directAccessPlugin())); pAction->setCheckable(true); pAction->setChecked(iDirectAccessParamIndex < 0); pAction->setData(int(-1)); } pDirectAccessParamMenu->setEnabled(bParams); } else pDirectAccessParamMenu->setEnabled(false); menu.addSeparator(); pAction = menu.addAction( QIcon(":/images/trackProperties.png"), tr("&Properties..."), this, SLOT(propertiesPlugin())); pAction->setCheckable(true); pAction->setChecked(pPlugin && pPlugin->isFormVisible()); pAction->setEnabled(pItem != NULL); pAction = menu.addAction( QIcon(":/images/formEdit.png"), tr("&Edit"), this, SLOT(editPlugin())); pAction->setCheckable(true); pAction->setChecked(pPlugin && pPlugin->isEditorVisible()); pAction->setEnabled(pPlugin && pPlugin->type()->isEditor()); qtractorMidiManager *pMidiManager = m_pPluginList->midiManager(); if (pMidiManager) { menu.addSeparator(); QMenu *pAudioMenu = menu.addMenu( QIcon(":/images/trackAudio.png"), "Audi&o"); pAction = pAudioMenu->addAction( tr("&Outputs"), this, SLOT(audioOutputs())); pAction->setEnabled(pMidiManager->audioOutputBus() != NULL); pAction = pAudioMenu->addAction( tr("&Dedicated"), this, SLOT(audioOutputBus())); pAction->setCheckable(true); pAction->setChecked(pMidiManager->isAudioOutputBus()); pAction = pAudioMenu->addAction( tr("&Auto-connect"), this, SLOT(audioOutputAutoConnect())); pAction->setCheckable(true); pAction->setChecked(pMidiManager->isAudioOutputAutoConnect()); pAction->setEnabled(pMidiManager->isAudioOutputBus()); } menu.exec(pContextMenuEvent->globalPos()); } // Common pixmap accessors. QIcon *qtractorPluginListView::itemIcon ( int iIndex ) { return g_pItemIcons[iIndex]; } static const char *c_pszPluginListItemMimeType = "qtractor/plugin-item"; // Encoder method (static). void qtractorPluginListView::encodeItem ( QMimeData *pMimeData, qtractorPluginListItem *pItem ) { // Allocate the data array... pMimeData->setData(c_pszPluginListItemMimeType, QByteArray((const char *) &pItem, sizeof(qtractorPluginListItem *))); } // Decode trial method (static). bool qtractorPluginListView::canDecodeItem ( const QMimeData *pMimeData ) { return pMimeData->hasFormat(c_pszPluginListItemMimeType); } // Decode method (static). qtractorPluginListItem *qtractorPluginListView::decodeItem ( const QMimeData *pMimeData ) { qtractorPluginListItem *pItem = NULL; QByteArray data = pMimeData->data(c_pszPluginListItemMimeType); if (data.size() == sizeof(qtractorPluginListItem *)) ::memcpy(&pItem, data.constData(), sizeof(qtractorPluginListItem *)); return pItem; } // Direct access parameter handle. void qtractorPluginListView::dragDirectAccess ( const QPoint& pos ) { qtractorPluginListItem *pItem = m_pDragItem; if (pItem == NULL) pItem = static_cast (QListWidget::itemAt(pos)); if (pItem == NULL) return; qtractorPlugin *pPlugin = pItem->plugin(); if (pPlugin == NULL) return; qtractorPluginParam *pDirectAccessParam = pPlugin->directAccessParam(); if (pDirectAccessParam == NULL) return; qtractorMidiControlObserver *pDirectAccessObserver = pDirectAccessParam->observer(); if (pDirectAccessObserver == NULL) return; const bool bLogarithmic = pDirectAccessParam->isLogarithmic(); const int iDirectAccessWidth = pItem->directAccessWidth(); const QRect& rectItem = QListWidget::visualItemRect(pItem) .adjusted(QListWidget::iconSize().width(), 1, -2, -2); if (m_dragState == DragNone) { float fValue = pDirectAccessParam->value(); float fScale = pDirectAccessObserver->scaleFromValue(fValue, bLogarithmic); int x = rectItem.x() + int(fScale * float(iDirectAccessWidth)); if (pos.x() > x - 5 && pos.x() < x + 5) { m_dragCursor = DragDirectAccess; QListWidget::setCursor(QCursor(Qt::PointingHandCursor)); } else { QListWidget::unsetCursor(); m_dragCursor = DragNone; } } else if (m_dragState == DragDirectAccess) { float fScale = float(pos.x() - rectItem.x()) / float(iDirectAccessWidth); float fValue = pDirectAccessObserver->valueFromScale(fScale, bLogarithmic); pDirectAccessParam->updateValue(fValue, true); QWidget *pViewport = QListWidget::viewport(); QToolTip::showText(pViewport->mapToGlobal(pos), QString("%1\n(%2: %3)") .arg(pItem->text()) // (pPlugin->type())->name(); .arg(pDirectAccessParam->name()) .arg(pDirectAccessParam->display()), pViewport); } } // end of qtractorPluginListView.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorSessionForm.cpp0000644000175000001440000000012212166526620022003 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134668.98708 29 ctime=1381134668.98808008 qtractor-0.5.11/src/qtractorSessionForm.cpp0000644000175000001440000002252612166526620021302 0ustar00rncbcusers00000000000000// qtractorSessionForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorSessionForm.h" #include "qtractorAbout.h" #include "qtractorSession.h" #include "qtractorOptions.h" #include #include #include #include #include #include #include //---------------------------------------------------------------------------- // qtractorSessionForm -- UI wrapper form. // Constructor. qtractorSessionForm::qtractorSessionForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::WindowModal); // Initialize conveniency options... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) pOptions->loadComboBoxHistory(m_ui.SessionDirComboBox); // Setup some specific validators. m_ui.SampleRateComboBox->setValidator( new QIntValidator(m_ui.SampleRateComboBox)); // Fill-up snap-per-beat items... m_ui.SnapPerBeatComboBox->clear(); m_ui.SnapPerBeatComboBox->insertItems(0, qtractorTimeScale::snapItems()); // Initialize dirty control state. m_iDirtyCount = 0; // Try to restore old window positioning. adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.SessionNameLineEdit, SIGNAL(textChanged(const QString&)), SLOT(changed())); QObject::connect(m_ui.SessionDirComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(changed())); QObject::connect(m_ui.SessionDirToolButton, SIGNAL(clicked()), SLOT(browseSessionDir())); QObject::connect(m_ui.DescriptionTextEdit, SIGNAL(textChanged()), SLOT(changed())); QObject::connect(m_ui.SampleRateComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(changed())); QObject::connect(m_ui.TempoSpinBox, SIGNAL(valueChanged(float, unsigned short, unsigned short)), SLOT(changed())); QObject::connect(m_ui.TicksPerBeatSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.SnapPerBeatComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.PixelsPerBeatSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.HorizontalZoomSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.VerticalZoomSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); } // Destructor. qtractorSessionForm::~qtractorSessionForm (void) { } // Populate (setup) dialog controls from settings descriptors. void qtractorSessionForm::setSession ( qtractorSession *pSession ) { // Session properties cloning... m_props = pSession->properties(); // Initialize dialog widgets... m_ui.SessionNameLineEdit->setText(m_props.sessionName); m_ui.SessionDirComboBox->setEditText(m_props.sessionDir); m_ui.DescriptionTextEdit->setPlainText(m_props.description); // Time properties... m_ui.SampleRateComboBox->setEditText( QString::number(m_props.timeScale.sampleRate())); m_ui.SampleRateTextLabel->setEnabled(!pSession->isActivated()); m_ui.SampleRateComboBox->setEnabled(!pSession->isActivated()); m_ui.TempoSpinBox->setTempo(m_props.timeScale.tempo(), false); m_ui.TempoSpinBox->setBeatsPerBar(m_props.timeScale.beatsPerBar(), false); m_ui.TempoSpinBox->setBeatDivisor(m_props.timeScale.beatDivisor(), false); m_ui.TicksPerBeatSpinBox->setValue(int(m_props.timeScale.ticksPerBeat())); // View properties... m_ui.SnapPerBeatComboBox->setCurrentIndex( qtractorTimeScale::indexFromSnap(m_props.timeScale.snapPerBeat())); m_ui.PixelsPerBeatSpinBox->setValue(int(m_props.timeScale.pixelsPerBeat())); m_ui.HorizontalZoomSpinBox->setValue(int(m_props.timeScale.horizontalZoom())); m_ui.VerticalZoomSpinBox->setValue(int(m_props.timeScale.verticalZoom())); // Start editing session name, if empty... if (m_props.sessionName.isEmpty()) m_ui.SessionNameLineEdit->setFocus(); // Backup clean. m_iDirtyCount = 0; // Done. stabilizeForm(); } // Retrieve the accepted session properties, if the case arises. const qtractorSession::Properties& qtractorSessionForm::properties (void) { return m_props; } // Accept settings (OK button slot). void qtractorSessionForm::accept (void) { // Check if session directory is new... QDir dir; const QString& sSessionDir = m_ui.SessionDirComboBox->currentText(); while (!dir.exists(sSessionDir)) { // Ask user... if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Session directory does not exist:\n\n" "\"%1\"\n\n" "Do you want to create it?").arg(sSessionDir), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; // Proceed... dir.mkdir(sSessionDir); } // Save options... if (m_iDirtyCount > 0) { // Make changes permanent... m_props.sessionName = m_ui.SessionNameLineEdit->text(); m_props.sessionDir = m_ui.SessionDirComboBox->currentText(); m_props.description = m_ui.DescriptionTextEdit->toPlainText(); // Time properties... m_props.timeScale.setSampleRate( m_ui.SampleRateComboBox->currentText().toUInt()); m_props.timeScale.setTempo(m_ui.TempoSpinBox->tempo()); m_props.timeScale.setBeatType(2); m_props.timeScale.setBeatsPerBar(m_ui.TempoSpinBox->beatsPerBar()); m_props.timeScale.setBeatDivisor(m_ui.TempoSpinBox->beatDivisor()); m_props.timeScale.setTicksPerBeat(m_ui.TicksPerBeatSpinBox->value()); // View properties... m_props.timeScale.setSnapPerBeat(qtractorTimeScale::snapFromIndex( m_ui.SnapPerBeatComboBox->currentIndex())); m_props.timeScale.setPixelsPerBeat(m_ui.PixelsPerBeatSpinBox->value()); m_props.timeScale.setHorizontalZoom(m_ui.HorizontalZoomSpinBox->value()); m_props.timeScale.setVerticalZoom(m_ui.VerticalZoomSpinBox->value()); // Reset dirty flag. m_iDirtyCount = 0; } // Save other conveniency options... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) pOptions->saveComboBoxHistory(m_ui.SessionDirComboBox); // Just go with dialog acceptance. QDialog::accept(); } // Reject settings (Cancel button slot). void qtractorSessionForm::reject (void) { bool bReject = true; // Check if there's any pending changes... if (m_iDirtyCount > 0) { QMessageBox::StandardButtons buttons = QMessageBox::Discard | QMessageBox::Cancel; if (m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->isEnabled()) buttons |= QMessageBox::Apply; switch (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Some settings have been changed.\n\n" "Do you want to apply the changes?"), buttons)) { case QMessageBox::Apply: accept(); return; case QMessageBox::Discard: break; default: // Cancel. bReject = false; } } if (bReject) QDialog::reject(); } // Dirty up settings. void qtractorSessionForm::changed (void) { ++m_iDirtyCount; stabilizeForm(); } // Stabilize current form state. void qtractorSessionForm::stabilizeForm (void) { QFileInfo fi(QFileInfo(m_ui.SessionDirComboBox->currentText()).path()); bool bValid = !m_ui.SessionNameLineEdit->text().isEmpty(); bValid = bValid && fi.isDir() && fi.isReadable() && fi.isWritable(); // bValid = bValid && !m_ui.DescriptionTextEdit->text().isEmpty(); m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(bValid); } // Browse for session directory. void qtractorSessionForm::browseSessionDir (void) { const QString& sTitle = tr("Session Directory") + " - " QTRACTOR_TITLE; #if 1// QT_VERSION < 0x040400 QString sSessionDir = QFileDialog::getExistingDirectory(this, // Parent. sTitle, m_ui.SessionDirComboBox->currentText()); #else // Construct open-directory dialog... QFileDialog fileDialog(this, sTitle, m_ui.SessionDirComboBox->currentText()); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::DirectoryOnly); // Stuff sidebar... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); fileDialog.setSidebarUrls(urls); } // Show dialog... if (!fileDialog.exec()) return; QString sSessionDir = fileDialog.selectedFiles().first(); #endif if (sSessionDir.isEmpty()) return; m_ui.SessionDirComboBox->setEditText(sSessionDir); m_ui.SessionDirComboBox->setFocus(); changed(); } // end of qtractorSessionForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorInstrumentForm.cpp0000644000175000001440000000012312166526620022531 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134667.59108 30 ctime=1381134667.591080058 qtractor-0.5.11/src/qtractorInstrumentForm.cpp0000644000175000001440000005212612166526620022026 0ustar00rncbcusers00000000000000// qtractorInstrumentForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorInstrumentForm.h" #include "qtractorInstrument.h" #include "qtractorSession.h" #include "qtractorOptions.h" #include #include #include #include #include //---------------------------------------------------------------------- // class qtractorInstrumentGroupItem -- custom group list view item. // class qtractorInstrumentGroupItem : public QTreeWidgetItem { public: // Constructors. qtractorInstrumentGroupItem() : QTreeWidgetItem(qtractorInstrumentForm::GroupItem) { initGroupItem(); } qtractorInstrumentGroupItem(QTreeWidgetItem *pParent, QTreeWidgetItem *pAfter) : QTreeWidgetItem(pParent, pAfter, qtractorInstrumentForm::GroupItem) { initGroupItem(); } protected: // Initializer. void initGroupItem() { setIcon(0, QIcon(":/images/itemGroup.png")); } }; //---------------------------------------------------------------------- // class qtractorInstrumentForm -- instrument file manager form. // // Constructor. qtractorInstrumentForm::qtractorInstrumentForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::WindowModal); m_pInstruments = NULL; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) m_pInstruments = pSession->instruments(); m_iDirtyCount = 0; QHeaderView *pHeader = m_ui.InstrumentsListView->header(); pHeader->setDefaultAlignment(Qt::AlignLeft); #if QT_VERSION >= 0x050000 // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionResizeMode(QHeaderView::ResizeToContents); pHeader->setSectionsMovable(false); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setResizeMode(QHeaderView::ResizeToContents); pHeader->setMovable(false); #endif pHeader = m_ui.FilesListView->header(); pHeader->setDefaultAlignment(Qt::AlignLeft); #if QT_VERSION >= 0x050000 // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionResizeMode(QHeaderView::ResizeToContents); pHeader->setSectionsMovable(false); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setResizeMode(QHeaderView::ResizeToContents); pHeader->setMovable(false); #endif pHeader = m_ui.NamesListView->header(); pHeader->setDefaultAlignment(Qt::AlignLeft); #if QT_VERSION >= 0x050000 // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionResizeMode(QHeaderView::ResizeToContents); pHeader->setSectionsMovable(false); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setResizeMode(QHeaderView::ResizeToContents); pHeader->setMovable(false); #endif refreshForm(); stabilizeForm(); adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.FilesListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(stabilizeForm())); QObject::connect(m_ui.NamesListView, SIGNAL(itemCollapsed(QTreeWidgetItem*)), SLOT(itemCollapsed(QTreeWidgetItem*))); QObject::connect(m_ui.NamesListView, SIGNAL(itemExpanded(QTreeWidgetItem*)), SLOT(itemExpanded(QTreeWidgetItem*))); QObject::connect(m_ui.InstrumentsListView, SIGNAL(itemCollapsed(QTreeWidgetItem*)), SLOT(itemCollapsed(QTreeWidgetItem*))); QObject::connect(m_ui.InstrumentsListView, SIGNAL(itemExpanded(QTreeWidgetItem*)), SLOT(itemExpanded(QTreeWidgetItem*))); QObject::connect(m_ui.ImportPushButton, SIGNAL(clicked()), SLOT(importSlot())); QObject::connect(m_ui.RemovePushButton, SIGNAL(clicked()), SLOT(removeSlot())); QObject::connect(m_ui.MoveUpPushButton, SIGNAL(clicked()), SLOT(moveUpSlot())); QObject::connect(m_ui.MoveDownPushButton, SIGNAL(clicked()), SLOT(moveDownSlot())); QObject::connect(m_ui.ReloadPushButton, SIGNAL(clicked()), SLOT(reloadSlot())); QObject::connect(m_ui.ExportPushButton, SIGNAL(clicked()), SLOT(exportSlot())); QObject::connect(m_ui.ClosePushButton, SIGNAL(clicked()), SLOT(reject())); } // Destructor. qtractorInstrumentForm::~qtractorInstrumentForm (void) { } // Instrument list accessors. void qtractorInstrumentForm::setInstruments ( qtractorInstrumentList *pInstruments ) { m_pInstruments = pInstruments; refreshForm(); stabilizeForm(); } qtractorInstrumentList *qtractorInstrumentForm::instruments (void) const { return m_pInstruments; } // Import new intrument file(s) into listing. void qtractorInstrumentForm::importSlot (void) { if (m_pInstruments == NULL) return; qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; QStringList files; const QString sExt("ins"); const QString& sTitle = tr("Import Instrument Files") + " - " QTRACTOR_TITLE; const QString& sFilter = tr("Instrument files (*.%1 *.sf2 *.midnam)").arg(sExt); #if 0//QT_VERSION < 0x040400 // Ask for the filename to open... files = QFileDialog::getOpenFileNames(this, sTitle, pOptions->sInstrumentDir, sFilter); #else // Construct open-files dialog... QFileDialog fileDialog(this, sTitle, pOptions->sInstrumentDir, sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::ExistingFiles); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(pOptions->sInstrumentDir)); fileDialog.setSidebarUrls(urls); // Show dialog... if (fileDialog.exec()) files = fileDialog.selectedFiles(); #endif if (files.isEmpty()) return; // Tell that we may take some time... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // For avery selected instrument file to load... QTreeWidgetItem *pItem = NULL; QStringListIterator iter(files); while (iter.hasNext()) { // Merge the file contents into global container... const QString& sPath = iter.next(); if (m_pInstruments->load(sPath)) { // Start inserting in the current selected or last item... if (pItem == NULL) pItem = m_ui.FilesListView->currentItem(); if (pItem == NULL) { int iLastItem = m_ui.FilesListView->topLevelItemCount() - 1; if (iLastItem >= 0) pItem = m_ui.FilesListView->topLevelItem(iLastItem); } // New item on the block :-) pItem = new QTreeWidgetItem(m_ui.FilesListView, pItem); if (pItem) { QFileInfo info(sPath); pItem->setIcon(0, QIcon(":/images/itemFile.png")); pItem->setText(0, info.completeBaseName()); pItem->setText(1, sPath); m_ui.FilesListView->setCurrentItem(pItem); pOptions->sInstrumentDir = info.absolutePath(); // ++m_iDirtyCount; } } } // May refresh the whole form? refreshForm(); stabilizeForm(); // Done waiting. QApplication::restoreOverrideCursor(); } // Remove a file from instrument list. void qtractorInstrumentForm::removeSlot (void) { if (m_pInstruments == NULL) return; QTreeWidgetItem *pItem = m_ui.FilesListView->currentItem(); if (pItem) { delete pItem; ++m_iDirtyCount; } stabilizeForm(); } // Move a file up on the instrument list. void qtractorInstrumentForm::moveUpSlot (void) { QTreeWidgetItem *pItem = m_ui.FilesListView->currentItem(); if (pItem) { int iItem = m_ui.FilesListView->indexOfTopLevelItem(pItem); if (iItem > 0) { pItem = m_ui.FilesListView->takeTopLevelItem(iItem); m_ui.FilesListView->insertTopLevelItem(iItem - 1, pItem); m_ui.FilesListView->setCurrentItem(pItem); ++m_iDirtyCount; } } stabilizeForm(); } // Move a file down on the instrument list. void qtractorInstrumentForm::moveDownSlot (void) { QTreeWidgetItem *pItem = m_ui.FilesListView->currentItem(); if (pItem) { int iItem = m_ui.FilesListView->indexOfTopLevelItem(pItem); if (iItem < m_ui.FilesListView->topLevelItemCount() - 1) { pItem = m_ui.FilesListView->takeTopLevelItem(iItem); m_ui.FilesListView->insertTopLevelItem(iItem + 1, pItem); m_ui.FilesListView->setCurrentItem(pItem); ++m_iDirtyCount; } } stabilizeForm(); } // Reload the complete instrument definitions, from list. void qtractorInstrumentForm::reloadSlot (void) { if (m_pInstruments == NULL) return; // Tell that we may take some time... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // Ooops... m_pInstruments->clearAll(); // Load each file in order... int iItemCount = m_ui.FilesListView->topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = m_ui.FilesListView->topLevelItem(iItem); if (pItem) m_pInstruments->load(pItem->text(1)); } // We're clear. m_iDirtyCount = 0; refreshForm(); stabilizeForm(); // Done with reload. QApplication::restoreOverrideCursor(); } // Export the whole state into a single instrument file. void qtractorInstrumentForm::exportSlot (void) { if (m_pInstruments == NULL) return; qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; QString sPath; const QString sExt("ins"); const QString& sTitle = tr("Export Instrument File") + " - " QTRACTOR_TITLE; const QString& sFilter = tr("Instrument files (*.%1)").arg(sExt); #if 0//QT_VERSION < 0x040400 // Ask for the filename to open... sPath = QFileDialog::getSaveFileName(this, sTitle, pOptions->sInstrumentDir, sFilter); #else // Construct open-files dialog... QFileDialog fileDialog(this, sTitle, pOptions->sInstrumentDir, sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptSave); fileDialog.setFileMode(QFileDialog::AnyFile); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(pOptions->sInstrumentDir)); fileDialog.setSidebarUrls(urls); // Show dialog... if (fileDialog.exec()) sPath = fileDialog.selectedFiles().first(); #endif if (sPath.isEmpty()) return; // Enforce .ins extension... if (QFileInfo(sPath).suffix().isEmpty()) { sPath += '.' + sExt; // Check if already exists... if (QFileInfo(sPath).exists()) { if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("The instrument file already exists:\n\n" "\"%1\"\n\n" "Do you want to replace it?") .arg(sPath), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; } } // Tell that we may take some time... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // Just save the whole bunch... if (m_pInstruments->save(sPath)) pOptions->sInstrumentDir = QFileInfo(sPath).absolutePath(); // Done with export. QApplication::restoreOverrideCursor(); } // Accept settings (OK button slot). void qtractorInstrumentForm::accept (void) { // If we're dirty do a complete and final reload... if (m_iDirtyCount > 0) reloadSlot(); // Just go with dialog acceptance. QDialog::accept(); } // Reject settings (Cancel button slot). void qtractorInstrumentForm::reject (void) { bool bReject = true; // Check if there's any pending changes... if (m_iDirtyCount > 0) { switch (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Instrument settings have been changed.\n\n" "Do you want to apply the changes?"), QMessageBox::Apply | QMessageBox::Discard | QMessageBox::Cancel)) { case QMessageBox::Apply: accept(); return; case QMessageBox::Discard: break; default: // Cancel. bReject = false; } } if (bReject) QDialog::reject(); } // Stabilize form status. void qtractorInstrumentForm::stabilizeForm (void) { QTreeWidgetItem *pItem = m_ui.FilesListView->currentItem(); if (pItem) { int iItemCount = m_ui.FilesListView->topLevelItemCount(); int iItem = m_ui.FilesListView->indexOfTopLevelItem(pItem); m_ui.RemovePushButton->setEnabled(true); m_ui.MoveUpPushButton->setEnabled(iItem > 0); m_ui.MoveDownPushButton->setEnabled(iItem < iItemCount - 1); } else { m_ui.RemovePushButton->setEnabled(false); m_ui.MoveUpPushButton->setEnabled(false); m_ui.MoveDownPushButton->setEnabled(false); } m_ui.ReloadPushButton->setEnabled(m_iDirtyCount > 0); m_ui.ExportPushButton->setEnabled( m_pInstruments && m_pInstruments->count() > 0); } // Refresh all instrument definition views. void qtractorInstrumentForm::refreshForm (void) { if (m_pInstruments == NULL) return; // Freeze... m_ui.InstrumentsListView->setUpdatesEnabled(false); m_ui.FilesListView->setUpdatesEnabled(false); m_ui.NamesListView->setUpdatesEnabled(false); // Files list view... m_ui.FilesListView->clear(); QList files; QStringListIterator ifile(m_pInstruments->files()); while (ifile.hasNext()) { const QString& sPath = ifile.next(); QTreeWidgetItem *pFileItem = new QTreeWidgetItem(); pFileItem->setIcon(0, QIcon(":/images/itemFile.png")); pFileItem->setText(0, QFileInfo(sPath).completeBaseName()); pFileItem->setText(1, sPath); files.append(pFileItem); } m_ui.FilesListView->addTopLevelItems(files); // Instruments list view... m_ui.InstrumentsListView->clear(); QList instrs; qtractorInstrumentList::ConstIterator iter = m_pInstruments->constBegin(); const qtractorInstrumentList::ConstIterator& iter_end = m_pInstruments->constEnd(); for ( ; iter != iter_end; ++iter) { const qtractorInstrument& instr = iter.value(); // Instrument Name... QTreeWidgetItem *pChildItem = NULL; QTreeWidgetItem *pInstrItem = new QTreeWidgetItem(); pInstrItem->setIcon(0, QIcon(":/images/itemInstrument.png")); pInstrItem->setText(0, instr.instrumentName()); // - Patches Names for Banks... pChildItem = new qtractorInstrumentGroupItem(pInstrItem, pChildItem); pChildItem->setText(0, tr("Patch Names for Banks")); QTreeWidgetItem *pBankItem = NULL; const qtractorInstrumentPatches& patches = instr.patches(); qtractorInstrumentPatches::ConstIterator pat = patches.constBegin(); const qtractorInstrumentPatches::ConstIterator& pat_end = patches.constEnd(); for ( ; pat != pat_end; ++pat) { pBankItem = new QTreeWidgetItem(pChildItem, pBankItem); int iBank = pat.key(); const QString sBank = (iBank < 0 ? QString("*") : QString::number(iBank)); pBankItem->setIcon(0, QIcon(":/images/itemPatches.png")); pBankItem->setText(0, QString("%1 = %2").arg(sBank).arg(pat.value().name())); // Patches/Progs... const qtractorInstrumentData& patch = instr.patch(iBank); QTreeWidgetItem *pProgItem = NULL; if (!patch.basedOn().isEmpty()) { pProgItem = new QTreeWidgetItem(pBankItem, pProgItem); pProgItem->setIcon(0, QIcon(":/images/itemProperty.png")); pProgItem->setText(0, QString("Based On = %1").arg(patch.basedOn())); } qtractorInstrumentData::ConstIterator it = patch.constBegin(); const qtractorInstrumentData::ConstIterator& it_end = patch.constEnd(); for ( ; it != it_end; ++it) { int iProg = it.key(); pProgItem = new QTreeWidgetItem(pBankItem, pProgItem); pProgItem->setText(0, QString("%1 = %2").arg(iProg).arg(it.value())); if (instr.isDrum(iBank, iProg)) listInstrumentData(pProgItem, instr.notes(iBank, iProg)); } } // - Controller Names... if (instr.control().count() > 0) { pChildItem = new QTreeWidgetItem(pInstrItem, pChildItem); pChildItem->setIcon(0, QIcon(":/images/itemControllers.png")); pChildItem->setText(0, tr("Controller Names = %1").arg(instr.control().name())); listInstrumentData(pChildItem, instr.control()); } // - RPN Names... if (instr.rpn().count() > 0) { pChildItem = new QTreeWidgetItem(pInstrItem, pChildItem); pChildItem->setIcon(0, QIcon(":/images/itemRpns.png")); pChildItem->setText(0, tr("RPN Names = %1").arg(instr.rpn().name())); listInstrumentData(pChildItem, instr.rpn()); } // - NRPN Names... if (instr.nrpn().count() > 0) { pChildItem = new QTreeWidgetItem(pInstrItem, pChildItem); pChildItem->setIcon(0, QIcon(":/images/itemNrpns.png")); pChildItem->setText(0, tr("NRPN Names = %1").arg(instr.nrpn().name())); listInstrumentData(pChildItem, instr.nrpn()); } // - BankSelMethod... pChildItem = new QTreeWidgetItem(pInstrItem, pChildItem); pChildItem->setIcon(0, QIcon(":/images/itemProperty.png")); pChildItem->setText(0, tr("Bank Select Method = %1") .arg(bankSelMethod(instr.bankSelMethod()))); instrs.append(pInstrItem); } m_ui.InstrumentsListView->addTopLevelItems(instrs); // Names list view... m_ui.NamesListView->clear(); QList names; if (m_pInstruments->count() > 0) { QTreeWidgetItem *pListItem = NULL; // - Patch Names... pListItem = new qtractorInstrumentGroupItem(); pListItem->setText(0, tr("Patch Names")); listInstrumentDataList(pListItem, m_pInstruments->patches(), QIcon(":/images/itemPatches.png")); names.append(pListItem); // - Note Names... pListItem = new qtractorInstrumentGroupItem(); pListItem->setText(0, tr("Note Names")); listInstrumentDataList(pListItem, m_pInstruments->notes(), QIcon(":/images/itemNotes.png")); names.append(pListItem); // - Controller Names... pListItem = new qtractorInstrumentGroupItem(); pListItem->setText(0, tr("Controller Names")); listInstrumentDataList(pListItem, m_pInstruments->controls(), QIcon(":/images/itemControllers.png")); names.append(pListItem); // - RPN Names... pListItem = new qtractorInstrumentGroupItem(); pListItem->setText(0, tr("RPN Names")); listInstrumentDataList(pListItem, m_pInstruments->rpns(), QIcon(":/images/itemRpns.png")); names.append(pListItem); // - NRPN Names... pListItem = new qtractorInstrumentGroupItem(); pListItem->setText(0, tr("NRPN Names")); listInstrumentDataList(pListItem, m_pInstruments->nrpns(), QIcon(":/images/itemNrpns.png")); names.append(pListItem); // - Bank Select Methods... pListItem = new qtractorInstrumentGroupItem(); pListItem->setText(0, tr("Bank Select Methods")); if (m_pInstruments->count() > 0) { QTreeWidgetItem *pChildItem = NULL; for (int iBankSelMethod = 0; iBankSelMethod < 4; ++iBankSelMethod) { pChildItem = new qtractorInstrumentGroupItem(pListItem, pChildItem); pChildItem->setIcon(0, QIcon(":/images/itemProperty.png")); pChildItem->setText(0, tr("%1 = %2").arg(iBankSelMethod) .arg(bankSelMethod(iBankSelMethod))); } } names.append(pListItem); } m_ui.NamesListView->addTopLevelItems(names); // Bail out... m_ui.NamesListView->setUpdatesEnabled(true); m_ui.FilesListView->setUpdatesEnabled(true); m_ui.InstrumentsListView->setUpdatesEnabled(true); } void qtractorInstrumentForm::itemCollapsed ( QTreeWidgetItem *pItem ) { if (pItem->type() == GroupItem) pItem->setIcon(0, QIcon(":/images/itemGroup.png")); } void qtractorInstrumentForm::itemExpanded ( QTreeWidgetItem *pItem ) { if (pItem->type() == GroupItem) pItem->setIcon(0, QIcon(":/images/itemGroupOpen.png")); } void qtractorInstrumentForm::listInstrumentData ( QTreeWidgetItem *pParentItem, const qtractorInstrumentData& data ) { QTreeWidgetItem *pItem = NULL; if (!data.basedOn().isEmpty()) { pItem = new QTreeWidgetItem(pParentItem, pItem); pItem->setIcon(0, QIcon(":/images/itemProperty.png")); pItem->setText(0, tr("Based On = %1").arg(data.basedOn())); } qtractorInstrumentData::ConstIterator it = data.constBegin(); const qtractorInstrumentData::ConstIterator& it_end = data.constEnd(); for ( ; it != it_end; ++it) { pItem = new QTreeWidgetItem(pParentItem, pItem); pItem->setText(0, QString("%1 = %2").arg(it.key()).arg(it.value())); } } void qtractorInstrumentForm::listInstrumentDataList ( QTreeWidgetItem *pParentItem, const qtractorInstrumentDataList& list, const QIcon& icon ) { QTreeWidgetItem *pItem = NULL; qtractorInstrumentDataList::ConstIterator it = list.constBegin(); const qtractorInstrumentDataList::ConstIterator& it_end = list.constEnd(); for ( ; it != it_end; ++it) { pItem = new QTreeWidgetItem(pParentItem, pItem); pItem->setIcon(0, icon); pItem->setText(0, it.value().name()); listInstrumentData(pItem, it.value()); } } QString qtractorInstrumentForm::bankSelMethod ( int iBankSelMethod ) { QString sText; switch (iBankSelMethod) { case 0: sText = tr("Normal"); break; case 1: sText = tr("Bank MSB"); break; case 2: sText = tr("Bank LSB"); break; case 3: sText = tr("Patch"); break; default: sText = tr("Unknown"); break; } return sText; } // end of qtractorInstrumentForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorInstrumentForm.h0000644000175000001440000000012312073012112022155 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134666.95108 30 ctime=1381134666.951080048 qtractor-0.5.11/src/qtractorInstrumentForm.h0000644000175000001440000000514012073012112021444 0ustar00rncbcusers00000000000000// qtractorInstrumentForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorInstrumentForm_h #define __qtractorInstrumentForm_h #include "ui_qtractorInstrumentForm.h" // Forward declarations... class qtractorInstrumentData; class qtractorInstrumentDataList; class qtractorInstrumentList; //---------------------------------------------------------------------------- // qtractorInstrumentForm -- UI wrapper form. class qtractorInstrumentForm : public QDialog { Q_OBJECT public: // Constructor. qtractorInstrumentForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorInstrumentForm(); // Special group item types. enum { GroupItem = QTreeWidgetItem::UserType + 1 }; // Instrument list accessors. void setInstruments(qtractorInstrumentList *pInstruments); qtractorInstrumentList *instruments() const; protected slots: void accept(); void reject(); void importSlot(); void removeSlot(); void moveUpSlot(); void moveDownSlot(); void reloadSlot(); void exportSlot(); void stabilizeForm(); void refreshForm(); void itemCollapsed(QTreeWidgetItem*); void itemExpanded(QTreeWidgetItem*); protected: void listInstrumentData(QTreeWidgetItem *pParentItem, const qtractorInstrumentData& data); void listInstrumentDataList(QTreeWidgetItem *pParentItem, const qtractorInstrumentDataList& list, const QIcon& icon); QString bankSelMethod(int iBankSelMethod); private: // The Qt-designer UI struct... Ui::qtractorInstrumentForm m_ui; // Main editable data structure. qtractorInstrumentList *m_pInstruments; // Instance variables... int m_iDirtyCount; }; #endif // __qtractorInstrumentForm_h // end of qtractorInstrumentForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioClip.cpp0000644000175000001440000000012312166526620021406 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134670.93108 30 ctime=1381134670.931080111 qtractor-0.5.11/src/qtractorAudioClip.cpp0000644000175000001440000005214112166526620020700 0ustar00rncbcusers00000000000000// qtractorAudioClip.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorAudioClip.h" #include "qtractorAudioEngine.h" #include "qtractorAudioPeak.h" #include "qtractorDocument.h" #include "qtractorSession.h" #include "qtractorFileList.h" #include #include #include #include #include //---------------------------------------------------------------------- // class qtractorAudioClip::Key -- Audio buffered clip (hash key). // class qtractorAudioClip::Key { public: // Constructor. Key(qtractorAudioClip *pAudioClip) { update(pAudioClip); } // Key settler. void update(qtractorAudioClip *pAudioClip) { m_pTrack = pAudioClip->track(); m_sFilename = pAudioClip->filename();; m_iClipOffset = pAudioClip->clipOffset(); m_iClipLength = pAudioClip->clipLength(); m_fTimeStretch = pAudioClip->timeStretch(); m_fPitchShift = pAudioClip->pitchShift(); m_iOverlap = pAudioClip->overlap(); } // Key accessors. qtractorTrack *track() const { return m_pTrack; } const QString& filename() const { return m_sFilename; } unsigned long clipOffset() const { return m_iClipOffset; } unsigned long clipLength() const { return m_iClipLength; } float timeStretch() const { return m_fTimeStretch; } float pitchShift() const { return m_fPitchShift; } unsigned int overlap() const { return m_iOverlap; } // Match descriminator. bool operator== (const Key& other) const { return m_pTrack == other.track() && m_sFilename == other.filename() && m_iClipOffset == other.clipOffset() && m_iClipLength == other.clipLength() && m_fTimeStretch == other.timeStretch() && m_fPitchShift == other.pitchShift() && m_iOverlap == other.overlap(); } private: // Interesting variables. qtractorTrack *m_pTrack; QString m_sFilename; unsigned long m_iClipOffset; unsigned long m_iClipLength; float m_fTimeStretch; float m_fPitchShift; unsigned int m_iOverlap; }; uint qHash ( const qtractorAudioClip::Key& key ) { return qHash(key.track()) ^ qHash(key.filename()) ^ qHash(key.clipOffset()) ^ qHash(key.clipLength()) ^ qHash(long(100.0f * key.timeStretch())) ^ qHash(long(100.0f * key.pitchShift())) ^ qHash(key.overlap()); } qtractorAudioClip::Hash qtractorAudioClip::g_hashTable; //---------------------------------------------------------------------- // class qtractorAudioClip -- Audio file/buffer clip. // // Constructor. qtractorAudioClip::qtractorAudioClip ( qtractorTrack *pTrack ) : qtractorClip(pTrack) { m_pPeak = NULL; m_pKey = NULL; m_pData = NULL; m_fTimeStretch = 1.0f; m_fPitchShift = 1.0f; m_iOverlap = 0; } // Copy constructor. qtractorAudioClip::qtractorAudioClip ( const qtractorAudioClip& clip ) : qtractorClip(clip.track()) { m_pPeak = NULL; m_pKey = NULL; m_pData = NULL; m_fTimeStretch = clip.timeStretch(); m_fPitchShift = clip.pitchShift(); m_iOverlap = clip.overlap(); setFilename(clip.filename()); setClipGain(clip.clipGain()); // Clone the audio peak, if any... if (clip.m_pPeak) m_pPeak = new qtractorAudioPeak(*clip.m_pPeak); } // Destructor. qtractorAudioClip::~qtractorAudioClip (void) { close(); if (m_pPeak) delete m_pPeak; } // Time-stretch factor. void qtractorAudioClip::setTimeStretch ( float fTimeStretch ) { m_fTimeStretch = fTimeStretch; } float qtractorAudioClip::timeStretch (void) const { return m_fTimeStretch; } // Pitch-shift factor. void qtractorAudioClip::setPitchShift ( float fPitchShift ) { m_fPitchShift = fPitchShift; } float qtractorAudioClip::pitchShift (void) const { return m_fPitchShift; } // Alternate overlap tag. unsigned int qtractorAudioClip::overlap (void) const { return m_iOverlap; } // Alternating overlap test. bool qtractorAudioClip::isOverlap ( unsigned int iOverlapSize ) const { if (m_pData == NULL) return false; unsigned long iClipStart = clipStart(); unsigned long iClipEnd = iClipStart + clipLength() + iOverlapSize; QListIterator iter(m_pData->clips()); while (iter.hasNext()) { qtractorAudioClip *pClip = iter.next(); unsigned long iClipStart2 = pClip->clipStart(); unsigned long iClipEnd2 = iClipStart2 + pClip->clipLength() + iOverlapSize; if ((iClipStart >= iClipStart2 && iClipEnd2 > iClipStart) || (iClipEnd > iClipStart2 && iClipEnd2 >= iClipEnd)) return true; } return false; } // The main use method. bool qtractorAudioClip::openAudioFile ( const QString& sFilename, int iMode ) { closeAudioFile(); #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioClip[%p]::openAudioFile(\"%s\", %d)", this, sFilename.toUtf8().constData(), iMode); #endif qtractorTrack *pTrack = track(); if (pTrack == NULL) return false; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return false; // Check file buffer number of channels... unsigned short iChannels = 0; bool bWrite = (iMode & qtractorAudioFile::Write); qtractorAudioBus *pAudioBus = static_cast (bWrite ? pTrack->inputBus() : pTrack->outputBus()); if (pAudioBus) iChannels = pAudioBus->channels(); // However, this number of channels is only useful // only when recording, otherwise we'll stick with // source audio file's one... if (bWrite && iChannels < 1) return false; // Save old property (need for peak file ignition)... bool bFilenameChanged = (sFilename != filename()); // Set local properties... setFilename(sFilename); setDirty(false); // Register file path... pSession->files()->addClipItem(qtractorFileList::Audio, this, bWrite); // New key-data sequence... if (!bWrite) { m_pKey = new Key(this); m_pData = g_hashTable.value(*m_pKey, NULL); if (m_pData) { // Check if current clip overlaps any other... unsigned int iOverlapSize = pSession->audioEngine()->bufferSize() << 2; bool bOverlap = isOverlap(iOverlapSize); while (bOverlap) { ++m_iOverlap; m_pKey->update(this); m_pData = g_hashTable.value(*m_pKey, NULL); bOverlap = isOverlap(iOverlapSize); } // Only if it doesn't overlap any... if (m_pData && !bOverlap) { m_pData->attach(this); // Peak files should also be created on-the-fly... qtractorAudioBuffer *pBuff = m_pData->buffer(); if ((m_pPeak == NULL || bFilenameChanged) && pSession->audioPeakFactory()) { if (m_pPeak) delete m_pPeak; m_pPeak = pSession->audioPeakFactory()->createPeak( sFilename, pBuff->timeStretch()); } // Clip name should be clear about it all. if (clipName().isEmpty()) setClipName(shortClipName(QFileInfo(filename()).baseName())); return true; } } } // Initialize audio buffer container... m_pData = new Data(pTrack, iChannels, pSession->sampleRate()); m_pData->attach(this); qtractorAudioBuffer *pBuff = m_pData->buffer(); pBuff->setOffset(clipOffset()); pBuff->setLength(clipLength()); pBuff->setTimeStretch(m_fTimeStretch); pBuff->setPitchShift(m_fPitchShift); if (!pBuff->open(sFilename, iMode)) { delete m_pData; m_pData = NULL; return false; } // Default clip length will be the whole file length. if (clipLength() == 0) setClipLength(pBuff->length() - pBuff->offset()); // Peak files should also be created on-the-fly? if ((m_pPeak == NULL || bFilenameChanged) && pSession->audioPeakFactory()) { if (m_pPeak) delete m_pPeak; m_pPeak = pSession->audioPeakFactory()->createPeak( sFilename, pBuff->timeStretch()); if (bWrite) pBuff->setPeak(m_pPeak); } // Clip name should be clear about it all. if (clipName().isEmpty()) setClipName(shortClipName(QFileInfo(filename()).baseName())); // Something might have changed... updateHashKey(); insertHashKey(); return true; } // Private cleanup. void qtractorAudioClip::closeAudioFile (void) { if (m_pData) { m_pData->detach(this); if (m_pData->count() < 1) { removeHashKey(); delete m_pData; #if 0 // ATTN: If proven empty, remove the file... if (clipLength() < 1) QFile::remove(filename()); #endif } m_pData = NULL; // Unregister file path... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) pSession->files()->removeClipItem(qtractorFileList::Audio, this); } if (m_pKey) { delete m_pKey; m_pKey = NULL; } } // Manage local hash key. void qtractorAudioClip::insertHashKey (void) { if (m_pKey) g_hashTable.insert(*m_pKey, m_pData); } void qtractorAudioClip::updateHashKey (void) { if (m_pKey == NULL) m_pKey = new Key(this); else m_pKey->update(this); } void qtractorAudioClip::removeHashKey (void) { if (m_pKey) g_hashTable.remove(*m_pKey); } // Unlink (clone) local hash data. void qtractorAudioClip::unlinkHashData (void) { if (m_pData == NULL) return; if (m_pData->count() < 2) return; qtractorAudioBuffer *pBuff = m_pData->buffer(); Data *pNewData = new Data(track(), pBuff->channels(), pBuff->sampleRate()); qtractorAudioBuffer *pNewBuff = pNewData->buffer(); pNewBuff->setOffset(pBuff->offset()); pNewBuff->setLength(pBuff->length()); pNewBuff->setTimeStretch(pBuff->timeStretch()); pNewBuff->setPitchShift(pBuff->pitchShift()); if (pNewBuff->open(filename())) { m_pData->detach(this); m_pData = pNewData; if (m_pKey) { delete m_pKey; m_pKey = NULL; } m_pData->attach(this); } else { delete pNewData; } } // Relink local hash data. void qtractorAudioClip::relinkHashData (void) { if (m_pData == NULL) return; if (m_pData->count() > 1) return; removeHashKey(); updateHashKey(); Data *pNewData = g_hashTable.value(*m_pKey, NULL); if (pNewData == NULL) { delete m_pKey; m_pKey = NULL; } else { m_pData->detach(this); delete m_pData; m_pData = pNewData; m_pData->attach(this); } insertHashKey(); } // Whether local hash is being shared. bool qtractorAudioClip::isHashLinked (void) const { return (m_pData && m_pData->count() > 1); } // Make sure the clip hash-table gets reset. void qtractorAudioClip::clearHashTable (void) { g_hashTable.clear(); } // Direct write method. void qtractorAudioClip::write ( float **ppBuffer, unsigned int iFrames, unsigned short iChannels, unsigned int iOffset ) { if (m_pData) m_pData->write(ppBuffer, iFrames, iChannels, iOffset); } // Direct sync method. void qtractorAudioClip::syncExport (void) { if (m_pData) m_pData->syncExport(); } // Intra-clip frame positioning. void qtractorAudioClip::seek ( unsigned long iFrame ) { if (m_pData) m_pData->seek(iFrame); } // Reset clip state. void qtractorAudioClip::reset ( bool bLooping ) { if (m_pData) m_pData->reset(bLooping); } // Loop positioning. void qtractorAudioClip::setLoop ( unsigned long iLoopStart, unsigned long iLoopEnd ) { if (m_pData == NULL) return; qtractorAudioBuffer *pBuff = m_pData->buffer(); if (pBuff == NULL) return; if (iLoopStart == 0 && iLoopEnd >= pBuff->length()) iLoopStart = iLoopEnd = 0; if (iLoopStart == pBuff->loopStart() && iLoopEnd == pBuff->loopEnd()) return; // Check if buffer data has been hash-linked, // unlink (clone) it for proper loop isolation... if (iLoopStart < iLoopEnd) { // Unlink (clone) buffer data... unlinkHashData(); } else { // Relink buffer data... relinkHashData(); } // A brand new one is up! pBuff = m_pData->buffer(); pBuff->setLoop(iLoopStart, iLoopEnd); } // Clip close-commit (record specific) void qtractorAudioClip::close (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioClip[%p]::close()", this); #endif // Take pretended clip-length... qtractorAudioBuffer *pBuff = buffer(); if (pBuff) { // Commit the final clip length (record specific)... if (clipLength() < 1) setClipLength(pBuff->fileLength()); else // Shall we ditch the current peak file? // (don't if closing from recording) if (m_pPeak && pBuff->peak() == NULL) { delete m_pPeak; m_pPeak = NULL; } } // Close and ditch stuff... closeAudioFile(); } // Audio clip (re)open method. void qtractorAudioClip::open (void) { openAudioFile(filename()); } // Audio clip special process cycle executive. void qtractorAudioClip::process ( unsigned long iFrameStart, unsigned long iFrameEnd ) { qtractorAudioBuffer *pBuff = buffer(); if (pBuff == NULL) return; qtractorAudioBus *pAudioBus = static_cast (track()->outputBus()); if (pAudioBus == NULL) return; // Get the next bunch from the clip... unsigned long iClipStart = clipStart(); if (iClipStart > iFrameEnd) return; unsigned long iClipEnd = iClipStart + clipLength(); if (iClipEnd < iFrameStart) return; unsigned long iOffset = (iFrameEnd < iClipEnd ? iFrameEnd : iClipEnd) - iClipStart; if (iClipStart > iFrameStart) { if (pBuff->inSync(0, iOffset)) { pBuff->readMix( pAudioBus->buffer(), iOffset, pAudioBus->channels(), iClipStart - iFrameStart, gain(iOffset)); } } else { if (pBuff->inSync(iFrameStart - iClipStart, iOffset)) { pBuff->readMix( pAudioBus->buffer(), (iFrameEnd < iClipEnd ? iFrameEnd : iClipEnd) - iFrameStart, pAudioBus->channels(), 0, gain(iOffset)); } } } // Audio clip paint method. void qtractorAudioClip::draw ( QPainter *pPainter, const QRect& clipRect, unsigned long iClipOffset ) { qtractorSession *pSession = track()->session(); if (pSession == NULL) return; // Cache some peak data... if (m_pPeak == NULL) return; if (!m_pPeak->openRead()) return; unsigned short iPeriod = m_pPeak->period(); if (iPeriod < 1) return; unsigned short iChannels = m_pPeak->channels(); if (iChannels < 1) return; unsigned long iframe = ((iClipOffset + clipOffset()) / iPeriod); unsigned long nframes = (pSession->frameFromPixel(clipRect.width()) / iPeriod) + 2; // Needed an even number of polygon points... bool bZoomedIn = (clipRect.width() > int(nframes)); unsigned int iPolyPoints = (bZoomedIn ? nframes: (clipRect.width() >> 1)) << 1; if (iPolyPoints < 2) return; // Grab them in... qtractorAudioPeakFile::Frame *pframes = m_pPeak->read(iframe, nframes); if (pframes == NULL) return; // Polygon init... unsigned short i; QPolygon **pPolyMax = new QPolygon* [iChannels]; QPolygon **pPolyRms = new QPolygon* [iChannels]; for (i = 0; i < iChannels; ++i) { pPolyMax[i] = new QPolygon(iPolyPoints); pPolyRms[i] = new QPolygon(iPolyPoints); } // Draw peak chart... const QColor& fg = track()->foreground(); int h1 = (clipRect.height() / iChannels); int h2 = (h1 >> 1); int h2gain = (h2 * m_fractGain.num); int ymax, ymin, yrms; unsigned int n, n2; int x, y; // Build polygonal vertexes... if (bZoomedIn) { // Zoomed in... // - trade peak-frames for pixels. n2 = nframes - 1; for (n = 0; n < nframes; ++n) { x = clipRect.x() + (n * clipRect.width()) / n2; y = clipRect.y() + h2; for (i = 0; i < iChannels; ++i) { ymax = (h2gain * pframes->max) >> m_fractGain.den; ymin = (h2gain * pframes->min) >> m_fractGain.den; yrms = (h2gain * pframes->rms) >> m_fractGain.den; pPolyMax[i]->setPoint(n, x, y - ymax); pPolyMax[i]->setPoint(iPolyPoints - n - 1, x, y + ymin); pPolyRms[i]->setPoint(n, x, y - yrms); pPolyRms[i]->setPoint(iPolyPoints - n - 1, x, y + yrms); y += h1; ++pframes; } } } else { // Zoomed out... // - trade (2) pixels for peak-frames (expensiver). int x2, k = 0; unsigned int n0 = 0; unsigned char v, vmax, vmin, vrms; for (x2 = 0; x2 < clipRect.width(); x2 += 2) { x = clipRect.x() + x2; y = clipRect.y() + h2; n = (iChannels * x2 * nframes) / clipRect.width(); for (i = 0; i < iChannels; ++i) { vmax = pframes[n + i].max; vmin = pframes[n + i].min; vrms = pframes[n + i].rms;; for (n2 = n0 + i; n2 < n + i; n2 += iChannels) { v = pframes[n2].max; if (vmax < v) vmax = v; v = pframes[n2].min; if (vmin < v) vmin = v; v = pframes[n2].rms; if (vrms < v) vrms = v; } ymax = (h2gain * vmax) >> m_fractGain.den; ymin = (h2gain * vmin) >> m_fractGain.den; yrms = (h2gain * vrms) >> m_fractGain.den; pPolyMax[i]->setPoint(k, x, y - ymax); pPolyMax[i]->setPoint(iPolyPoints - k - 1, x, y + ymin); pPolyRms[i]->setPoint(k, x, y - yrms); pPolyRms[i]->setPoint(iPolyPoints - k - 1, x, y + yrms); y += h1; } n0 = n + iChannels; ++k; } } // Close, draw and free the polygons... pPainter->setPen(fg.lighter(140)); for (i = 0; i < iChannels; ++i) { pPainter->setBrush(fg); pPainter->drawPolygon(*pPolyMax[i]); pPainter->setBrush(fg.lighter(120)); pPainter->drawPolygon(*pPolyRms[i]); delete pPolyMax[i]; delete pPolyRms[i]; } // Done on polygons. delete [] pPolyMax; delete [] pPolyRms; } // Audio clip tool-tip. QString qtractorAudioClip::toolTip (void) const { QString sToolTip = qtractorClip::toolTip(); qtractorAudioBuffer *pBuff = buffer(); if (pBuff) { qtractorAudioFile *pFile = pBuff->file(); if (pFile) { sToolTip += QObject::tr("\nAudio:\t%1 channels, %2 Hz") .arg(pFile->channels()) .arg(pFile->sampleRate()); float fGain = clipGain(); if (fGain < 0.999f || fGain > 1.001f) sToolTip += QObject::tr(" (%1 dB)") .arg(20.0f * ::log10f(fGain), 0, 'g', 2); if (pBuff->isTimeStretch()) sToolTip += QObject::tr("\n\t(%1% time stretch)") .arg(100.0f * pBuff->timeStretch(), 0, 'g', 3); if (pBuff->isPitchShift()) sToolTip += QObject::tr("\n\t(%1 semitones pitch shift)") .arg(12.0f * ::logf(pBuff->pitchShift()) / M_LN2, 0, 'g', 2); } } return sToolTip; } // Virtual document element methods. bool qtractorAudioClip::loadClipElement ( qtractorDocument * /* pDocument */, QDomElement *pElement ) { // Load track children... for (QDomNode nChild = pElement->firstChild(); !nChild.isNull(); nChild = nChild.nextSibling()) { // Convert node to element... QDomElement eChild = nChild.toElement(); if (eChild.isNull()) continue; // Load clip properties.. if (eChild.tagName() == "filename") qtractorAudioClip::setFilename(eChild.text()); else if (eChild.tagName() == "time-stretch") qtractorAudioClip::setTimeStretch(eChild.text().toFloat()); else if (eChild.tagName() == "pitch-shift") qtractorAudioClip::setPitchShift(eChild.text().toFloat()); } return true; } bool qtractorAudioClip::saveClipElement ( qtractorDocument *pDocument, QDomElement *pElement ) const { QDomElement eAudioClip = pDocument->document()->createElement("audio-clip"); pDocument->saveTextElement("filename", qtractorAudioClip::relativeFilename(pDocument), &eAudioClip); pDocument->saveTextElement("time-stretch", QString::number(qtractorAudioClip::timeStretch()), &eAudioClip); pDocument->saveTextElement("pitch-shift", QString::number(qtractorAudioClip::pitchShift()), &eAudioClip); pElement->appendChild(eAudioClip); return true; } // Audio clip export method. bool qtractorAudioClip::clipExport ( ClipExport pfnClipExport, void *pvArg, unsigned long iOffset, unsigned long iLength ) const { qtractorTrack *pTrack = track(); if (pTrack == NULL) return false; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return false; unsigned short iChannels = 0; qtractorAudioBus *pAudioBus = static_cast (pTrack->outputBus()); if (pAudioBus) iChannels = pAudioBus->channels(); if (iChannels < 1) return false; iOffset += clipOffset(); if (iLength < 1) iLength = clipLength(); qtractorAudioBuffer *pBuff = new qtractorAudioBuffer( pTrack->syncThread(), iChannels, pSession->sampleRate()); pBuff->setOffset(iOffset); pBuff->setLength(iLength); pBuff->setTimeStretch(timeStretch()); pBuff->setPitchShift(pitchShift()); if (!pBuff->open(filename())) { delete pBuff; return false; } unsigned short i; unsigned int iFrames = pBuff->bufferSize(); float **ppFrames = new float * [iChannels]; for (i = 0; i < iChannels; ++i) { ppFrames[i] = new float[iFrames]; ::memset(ppFrames[i], 0, iFrames * sizeof(float)); } float fGain = clipGain(); unsigned long iFrameStart = 0; while (iFrameStart < iLength) { pBuff->syncExport(); if (pBuff->inSync(iFrameStart, iFrameStart + iFrames)) { int nread = pBuff->read(ppFrames, iFrames); if (nread < 1) break; for (i = 0; i < iChannels; ++i) { float *pFrames = ppFrames[i]; for (int n = 0; n < nread; ++n) *pFrames++ *= fGain; } (*pfnClipExport)(ppFrames, nread, pvArg); iFrameStart += nread; } } for (i = 0; i < iChannels; ++i) delete ppFrames[i]; delete [] ppFrames; delete pBuff; return true; } // end of qtractorAudioClip.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditor.h0000644000175000001440000000012312170747402021231 xustar000000000000000027 mtime=1373884162.493407 26 atime=1381134667.77408 30 ctime=1381134667.774080061 qtractor-0.5.11/src/qtractorMidiEditor.h0000644000175000001440000004215212170747402020524 0ustar00rncbcusers00000000000000// qtractorMidiEditor.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiEditor_h #define __qtractorMidiEditor_h #include "qtractorMidiCursor.h" #include "qtractorMidiEditSelect.h" #include "qtractorMidiEvent.h" #include #include // Forward declarations. class qtractorScrollView; class qtractorRubberBand; class qtractorCommandList; class qtractorMidiEditList; class qtractorMidiEditTime; class qtractorMidiEditView; class qtractorMidiEditEventScale; class qtractorMidiEditEvent; class qtractorMidiEditCommand; class qtractorMidiClip; class qtractorTimeScale; class QFrame; class QComboBox; class QCloseEvent; class QCursor; //---------------------------------------------------------------------------- // qtractorMidiEditor -- The main session track listview widget. class qtractorMidiEditor : public QSplitter { Q_OBJECT public: // Constructor. qtractorMidiEditor(QWidget *pParent); // Destructor. ~qtractorMidiEditor(); // MIDI clip sequence accessors. void setMidiClip(qtractorMidiClip *pMidiClip); qtractorMidiClip *midiClip() const; // MIDI clip properties accessors. const QString& filename() const; unsigned short trackChannel() const; unsigned short format() const; qtractorMidiSequence *sequence() const; // Event foreground (outline) color. void setForeground(const QColor& fore); const QColor& foreground() const; // Event background (fill) color. void setBackground(const QColor& back); const QColor& background() const; // Snap-to-bar zebra mode. void setSnapZebra(bool bSnapZebra); bool isSnapZebra() const; // Snap-to-beat grid mode. void setSnapGrid(bool bSnapGrid); bool isSnapGrid() const; // Floating tool-tips mode. void setToolTips(bool bToolTips); bool isToolTips() const; // Edit (creational) mode. void setEditMode(bool bEditMode); bool isEditMode() const; // Edit draw (notes) mode. void setEditModeDraw(bool bEditModeDraw); bool isEditModeDraw() const; // Zoom (view) modes. enum { ZoomNone = 0, ZoomHorizontal = 1, ZoomVertical = 2, ZoomAll = 3 }; void setZoomMode(int iZoomMode); int zoomMode() const; // Zoom ratio accessors. void setHorizontalZoom(unsigned short iHorizontalZoom); unsigned short horizontalZoom() const; void setVerticalZoom(unsigned short iVerticalZoom); unsigned short verticalZoom() const; // Local time scale accessors. qtractorTimeScale *timeScale() const; unsigned long timeOffset() const; // The original clip time-scale length/time. void setClipLength(unsigned long iClipLength); unsigned long clipLength() const; // Reset original clip time-scale length/time. void resetClipLength(); // Time-scale offset (in frames) accessors. void setOffset(unsigned long iOffset); unsigned long offset() const; // Time-scale length (in frames) accessors. void setLength(unsigned long iLength); unsigned long length() const; // Child widgets accessors. QFrame *editListHeader() const; qtractorMidiEditList *editList() const; qtractorMidiEditTime *editTime() const; qtractorMidiEditView *editView() const; qtractorMidiEditEventScale *editEventScale() const; qtractorMidiEditEvent *editEvent() const; QFrame *editEventFrame() const; // Edit-head/tail accessors. void setEditHead(unsigned long iEditHead, bool bSyncView = true); unsigned long editHead() const; int editHeadX() const; void setEditTail(unsigned long iEditTail, bool bSyncView = true); unsigned long editTail() const; int editTailX() const; // Play-head positioning. void setPlayHead(unsigned long iPlayHead, bool bSyncView = true); unsigned long playHead() const; int playHeadX() const; // Update time-scale to master session. void updateTimeScale(); // Play-head follow-ness. void setSyncView(bool bSyncView); bool isSyncView() const; // Note autition while editing. void setSendNotes(bool bSendNotes); bool isSendNotes() const; // Note event value vs. duration display. void setNoteDuration(bool bNoteDuration); bool isNoteDuration() const; // Note event coloring. void setNoteColor(bool bNoteColor); bool isNoteColor() const; // Note event coloring. void setValueColor(bool bValueColor); bool isValueColor() const; // Snap-to-scale/quantize key accessor. void setSnapToScaleKey(int iSnapToScaleKey); int snapToScaleKey() const; // Snap-to-scale/quantize type accessor. void setSnapToScaleType(int iSnapToScaleType); int snapToScaleType() const; // Alterrnate command action update helper... void updateUndoAction(QAction *pAction) const; void updateRedoAction(QAction *pAction) const; // Command predicate status. bool canUndo() const; bool canRedo() const; // Undo/redo last edit command. void undoCommand(); void redoCommand(); // Whether there's any items currently selected. bool isSelected() const; // Whether there's any items on the clipboard. static bool isClipboard(); // Clipboard commands. void cutClipboard(); void copyClipboard(); void pasteClipboard( unsigned short iPasteCount = 1, unsigned long iPastePeriod = 0); // Retrieve current paste period. // (as from current clipboard width) unsigned long pastePeriod() const; // Execute event removal. void deleteSelect(); // Select all/none contents. void selectAll(qtractorScrollView *pScrollView, bool bSelect = true, bool bToggle = false); // Select range view contents. void selectRange(qtractorScrollView *pScrollView, bool bToggle = false, bool bCommit = false); // Select everything between a given view rectangle. void selectRect(qtractorScrollView *pScrollView, const QRect& rect, bool bToggle = false, bool bCommit = false); // Add/remove one single event to current selection. void selectEvent(qtractorMidiEvent *pEvent, bool bSelect = true); // Retrieve current selection. QList selectedEvents() const; // Selectable event predicate. bool isEventSelectable(qtractorMidiEvent *pEvent) const; // Whether there's any events beyond the insertion point (edit-tail). bool isInsertable() const; // Whether there's any selected range (edit-head/tail). bool isSelectable() const; // Insert/remove edit range. void insertEditRange(); void removeEditRange(); // Update/sync integral contents. void updateContents(); // Try to center vertically the edit-view... void centerContents(); // Reset event cursors. void reset(bool bSelectClear); // Clear all contents. void clear(); // To optimize and keep track of current (re)draw // position, mostly like an sequence cursor/iterator. qtractorMidiEvent *seekEvent(unsigned long iTime); // Get event from given contents position. qtractorMidiEvent *eventAt(qtractorScrollView *pScrollView, const QPoint& pos, QRect *pRect = NULL); // Start immediate some drag-edit mode... qtractorMidiEvent *dragEditEvent(qtractorScrollView *pScrollView, const QPoint& pos, Qt::KeyboardModifiers modifiers); // Track drag-move-select cursor and mode... qtractorMidiEvent *dragMoveEvent (qtractorScrollView *pScrollView, const QPoint& pos, Qt::KeyboardModifiers modifiers); // Start drag-move-selecting... void dragMoveStart(qtractorScrollView *pScrollView, const QPoint& pos, Qt::KeyboardModifiers modifiers); // Update drag-move-selection... void dragMoveUpdate(qtractorScrollView *pScrollView, const QPoint& pos, Qt::KeyboardModifiers modifiers); // Commit drag-move-selection... void dragMoveCommit(qtractorScrollView *pScrollView, const QPoint& pos, Qt::KeyboardModifiers modifiers); // Trap for help/tool-tip and leave events. bool dragMoveFilter(qtractorScrollView *pScrollView, QObject *pObject, QEvent *pEvent); // Keyboard event handler (common). bool keyPress(qtractorScrollView *pScrollView, int iKey, Qt::KeyboardModifiers modifiers); // Keyboard step handler. bool keyStep(int iKey); // Lost focus handler. void focusOut(qtractorScrollView *pScrollView); // Show selection tooltip... void showToolTip(qtractorScrollView *pScrollView, const QRect& rect) const; // MIDI event tool tip helper. QString eventToolTip(qtractorMidiEvent *pEvent, long iTimeDelta = 0, int iNoteDelta = 0, int iValueDelta = 0) const; // Visualize the event selection drag-move. void paintDragState(qtractorScrollView *pScrollView, QPainter *pPainter); // Reset drag/select/move state. void resetDragState(qtractorScrollView *pScrollView); // Tool indexes. enum Tool { Quantize = 0, Transpose = 1, Normalize = 2, Randomize = 3, Resize = 4, Rescale = 5, Timeshift = 6 }; // Edit tools form page selector. void executeTool(int iToolIndex); // Command list accessor. qtractorCommandList *commands() const; // Note name map accessor. const QString noteName(unsigned char note) const; // Controller name map accessor. const QString& controllerName(unsigned char controller) const; // Default note name map accessor. static const QString defaultNoteName(unsigned char note, bool fDrums = false); // Default controller name accessor. static const QString& defaultControllerName(unsigned char controller); // Default scale key/type names accessors. static const QStringList& scaleKeyNames(); static const QStringList& scaleTypeNames(); // Scale quantizer method. static unsigned char snapToScale( unsigned char note, int iKey, int iScale); public slots: // Redirect selection/change notification. void selectionChangeNotify(); void contentsChangeNotify(); // Redirect note on/off; void sendNote(int iNote, int iVelocity = 0); // Update instrument defined names for current clip/track. void updateInstrumentNames(); // Zoom view slots. void zoomIn(); void zoomOut(); void zoomReset(); protected: // Update instrument default note names (nb. drum key names). void updateDefaultDrumNoteNames(); // Zoom factor constants. enum { ZoomMin = 10, ZoomBase = 100, ZoomMax = 1000, ZoomStep = 10 }; // Common zoom factor settlers. void horizontalZoomStep(int iZoomStep); void verticalZoomStep(int iZoomStep); // Zoom centering context. struct ZoomCenter { int x, y, item; unsigned long frame; }; // Zoom centering prepare and post methods. void zoomCenterPre(ZoomCenter& zc) const; void zoomCenterPost(const ZoomCenter& zc); // Ensuere point visibility depending on view. void ensureVisible(qtractorScrollView *pScrollView, const QPoint& pos); // Selection flags enum { SelectNone = 0, SelectClear = 1, SelectToggle = 2, SelectCommit = 4 }; // Clear all selection. void clearSelect(); // Update all selection rectangular areas. void updateSelect(bool bSelectReset); // Update the event selection list. void updateDragSelect(qtractorScrollView *pScrollView, const QRect& rectSelect, int flags); // Compute current drag time snap (in ticks). long timeSnap(long iTime) const; // Compute current drag time delta (in ticks). long timeDelta(qtractorScrollView *pScrollView) const; // Compute current drag note delta. int noteDelta(qtractorScrollView *pScrollView) const; // Compute current drag value delta. int valueDelta(qtractorScrollView *pScrollView) const; // Apply the event drag-resize (also editing). void resizeEvent(qtractorMidiEvent *pEvent, long iTimeDelta, int iValueDelta, qtractorMidiEditCommand *pEditCommand = NULL); // Update event selection rectangle. void updateEvent(qtractorMidiEvent *pEvent); // Update event visual rectangles. void updateEventRects(qtractorMidiEvent *pEvent, QRect& rectEvent, QRect& rectView) const; // Drag-move current selection. void updateDragMove(qtractorScrollView *pScrollView, const QPoint& pos); // Finalize the event drag-move. void executeDragMove(qtractorScrollView *pScrollView, const QPoint& pos); // Drag-rescale current selection. void updateDragRescale(qtractorScrollView *pScrollView, const QPoint& pos); // Finalize the event drag-rescale. void executeDragRescale(qtractorScrollView *pScrollView, const QPoint& pos); // Drag-resize current selection (also editing). void updateDragResize(qtractorScrollView *pScrollView, const QPoint& pos); // Finalize the event drag-resize (also editing). void executeDragResize(qtractorScrollView *pScrollView, const QPoint& pos); // Finalize the event drag-paste. void executeDragPaste(qtractorScrollView *pScrollView, const QPoint& pos); // Drag(draw) event value-resize check. bool isDragEventResize(Qt::KeyboardModifiers modifiers) const; // Drag(draw) event value-resize to current selection... void updateDragEventResize(const QPoint& pos); // Apply drag(draw) event value-resize to current selection. void executeDragEventResize(const QPoint& pos); // Vertical line position drawing. void drawPositionX(int& iPositionX, int x, bool bSyncView); // Specialized drag/time-scale (draft)... struct DragTimeScale; protected slots: // Horizontal zoom view slots. void horizontalZoomInSlot(); void horizontalZoomOutSlot(); void horizontalZoomResetSlot(); // Vertical zoom view slots. void verticalZoomInSlot(); void verticalZoomOutSlot(); void verticalZoomResetSlot(); // Command execution notification slot. void updateNotifySlot(unsigned int flags); signals: // Emitted on selection/changes. void selectNotifySignal(qtractorMidiEditor *); void changeNotifySignal(qtractorMidiEditor *); // Send note event signale. void sendNoteSignal(int, int); private: // The editing sequence. qtractorMidiClip *m_pMidiClip; // Event fore/background colors. QColor m_foreground; QColor m_background; // The main child widgets. QFrame *m_pEditListHeader; qtractorMidiEditList *m_pEditList; qtractorMidiEditTime *m_pEditTime; qtractorMidiEditView *m_pEditView; qtractorMidiEditEventScale *m_pEditEventScale; qtractorMidiEditEvent *m_pEditEvent; QFrame *m_pEditEventFrame; // The local time scale. qtractorTimeScale *m_pTimeScale; // The original clip time-scale length/time. unsigned long m_iClipLengthTime; // The local time-scale offset/length. unsigned long m_iOffset; unsigned long m_iLength; // Event cursors (main time-line). qtractorMidiCursor m_cursor; qtractorMidiCursor m_cursorAt; // The current selection list. qtractorMidiEditSelect m_select; // Common drag state. enum DragState { DragNone = 0, DragStart, DragSelect, DragMove, DragRescale, DragResize, DragEventResize, DragPaste, DragStep } m_dragState, m_dragCursor; // Common drag-resize mode. enum ResizeMode { ResizeNone = 0, ResizeNoteRight, ResizeNoteLeft, ResizeValue, ResizePitchBend } m_resizeMode; // The current selecting/dragging stuff. qtractorMidiEvent *m_pEventDrag; QPoint m_posDrag; QRect m_rectDrag; // Differential drag-move position. QPoint m_posDelta; // Step (keyboard) drag-move position QPoint m_posStep; // Drag(draw) event-value position. QPoint m_posDragEventResize; // Which widget holds focus on drag-paste? qtractorScrollView *m_pEditPaste; // Viewport rubber-banding stuff. qtractorRubberBand *m_pRubberBand; // Zoom mode flag. int m_iZoomMode; // Edit mode flags. bool m_bEditMode; bool m_bEditModeDraw; bool m_bEventDragEdit; // Snap-to-beat/bar grid/zebra mode. bool m_bSnapZebra; bool m_bSnapGrid; // Floating tool-tips mode. bool m_bToolTips; // Last useful editing values. struct { unsigned char note; unsigned char value; unsigned long duration; unsigned short pitchBend; } m_last; // The local edit command list/queue. qtractorCommandList *m_pCommands; // Local edit-head/tail positioning. unsigned long m_iEditHead; int m_iEditHeadX; unsigned long m_iEditTail; int m_iEditTailX; // Local playhead positioning. unsigned long m_iPlayHead; int m_iPlayHeadX; bool m_bSyncView; // Note autition while editing. bool m_bSendNotes; // Event value stick vs. duration rectangle. bool m_bNoteDuration; // Event (note, velocity) coloring. bool m_bNoteColor; bool m_bValueColor; // The local clipboard stuff (singleton). static struct ClipBoard { // Constructor. ClipBoard() {} // Destructor. ~ClipBoard() { clear(); } // Clipboard clear. void clear() { qDeleteAll(items); items.clear(); } // Clipboard members. QList items; // Singleton declaration. } g_clipboard; // Instrument defined names for current clip/track. QHash m_controllerNames; QHash m_noteNames; // Snap-to-scale (aka.in-place scale-quantize) stuff. int m_iSnapToScaleKey; int m_iSnapToScaleType; }; #endif // __qtractorMidiEditor_h // end of qtractorMidiEditor.h qtractor-0.5.11/src/PaxHeaders.10084/qtractor.qrc0000644000175000001440000000012312156361710017613 xustar000000000000000027 mtime=1371136968.140159 26 atime=1381134666.56708 30 ctime=1381134666.567080042 qtractor-0.5.11/src/qtractor.qrc0000644000175000001440000000764712156361710017120 0ustar00rncbcusers00000000000000 images/qtractor.png images/qtractorMidiEditor.png images/qtractorTracks.png images/clipEdit.png images/clipNew.png images/editCopy.png images/editCut.png images/editDelete.png images/editModeDraw.png images/editModeOff.png images/editModeOn.png images/editPaste.png images/editRedo.png images/editSelectClip.png images/editSelectRange.png images/editSelectRect.png images/editSelectCurve.png images/editUndo.png images/fadeIn.png images/fadeOut.png images/fileNew.png images/fileOpen.png images/fileSave.png images/formAccept.png images/formAdd.png images/formColor.png images/formConnect.png images/formCreate.png images/formDisconnect.png images/formDisconnectAll.png images/formEdit.png images/formMoveDown.png images/formMoveUp.png images/formOpen.png images/formParamsOn.png images/formParamsOff.png images/formRefresh.png images/formReject.png images/formRemove.png images/formSave.png images/helpShortcuts.png images/itemAudioClientIn.png images/itemAudioClientOut.png images/itemAudioFile.png images/itemAudioPortIn.png images/itemAudioPortOut.png images/itemAudioPortPhysIn.png images/itemAudioPortPhysOut.png images/itemChannel.png images/itemControllers.png images/itemFile.png images/itemGroup.png images/itemGroupOpen.png images/itemInstrument.png images/itemLedOff.png images/itemLedOn.png images/itemMidiClientIn.png images/itemMidiClientOut.png images/itemMidiFile.png images/itemMidiPortIn.png images/itemMidiPortOut.png images/itemNotes.png images/itemNrpns.png images/itemPatches.png images/itemProperty.png images/itemRpns.png images/trackAdd.png images/trackAudio.png images/trackCurveCapture.png images/trackCurveEnabled.png images/trackCurveNone.png images/trackCurveProcess.png images/trackMidi.png images/trackMidiOff.png images/trackMidiOn.png images/trackProperties.png images/trackRemove.png images/transportAutoBackward.png images/transportBackward.png images/transportContinue.png images/transportFastForward.png images/transportFollow.png images/transportForward.png images/transportLoop.png images/transportMetro.png images/transportPause.png images/transportPanic.png images/transportPlay.png images/transportPunch.png images/transportRecord.png images/transportRewind.png images/transportStop.png images/viewConnections.png images/viewEvents.png images/viewFiles.png images/viewMessages.png images/viewMixer.png images/viewPreview.png images/viewZoomIn.png images/viewZoomOut.png images/viewZoomTool.png qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEvent.h0000644000175000001440000000012312075634407021070 xustar000000000000000027 mtime=1358379271.965668 26 atime=1381134669.66908 30 ctime=1381134669.669080091 qtractor-0.5.11/src/qtractorMidiEvent.h0000644000175000001440000001176412075634407020370 0ustar00rncbcusers00000000000000// qtractorMidiEvent.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiEvent_h #define __qtractorMidiEvent_h #include "qtractorList.h" #include #include //---------------------------------------------------------------------- // class qtractorMidiEvent -- The generic MIDI event element. // class qtractorMidiEvent : public qtractorList::Link { public: // Typical event types. enum EventType { NOTEOFF = 0x80, NOTEON = 0x90, KEYPRESS = 0xa0, CONTROLLER = 0xb0, PGMCHANGE = 0xc0, CHANPRESS = 0xd0, PITCHBEND = 0xe0, SYSEX = 0xf0, META = 0xff }; // Meta event types. enum MetaType { SEQUENCE = 0x00, TEXT = 0x01, COPYRIGHT = 0x02, TRACKNAME = 0x03, INSTRUMENT = 0x04, LYRIC = 0x05, MARKER = 0x06, CUE = 0x07, CHANNEL = 0x20, PORT = 0x21, EOT = 0x2f, TEMPO = 0x51, SMPTE = 0x54, TIME = 0x58, KEY = 0x59, PROPRIETARY = 0x7f }; // Constructor. qtractorMidiEvent(unsigned long time, EventType type, unsigned char data1 = 0, unsigned char data2 = 0, unsigned long duration = 0) : m_time(time), m_type(type) { m_v.data[0] = data1; m_v.data[1] = data2; m_u.duration = duration; } // Copy constructor. qtractorMidiEvent(const qtractorMidiEvent& e) : m_time(e.m_time), m_type(e.m_type) { if (m_type == SYSEX) { m_v.iSysex = e.m_v.iSysex; m_u.pSysex = new unsigned char [m_v.iSysex]; ::memcpy(m_u.pSysex, e.m_u.pSysex, m_v.iSysex); } else { m_v.data[0] = e.m_v.data[0]; m_v.data[1] = e.m_v.data[1]; m_u.duration = e.m_u.duration; } } // Destructor. ~qtractorMidiEvent() { if (m_type == SYSEX && m_u.pSysex) delete [] m_u.pSysex; } // Event properties accessors (getters). unsigned long time() const { return m_time; } EventType type() const { return m_type; } // Underloaded accessors (getters). unsigned char note() const { return m_v.data[0]; } unsigned char velocity() const { return m_v.data[1]; } unsigned char controller() const { return m_v.data[0]; } unsigned char value() const { return m_v.data[1]; } // Event properties accessors (setters). void setTime(unsigned long time) { m_time = time; } void setType(EventType type) { m_type = type; } // Special event time offset adjust. void adjustTime(unsigned long iOffset) { m_time = (m_time > iOffset ? m_time - iOffset : 0); } // Underloaded accessors (setters). void setNote(unsigned char note) { m_v.data[0] = note; } void setVelocity(unsigned char velocity) { m_v.data[1] = velocity; } void setController(unsigned char controller) { m_v.data[0] = controller; } void setValue(unsigned char value) { m_v.data[1] = value; } // Duration accessors (NOTEON). void setDuration(unsigned long duration) { m_u.duration = duration; } unsigned long duration() const { return m_u.duration; } // Sysex data accessors (SYSEX). unsigned char *sysex() const { return m_u.pSysex; } unsigned short sysex_len() const { return m_v.iSysex; } // Allocate and set a new sysex buffer. void setSysex(unsigned char *pSysex, unsigned short iSysex) { if (m_type == SYSEX && m_u.pSysex) delete [] m_u.pSysex; m_v.iSysex = iSysex; m_u.pSysex = new unsigned char [m_v.iSysex]; ::memcpy(m_u.pSysex, pSysex, m_v.iSysex); } // Special accessors for pitch-bend event types. int pitchBend() const { unsigned short val = ((unsigned short) m_v.data[1] << 7) | m_v.data[0]; return int(val) - 0x2000; } void setPitchBend(int iPitchBend) { unsigned short val = (unsigned short) (0x2000 + iPitchBend); m_v.data[0] = (val & 0x007f); m_v.data[1] = (val & 0x3f80) >> 7; } private: // Event instance members. unsigned long m_time; EventType m_type; // Nominal event data. union { unsigned char data[2]; // type != SYSEX unsigned short iSysex; // type == SYSEX } m_v; // Extra event data. union { unsigned long duration; // type == NOTEON unsigned char *pSysex; // type == SYSEX } m_u; }; #endif // __qtractorMidiEvent_h // end of qtractorMidiEvent.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiControlCommand.cpp0000644000175000001440000000012312156127233023253 xustar000000000000000027 mtime=1371057819.151017 26 atime=1381134666.76108 30 ctime=1381134666.762080045 qtractor-0.5.11/src/qtractorMidiControlCommand.cpp0000644000175000001440000000430012156127233022537 0ustar00rncbcusers00000000000000// qtractorMidiControlCommand.cpp // /**************************************************************************** Copyright (C) 2010-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiControlCommand.h" #include "qtractorMidiControlObserver.h" //---------------------------------------------------------------------- // class qtractorMidiControlObserverCommand - declaration. // // Constructor. qtractorMidiControlObserverCommand::qtractorMidiControlObserverCommand ( const QString& sName, qtractorMidiControlObserver *pMidiObserver ) : qtractorCommand(sName), m_pMidiObserver(pMidiObserver) { setRefresh(false); } // Map/unmap observer methods. bool qtractorMidiControlObserverCommand::mapMidiObserver (void) const { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return false; if (pMidiControl->isMidiObserverMapped(m_pMidiObserver)) return false; pMidiControl->mapMidiObserver(m_pMidiObserver); return true; } // Unmap observer methods. bool qtractorMidiControlObserverCommand::unmapMidiObserver (void) const { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return false; if (!pMidiControl->isMidiObserverMapped(m_pMidiObserver)) return false; pMidiControl->unmapMidiObserver(m_pMidiObserver); return true; } // end of qtractorMidiControlCommand.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTimeScale.cpp0000644000175000001440000000012312166134117021377 xustar000000000000000027 mtime=1373157455.942698 26 atime=1381134666.99808 30 ctime=1381134666.999080049 qtractor-0.5.11/src/qtractorTimeScale.cpp0000644000175000001440000004744612166134117020705 0ustar00rncbcusers00000000000000// qtractorTimeScale.cpp // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorTimeScale.h" //---------------------------------------------------------------------- // class qtractorTimeScale -- Time scale conversion helper class. // // Node list cleaner. void qtractorTimeScale::reset (void) { m_nodes.setAutoDelete(true); m_markers.setAutoDelete(true); // Clear/reset location-markers... m_markers.clear(); m_markerCursor.reset(); // Clear/reset tempo-map... m_nodes.clear(); m_cursor.reset(); // There must always be one node, always. addNode(0); // Commit new scale... updateScale(); } // (Re)nitializer method. void qtractorTimeScale::clear (void) { m_iSnapPerBeat = 4; m_iHorizontalZoom = 100; m_iVerticalZoom = 100; // m_displayFormat = Frames; m_iSampleRate = 44100; m_iTicksPerBeat = 960; m_iPixelsPerBeat = 32; // Clear/reset tempo-map... reset(); } // Sync method. void qtractorTimeScale::sync ( const qtractorTimeScale& ts ) { // Copy master parameters... m_iSampleRate = ts.m_iSampleRate; m_iTicksPerBeat = ts.m_iTicksPerBeat; m_iPixelsPerBeat = ts.m_iPixelsPerBeat; // Copy location markers... m_markers.clear(); Marker *pMarker = ts.m_markers.first(); while (pMarker) { m_markers.append(new Marker(*pMarker)); pMarker = pMarker->next(); } m_markerCursor.reset(); // Copy tempo-map nodes... m_nodes.clear(); Node *pNode = ts.nodes().first(); while (pNode) { m_nodes.append(new Node(this, pNode->frame, pNode->tempo, pNode->beatType, pNode->beatsPerBar, pNode->beatDivisor)); pNode = pNode->next(); } m_cursor.reset(); updateScale(); } // Copy method. qtractorTimeScale& qtractorTimeScale::copy ( const qtractorTimeScale& ts ) { if (&ts != this) { m_nodes.setAutoDelete(true); m_markers.setAutoDelete(true); m_iSampleRate = ts.m_iSampleRate; m_iSnapPerBeat = ts.m_iSnapPerBeat; m_iHorizontalZoom = ts.m_iHorizontalZoom; m_iVerticalZoom = ts.m_iVerticalZoom; m_displayFormat = ts.m_displayFormat; // Sync/copy tempo-map nodes... sync(ts); } return *this; } // Update scale coefficient divisor factors. void qtractorTimeScale::Node::update (void) { ticksPerBeat = ts->ticksPerBeat(); tickRate = tempo * ticksPerBeat; beatRate = tempo; #if 0 if (beatDivisor > beatType) { unsigned short n = (beatDivisor - beatType); ticksPerBeat >>= n; beatRate *= float(1 << n); } else if (beatDivisor < beatType) { unsigned short n = (beatType - beatDivisor); ticksPerBeat <<= n; beatRate /= float(1 << n); } #endif } // Update time-scale node position metrics. void qtractorTimeScale::Node::reset ( qtractorTimeScale::Node *pNode ) { if (bar > pNode->bar) frame = pNode->frameFromBar(bar); else bar = pNode->barFromFrame(frame); beat = pNode->beatFromFrame(frame); tick = pNode->tickFromFrame(frame); pixel = ts->pixelFromFrame(frame); } // Tempo accessor/convertors. void qtractorTimeScale::Node::setTempoEx ( float fTempo, unsigned short iBeatType ) { if (iBeatType > beatType) fTempo /= float(1 << (iBeatType - beatType)); else if (beatType > iBeatType) fTempo *= float(1 << (beatType - iBeatType)); tempo = fTempo; } float qtractorTimeScale::Node::tempoEx ( unsigned short iBeatType ) const { float fTempo = tempo; if (beatType > iBeatType) fTempo /= float(1 << (beatType - iBeatType)); else if (iBeatType > beatType) fTempo *= float(1 << (iBeatType - beatType)); return fTempo; } // Beat/frame snap filters. unsigned long qtractorTimeScale::Node::tickSnap ( unsigned long iTick, unsigned short p ) const { unsigned long iTickSnap = iTick - tick; if (ts->snapPerBeat() > 0) { unsigned long q = ticksPerBeat / ts->snapPerBeat(); iTickSnap = q * ((iTickSnap + (q >> p)) / q); } return tick + iTickSnap; } // Time-scale cursor frame positioning reset. void qtractorTimeScale::Cursor::reset ( qtractorTimeScale::Node *pNode ) { node = (pNode ? pNode : ts->nodes().first()); } // Time-scale cursor node seeker (by frame). qtractorTimeScale::Node *qtractorTimeScale::Cursor::seekFrame ( unsigned long iFrame ) { if (node == 0) { node = ts->nodes().first(); if (node == 0) return 0; } if (iFrame > node->frame) { // Seek frame forward... while (node && node->next() && iFrame >= (node->next())->frame) node = node->next(); } else if (iFrame < node->frame) { // Seek frame backward... while (node && node->frame > iFrame) node = node->prev(); if (node == 0) node = ts->nodes().first(); } return node; } // Time-scale cursor node seeker (by bar). qtractorTimeScale::Node *qtractorTimeScale::Cursor::seekBar ( unsigned short iBar ) { if (node == 0) { node = ts->nodes().first(); if (node == 0) return 0; } if (iBar > node->bar) { // Seek bar forward... while (node && node->next() && iBar >= (node->next())->bar) node = node->next(); } else if (iBar < node->bar) { // Seek bar backward... while (node && node->bar > iBar) node = node->prev(); if (node == 0) node = ts->nodes().first(); } return node; } // Time-scale cursor node seeker (by beat). qtractorTimeScale::Node *qtractorTimeScale::Cursor::seekBeat ( unsigned int iBeat ) { if (node == 0) { node = ts->nodes().first(); if (node == 0) return 0; } if (iBeat > node->beat) { // Seek beat forward... while (node && node->next() && iBeat >= (node->next())->beat) node = node->next(); } else if (iBeat < node->beat) { // Seek beat backward... while (node && node->beat > iBeat) node = node->prev(); if (node == 0) node = ts->nodes().first(); } return node; } // Time-scale cursor node seeker (by tick). qtractorTimeScale::Node *qtractorTimeScale::Cursor::seekTick ( unsigned long iTick ) { if (node == 0) { node = ts->nodes().first(); if (node == 0) return 0; } if (iTick > node->tick) { // Seek tick forward... while (node && node->next() && iTick >= (node->next())->tick) node = node->next(); } else if (iTick < node->tick) { // Seek tick backward... while (node && node->tick > iTick) node = node->prev(); if (node == 0) node = ts->nodes().first(); } return node; } // Time-scale cursor node seeker (by pixel). qtractorTimeScale::Node *qtractorTimeScale::Cursor::seekPixel ( int x ) { if (node == 0) { node = ts->nodes().first(); if (node == 0) return 0; } if (x > node->pixel) { // Seek pixel forward... while (node && node->next() && x >= (node->next())->pixel) node = node->next(); } else if (x < node->pixel) { // Seek tick backward... while (node && node->pixel > x) node = node->prev(); if (node == 0) node = ts->nodes().first(); } return node; } // Node list specifics. qtractorTimeScale::Node *qtractorTimeScale::addNode ( unsigned long iFrame, float fTempo, unsigned short iBeatType, unsigned short iBeatsPerBar, unsigned short iBeatDivisor ) { Node *pNode = 0; // Seek for the nearest preceding node... Node *pPrev = m_cursor.seekFrame(iFrame); // Snap frame to nearest bar... if (pPrev) { iFrame = pPrev->frameSnapToBar(iFrame); pPrev = m_cursor.seekFrame(iFrame); } // Either update existing node or add new one... Node *pNext = (pPrev ? pPrev->next() : 0); if (pPrev && pPrev->frame == iFrame) { // Update exact matching node... pNode = pPrev; pNode->tempo = fTempo; pNode->beatType = iBeatType; pNode->beatsPerBar = iBeatsPerBar; pNode->beatDivisor = iBeatDivisor; } else if (pPrev && pPrev->tempo == fTempo && pPrev->beatType == iBeatType && pPrev->beatsPerBar == iBeatsPerBar && pPrev->beatDivisor == iBeatDivisor) { // No need for a new node... return pPrev; } else if (pNext && pNext->tempo == fTempo && pNext->beatType == iBeatType && pNext->beatsPerBar == iBeatsPerBar && pNext->beatDivisor == iBeatDivisor) { // Update next exact matching node... pNode = pNext; pNode->frame = iFrame; pNode->bar = 0; } else { // Add/insert a new node... pNode = new Node(this, iFrame, fTempo, iBeatType, iBeatsPerBar, iBeatDivisor); if (pPrev) m_nodes.insertAfter(pNode, pPrev); else m_nodes.append(pNode); } // Update coefficients and positioning thereafter... updateNode(pNode); return pNode; } void qtractorTimeScale::updateNode ( qtractorTimeScale::Node *pNode ) { // Update coefficients... pNode->update(); // Relocate internal cursor... m_cursor.reset(pNode); // Update positioning on all nodes thereafter... Node *pNext = pNode; Node *pPrev = pNext->prev(); while (pNext) { if (pPrev) pNext->reset(pPrev); pPrev = pNext; pNext = pNext->next(); } // And update marker/bar positions too... updateMarkers(pNode->prev()); } void qtractorTimeScale::removeNode ( qtractorTimeScale::Node *pNode ) { // Don't ever remove the very first node... Node *pNodePrev = pNode->prev(); if (pNodePrev == 0) return; // Relocate internal cursor... m_cursor.reset(pNodePrev); // Update positioning on all nodes thereafter... Node *pPrev = pNodePrev; Node *pNext = pNode->next(); while (pNext) { if (pPrev) pNext->reset(pPrev); pPrev = pNext; pNext = pNext->next(); } // Actually remove/unlink the node... m_nodes.remove(pNode); // Then update marker/bar positions too... updateMarkers(pNodePrev); } // Complete time-scale update method. void qtractorTimeScale::updateScale (void) { // Update time-map independent coefficients... m_fPixelRate = 1.20f * float(m_iHorizontalZoom * m_iPixelsPerBeat); m_fFrameRate = 60.0f * float(m_iSampleRate); // Update all nodes thereafter... Node *pPrev = 0; Node *pNext = m_nodes.first(); while (pNext) { pNext->update(); if (pPrev) pNext->reset(pPrev); pPrev = pNext; pNext = pNext->next(); } // Also update all marker/bar positions too... updateMarkers(m_nodes.first()); } // Convert frames to time string and vice-versa. unsigned long qtractorTimeScale::frameFromTextEx ( DisplayFormat displayFormat, const QString& sText, bool bDelta, unsigned long iFrame ) { switch (displayFormat) { case BBT: { // Time frame code in bars.beats.ticks ... unsigned short bars = sText.section('.', 0, 0).toUShort(); unsigned int beats = sText.section('.', 1, 1).toUInt(); unsigned long ticks = sText.section('.', 2).toULong(); Node *pNode; if (bDelta) { pNode = m_cursor.seekFrame(iFrame); if (pNode) bars += pNode->bar; } else { if (bars > 0) --bars; if (beats > 0) --beats; } pNode = m_cursor.seekBar(bars); if (pNode) { beats += (bars - pNode->bar) * pNode->beatsPerBar; ticks += pNode->tick + beats * pNode->ticksPerBeat; iFrame = pNode->frameFromTick(ticks); } break; } case Time: { // Time frame code in hh:mm:ss.zzz ... unsigned int hh = sText.section(':', 0, 0).toUInt(); unsigned int mm = sText.section(':', 1, 1).toUInt(); float secs = sText.section(':', 2).toFloat(); mm += 60 * hh; secs += 60.f * float(mm); iFrame = uroundf(secs * float(m_iSampleRate)); break; } case Frames: default: { iFrame = sText.toULong(); break; } } return iFrame; } unsigned long qtractorTimeScale::frameFromText ( const QString& sText, bool bDelta, unsigned long iFrame ) { return frameFromTextEx(m_displayFormat, sText, bDelta, iFrame); } QString qtractorTimeScale::textFromFrameEx ( DisplayFormat displayFormat, unsigned long iFrame, bool bDelta, unsigned long iDelta ) { QString sText; switch (displayFormat) { case BBT: { // Time frame code in bars.beats.ticks ... unsigned short bars = 0; unsigned int beats = 0; unsigned long ticks = 0; Node *pNode = m_cursor.seekFrame(iFrame); if (pNode) { if (bDelta) { ticks = pNode->tickFromFrame(iFrame + iDelta) - pNode->tickFromFrame(iFrame); } else { ticks = pNode->tickFromFrame(iFrame) - pNode->tick; } if (ticks >= (unsigned long) pNode->ticksPerBeat) { beats = (unsigned int) (ticks / pNode->ticksPerBeat); ticks -= (unsigned long) (beats * pNode->ticksPerBeat); } if (beats >= (unsigned int) pNode->beatsPerBar) { bars = (unsigned short) (beats / pNode->beatsPerBar); beats -= (unsigned int) (bars * pNode->beatsPerBar); } if (!bDelta) bars += pNode->bar; } if (!bDelta) { ++bars; ++beats; } sText.sprintf("%u.%u.%03lu", bars, beats, ticks); break; } case Time: { // Time frame code in hh:mm:ss.zzz ... unsigned int hh, mm, ss, zzz; float secs = float(bDelta ? iDelta : iFrame) / float(m_iSampleRate); hh = mm = ss = 0; if (secs >= 3600.0f) { hh = (unsigned int) (secs / 3600.0f); secs -= float(hh) * 3600.0f; } if (secs >= 60.0f) { mm = (unsigned int) (secs / 60.0f); secs -= float(mm) * 60.0f; } if (secs >= 0.0f) { ss = (unsigned int) secs; secs -= float(ss); } zzz = (unsigned int) (secs * 1000.0f); sText.sprintf("%02u:%02u:%02u.%03u", hh, mm, ss, zzz); break; } case Frames: default: { sText = QString::number(bDelta ? iDelta : iFrame); break; } } return sText; } QString qtractorTimeScale::textFromFrame ( unsigned long iFrame, bool bDelta, unsigned long iDelta ) { return textFromFrameEx(m_displayFormat, iFrame, bDelta, iDelta); } // Convert ticks to time string and vice-versa. unsigned long qtractorTimeScale::tickFromText ( const QString& sText, bool bDelta, unsigned long iTick ) { unsigned long iFrame = 0; if (bDelta) { Node *pNode = m_cursor.seekTick(iTick); iFrame = (pNode ? pNode->frameFromTick(iTick) : 0); } return tickFromFrame(frameFromText(sText, bDelta, iFrame)); } QString qtractorTimeScale::textFromTick ( unsigned long iTick, bool bDelta, unsigned long iDelta ) { Node *pNode = m_cursor.seekTick(iTick); unsigned long iFrame = (pNode ? pNode->frameFromTick(iTick) : 0); if (bDelta > 0 && pNode) { iTick += iDelta; pNode = m_cursor.seekTick(iTick); iDelta = (pNode ? pNode->frameFromTick(iTick) - iFrame : 0); } return textFromFrame(iFrame, bDelta, iDelta); } // Beat divisor (snap index) map. static int s_aiSnapPerBeat[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 21, 24, 28, 32, 48, 64, 96 }; const int c_iSnapItemCount = sizeof(s_aiSnapPerBeat) / sizeof(int); // Beat divisor (snap index) accessors. unsigned short qtractorTimeScale::snapFromIndex ( int iSnap ) { return s_aiSnapPerBeat[iSnap]; } // Beat divisor (snap index) accessors. int qtractorTimeScale::indexFromSnap ( unsigned short iSnapPerBeat ) { for (int iSnap = 0; iSnap < c_iSnapItemCount; ++iSnap) { if (s_aiSnapPerBeat[iSnap] == iSnapPerBeat) return iSnap; } return 0; } // Beat divisor (snap index) text item list. QStringList qtractorTimeScale::snapItems ( int iSnap ) { QStringList items; if (iSnap == 0) { items.append(QObject::tr("None")); ++iSnap; } QString sPrefix = QObject::tr("Beat"); if (iSnap == 1) { items.append(sPrefix); ++iSnap; } sPrefix += "/%1"; while (iSnap < c_iSnapItemCount) items.append(sPrefix.arg(s_aiSnapPerBeat[iSnap++])); return items; } // Tick/Frame range conversion (delta conversion). unsigned long qtractorTimeScale::frameFromTickRange ( unsigned long iTickStart, unsigned long iTickEnd ) { Node *pNode = m_cursor.seekTick(iTickStart); unsigned long iFrameStart = (pNode ? pNode->frameFromTick(iTickStart) : 0); pNode = m_cursor.seekTick(iTickEnd); unsigned long iFrameEnd = (pNode ? pNode->frameFromTick(iTickEnd) : 0); return (iFrameEnd > iFrameStart ? iFrameEnd - iFrameStart : 0); } unsigned long qtractorTimeScale::tickFromFrameRange ( unsigned long iFrameStart, unsigned long iFrameEnd ) { Node *pNode = m_cursor.seekFrame(iFrameStart); unsigned long iTickStart = (pNode ? pNode->tickFromFrame(iFrameStart) : 0); pNode = m_cursor.seekFrame(iFrameEnd); unsigned long iTickEnd = (pNode ? pNode->tickFromFrame(iFrameEnd) : 0); return (iTickEnd > iTickStart ? iTickEnd - iTickStart : 0); } // Location marker reset method. void qtractorTimeScale::MarkerCursor::reset ( qtractorTimeScale::Marker *pMarker ) { marker = (pMarker ? pMarker : ts->markers().first()); } // Location marker seek methods. qtractorTimeScale::Marker *qtractorTimeScale::MarkerCursor::seekFrame ( unsigned long iFrame ) { if (marker == 0) { marker = ts->markers().first(); if (marker == 0) return 0; } if (iFrame > marker->frame) { // Seek frame forward... while (marker && marker->next() && iFrame >= (marker->next())->frame) marker = marker->next(); } else if (iFrame < marker->frame) { // Seek frame backward... while (marker && marker->frame > iFrame) marker = marker->prev(); if (marker == 0) marker = ts->markers().first(); } return marker; } qtractorTimeScale::Marker *qtractorTimeScale::MarkerCursor::seekBar ( unsigned short iBar ) { return seekFrame(ts->frameFromBar(iBar)); } qtractorTimeScale::Marker *qtractorTimeScale::MarkerCursor::seekBeat ( unsigned int iBeat ) { return seekFrame(ts->frameFromBeat(iBeat)); } qtractorTimeScale::Marker *qtractorTimeScale::MarkerCursor::seekTick ( unsigned long iTick ) { return seekFrame(ts->frameFromTick(iTick)); } qtractorTimeScale::Marker *qtractorTimeScale::MarkerCursor::seekPixel ( int x ) { return seekFrame(ts->frameFromPixel(x)); } // Location markers list specifics. qtractorTimeScale::Marker *qtractorTimeScale::addMarker ( unsigned long iFrame, const QString& sText, const QColor& rgbColor ) { Marker *pMarker = 0; // Snap to nearest bar... unsigned short iBar = 0; Node *pNodePrev = m_cursor.seekFrame(iFrame); if (pNodePrev) { iBar = pNodePrev->barFromFrame(iFrame); iFrame = pNodePrev->frameFromBar(iBar); } // Seek for the nearest marker... Marker *pMarkerNear = m_markerCursor.seekFrame(iFrame); // Either update existing marker or add new one... if (pMarkerNear && pMarkerNear->frame == iFrame) { // Update exact matching marker... pMarker = pMarkerNear; pMarker->bar = iBar; pMarker->text = sText; pMarker->color = rgbColor; } else { // Add/insert a new marker... pMarker = new Marker(iFrame, iBar, sText, rgbColor); if (pMarkerNear && pMarkerNear->frame > iFrame) m_markers.insertBefore(pMarker, pMarkerNear); else if (pMarkerNear && pMarkerNear->frame < iFrame) m_markers.insertAfter(pMarker, pMarkerNear); else m_markers.append(pMarker); } // Update positioning... updateMarker(pMarker); return pMarker; } void qtractorTimeScale::updateMarker ( qtractorTimeScale::Marker *pMarker ) { // Relocate internal cursor... m_markerCursor.reset(pMarker); } void qtractorTimeScale::removeMarker ( qtractorTimeScale::Marker *pMarker ) { // Actually remove/unlink the marker // and relocate internal cursor... Marker *pMarkerPrev = pMarker->prev(); m_markers.remove(pMarker); m_markerCursor.reset(pMarkerPrev); } // Update markers from given node position. void qtractorTimeScale::updateMarkers ( qtractorTimeScale::Node *pNode ) { if (pNode == 0) pNode = m_nodes.first(); if (pNode == 0) return; Marker *pMarker = m_markerCursor.seekFrame(pNode->frame); while (pMarker) { while (pNode->next() && pMarker->frame > pNode->next()->frame) pNode = pNode->next(); if (pMarker->frame >= pNode->frame) pMarker->frame = pNode->frameFromBar(pMarker->bar); pMarker = pMarker->next(); } } // end of qtractorTimeScale.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorSessionCommand.h0000644000175000001440000000012312065723502022120 xustar000000000000000027 mtime=1356310338.523936 26 atime=1381134666.77308 30 ctime=1381134666.773080045 qtractor-0.5.11/src/qtractorSessionCommand.h0000644000175000001440000000644712065723502021422 0ustar00rncbcusers00000000000000// qtractorSessionCommand.h // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorSessionCommand_h #define __qtractorSessionCommand_h #include "qtractorPropertyCommand.h" #include "qtractorSession.h" // Forward declarations. class qtractorTimeScaleUpdateNodeCommand; //---------------------------------------------------------------------- // class qtractorSessionCommand - declaration. // class qtractorSessionCommand : public qtractorCommand { public: // Constructor. qtractorSessionCommand(const QString& sName, qtractorSession *pSession); // Destructor. virtual ~qtractorSessionCommand(); // Track accessor. qtractorSession *session() const { return m_pSession; } private: // Instance variables. qtractorSession *m_pSession; }; //---------------------------------------------------------------------- // class qtractorSessionLoopCommand - declaration. // class qtractorSessionLoopCommand : public qtractorSessionCommand { public: // Constructor. qtractorSessionLoopCommand(qtractorSession *pSession, unsigned long iLoopStart, unsigned long iLoopEnd); // Session-loop command methods. bool redo(); bool undo(); private: // Instance variables. unsigned long m_iLoopStart; unsigned long m_iLoopEnd; }; //---------------------------------------------------------------------- // class qtractorSessionPunchCommand - declaration. // class qtractorSessionPunchCommand : public qtractorSessionCommand { public: // Constructor. qtractorSessionPunchCommand(qtractorSession *pSession, unsigned long iPunchIn, unsigned long iPunchOut); // Session-punch command methods. bool redo(); bool undo(); private: // Instance variables. unsigned long m_iPunchIn; unsigned long m_iPunchOut; }; //---------------------------------------------------------------------- // class qtractorSessionEditCommand - declaration. // class qtractorSessionEditCommand : public qtractorSessionCommand { public: // Constructor. qtractorSessionEditCommand(qtractorSession *pSession, const qtractorSession::Properties& properties); // Destructor. ~qtractorSessionEditCommand(); // Session-tempo command methods. bool redo(); bool undo(); private: // Instance variables. qtractorPropertyCommand *m_pPropertiesCommand; qtractorTimeScaleUpdateNodeCommand *m_pTempoCommand; unsigned short m_iTicksPerBeat; }; #endif // __qtractorSessionCommand_h // end of qtractorSessionCommand.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioSndFile.h0000644000175000001440000000012311563576072021516 xustar000000000000000027 mtime=1305410618.253123 26 atime=1381134667.63108 30 ctime=1381134667.632080059 qtractor-0.5.11/src/qtractorAudioSndFile.h0000644000175000001440000000454311563576072021013 0ustar00rncbcusers00000000000000// qtractorAudioSndFile.h // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorAudioSndFile_h #define __qtractorAudioSndFile_h #include "qtractorAudioFile.h" // libsndfile API. #include //---------------------------------------------------------------------- // class qtractorAudioSndFile -- Buffered audio file declaration. // class qtractorAudioSndFile : public qtractorAudioFile { public: // Constructor. qtractorAudioSndFile(unsigned short iChannels = 0, unsigned int iSampleRate = 0, unsigned int iBufferSize = 0); // Destructor. virtual ~qtractorAudioSndFile(); // Virtual method mockups. bool open (const QString& sFilename, int iMode = Read); int read (float **ppFrames, unsigned int iFrames); int write (float **ppFrames, unsigned int iFrames); bool seek (unsigned long iOffset); void close (); // Virtual accessor mockups. int mode() const; unsigned short channels() const; unsigned long frames() const; // Specialty methods. unsigned int sampleRate() const; protected: // De/interleaving buffer (re)allocation check. void allocBufferCheck(unsigned int iBufferSize); private: int m_iMode; // open mode (Read|Write). SNDFILE *m_pSndFile; // libsndfile descriptor. SF_INFO m_sfinfo; // libsndfile info struct. // De/interleaving buffer stuff. float *m_pBuffer; unsigned int m_iBufferSize; }; #endif // __qtractorAudioSndFile_h // end of qtractorAudioSndFile.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorPlugin.h0000644000175000001440000000012312161335204020427 xustar000000000000000027 mtime=1371912836.382031 26 atime=1381134666.67708 30 ctime=1381134666.677080044 qtractor-0.5.11/src/qtractorPlugin.h0000644000175000001440000005662112161335204017730 0ustar00rncbcusers00000000000000// qtractorPlugin.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorPlugin_h #define __qtractorPlugin_h #include "qtractorEngine.h" #include "qtractorMidiControlObserver.h" #include #include #include #include // Forward declarations. class qtractorPluginPath; class qtractorPluginFile; class qtractorPluginList; class qtractorPluginParam; class qtractorPluginForm; class qtractorPlugin; class qtractorPluginListView; class qtractorPluginListItem; class qtractorMidiManager; class qtractorDocument; class qtractorCurveList; class qtractorCurveFile; class QDomDocument; class QDomElement; //---------------------------------------------------------------------------- // qtractorPluginType -- Plugin type instance. // class qtractorPluginType { public: // Have hints for plugin paths. enum Hint { Any = 0, Ladspa, Dssi, Vst, Lv2, Insert, AuxSend }; // Constructor. qtractorPluginType(qtractorPluginFile *pFile, unsigned long iIndex, Hint typeHint) : m_iUniqueID(0), m_iControlIns(0), m_iControlOuts(0), m_iAudioIns(0), m_iAudioOuts(0), m_iMidiIns(0), m_iMidiOuts(0), m_bRealtime(false), m_bConfigure(false), m_bEditor(false), m_pFile(pFile), m_iIndex(iIndex), m_typeHint(typeHint) {} // Destructor (virtual) virtual ~qtractorPluginType() {} // Main properties accessors. qtractorPluginFile *file() const { return m_pFile; } unsigned long index() const { return m_iIndex; } Hint typeHint() const { return m_typeHint; } // Plugin filename accessor (default virtual). virtual QString filename() const; // Must be derived methods. virtual bool open() = 0; virtual void close() = 0; // Cache accessors. const QString& name() const { return m_sName; } const QString& label() const { return m_sLabel; } unsigned long uniqueID() const { return m_iUniqueID; } // Port count accessors.. unsigned short controlIns() const { return m_iControlIns; } unsigned short controlOuts() const { return m_iControlOuts; } unsigned short audioIns() const { return m_iAudioIns; } unsigned short audioOuts() const { return m_iAudioOuts; } unsigned short midiIns() const { return m_iMidiIns; } unsigned short midiOuts() const { return m_iMidiOuts; } // Attribute accessors. bool isRealtime() const { return m_bRealtime; } bool isConfigure() const { return m_bConfigure; } bool isEditor() const { return m_bEditor; } bool isMidi() const { return m_iMidiIns + m_iMidiOuts > 0; } // Compute the number of instances needed // for the given input/output audio channels. virtual unsigned short instances( unsigned short iChannels, bool bMidi) const; // Plugin type(hint) textual helpers. static Hint hintFromText(const QString& sText); static QString textFromHint(Hint typeHint); protected: // Cached name strings. QString m_sName; QString m_sLabel; // Cache unique identifier. unsigned long m_iUniqueID; // Cached port counts. unsigned short m_iControlIns; unsigned short m_iControlOuts; unsigned short m_iAudioIns; unsigned short m_iAudioOuts; unsigned short m_iMidiIns; unsigned short m_iMidiOuts; // Cached flags. bool m_bRealtime; bool m_bConfigure; bool m_bEditor; private: // Instance variables. qtractorPluginFile *m_pFile; unsigned long m_iIndex; Hint m_typeHint; }; //---------------------------------------------------------------------------- // qtractorDummyPluginType -- Dummy plugin type instance. // class qtractorDummyPluginType : public qtractorPluginType { public: // Constructor. qtractorDummyPluginType( qtractorPluginFile *pFile, unsigned long iIndex, Hint typeHint); // Must be overriden methods. bool open(); void close(); // Factory method (static) static qtractorDummyPluginType *createType( qtractorPluginFile *pFile, unsigned long iIndex = 0, Hint typeHint = Vst); }; //---------------------------------------------------------------------------- // qtractorPluginFile -- Plugin file library instance. // class qtractorPluginFile : public QLibrary { public: // Constructor. qtractorPluginFile(const QString& sFilename, bool bAutoUnload = true) : QLibrary(sFilename), m_bAutoUnload(bAutoUnload) {} // Destructor. ~qtractorPluginFile() { close(); } // Helper property accessors. QString filename() const { return QLibrary::fileName(); } // Executive methods. bool open(); void close(); // Auto-unload flag accessors. void setAutoUnload(bool bAutoUnload) { m_bAutoUnload = bAutoUnload; } bool isAutoUnload() const { return m_bAutoUnload; } // Plugin type listing. bool getTypes(qtractorPluginPath& path, qtractorPluginType::Hint typeHint = qtractorPluginType::Any); // Plugin factory method. static qtractorPlugin *createPlugin(qtractorPluginList *pList, const QString& sFilename, unsigned long iIndex = 0, qtractorPluginType::Hint typeHint = qtractorPluginType::Any); private: // Instance variables. bool m_bAutoUnload; }; //---------------------------------------------------------------------------- // qtractorPluginPath -- Plugin path helper. // class qtractorPluginPath { public: // Constructor. qtractorPluginPath(qtractorPluginType::Hint typeHint = qtractorPluginType::Any) : m_typeHint(typeHint) {} // Destructor. ~qtractorPluginPath() { close(); clear(); } // Type-hint accessors... void setTypeHint(qtractorPluginType::Hint typeHint) { m_typeHint = typeHint; } qtractorPluginType::Hint typeHint() const { return m_typeHint; } // Main properties accessors. void setPaths(qtractorPluginType::Hint typeHint, const QString& sPaths); void setPaths(qtractorPluginType::Hint typeHint, const QStringList& paths) { m_paths.insert(typeHint, paths); } QStringList paths(qtractorPluginType::Hint typeHint) const { return m_paths.value(typeHint); } // Executive methods. bool open(); void close(); // Plugin file/types list. const QList& files() const { return m_files; } const QList& types() const { return m_types; } // Plugin type adder. void addType(qtractorPluginType *pType) { m_types.append(pType); } // Type list reset method. void clear() { qDeleteAll(m_types); m_types.clear(); } private: // Instance variables. qtractorPluginType::Hint m_typeHint; QHash m_paths; // Internal plugin file/type list. QList m_files; QList m_types; }; //---------------------------------------------------------------------------- // qtractorPluginParam -- Plugin paramater (control input port) instance. // class qtractorPluginParam { public: // Constructor. qtractorPluginParam(qtractorPlugin *pPlugin, unsigned long iIndex) : m_pPlugin(pPlugin), m_iIndex(iIndex), m_subject(0.0f), m_observer(this), m_iDecimals(-1) {} // Virtual destructor. virtual ~qtractorPluginParam() {} // Main properties accessors. qtractorPlugin *plugin() const { return m_pPlugin; } unsigned long index() const { return m_iIndex; } // Parameter name accessors. void setName(const QString& sName) { m_subject.setName(sName); } const QString& name() const { return m_subject.name(); } // Parameter range hints predicate methods. virtual bool isBoundedBelow() const = 0; virtual bool isBoundedAbove() const = 0; virtual bool isDefaultValue() const = 0; virtual bool isLogarithmic() const = 0; virtual bool isSampleRate() const = 0; virtual bool isInteger() const = 0; virtual bool isToggled() const = 0; virtual bool isDisplay() const = 0; // Current display value. virtual QString display() const { return QString::number(value(), 'f', decimals()); } // Bounding range values. void setMinValue(float fMinValue) { m_subject.setMinValue(fMinValue); } float minValue() const { return m_subject.minValue(); } void setMaxValue(float fMaxValue) { m_subject.setMaxValue(fMaxValue); } float maxValue() const { return m_subject.maxValue(); } // Default value void setDefaultValue(float fDefaultValue) { m_subject.setDefaultValue(fDefaultValue); } float defaultValue() const { return m_subject.defaultValue(); } // Current parameter value. void setValue(float fValue, bool bUpdate); float value() const { return m_observer.value(); } float prevValue() const { return m_observer.prevValue(); } // Parameter update method. void updateValue(float fValue, bool bUpdate); // Reset-to-default method. void reset() { setValue(defaultValue(), true); } // Direct parameter subject value. qtractorSubject *subject() { return &m_subject; } // Specialized observer value. qtractorMidiControlObserver *observer() { return &m_observer; } // Parameter decimals helper (cached). int decimals() const { return m_iDecimals; } private: // Instance variables. qtractorPlugin *m_pPlugin; unsigned long m_iIndex; // Port subject value. qtractorSubject m_subject; // Port observer manager. class Observer : public qtractorMidiControlObserver { public: // Constructor. Observer(qtractorPluginParam *pParam); protected: // Virtual observer updater. void update(bool Update); private: // Instance members. qtractorPluginParam *m_pParam; } m_observer; // Decimals cache. int m_iDecimals; }; //---------------------------------------------------------------------------- // qtractorPlugin -- Plugin instance. // class qtractorPlugin : public qtractorList::Link { public: // Constructors. qtractorPlugin(qtractorPluginList *pList, qtractorPluginType *pType); // Destructor. virtual ~qtractorPlugin(); // DANGER: This one should be used by qtractorPluginList class only! void setPluginList(qtractorPluginList *pList) { m_pList = pList; } // Main properties accessors. qtractorPluginList *list() const { return m_pList; } qtractorPluginType *type() const { return m_pType; } unsigned short instances() const { return m_iInstances; } // Chain helper ones. unsigned int sampleRate() const; unsigned int bufferSize() const; unsigned short channels() const; bool isMidi() const; // Activation methods. void setActivated(bool bActivated); bool isActivated() const { return m_bActivated; } // An accessible list of parameters. typedef QHash Params; const Params& params() const { return m_params; } typedef QHash ParamNames; const ParamNames& paramNames() const { return m_paramNames; } // Parameter list accessor. void addParam(qtractorPluginParam *pParam) { if (pParam->isLogarithmic()) pParam->observer()->setLogarithmic(true); m_params.insert(pParam->index(), pParam); m_paramNames.insert(pParam->name(), pParam); } // Instance capped number of audio ports. unsigned short audioIns() const { return m_pType->audioIns(); } unsigned short audioOuts() const { return m_pType->audioOuts(); } // Plugin state serialization methods. void setValueList(const QStringList& vlist); QStringList valueList() const; // Reset-to-default method. void reset(); // Channel/instance number settler. virtual void setChannels(unsigned short iChannels) = 0; // Do the actual (de)activation. virtual void activate() = 0; virtual void deactivate() = 0; // The main plugin processing procedure. virtual void process( float **ppIBuffer, float **ppOBuffer, unsigned int nframes) = 0; // Parameter update method. virtual void updateParam( qtractorPluginParam */*pParam*/, float /*fValue*/, bool /*bUpdate*/) {} // Specific MIDI instrument selector. virtual void selectProgram(int /*iBank*/, int /*iProg*/) {} // Program (patch) descriptor. struct Program { int bank; int prog; QString name; }; // Provisional program/patch accessor. virtual bool getProgram(int /*iIndex*/, Program& /*program*/) const { return false; } // MIDI continuous controller handler. virtual void setController(int /*iController*/, int /*iValue*/) {} // Plugin configuration handlers. virtual void configure( const QString& /*sKey*/, const QString& /*sValue*/) {} // Plugin configuration/state snapshot. virtual void freezeConfigs() {} virtual void releaseConfigs() {} // Plugin configure realization. virtual void realizeConfigs(); // GUI Editor stuff. virtual void openEditor(QWidget */*pParent*/) {} virtual void closeEditor() {}; virtual void idleEditor() {}; // GUI editor visibility state. virtual void setEditorVisible(bool /*bVisible*/) {} virtual bool isEditorVisible() const { return false; } virtual void setEditorTitle(const QString& sTitle) { m_sEditorTitle = sTitle; } const QString& editorTitle() const { return m_sEditorTitle; } void updateEditorTitle(); // An accessible list of observers. const QList& items() const { return m_items; } // List of observers management. void addItem(qtractorPluginListItem *pItem); void removeItem(qtractorPluginListItem *pItem); void clearItems(); // Special plugin form accessors. bool isFormVisible() const; qtractorPluginForm *form(); // Provisional preset accessors. virtual QStringList presetList() const; virtual bool loadPreset(const QString& /*sPreset*/) { return false; } virtual bool savePreset(const QString& /*sPreset*/) { return false; } virtual bool deletePreset(const QString& /*sPreset*/) { return false; } virtual bool isReadOnlyPreset(const QString& /*sPreset*/) const { return false; } // Plugin default preset name accessor (informational) void setPreset(const QString& sPreset); const QString& preset() const; // Plugin preset group - common identification prefix. QString presetGroup() const; QString presetPrefix() const; // Plugin configuration from/to xml file. bool loadPresetFile(const QString& sFilename); bool savePresetFile(const QString& sFilename); // Plugin parameter lookup. qtractorPluginParam *findParam(unsigned long iIndex) const; qtractorPluginParam *findParamName(const QString& sName) const; // Plugin configuration (CLOB) stuff. typedef QHash Configs; void setConfigs(const Configs& configs) { m_configs = configs; } const Configs& configs() const { return m_configs; } void setConfig(const QString& sKey, const QString& sValue) { m_configs[sKey] = sValue; } const QString& config(const QString& sKey) { return m_configs[sKey]; } // Plugin configuration (types) stuff. typedef QHash ConfigTypes; void setConfigTypes(const ConfigTypes& ctypes) { m_ctypes = ctypes; } const ConfigTypes& configTypes() const { return m_ctypes; } void setConfigType(const QString& sKey, const QString& sType) { m_ctypes[sKey] = sType; } const QString& configType(const QString& sKey) { return m_ctypes[sKey]; } // Plugin parameter values stuff. typedef QHash ValueNames; typedef QHash ValueIndex; typedef struct { ValueNames names; ValueIndex index; } Values; // Plugin parameter/state snapshot. void freezeValues(); void releaseValues(); // Plugin aparameter/state realization. void realizeValues(); void setValues(const Values& values) { m_values = values; } const Values& values() const { return m_values; } // Plugin configure clearance. void clearConfigs() { m_configs.clear(); m_ctypes.clear(); } void clearValues() { m_values.names.clear(); m_values.index.clear(); } // Load plugin configuration/parameter values stuff. static void loadConfigs( QDomElement *pElement, Configs& configs, ConfigTypes& ctypes); static void loadValues(QDomElement *pElement, Values& values); // Save plugin configuration/parameter values stuff. void saveConfigs(QDomDocument *pDocument, QDomElement *pElement); void saveValues(QDomDocument *pDocument, QDomElement *pElement); // Load/save plugin parameter controllers (MIDI). static void loadControllers( QDomElement *pElement, qtractorMidiControl::Controllers& controllers); void saveControllers( qtractorDocument *pDocument, QDomElement *pElement) const; // Map/realize plugin parameter controllers (MIDI). void mapControllers(const qtractorMidiControl::Controllers& controllers); // Plugin automation curve serialization methods. static void loadCurveFile( QDomElement *pElement, qtractorCurveFile *pCurveFile); void saveCurveFile(qtractorDocument *pDocument, QDomElement *pElement, qtractorCurveFile *pCurveFile) const; void applyCurveFile (qtractorCurveFile *pCurveFile) const; // Direct access parameter accessors. qtractorPluginParam *directAccessParam() const; void setDirectAccessParamIndex(long iDirectAccessParamIndex); long directAccessParamIndex() const; bool isDirectAccessParam() const; void updateDirectAccessParam(); // Parameter update executive. void updateParamValue(unsigned long iIndex, float fValue, bool bUpdate); protected: // Instance number settler. void setInstances(unsigned short iInstances); private: // Instance variables. qtractorPluginList *m_pList; qtractorPluginType *m_pType; unsigned short m_iInstances; bool m_bActivated; // List of input control ports (parameters). Params m_params; // List of parameters (by name). ParamNames m_paramNames; // An accessible list of observers. QList m_items; // The plugin form reference. qtractorPluginForm *m_pForm; QString m_sPreset; // GUI editor stuff. QString m_sEditorTitle; // Plugin configuration (CLOB) stuff. Configs m_configs; // Plugin configuration (type) stuff. ConfigTypes m_ctypes; // Plugin parameter values (part of configuration). Values m_values; // Direct access parameter, if any. long m_iDirectAccessParamIndex; }; //---------------------------------------------------------------------------- // qtractorPluginList -- Plugin chain list instance. // class qtractorPluginList : public qtractorList { public: // Plugin-list type flags. enum Flags { // Basic flags. Audio = 0, Midi = 1, Track = 0, Bus = 2, Out = 0, In = 4, // Composite helper flags. AudioTrack = Audio | Track, AudioBus = Audio | Bus, AudioInBus = Audio | Bus | In, AudioOutBus = Audio | Bus | Out, MidiTrack = Midi | Track, MidiBus = Midi | Bus, MidiInBus = Midi | Bus | In, MidiOutBus = Midi | Bus | Out }; // Constructor. qtractorPluginList( unsigned short iChannels, unsigned int iBufferSize, unsigned int iSampleRate, unsigned int iFlags); // Destructor. ~qtractorPluginList(); // The title to show up on plugin forms... void setName(const QString& sName); const QString& name() const { return m_sName; } // Main-parameters accessor. void setBuffer( unsigned short iChannels, unsigned int iBufferSize, unsigned int iSampleRate, unsigned int iFlags); // Reset and (re)activate all plugin chain. void resetBuffer(); // Brainless accessors. unsigned short channels() const { return m_iChannels; } unsigned int sampleRate() const { return m_iSampleRate; } unsigned int bufferSize() const { return m_iBufferSize; } unsigned int flags() const { return m_iFlags; } // Brainless helper. bool isMidi() const { return (m_iFlags & Midi); } // Specific automation curve list accessor. qtractorCurveList *curveList() const { return m_pCurveList; } // Specific MIDI manager accessor. qtractorMidiManager *midiManager() const { return m_pMidiManager; } // Special activation methods. bool isActivatedAll() const; void updateActivated(bool bActivated); unsigned int activated() const { return m_iActivated; } // Guarded plugin methods. void addPlugin(qtractorPlugin *pPlugin); void insertPlugin(qtractorPlugin *pPlugin, qtractorPlugin *pNextPlugin); void movePlugin(qtractorPlugin *pPlugin, qtractorPlugin *pNextPlugin); void removePlugin(qtractorPlugin *pPlugin); // Clone/copy plugin method. qtractorPlugin *copyPlugin(qtractorPlugin *pPlugin); // An accessible list of views. const QList& views() const { return m_views; } // list of views management. void addView(qtractorPluginListView *pView); void removeView(qtractorPluginListView *pView); // The meta-main audio-processing plugin-chain procedure. void process(float **ppBuffer, unsigned int nframes); // Document element methods. bool loadElement(qtractorDocument *pDocument, QDomElement *pElement); bool saveElement(qtractorDocument *pDocument, QDomElement *pElement); // MIDI manager deferred load/cache specifics. void setMidiBank(int iMidiBank) { m_iMidiBank = iMidiBank; } int midiBank() const { return m_iMidiBank; } void setMidiProg(int iMidiProg) { m_iMidiProg = iMidiProg; } int midiProg() const { return m_iMidiProg; } void setAudioOutputBus(bool bAudioOutputBus) { m_bAudioOutputBus = bAudioOutputBus; } bool isAudioOutputBus() const { return m_bAudioOutputBus; } void setAudioOutputAutoConnect(bool bAudioOutputAutoConnect) { m_bAudioOutputAutoConnect = bAudioOutputAutoConnect; } bool isAudioOutputAutoConnect() const { return m_bAudioOutputAutoConnect; } // MIDI bank/program observable subject. class MidiProgramSubject : public qtractorSubject { public: // Constructor. MidiProgramSubject(int iBank, int iProg) : qtractorSubject(valueFromProgram(iBank, iProg)) { setMaxValue(valueFromProgram(0x3fff, 0x7f)); } // Bank/program setter. void setProgram(int iBank, int iProg) { setValue(valueFromProgram(iBank, iProg)); } // Bank/program getters. int bank() const { return bankFromValue(value()); } int prog() const { return progFromValue(value()); } protected: // Bank/program value helpers. static float valueFromProgram(int iBank, int iProg) { if (iBank < 0) iBank = 0; if (iProg < 0) iProg = 0; return float((iBank << 7) | (iProg & 0x7f)); } static int bankFromValue(float fValue) { return ((int(fValue) >> 7) & 0x3fff); } static int progFromValue(float fValue) { return (int(fValue) & 0x7f); } }; MidiProgramSubject *midiProgramSubject() const { return m_pMidiProgramSubject; } private: // Instance variables. unsigned short m_iChannels; unsigned int m_iBufferSize; unsigned int m_iSampleRate; unsigned int m_iFlags; // Activation state. unsigned int m_iActivated; // Plugin-chain name. QString m_sName; // An accessible list of observers. QList m_views; // Specific automation curve list accessor. qtractorCurveList *m_pCurveList; // Specific MIDI manager. qtractorMidiManager *m_pMidiManager; int m_iMidiBank; int m_iMidiProg; bool m_bAudioOutputBus; bool m_bAudioOutputAutoConnect; qtractorBus::ConnectList m_audioOutputs; // Internal running buffer chain references. float **m_pppBuffers[2]; // MIDI bank/program observable subject. MidiProgramSubject *m_pMidiProgramSubject; }; #endif // __qtractorPlugin_h // end of qtractorPlugin.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditSelect.h0000644000175000001440000000012312073012112022011 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134669.93708 30 ctime=1381134669.937080095 qtractor-0.5.11/src/qtractorMidiEditSelect.h0000644000175000001440000000600312073012112021277 0ustar00rncbcusers00000000000000// qtractorMidiEditSelect.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiEditSelect_h #define __qtractorMidiEditSelect_h #include #include // Forward declarations. class qtractorMidiEvent; //------------------------------------------------------------------------- // qtractorMidiEditSelect -- MIDI event selection capsule. class qtractorMidiEditSelect { public: // Constructor. qtractorMidiEditSelect(); // Default destructor. ~qtractorMidiEditSelect(); // Selection item struct. struct Item { // Item constructor. Item(const QRect& re, const QRect& rv, unsigned long dt = 0) : rectEvent(re), rectView(rv), delta(dt), flags(1) {} // Item members. QRect rectEvent; QRect rectView; unsigned long delta; unsigned int flags; }; typedef QHash ItemList; // Event selection item lookup. Item *findItem(qtractorMidiEvent *pEvent); // Event insertion method. void addItem(qtractorMidiEvent *pEvent, const QRect& rectEvent, const QRect& rectView, unsigned long iDeltaTime = 0); // Event selection method. void selectItem(qtractorMidiEvent *pEvent, const QRect& rectEvent, const QRect& rectView, bool bSelect = true, bool bToggle = false); // Item update method (visual rects). void updateItem ( Item *pItem ) { m_rectEvent = m_rectEvent.united(pItem->rectEvent); m_rectView = m_rectView.united(pItem->rectView); } // The united selection rectangle. const QRect& rectEvent() const { return m_rectEvent; } const QRect& rectView() const { return m_rectView; } // Selection list accessor. const ItemList& items() const { return m_items; } // Selection update method. void update(bool bCommit); // Selection commit method. void commit(); // Reset event selection. void clear(); qtractorMidiEvent *anchorEvent() const { return m_pAnchorEvent; } private: // The clip selection list. ItemList m_items; // The united selection rectangle. QRect m_rectEvent; QRect m_rectView; // The most probable anchor event. qtractorMidiEvent *m_pAnchorEvent; }; #endif // __qtractorMidiEditSelect_h // end of qtractorMidiEditSelect.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorEngine.cpp0000644000175000001440000000012212217361266020741 xustar000000000000000026 mtime=1379787446.61859 26 atime=1381134666.95108 30 ctime=1381134666.952080048 qtractor-0.5.11/src/qtractorEngine.cpp0000644000175000001440000005455512217361266020247 0ustar00rncbcusers00000000000000// qtractorEngine.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorEngine.h" #include "qtractorSession.h" #include "qtractorSessionCursor.h" #include "qtractorMidiControlObserver.h" #include "qtractorEngineCommand.h" #include "qtractorMainForm.h" #include "qtractorMonitor.h" #include "qtractorMeter.h" #include "qtractorMixer.h" #include "qtractorDocument.h" #include "qtractorCurveFile.h" #include #include //---------------------------------------------------------------------- // class qtractorEngine -- Abstract device engine instance (singleton). // // Constructor. qtractorEngine::qtractorEngine ( qtractorSession *pSession, qtractorTrack::TrackType syncType ) { m_pSession = pSession; m_pSessionCursor = m_pSession->createSessionCursor(0, syncType); m_bActivated = false; m_bPlaying = false; m_buses.setAutoDelete(true); m_busesEx.setAutoDelete(false); } // Destructor. qtractorEngine::~qtractorEngine (void) { clear(); if (m_pSessionCursor) delete m_pSessionCursor; } // Buses list clear. void qtractorEngine::clear (void) { m_buses.clear(); m_busesEx.clear(); } // Session accessor. qtractorSession *qtractorEngine::session (void) const { return m_pSession; } // Session cursor accessor. qtractorSessionCursor *qtractorEngine::sessionCursor (void) const { return m_pSessionCursor; } // Engine type accessor. qtractorTrack::TrackType qtractorEngine::syncType (void) const { return m_pSessionCursor->syncType(); } // Client name accessor. const QString& qtractorEngine::clientName (void) const { return m_pSession->clientName(); } // Activation status accessor. bool qtractorEngine::isActivated(void) const { return m_bActivated; } // Buses list managament methods. const qtractorList& qtractorEngine::buses (void) const { return m_buses; } // Add a bus to a device engine. void qtractorEngine::addBus ( qtractorBus *pBus ) { m_buses.append(pBus); } // Remove a bus from a device. void qtractorEngine::removeBus ( qtractorBus *pBus ) { m_buses.remove(pBus); } // Find a device bus by name qtractorBus *qtractorEngine::findBus ( const QString& sBusName ) const { for (qtractorBus *pBus = m_buses.first(); pBus; pBus = pBus->next()) { if (pBus->busName() == sBusName) return pBus; } return NULL; } // Find an input bus by name qtractorBus *qtractorEngine::findInputBus ( const QString& sInputBusName ) const { for (qtractorBus *pBus = m_buses.first(); pBus; pBus = pBus->next()) { if ((pBus->busMode() & qtractorBus::Input) && pBus->busName() == sInputBusName) return pBus; } return NULL; } // Find an output bus by name qtractorBus *qtractorEngine::findOutputBus ( const QString& sOutputBusName ) const { for (qtractorBus *pBus = m_buses.first(); pBus; pBus = pBus->next()) { if ((pBus->busMode() & qtractorBus::Output) && pBus->busName() == sOutputBusName) return pBus; } return NULL; } // Exo-buses list managament methods. const qtractorList& qtractorEngine::busesEx (void) const { return m_busesEx; } // Add an exo-bus to a device engine. void qtractorEngine::addBusEx ( qtractorBus *pBus ) { m_busesEx.append(pBus); } // Remove an exo-bus from a device. void qtractorEngine::removeBusEx ( qtractorBus *pBus ) { for (qtractorBus *pBusEx = m_busesEx.first(); pBusEx; pBusEx = pBusEx->next()) { if (pBusEx == pBus) { m_busesEx.remove(pBus); break; } } } // Find a exo-device bus by name qtractorBus *qtractorEngine::findBusEx ( const QString& sBusName ) const { for (qtractorBus *pBusEx = m_busesEx.first(); pBusEx; pBusEx = pBusEx->next()) { if (pBusEx->busName() == sBusName) return pBusEx; } return NULL; } // Device engine activation method. bool qtractorEngine::open (void) { // Update the session cursor tracks... m_pSessionCursor->resetClips(); m_pSessionCursor->reset(); // Open all buses (allocated and register ports...) qtractorBus *pBus = m_buses.first(); while (pBus) { if (!pBus->open()) return false; pBus = pBus->next(); } // Nows time to activate... if (!activate()) return false; // We're now ready and running... m_bActivated = true; return true; } // Device engine deactivation method. void qtractorEngine::close (void) { // Save current activation state... bool bActivated = m_bActivated; // We're stopping now... m_bActivated = false; if (bActivated) { // Deactivate the derived engine first. deactivate(); // Close all dependant buses... for (qtractorBus *pBus = m_buses.first(); pBus; pBus = pBus->next()) { pBus->close(); } } // Clean-up everything, finally clean(); } // Engine state methods. void qtractorEngine::setPlaying ( bool bPlaying ) { if (bPlaying && !m_bPlaying) { m_pSessionCursor->setFrameTime(0); m_bPlaying = start(); } else if (!bPlaying && m_bPlaying) { m_bPlaying = false; stop(); } } bool qtractorEngine::isPlaying(void) const { return m_bPlaying; } // Retrieve/restore all connections, on all buses. // return the total number of effective (re)connection attempts... int qtractorEngine::updateConnects (void) { // It must be activated, sure... if (!isActivated()) return 0; // On all dependable buses... int iUpdate = 0; iUpdate += updateConnects(m_buses.first()); iUpdate += updateConnects(m_busesEx.first()); // Done. return iUpdate; } int qtractorEngine::updateConnects ( qtractorBus *pBus ) { int iUpdate = 0; for (; pBus; pBus = pBus->next()) { // Input connections... if (pBus->busMode() & qtractorBus::Input) { iUpdate += pBus->updateConnects( qtractorBus::Input, pBus->inputs(), true); } // Output connections... if (pBus->busMode() & qtractorBus::Output) { iUpdate += pBus->updateConnects( qtractorBus::Output, pBus->outputs(), true); } } return iUpdate; } // Clear/reset all pending connections. void qtractorEngine::clearConnects (void) { qtractorBus *pBus; pBus = m_buses.first(); for (; pBus; pBus = pBus->next()) { pBus->outputs().clear(); pBus->inputs().clear(); } pBus = m_busesEx.first(); for (; pBus; pBus = pBus->next()) { pBus->outputs().clear(); pBus->inputs().clear(); } } //---------------------------------------------------------------------- // class qtractorBus -- Managed ALSA sequencer port set // // Constructor. qtractorBus::qtractorBus ( qtractorEngine *pEngine, const QString& sBusName, BusMode busMode, bool bMonitor ) { m_pEngine = pEngine; m_sBusName = sBusName; m_busMode = busMode; if (m_busMode & Ex) { m_pMonitorSubject = NULL; } else { m_pMonitorSubject = new qtractorSubject(); m_pMonitorSubject->setToggled(true); } if (m_busMode & Ex) { m_pMonitorObserver = NULL; } else { m_pMonitorObserver = new qtractorMidiControlObserver(m_pMonitorSubject); m_pMonitorObserver->setValue(bMonitor ? 1.0f : 0.0f); } } // Destructor. qtractorBus::~qtractorBus (void) { if (m_pMonitorObserver) delete m_pMonitorObserver; if (m_pMonitorSubject) delete m_pMonitorSubject; qDeleteAll(m_controllers_out); m_controllers_out.clear(); qDeleteAll(m_controllers_in); m_controllers_in.clear(); } // Engine accessor. qtractorEngine *qtractorBus::engine (void) const { return m_pEngine; } // Bus type accessor. qtractorTrack::TrackType qtractorBus::busType (void) const { return (m_pEngine ? m_pEngine->syncType() : qtractorTrack::None); } // Bus name accessors. void qtractorBus::setBusName ( const QString& sBusName ) { m_sBusName = sBusName; if (m_pMonitorSubject) m_pMonitorSubject->setName(QObject::tr("%1 Monitor").arg(sBusName)); } const QString& qtractorBus::busName (void) const { return m_sBusName; } // Bus mode property accessor. void qtractorBus::setBusMode ( qtractorBus::BusMode busMode ) { m_busMode = busMode; updateBusMode(); } qtractorBus::BusMode qtractorBus::busMode (void) const { return m_busMode; } // Pass-thru mode accessor. void qtractorBus::setMonitor ( bool bMonitor ) { if (m_pMonitorObserver) m_pMonitorObserver->setValue(bMonitor ? 1.0f : 0.0f); } bool qtractorBus::isMonitor (void) const { return (m_pMonitorSubject ? (m_pMonitorSubject->value() > 0.0f) : false); } // Bus state (monitor) button setup. qtractorSubject *qtractorBus::monitorSubject (void) const { return m_pMonitorSubject; } qtractorMidiControlObserver *qtractorBus::monitorObserver (void) const { return m_pMonitorObserver; } // Bus state (monitor) notifier (proto-slot). void qtractorBus::monitorChangeNotify ( bool bOn ) { #ifdef CONFIG_DEBUG qDebug("qtractorBus[%p]::monitorChangeNotify(%d)", this, int(bOn)); #endif // Put it in the form of an undoable command... qtractorSession *pSession = m_pEngine->session(); if (pSession) pSession->execute( new qtractorBusMonitorCommand(this, bOn)); } // Load bus (monitor, gain, pan) controllers (MIDI). void qtractorBus::loadControllers ( QDomElement *pElement, BusMode busMode ) { if (busMode & Input) qtractorMidiControl::loadControllers(pElement, m_controllers_in); else qtractorMidiControl::loadControllers(pElement, m_controllers_out); } // Save bus (monitor, gain, pan) controllers (MIDI). void qtractorBus::saveControllers ( qtractorDocument *pDocument, QDomElement *pElement, BusMode busMode ) const { if (m_pMonitorObserver == NULL) return; qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; qtractorMixer *pMixer = pMainForm->mixer(); if (pMixer == NULL) return; qtractorMonitor *pMonitor = NULL; qtractorMixerRack *pMixerRack = NULL; if (busMode & Input) { pMonitor = monitor_in(); pMixerRack = pMixer->inputRack(); } else { pMonitor = monitor_out(); pMixerRack = pMixer->outputRack(); } qtractorMixerStrip *pMixerStrip = pMixerRack->findStrip(pMonitor); if (pMixerStrip == NULL) return; qtractorMidiControl::Controllers controllers; if (busMode & Input) // It suffices for Duplex... if (pMidiControl->isMidiObserverMapped(m_pMonitorObserver)) { qtractorMidiControl::Controller *pController = new qtractorMidiControl::Controller; pController->name = m_pMonitorObserver->subject()->name(); pController->index = 0; // 0=MonitorObserver pController->ctype = m_pMonitorObserver->type(); pController->channel = m_pMonitorObserver->channel(); pController->param = m_pMonitorObserver->param(); pController->logarithmic = m_pMonitorObserver->isLogarithmic(); pController->feedback = m_pMonitorObserver->isFeedback(); pController->invert = m_pMonitorObserver->isInvert(); pController->hook = m_pMonitorObserver->isHook(); controllers.append(pController); } qtractorMidiControlObserver *pPanObserver = pMixerStrip->meter()->panningObserver(); if (pMidiControl->isMidiObserverMapped(pPanObserver)) { qtractorMidiControl::Controller *pController = new qtractorMidiControl::Controller; pController->name = pPanObserver->subject()->name(); pController->index = 1; // 1=PanObserver pController->ctype = pPanObserver->type(); pController->channel = pPanObserver->channel(); pController->param = pPanObserver->param(); pController->logarithmic = pPanObserver->isLogarithmic(); pController->feedback = pPanObserver->isFeedback(); pController->invert = pPanObserver->isInvert(); pController->hook = pPanObserver->isHook(); controllers.append(pController); } qtractorMidiControlObserver *pGainObserver = pMixerStrip->meter()->gainObserver(); if (pMidiControl->isMidiObserverMapped(pGainObserver)) { qtractorMidiControl::Controller *pController = new qtractorMidiControl::Controller; pController->name = pGainObserver->subject()->name(); pController->index = 2; // 2=GainObserver pController->ctype = pGainObserver->type(); pController->channel = pGainObserver->channel(); pController->param = pGainObserver->param(); pController->logarithmic = pGainObserver->isLogarithmic(); pController->feedback = pGainObserver->isFeedback(); pController->invert = pGainObserver->isInvert(); pController->hook = pGainObserver->isHook(); controllers.append(pController); } qtractorMidiControl::saveControllers(pDocument, pElement, controllers); qDeleteAll(controllers); controllers.clear(); } // Map bus (monitor, gain, pan) controllers (MIDI). void qtractorBus::mapControllers ( BusMode busMode ) { if (m_pMonitorObserver == NULL) return; qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; qtractorMixer *pMixer = pMainForm->mixer(); if (pMixer == NULL) return; qtractorMonitor *pMonitor = NULL; qtractorMixerRack *pMixerRack = NULL; if (busMode & Input) { pMonitor = monitor_in(); pMixerRack = pMixer->inputRack(); } else { pMonitor = monitor_out(); pMixerRack = pMixer->outputRack(); } qtractorMixerStrip *pMixerStrip = pMixerRack->findStrip(pMonitor); if (pMixerStrip == NULL) return; qtractorMidiControl::Controllers& controllers = (busMode & Input ? m_controllers_in : m_controllers_out); QListIterator iter(controllers); while (iter.hasNext()) { qtractorMidiControl::Controller *pController = iter.next(); qtractorMidiControlObserver *pObserver = NULL; switch (pController->index) { case 0: // 0=MonitorObserver pObserver = monitorObserver(); break; case 1: // 1=PanObserver pObserver = pMixerStrip->meter()->panningObserver(); break; case 2: // 2=GainObserver pObserver = pMixerStrip->meter()->gainObserver(); break; } if (pObserver) { pObserver->setType(pController->ctype); pObserver->setChannel(pController->channel); pObserver->setParam(pController->param); pObserver->setLogarithmic(pController->logarithmic); pObserver->setFeedback(pController->feedback); pObserver->setInvert(pController->invert); pObserver->setHook(pController->hook); pMidiControl->mapMidiObserver(pObserver); } } qDeleteAll(controllers); controllers.clear(); } // Load bus automation curves (monitor, gain, pan). void qtractorBus::loadCurveFile ( QDomElement *pElement, BusMode /*busMode*/, qtractorCurveFile *pCurveFile ) { if (pCurveFile) pCurveFile->load(pElement); } // Save bus automation curves (monitor, gain, pan). void qtractorBus::saveCurveFile ( qtractorDocument *pDocument, QDomElement *pElement, BusMode busMode, qtractorCurveFile *pCurveFile ) const { if (m_pMonitorSubject == NULL) return; if (pCurveFile == NULL) return; qtractorCurveList *pCurveList = pCurveFile->list(); if (pCurveList == NULL) return; qtractorSession *pSession = m_pEngine->session(); if (pSession == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; QString sBusName(busName()); qtractorMonitor *pMonitor = NULL; if (busMode & Input) { pMonitor = monitor_in(); sBusName += "_in"; } else { pMonitor = monitor_out(); sBusName += "_out"; } if (pMonitor == NULL) return; pCurveFile->clear(); pCurveFile->setBaseDir(pSession->sessionDir()); qtractorCurve *pCurve; if (busMode & Input) { // It suffices for Duplex... pCurve = monitorSubject()->curve(); if (pCurve) { qtractorCurveFile::Item *pCurveItem = new qtractorCurveFile::Item; pCurveItem->name = pCurve->subject()->name(); pCurveItem->index = 0; // 0=MonitorSubject pCurveItem->ctype = qtractorMidiEvent::CONTROLLER; pCurveItem->channel = 0; pCurveItem->param = 80; // 80=General Purpose Button 1 (on/off) pCurveItem->mode = pCurve->mode(); pCurveItem->process = pCurve->isProcess(); pCurveItem->capture = pCurve->isCapture(); pCurveItem->locked = pCurve->isLocked(); pCurveItem->logarithmic = pCurve->isLogarithmic(); pCurveItem->color = pCurve->color(); pCurveItem->subject = pCurve->subject(); pCurveFile->addItem(pCurveItem); }} pCurve = pMonitor->panningSubject()->curve(); if (pCurve) { qtractorCurveFile::Item *pCurveItem = new qtractorCurveFile::Item; pCurveItem->name = pCurve->subject()->name(); pCurveItem->index = 1; // 1=PanningSubject pCurveItem->ctype = qtractorMidiEvent::CONTROLLER; pCurveItem->channel = 0; pCurveItem->param = 10; // 10=Pan Position (coarse) pCurveItem->mode = pCurve->mode(); pCurveItem->process = pCurve->isProcess(); pCurveItem->capture = pCurve->isCapture(); pCurveItem->locked = pCurve->isLocked(); pCurveItem->logarithmic = pCurve->isLogarithmic(); pCurveItem->color = pCurve->color(); pCurveItem->subject = pCurve->subject(); pCurveFile->addItem(pCurveItem); } pCurve = pMonitor->gainSubject()->curve(); if (pCurve) { qtractorCurveFile::Item *pCurveItem = new qtractorCurveFile::Item; pCurveItem->name = pCurve->subject()->name(); pCurveItem->index = 2; // 2=GainSubject pCurveItem->ctype = qtractorMidiEvent::CONTROLLER; pCurveItem->channel = 0; pCurveItem->param = 7; // 7=Volume (coarse) pCurveItem->mode = pCurve->mode(); pCurveItem->process = pCurve->isProcess(); pCurveItem->capture = pCurve->isCapture(); pCurveItem->logarithmic = pCurve->isLogarithmic(); pCurveItem->locked = pCurve->isLocked(); pCurveItem->color = pCurve->color(); pCurveItem->subject = pCurve->subject(); pCurveFile->addItem(pCurveItem); } if (pCurveFile->isEmpty()) return; const QString sBaseName(sBusName + "_curve"); int iClipNo = (pCurveFile->filename().isEmpty() ? 0 : 1); pCurveFile->setFilename(pSession->createFilePath(sBaseName, "mid", iClipNo)); pCurveFile->save(pDocument, pElement, pSession->timeScale()); } // Apply bus automation curves (monitor, gain, pan). void qtractorBus::applyCurveFile ( BusMode busMode, qtractorCurveFile *pCurveFile ) const { if (m_pMonitorSubject == NULL) return; if (pCurveFile == NULL) return; if (pCurveFile->items().isEmpty()) return; qtractorCurveList *pCurveList = pCurveFile->list(); if (pCurveList == NULL) return; qtractorSession *pSession = m_pEngine->session(); if (pSession == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; qtractorMonitor *pMonitor = NULL; if (busMode & Input) pMonitor = monitor_in(); else pMonitor = monitor_out(); if (pMonitor == NULL) return; pCurveFile->setBaseDir(pSession->sessionDir()); QListIterator iter(pCurveFile->items()); while (iter.hasNext()) { qtractorCurveFile::Item *pCurveItem = iter.next(); switch (pCurveItem->index) { case 0: // 0=MonitorSubject pCurveItem->subject = monitorSubject(); break; case 1: // 1=PanSubject pCurveItem->subject = pMonitor->panningSubject(); break; case 2: // 2=GainSubject pCurveItem->subject = pMonitor->gainSubject(); break; } } pCurveFile->apply(pSession->timeScale()); } // Document element methods. bool qtractorBus::loadConnects ( ConnectList& connects, qtractorDocument * /*pDocument*/, QDomElement *pElement ) { connects.clear(); // Load map items... for (QDomNode nChild = pElement->firstChild(); !nChild.isNull(); nChild = nChild.nextSibling()) { // Convert node to element... QDomElement eChild = nChild.toElement(); if (eChild.isNull()) continue; // Load (other) track properties.. if (eChild.tagName() == "connect") { ConnectItem *pItem = new ConnectItem; pItem->index = eChild.attribute("index").toUShort(); for (QDomNode nConnect = eChild.firstChild(); !nConnect.isNull(); nConnect = nConnect.nextSibling()) { // Convert connect node to element... QDomElement eConnect = nConnect.toElement(); if (eConnect.isNull()) continue; // Add this one to map... if (eConnect.tagName() == "client") { const QString& sClient = eConnect.text(); const QString& sClientName = sClient.section(':', 1); if (sClientName.isEmpty()) { pItem->clientName = sClient; } else { // pItem->client = sClient.section(':', 0, 0).toInt(); pItem->clientName = sClientName; } } else if (eConnect.tagName() == "port") { const QString& sPort = eConnect.text(); const QString& sPortName = sPort.section(':', 1); if (sPortName.isEmpty()) { pItem->portName = sPort; } else { // pItem->port = sPort.section(':', 0, 0).toInt(); pItem->portName = sPortName; } } } connects.append(pItem); } } return true; } bool qtractorBus::saveConnects ( ConnectList& connects, qtractorDocument *pDocument, QDomElement *pElement ) { // Save connect items... QListIterator iter(connects); while (iter.hasNext()) { ConnectItem *pItem = iter.next(); QDomElement eItem = pDocument->document()->createElement("connect"); eItem.setAttribute("index", QString::number(pItem->index)); QString sClient; if (pItem->client >= 0) sClient += QString::number(pItem->client) + ':'; sClient += pItem->clientName; pDocument->saveTextElement("client", sClient, &eItem); QString sPort; if (pItem->port >= 0) sPort += QString::number(pItem->port) + ':'; sPort += pItem->portName; pDocument->saveTextElement("port", sPort, &eItem); pElement->appendChild(eItem); } return true; } // Bus mode textual helper methods. qtractorBus::BusMode qtractorBus::busModeFromText ( const QString& sText ) { BusMode busMode = None; if (sText == "input") busMode = Input; else if (sText == "output") busMode = Output; else if (sText == "duplex") busMode = Duplex; return busMode; } QString qtractorBus::textFromBusMode ( BusMode busMode ) { QString sText; switch (busMode) { case Input: sText = "input"; break; case Output: sText = "output"; break; case Duplex: sText = "duplex"; break; case None: default: sText = "none"; break; } return sText; } // end of qtractorEngine.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorOptions.h0000644000175000001440000000012112203713015020617 xustar000000000000000025 mtime=1376753165.6215 26 atime=1381134669.93708 30 ctime=1381134669.937080095 qtractor-0.5.11/src/qtractorOptions.h0000644000175000001440000001514412203713015020115 0ustar00rncbcusers00000000000000// qtractorOptions.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorOptions_h #define __qtractorOptions_h #include #include class QWidget; class QComboBox; class QSplitter; class QObject; //------------------------------------------------------------------------- // qtractorOptions - Prototype settings class (singleton). // class qtractorOptions { public: // Constructor. qtractorOptions(); // Default destructor. ~qtractorOptions(); // The settings object accessor. QSettings& settings(); // Explicit I/O methods. void loadOptions(); void saveOptions(); // Command line arguments parser. bool parse_args(const QStringList& args); // Command line usage helper. void print_usage(const QString& arg0); // Startup supplied session uuid. QString sSessionId; // Startup supplied session file. QString sSessionFile; // Display options... QString sMessagesFont; bool bMessagesLimit; int iMessagesLimitLines; bool bConfirmRemove; bool bStdoutCapture; bool bCompletePath; bool bPeakAutoRemove; bool bKeepToolsOnTop; int iDisplayFormat; int iBaseFontSize; // Logging options... bool bMessagesLog; QString sMessagesLogPath; // View options... bool bMenubar; bool bStatusbar; bool bFileToolbar; bool bEditToolbar; bool bTrackToolbar; bool bViewToolbar; bool bOptionsToolbar; bool bTransportToolbar; bool bTimeToolbar; bool bThumbToolbar; int iZoomMode; // Transport options... bool bMetronome; bool bFollowPlayhead; bool bAutoBackward; bool bContinuePastEnd; int iTransportMode; // Audio options... QString sAudioCaptureExt; int iAudioCaptureType; int iAudioCaptureFormat; int iAudioCaptureQuality; int iAudioResampleType; bool bAudioAutoTimeStretch; bool bAudioWsolaTimeStretch; bool bAudioWsolaQuickSeek; bool bAudioPlayerBus; bool bAudioMetroBus; bool bAudioMetronome; bool bAudioMasterAutoConnect; bool bAudioPlayerAutoConnect; bool bAudioMetroAutoConnect; // Audio metronome parameters. QString sMetroBarFilename; float fMetroBarGain; QString sMetroBeatFilename; float fMetroBeatGain; // MIDI options... int iMidiCaptureFormat; int iMidiCaptureQuantize; int iMidiQueueTimer; bool bMidiPlayerBus; bool bMidiControlBus; bool bMidiMetroBus; bool bMidiMetronome; int iMidiMmcDevice; int iMidiMmcMode; int iMidiSppMode; int iMidiClockMode; // MIDI Metronome parameters. int iMetroChannel; int iMetroBarNote; int iMetroBarVelocity; int iMetroBarDuration; int iMetroBeatNote; int iMetroBeatVelocity; int iMetroBeatDuration; // Default options... QString sSessionDir; QString sAudioDir; QString sMidiDir; QString sPresetDir; QString sInstrumentDir; QString sMidiControlDir; QString sMidiSysexDir; // Session options. QString sSessionExt; bool bSessionTemplate; QString sSessionTemplatePath; bool bSessionBackup; int iSessionBackupMode; bool bAutoMonitor; int iSnapPerBeat; float fTempo; int iBeatsPerBar; int iBeatDivisor; int iLoopRecordingMode; // Paste-repeat convenient defaults. int iPasteRepeatCount; bool bPasteRepeatPeriod; // Plugin search string. QString sPluginSearch; int iPluginType; bool bPluginActivate; // Automation curve mode default. int iCurveMode; // Edit-range options. int iEditRangeOptions; // Mouse modifier options. bool bMidButtonModifier; // Plug-in paths. QStringList ladspaPaths; QStringList dssiPaths; QStringList vstPaths; QStringList lv2Paths; QString sLv2PresetDir; // Plug-in instrument options. bool bAudioOutputBus; bool bAudioOutputAutoConnect; // Plug-in GUI options. bool bOpenEditor; // VST dummy plugin scan option. bool bDummyVstScan; // The instrument file list. QStringList instrumentFiles; // The MIDI controllers file list. QStringList midiControlFiles; // Recent file list. int iMaxRecentFiles; QStringList recentFiles; // Tracks view options... int iTrackViewSelectMode; bool bTrackViewDropSpan; bool bTrackViewSnapZebra; bool bTrackViewSnapGrid; bool bTrackViewToolTips; bool bTrackViewCurveEdit; // MIDI Editor options... bool bMidiMenubar; bool bMidiStatusbar; bool bMidiFileToolbar; bool bMidiEditToolbar; bool bMidiViewToolbar; bool bMidiTransportToolbar; bool bMidiScaleToolbar; bool bMidiNoteDuration; bool bMidiNoteColor; bool bMidiValueColor; bool bMidiPreview; bool bMidiFollow; bool bMidiEditMode; bool bMidiEditModeDraw; int iMidiZoomMode; int iMidiHorizontalZoom; int iMidiVerticalZoom; int iMidiSnapPerBeat; bool bMidiSnapZebra; bool bMidiSnapGrid; bool bMidiToolTips; int iMidiSnapToScaleKey; int iMidiSnapToScaleType; // Meter colors. QStringList audioMeterColors; QStringList midiMeterColors; // Widget geometry persistence helper prototypes. void saveWidgetGeometry(QWidget *pWidget, bool bVisible = false); void loadWidgetGeometry(QWidget *pWidget, bool bVisible = false); // Combo box history persistence helper prototypes. void loadComboBoxHistory(QComboBox *pComboBox, int iLimit = 8); void saveComboBoxHistory(QComboBox *pComboBox, int iLimit = 8); // Splitter widget sizes persistence helper methods. void loadSplitterSizes(QSplitter *pSplitter, QList& sizes); void saveSplitterSizes(QSplitter *pSplitter); // Action shortcut persistence helper methos. void loadActionShortcuts(QObject *pObject); void saveActionShortcuts(QObject *pObject); // Singleton instance accessor. static qtractorOptions *getInstance(); private: // Settings member variables. QSettings m_settings; // The singleton instance. static qtractorOptions *g_pOptions; }; #endif // __qtractorOptions_h // end of qtractorOptions.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorEditRangeForm.h0000644000175000001440000000012312166134117021664 xustar000000000000000027 mtime=1373157455.942698 26 atime=1381134669.93608 30 ctime=1381134669.936080095 qtractor-0.5.11/src/qtractorEditRangeForm.h0000644000175000001440000000526312166134117021161 0ustar00rncbcusers00000000000000// qtractorEditRangeForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorEditRangeForm_h #define __qtractorEditRangeForm_h #include "ui_qtractorEditRangeForm.h" // Forward declarations. class qtractorTimeScale; //---------------------------------------------------------------------------- // qtractorEditRangeForm -- UI wrapper form. class qtractorEditRangeForm : public QDialog { Q_OBJECT public: // Constructor. qtractorEditRangeForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorEditRangeForm(); // Set the current initial selection range. void setSelectionRange(unsigned long iSelectStart, unsigned long iSelectEnd); // Retrieve the current range, if the case arises. unsigned long rangeStart() const; unsigned long rangeEnd() const; // Range option flags. enum Option { None = 0, Clips = 1, Automation = 2, Loop = 4, Punch = 8, Markers = 16, TempoMap = 32 }; // Retrieve range option flags. unsigned int rangeOptions() const; protected: // Option flags accessors. void setOption(Option option, bool bOn); bool isOption(Option option) const; // Update options settings. void updateOptions(); protected slots: void optionsChanged(); void rangeChanged(); void formatChanged(int); void valueChanged(); void stabilizeForm(); void accept(); private: // The Qt-designer UI struct... Ui::qtractorEditRangeForm m_ui; // Instance variables... qtractorTimeScale *m_pTimeScale; // Initial static selection range. unsigned long m_iSelectStart; unsigned long m_iSelectEnd; // Applicable options; unsigned int m_options; // Pseudo-mutex. unsigned int m_iUpdate; }; #endif // __qtractorEditRangeForm_h // end of qtractorEditRangeForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorScrollView.cpp0000644000175000001440000000012311655015574021631 xustar000000000000000027 mtime=1320426364.920196 26 atime=1381134670.60308 30 ctime=1381134670.603080106 qtractor-0.5.11/src/qtractorScrollView.cpp0000644000175000001440000001320611655015574021122 0ustar00rncbcusers00000000000000// qtractorScrollView.cpp // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorScrollView.h" #include #include #include //---------------------------------------------------------------------------- // qtractorScrollView -- abstract scroll view widget. // Constructor. qtractorScrollView::qtractorScrollView ( QWidget *pParent ) : QAbstractScrollArea(pParent) { // Make it non-sense to the viewport background attribute... QWidget *pViewport = QAbstractScrollArea::viewport(); pViewport->setAttribute(Qt::WA_StaticContents); pViewport->setAttribute(Qt::WA_NoSystemBackground); pViewport->setBackgroundRole(QPalette::NoRole); pViewport->setAutoFillBackground(false); } // Destructor. qtractorScrollView::~qtractorScrollView (void) { } // Virtual contents methods. void qtractorScrollView::setContentsPos ( int cx, int cy ) { if (cx < 0) cx = 0; if (cx != m_rectContents.x()) QAbstractScrollArea::horizontalScrollBar()->setSliderPosition(cx); if (cy < 0) cy = 0; if (cy != m_rectContents.y()) QAbstractScrollArea::verticalScrollBar()->setSliderPosition(cy); } void qtractorScrollView::resizeContents ( int cw, int ch ) { if (cw >= 0 && m_rectContents.width() != cw) m_rectContents.setWidth(cw); if (ch >= 0 && m_rectContents.height() != ch) m_rectContents.setHeight(ch); updateScrollBars(); } // Scrolls contents so that given point is visible. void qtractorScrollView::ensureVisible ( int cx, int cy, int mx, int my ) { QWidget *pViewport = QAbstractScrollArea::viewport(); int w = pViewport->width(); int h = pViewport->height(); int dx = - m_rectContents.x(); int dy = - m_rectContents.y(); int cw = m_rectContents.width(); int ch = m_rectContents.height(); if (w < mx * 2) mx = w / 2; if (h < my * 2) my = h / 2; if (cw <= w) { mx = 0; dx = 0; } if (ch <= h) { my = 0; dy = 0; } if (cx < mx - dx) dx = mx - cx; else if (cx >= w - mx - dx) dx = w - mx - cx; if (cy < my - dy) dy = my - cy; else if (cy >= h - my - dy) dy = h - my - cy; if (dx > 0) dx = 0; else if (dx < w - cw && cw > w) dx = w - cw; if (dy > 0) dy = 0; else if (dy < h - ch && ch > h) dy = h - ch; setContentsPos(-dx, -dy); } // Scrollbar stabilization. void qtractorScrollView::updateScrollBars (void) { QWidget *pViewport = QAbstractScrollArea::viewport(); int w = pViewport->width() - 2; int h = pViewport->height() - 2; QScrollBar *pHScrollBar = QAbstractScrollArea::horizontalScrollBar(); int cw = (m_rectContents.width() > w ? m_rectContents.width() - w : 0); if (pHScrollBar->sliderPosition() > cw) pHScrollBar->setSliderPosition(cw); pHScrollBar->setRange(0, cw); pHScrollBar->setSingleStep((w >> 4) + 1); pHScrollBar->setPageStep(w); QScrollBar *pVScrollBar = QAbstractScrollArea::verticalScrollBar(); int ch = (m_rectContents.height() > h ? m_rectContents.height() - h : 0); if (pVScrollBar->sliderPosition() > ch) pVScrollBar->setSliderPosition(ch); pVScrollBar->setRange(0, ch); pVScrollBar->setSingleStep((h >> 4) + 1); pVScrollBar->setPageStep(h); } // Specialized event handlers. void qtractorScrollView::resizeEvent ( QResizeEvent *pResizeEvent ) { QAbstractScrollArea::resizeEvent(pResizeEvent); updateScrollBars(); } void qtractorScrollView::paintEvent ( QPaintEvent *pPaintEvent ) { QPainter painter(QAbstractScrollArea::viewport()); drawContents(&painter, pPaintEvent->rect().adjusted(0, 0, 1, 1)); } void qtractorScrollView::wheelEvent ( QWheelEvent *pWheelEvent ) { if (pWheelEvent->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) { setContentsPos( m_rectContents.x() + pWheelEvent->delta(), m_rectContents.y()); } else QAbstractScrollArea::wheelEvent(pWheelEvent); } // Scroll area updater. void qtractorScrollView::scrollContentsBy ( int dx, int dy ) { int iUpdate = 0; if (dx) { m_rectContents.moveLeft(m_rectContents.x() - dx); ++iUpdate; } if (dy) { m_rectContents.moveTop(m_rectContents.y() - dy); ++iUpdate; } if (iUpdate > 0) { updateContents(); emit contentsMoving(m_rectContents.x(), m_rectContents.y()); } } // Rectangular contents update. void qtractorScrollView::updateContents ( const QRect& rect ) { QAbstractScrollArea::viewport()->update( QRect(contentsToViewport(rect.topLeft()), rect.size())); } // Overall contents update. void qtractorScrollView::updateContents (void) { QAbstractScrollArea::viewport()->update(); } // Viewport/contents position converters. QPoint qtractorScrollView::viewportToContents ( const QPoint& pos ) const { return QPoint(pos.x() + m_rectContents.x(), pos.y() + m_rectContents.y()); } QPoint qtractorScrollView::contentsToViewport ( const QPoint& pos ) const { return QPoint(pos.x() - m_rectContents.x(), pos.y() - m_rectContents.y()); } // end of qtractorScrollView.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorCurveFile.h0000644000175000001440000000012311612246621021061 xustar000000000000000027 mtime=1311329681.807821 26 atime=1381134668.17408 30 ctime=1381134668.175080067 qtractor-0.5.11/src/qtractorCurveFile.h0000644000175000001440000000665511612246621020364 0ustar00rncbcusers00000000000000// qtractorCurveFile.h // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorCurveFile_h #define __qtractorCurveFile_h #include "qtractorCurve.h" // Forward declarations. class qtractorDocument; class QDomElement; //---------------------------------------------------------------------- // class qtractorCurveFile -- Automation curve file interface decl. // class qtractorCurveFile { public: // Controller types. typedef qtractorMidiEvent::EventType ControlType; // Constructor. qtractorCurveFile(qtractorCurveList *pCurveList) : m_pCurveList(pCurveList), m_iCurrentCurve(-1) {} // Destructor. ~qtractorCurveFile() { clear(); } // Curve list accessor. qtractorCurveList *list() const { return m_pCurveList; } // Base directory path. void setBaseDir(const QString& sBaseDir) { m_sBaseDir = sBaseDir; } const QString& baseDir() const { return m_sBaseDir; } // Filename accessors. void setFilename(const QString& sFilename) { m_sFilename = sFilename; } const QString& filename() const { return m_sFilename; } // Current curve index accesors. void setCurrentCurve(int iCurrentCurve) { m_iCurrentCurve = iCurrentCurve; } int currentCurve() const { return m_iCurrentCurve; } // Curve item escriptor. struct Item { QString name; unsigned long index; ControlType ctype; unsigned short channel; unsigned short param; qtractorCurve::Mode mode; bool process; bool capture; bool locked; bool logarithmic; QColor color; qtractorSubject *subject; }; // Curve item list accessors. const QList& items() const { return m_items; } void addItem(Item *pCurveItem) { m_items.append(pCurveItem); } // Curve item list emptyness predicate. bool isEmpty() const { return m_items.isEmpty(); } // Curve item list cleanup. void clear() { qDeleteAll(m_items); m_items.clear(); m_iCurrentCurve = -1; } // Curve item list serialization methods. void load(QDomElement *pElement); void save(qtractorDocument *pDocument, QDomElement *pElement, qtractorTimeScale *pTimeScale) const; void apply(qtractorTimeScale *pTimeScale); // Text/curve-mode converters... static qtractorCurve::Mode modeFromText(const QString& sText); static QString textFromMode(qtractorCurve::Mode mode); private: // Instance variables. qtractorCurveList *m_pCurveList; QString m_sBaseDir; QString m_sFilename; QList m_items; int m_iCurrentCurve; }; #endif // __qtractorCurveFile_h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEventList.h0000644000175000001440000000012212075634407021723 xustar000000000000000027 mtime=1358379271.965668 26 atime=1381134670.83808 29 ctime=1381134670.83908011 qtractor-0.5.11/src/qtractorMidiEventList.h0000644000175000001440000001423512075634407021220 0ustar00rncbcusers00000000000000// qtractorMidiEventList.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiEventList_h #define __qtractorMidiEventList_h #include #include #include #include // Forwards. class qtractorMidiEditor; class qtractorMidiSequence; class qtractorMidiEvent; //---------------------------------------------------------------------------- // qtractorMidiEventListModel -- List model. class qtractorMidiEventListModel : public QAbstractItemModel { Q_OBJECT public: // Constructor. qtractorMidiEventListModel(qtractorMidiEditor *pEditor, QObject *pParent = 0); // Concretizers (virtual). int rowCount(const QModelIndex& parent = QModelIndex()) const; int columnCount(const QModelIndex& parent = QModelIndex()) const; QVariant headerData(int section, Qt::Orientation orient, int role) const; QVariant data(const QModelIndex& index, int role) const; Qt::ItemFlags flags(const QModelIndex& index ) const; QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const; QModelIndex parent(const QModelIndex&) const; void reset(); // Specifics. qtractorMidiEvent *eventOfIndex(const QModelIndex& index) const; QModelIndex indexOfEvent(qtractorMidiEvent *pEvent) const; QModelIndex indexFromTick(unsigned long iTick) const; unsigned long tickFromIndex(const QModelIndex& index) const; QModelIndex indexFromFrame(unsigned long iFrame) const; unsigned long frameFromIndex(const QModelIndex& index) const; qtractorMidiEditor *editor() const; protected: qtractorMidiEvent *eventAt(int i) const; QString itemDisplay(const QModelIndex& index) const; QString itemToolTip(const QModelIndex& index) const; int columnAlignment(int column) const; private: // Model variables. QStringList m_headers; qtractorMidiEditor *m_pEditor; qtractorMidiSequence *m_pSeq; unsigned long m_iTimeOffset; mutable qtractorMidiEvent *m_pEvent; mutable int m_iEvent; }; //---------------------------------------------------------------------------- // qtractorMidiEventItemDelegate -- Custom (tree) list item delegate. class qtractorMidiEventItemDelegate : public QItemDelegate { Q_OBJECT public: // Constructor. qtractorMidiEventItemDelegate(QObject *pParent = NULL); // Destructor. ~qtractorMidiEventItemDelegate(); // Keyboard event hook. bool eventFilter(QObject *pObject, QEvent *pEvent); // QItemDelegate Interface... void paint(QPainter *pPainter, const QStyleOptionViewItem& option, const QModelIndex& index) const; QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index) const; QWidget *createEditor(QWidget *pParent, const QStyleOptionViewItem& option, const QModelIndex& index) const; void setEditorData(QWidget *pEditor, const QModelIndex& index) const; void setModelData(QWidget *pEditor, QAbstractItemModel *pModel, const QModelIndex& index) const; void updateEditorGeometry(QWidget *pEditor, const QStyleOptionViewItem& option, const QModelIndex& index) const; }; //---------------------------------------------------------------------------- // qtractorMidiEventListView -- Custom (tree) list view. class qtractorMidiEventListView : public QTreeView { Q_OBJECT public: // Constructor. qtractorMidiEventListView(QWidget *pParent = 0); // Destructor. ~qtractorMidiEventListView(); // Settlers. void setEditor(qtractorMidiEditor *pEditor); qtractorMidiEditor *editor() const; // Refreshener. void refresh(); // Locators. qtractorMidiEvent *eventOfIndex(const QModelIndex& index) const; QModelIndex indexOfEvent(qtractorMidiEvent *pEvent) const; QModelIndex indexFromTick(unsigned long iTick) const; unsigned long tickFromIndex(const QModelIndex& index) const; QModelIndex indexFromFrame(unsigned long iFrame) const; unsigned long frameFromIndex(const QModelIndex& index) const; // Selections. void selectEvent(qtractorMidiEvent *pEvent, bool bSelect = true); private: // Instance variables. qtractorMidiEventListModel *m_pListModel; qtractorMidiEventItemDelegate *m_pItemDelegate; }; //---------------------------------------------------------------------------- // qtractorMidiEventListView -- MIDI Event List dockable window. class qtractorMidiEventList : public QDockWidget { Q_OBJECT public: // Constructor. qtractorMidiEventList(QWidget *pParent = 0); // Destructor. ~qtractorMidiEventList(); // Settlers. void setEditor(qtractorMidiEditor *pEditor); qtractorMidiEditor *editor() const; // Event list view refreshner. void refresh(); protected: // Full update when show up. void showEvent(QShowEvent *); // Just about to notify main-window that we're closing. void closeEvent(QCloseEvent *); // Context menu request event handler. void contextMenuEvent(QContextMenuEvent *); protected slots: // Internal list view changes slots. void currentRowChangedSlot(const QModelIndex&, const QModelIndex&); void selectionChangedSlot(const QItemSelection&, const QItemSelection&); // External editor notification slots. void selectNotifySlot(qtractorMidiEditor *); void changeNotifySlot(qtractorMidiEditor *); private: // Instance variables. qtractorMidiEventListView * m_pListView; // Cross-selection fake-mutex. int m_iSelectUpdate; }; #endif // __qtractorMidiEventList_h // end of qtractorMidiEventList.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorConnectForm.ui0000644000175000001440000000012311354101152021570 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134666.99908 30 ctime=1381134666.999080049 qtractor-0.5.11/src/qtractorConnectForm.ui0000644000175000001440000003315411354101152021065 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2010, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorConnectForm 0 0 506 250 1 1 0 0 qtractorConnectTest :/images/viewConnections.png 4 4 Audio 8 4 Qt::Horizontal 0 4 Select output client/ports Qt::WheelFocus 0 4 Select input client/ports Qt::WheelFocus 0 4 Connect currently selected ports &Connect :/images/formConnect.png Alt+C Disconnect currently selected ports &Disconnect :/images/formDisconnect.png Alt+D Disconnect all currently connected ports Disconnect &All :/images/formDisconnectAll.png Alt+A Qt::Horizontal QSizePolicy::Expanding 87 8 Refresh current connections view &Refresh :/images/formRefresh.png Alt+R MIDI 8 4 Qt::Horizontal 0 4 Select output client/ports Qt::WheelFocus 0 4 Select input client/ports Qt::WheelFocus 0 4 Connect currently selected ports &Connect :/images/formConnect.png Alt+C Disconnect currently selected ports &Disconnect :/images/formDisconnect.png Alt+D Disconnect all currently connected ports Disconnect &All :/images/formDisconnectAll.png Alt+A Qt::Horizontal QSizePolicy::Expanding 87 8 Refresh current connections view &Refresh :/images/formRefresh.png Alt+R qtractorAudioClientListView QTreeWidget
qtractorAudioConnect.h
qtractorMidiClientListView QTreeWidget
qtractorMidiConnect.h
qtractorConnectorView QWidget
qtractorConnect.h
ConnectTabWidget AudioOClientsComboBox AudioOListView AudioIClientsComboBox AudioIListView AudioConnectPushButton AudioDisconnectPushButton AudioDisconnectAllPushButton AudioRefreshPushButton MidiOClientsComboBox MidiOListView MidiIClientsComboBox MidiIListView MidiConnectPushButton MidiDisconnectPushButton MidiDisconnectAllPushButton MidiRefreshPushButton
qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiSysexForm.h0000644000175000001440000000012312074050467021743 xustar000000000000000027 mtime=1357926711.346833 26 atime=1381134667.40808 30 ctime=1381134667.408080055 qtractor-0.5.11/src/qtractorMidiSysexForm.h0000644000175000001440000000536512074050467021243 0ustar00rncbcusers00000000000000// qtractorMidiSysexForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiSysexForm_h #define __qtractorMidiSysexForm_h #include "ui_qtractorMidiSysexForm.h" // Forward declarations... class qtractorMidiSysexList; //---------------------------------------------------------------------------- // qtractorMidiSysexForm -- UI wrapper form. class qtractorMidiSysexForm : public QDialog { Q_OBJECT public: // Constructor. qtractorMidiSysexForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorMidiSysexForm(); // SysEx list accessors. void setSysexList(qtractorMidiSysexList *pSysexList); qtractorMidiSysexList *sysexList() const; protected slots: void click(QAbstractButton *); void accept(); void reject(); void importSlot(); void exportSlot(); void moveUpSlot(); void moveDownSlot(); void nameChanged(const QString&); void textChanged(); void openSlot(); void loadSlot(const QString&); void saveSlot(); void deleteSlot(); void addSlot(); void updateSlot(); void removeSlot(); void clearSlot(); void refreshForm(); void stabilizeForm(); protected: // SysEx file i/o methods. bool loadSysexItems( QList& items, const QString& sFilename); bool saveSysexItems( const QList& items, const QString& sFilename) const; void loadSysexFile(const QString& sFilename); void saveSysexFile(const QString& sFilename); // Refresh SysEx names (presets). void refreshSysex(); // SysEx preset group path name. static QString sysexGroup(); private: // The Qt-designer UI struct... Ui::qtractorMidiSysexForm m_ui; // Main editable data structure. qtractorMidiSysexList *m_pSysexList; // Instance variables... int m_iDirtyCount; int m_iDirtyItem; int m_iDirtySysex; int m_iUpdateSysex; }; #endif // __qtractorMidiSysexForm_h // end of qtractorMidiSysexForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiClip.h0000644000175000001440000000012312141244677020676 xustar000000000000000027 mtime=1367689663.484158 26 atime=1381134670.67108 30 ctime=1381134670.672080107 qtractor-0.5.11/src/qtractorMidiClip.h0000644000175000001440000001626012141244677020172 0ustar00rncbcusers00000000000000// qtractorMidiClip.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiClip_h #define __qtractorMidiClip_h #include "qtractorClip.h" #include "qtractorMidiCursor.h" #include "qtractorMidiFile.h" // Forward declartiuons. class qtractorMidiEditorForm; //---------------------------------------------------------------------- // class qtractorMidiClip -- MIDI file/sequence clip. // class qtractorMidiClip : public qtractorClip { public: // Constructor. qtractorMidiClip(qtractorTrack *pTrack); // Copy constructor. qtractorMidiClip(const qtractorMidiClip& clip); // Destructor. ~qtractorMidiClip(); // Clip (re)open method. void open(); // Brand new clip contents new method. bool createMidiFile(const QString& sFilename, int iTrackChannel = 0); // The main use method. bool openMidiFile(const QString& sFilename, int iTrackChannel = 0, int iMode = qtractorMidiFile::Read); // MIDI file properties accessors. void setTrackChannel(unsigned short iTrackChannel) { m_iTrackChannel = iTrackChannel; } unsigned short trackChannel() const { return m_iTrackChannel; } void setFormat(unsigned short iFormat) { m_iFormat = iFormat; } unsigned short format() const { return m_iFormat; } // (Meta)Session flag accessors. void setSessionFlag(bool bSessionFlag) { m_bSessionFlag = bSessionFlag; } bool isSessionFlag() const { return m_bSessionFlag; } // Revisionist accessors. void setRevision(unsigned short iRevision) { m_iRevision = iRevision; } unsigned short revision() const { return m_iRevision; } // Revisionist method. QString createFilePathRevision(bool bForce = false); // Sequence properties accessors. qtractorMidiSequence *sequence() const { return (m_pData ? m_pData->sequence() : NULL); } unsigned short channel() const { return (m_pData ? m_pData->channel() : 0); } int bank() const { return (m_pData ? m_pData->bank() : -1); } int prog() const { return (m_pData ? m_pData->prog() : -1); } // Statistical cached accessors. unsigned char noteMin() const { return m_pData ? m_pData->noteMin() : m_noteMin; } unsigned char noteMax() const { return m_pData ? m_pData->noteMax() : m_noteMax; } // Intra-clip frame positioning. void seek(unsigned long iFrame); // Reset clip state. void reset(bool bLooping); // Loop positioning. void setLoop(unsigned long iLoopStart, unsigned long iLoopEnd); // Clip close-commit (record specific) void close(); // MIDI clip special process cycle executive. void process(unsigned long iFrameStart, unsigned long iFrameEnd); // Clip paint method. void draw(QPainter *pPainter, const QRect& clipRect, unsigned long iClipOffset); // Clip editor methods. bool startEditor(QWidget *pParent); void resetEditor(bool bSelectClear); void updateEditor(bool bSelectClear); bool queryEditor(); // MIDI clip tool-tip. QString toolTip() const; // Auto-save to (possible) new file revision. bool saveCopyFile(); // MIDI clip export method. typedef void (*ClipExport)(qtractorMidiSequence *, void *); bool clipExport(ClipExport pfnClipExport, void *pvArg, unsigned long iOffset = 0, unsigned long iLength = 0) const; // Default MIDI file format accessors // (specific to capture/recording) static void setDefaultFormat(unsigned short iFormat); static unsigned short defaultFormat(); // MIDI file hash key. class FileKey; typedef QHash FileHash; // Most interesting key/data (ref-counted?)... class Key; class Data { public: // Constructor. Data() : m_pSeq(new qtractorMidiSequence()) {} // Destructor. ~Data() { clear(); delete m_pSeq; } // Sequence accessor. qtractorMidiSequence *sequence() const { return m_pSeq; } // Sequence properties accessors. unsigned short channel() const { return m_pSeq->channel(); } int bank() const { return m_pSeq->bank(); } int prog() const { return m_pSeq->prog(); } unsigned char noteMin() const { return m_pSeq->noteMin(); } unsigned char noteMax() const { return m_pSeq->noteMax(); } // Ref-counting related methods. void attach(qtractorMidiClip *pMidiClip) { m_clips.append(pMidiClip); } void detach(qtractorMidiClip *pMidiClip) { m_clips.removeAll(pMidiClip); } unsigned short count() const { return m_clips.count(); } const QList& clips() const { return m_clips; } void clear() { m_clips.clear(); } private: // Interesting variables. qtractorMidiSequence *m_pSeq; // Ref-counting related stuff. QList m_clips; }; typedef QHash Hash; // Sync all ref-counted filenames. void setFilenameEx(const QString& sFilename); // Sync all ref-counted clip-lengths. void setClipLengthEx(unsigned long iClipLength); // Sync all ref-counted clip editors. void updateEditorEx(bool bSelectClear); void resetEditorEx(bool bSelectClear); // Sync all ref-counted clip-dirtyness. void setDirtyEx(bool bDirty); // Manage local hash key. void insertHashKey(); void updateHashKey(); void removeHashKey(); // Un/relink (de/clone) local hash data. void unlinkHashData(); void relinkHashData(); // Whether local hash is being shared. bool isHashLinked() const; // Make sure the clip hash-table gets reset. static void clearHashTable(); protected: // Virtual document element methods. bool loadClipElement(qtractorDocument *pDocument, QDomElement *pElement); bool saveClipElement(qtractorDocument *pDocument, QDomElement *pElement) const; // Private cleanup. void closeMidiFile(); private: // Instance variables. qtractorMidiFile *m_pFile; unsigned short m_iTrackChannel; unsigned short m_iFormat; bool m_bSessionFlag; // Revisionist count. unsigned short m_iRevision; // Statistical cached variables. unsigned char m_noteMin; unsigned char m_noteMax; // Most interesting key/data (ref-counted?)... Key *m_pKey; Data *m_pData; static Hash g_hashTable; // MIDI file hash key. static FileHash g_hashFiles; // To optimize and keep track of current playback // position, mostly like an sequence cursor/iterator. qtractorMidiCursor m_playCursor; qtractorMidiCursor m_drawCursor; // This clip editor form widget. qtractorMidiEditorForm *m_pMidiEditorForm; // Default MIDI file format (for capture/record) static unsigned short g_iDefaultFormat; }; #endif // __qtractorMidiClip_h // end of qtractorMidiClip.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditCommand.h0000644000175000001440000000012312075634407022173 xustar000000000000000027 mtime=1358379271.965668 26 atime=1381134668.01608 30 ctime=1381134668.016080065 qtractor-0.5.11/src/qtractorMidiEditCommand.h0000644000175000001440000000734612075634407021474 0ustar00rncbcusers00000000000000// qtractorMidiEditCommand.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiEditCommand_h #define __qtractorMidiEditCommand_h #include "qtractorCommand.h" #include "qtractorMidiEvent.h" #include // Forward declarations. class qtractorMidiClip; //---------------------------------------------------------------------- // class qtractorMidiEditCommand - declaration. // class qtractorMidiEditCommand : public qtractorCommand { public: // Constructor. qtractorMidiEditCommand(qtractorMidiClip *pMidiClip, const QString& sName); // Destructor. ~qtractorMidiEditCommand(); // Sequence accessor. qtractorMidiClip *midiClip() const { return m_pMidiClip; } // Primitive command types. enum CommandType { InsertEvent, MoveEvent, ResizeEventTime, ResizeEventValue, RemoveEvent }; // Primitive command methods. void insertEvent(qtractorMidiEvent *pEvent); void moveEvent(qtractorMidiEvent *pEvent, int iNote, unsigned long iTime); void resizeEventTime(qtractorMidiEvent *pEvent, unsigned long iTime, unsigned long iDuration); void resizeEventValue(qtractorMidiEvent *pEvent, int iValue); void removeEvent(qtractorMidiEvent *pEvent); // Check whether the event is already in chain. bool findEvent(qtractorMidiEvent *pEvent, CommandType cmd) const; // Virtual command methods. bool redo(); bool undo(); protected: // Common executive method. bool execute(bool bRedo); // Adjust edit-command result to prevent event overlapping. bool adjust(); private: // Event item struct. struct Item { // Item constructor. Item(CommandType cmd, qtractorMidiEvent *pEvent, int iNote = 0, unsigned long iTime = 0, unsigned long iDuration = 0, unsigned int iValue = 0) : command(cmd), event(pEvent), note(iNote), time(iTime), duration(iDuration), value(iValue), autoDelete(false) {} // Item members. CommandType command; qtractorMidiEvent *event; int note; unsigned long time; unsigned long duration; int value; bool autoDelete; }; // Instance variables. qtractorMidiClip *m_pMidiClip; QList m_items; bool m_bAdjusted; unsigned long m_iDuration; }; //---------------------------------------------------------------------- // class qtractorMidiClipCommand - declaration. // class qtractorMidiClipCommand : public qtractorCommand { public: // Constructor. qtractorMidiClipCommand(const QString& sName); // Destructor. virtual ~qtractorMidiClipCommand(); // Composite command methods. void addEditCommand(qtractorMidiEditCommand *pEditCommand); // Composite predicate. bool isEmpty() const; // Virtual command methods. bool redo(); bool undo(); private: // Multi-clip command list. QList m_editCommands; }; #endif // __qtractorMidiEditCommand_h // end of qtractorMidiEditCommand.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorPluginSelectForm.ui0000644000175000001440000000012311711516771022613 xustar000000000000000027 mtime=1327930873.409551 26 atime=1381134671.21108 30 ctime=1381134671.212080116 qtractor-0.5.11/src/qtractorPluginSelectForm.ui0000644000175000001440000001522511711516771022107 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorPluginSelectForm 0 0 480 320 Plugins - Qtractor true 4 4 0 4 22 22 22 22 Qt::TabFocus Reset filter X 320 0 Plugin search string (regular expression) true 80 22 Plugin type false 420 0 Available plugins true QAbstractItemView::ExtendedSelection false true false true true Name Audio MIDI Control Modes Path Index Instances Type 0 4 &Activate Activate plugin on insert Alt+A 240 0 Plugin scanning in progress... Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok PluginResetToolButton PluginSearchComboBox PluginTypeComboBox PluginListView PluginActivateCheckBox DialogButtonBox qtractor-0.5.11/src/PaxHeaders.10084/qtractorDssiPlugin.cpp0000644000175000001440000000012312161335204021605 xustar000000000000000027 mtime=1371912836.382031 26 atime=1381134667.96608 30 ctime=1381134667.966080064 qtractor-0.5.11/src/qtractorDssiPlugin.cpp0000644000175000001440000010157012161335204021100 0ustar00rncbcusers00000000000000// qtractorDssiPlugin.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #ifdef CONFIG_DSSI #include "qtractorDssiPlugin.h" #include "qtractorPluginForm.h" #include "qtractorMidiBuffer.h" #include #include #ifdef CONFIG_LIBLO #include #include #include //---------------------------------------------------------------------------- // qtractorDssiPlugin::DssiEditor -- DSSI GUI Editor instance. // struct DssiEditor { // Constructor. DssiEditor(qtractorDssiPlugin *pDssiPlugin) : plugin(pDssiPlugin), target(NULL), source(NULL), path(NULL), busy(0) {} // Destructor. ~DssiEditor() { if (target) lo_address_free(target); if (source) lo_address_free(source); if (path) ::free(path); } // Member variables. qtractorDssiPlugin *plugin; lo_address target; lo_address source; char *path; int busy; }; static lo_server_thread g_oscThread; static QString g_sOscPath; static QMutex g_oscMutex; static QHash g_dssiEditors; static QString osc_label ( qtractorDssiPlugin *pDssiPlugin ) { return (pDssiPlugin->type())->label() + '.' + QString::number(ulong(pDssiPlugin), 16); } static DssiEditor *osc_find_editor ( const QString& sOscLabel ) { #ifdef CONFIG_DEBUG_0 qDebug("osc_find_editor(\"%s\")", sOscLabel.toUtf8().constData()); #endif return g_dssiEditors.value(sOscLabel, NULL); } static void osc_error ( int num, const char *msg, const char *path ) { qWarning("osc_error: server error %d in path \"%s\": %s", num, path, msg); } static int osc_send_configure ( DssiEditor *pDssiEditor, const char *key, const char *value ) { if (pDssiEditor->busy > 0) return 1; if (pDssiEditor->target == NULL) return 1; #ifdef CONFIG_DEBUG qDebug("osc_send_configure: path \"%s\", key \"%s\", value \"%s\"", pDssiEditor->path, key, value); #endif QString sPath(pDssiEditor->path); sPath += "/configure"; lo_send(pDssiEditor->target, sPath.toUtf8().constData(), "ss", key, value); return 0; } static int osc_send_control ( DssiEditor *pDssiEditor, int param, float value ) { if (pDssiEditor->busy > 0) return 1; if (pDssiEditor->target == NULL) return 1; #ifdef CONFIG_DEBUG qDebug("osc_send_control: path \"%s\", param %d, value %g", pDssiEditor->path, param, value); #endif QString sPath(pDssiEditor->path); sPath += "/control"; lo_send(pDssiEditor->target, sPath.toUtf8().constData(), "if", param, value); return 0; } static int osc_send_program ( DssiEditor *pDssiEditor, int bank, int prog ) { if (pDssiEditor->busy > 0) return 1; if (pDssiEditor->target == NULL) return 1; #ifdef CONFIG_DEBUG qDebug("osc_send_program: path \"%s\", bank %d, prog %d", pDssiEditor->path, bank, prog); #endif QString sPath(pDssiEditor->path); sPath += "/program"; lo_send(pDssiEditor->target, sPath.toUtf8().constData(), "ii", bank, prog); return 0; } static int osc_send_show ( DssiEditor *pDssiEditor ) { if (pDssiEditor->busy > 0) return 1; if (pDssiEditor->target == NULL) return 1; #ifdef CONFIG_DEBUG qDebug("osc_send_show: path \"%s\"", pDssiEditor->path); #endif QString sPath(pDssiEditor->path); sPath += "/show"; lo_send(pDssiEditor->target, sPath.toUtf8().constData(), ""); return 0; } static int osc_send_hide ( DssiEditor *pDssiEditor ) { if (pDssiEditor->busy > 0) return 1; if (pDssiEditor->target == NULL) return 1; #ifdef CONFIG_DEBUG qDebug("osc_send_hide: path \"%s\"", pDssiEditor->path); #endif QString sPath(pDssiEditor->path); sPath += "/hide"; lo_send(pDssiEditor->target, sPath.toUtf8().constData(), ""); return 0; } static int osc_send_quit ( DssiEditor *pDssiEditor ) { if (pDssiEditor->busy > 0) return 1; if (pDssiEditor->target == NULL) return 1; #ifdef CONFIG_DEBUG qDebug("osc_send_quit: path \"%s\"", pDssiEditor->path); #endif QString sPath(pDssiEditor->path); sPath += "/quit"; lo_send(pDssiEditor->target, sPath.toUtf8().constData(), ""); return 0; } static int osc_update ( DssiEditor *pDssiEditor, lo_arg **argv, lo_address source ) { const char *url = (const char *) &argv[0]->s; const char *host, *port; #ifdef CONFIG_DEBUG qDebug("osc_update: path \"%s\"", url); #endif qtractorDssiPlugin *pDssiPlugin = pDssiEditor->plugin; if (pDssiPlugin == NULL) return 1; ++(pDssiEditor->busy); if (pDssiEditor->target) lo_address_free(pDssiEditor->target); host = lo_url_get_hostname(url); port = lo_url_get_port(url); pDssiEditor->target = lo_address_new(host, port); ::free((void *) host); ::free((void *) port); if (pDssiEditor->source) lo_address_free(pDssiEditor->source); host = lo_address_get_hostname(source); port = lo_address_get_port(source); pDssiEditor->source = lo_address_new(host, port); if (pDssiEditor->path) ::free(pDssiEditor->path); pDssiEditor->path = lo_url_get_path(url); --(pDssiEditor->busy); // Update plugin configuration... const qtractorPlugin::Configs& configs = pDssiPlugin->configs(); qtractorPlugin::Configs::ConstIterator iter = configs.constBegin(); const qtractorPlugin::Configs::ConstIterator& iter_end = configs.constEnd(); for (; iter != iter_end; ++iter) { osc_send_configure(pDssiEditor, iter.key().toUtf8().constData(), iter.value().toUtf8().constData()); } // Update program selection... qtractorMidiManager *pMidiManager = (pDssiPlugin->list())->midiManager(); if (pMidiManager && pMidiManager->currentBank() >= 0 && pMidiManager->currentProg() >= 0) { osc_send_program(pDssiEditor, pMidiManager->currentBank(), pMidiManager->currentProg()); } // Update control params... const qtractorPlugin::Params& params = pDssiPlugin->params(); qtractorPlugin::Params::ConstIterator param = params.constBegin(); const qtractorPlugin::Params::ConstIterator& param_end = params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); osc_send_control(pDssiEditor, pParam->index(), pParam->value()); } // Update all control output ports... pDssiPlugin->updateControlOuts(true); return osc_send_show(pDssiEditor); } static int osc_configure ( DssiEditor *pDssiEditor, lo_arg **argv ) { const char *key = (const char *) &argv[0]->s; const char *value = (const char *) &argv[1]->s; #ifdef CONFIG_DEBUG qDebug("osc_configure: path \"%s\", key \"%s\", value \"%s\"", pDssiEditor->path, key, value); #endif qtractorDssiPlugin *pDssiPlugin = pDssiEditor->plugin; if (pDssiPlugin == NULL) return 1; // Save and send configuration to plugin... ++(pDssiEditor->busy); pDssiPlugin->setConfig(key, value); pDssiPlugin->configure(key, value); --(pDssiEditor->busy); return 0; } static int osc_control ( DssiEditor *pDssiEditor, lo_arg **argv ) { int param = argv[0]->i; float value = argv[1]->f; #ifdef CONFIG_DEBUG qDebug("osc_control: path \"%s\", param %d, value %g", pDssiEditor->path, param, value); #endif qtractorDssiPlugin *pDssiPlugin = pDssiEditor->plugin; if (pDssiPlugin == NULL) return 1; // Plugin parameter lookup. ++(pDssiEditor->busy); pDssiPlugin->updateParamValue(param, value, true); --(pDssiEditor->busy); return 0; } static int osc_program ( DssiEditor *pDssiEditor, lo_arg **argv ) { int bank = argv[0]->i; int prog = argv[1]->i; #ifdef CONFIG_DEBUG qDebug("osc_program: path \"%s\", bank %d, prog %d", pDssiEditor->path, bank, prog); #endif qtractorDssiPlugin *pDssiPlugin = pDssiEditor->plugin; if (pDssiPlugin == NULL) return 1; // Bank/Program selection pending... ++(pDssiEditor->busy); pDssiPlugin->selectProgram(bank, prog); if ((pDssiPlugin->list())->midiProgramSubject()) ((pDssiPlugin->list())->midiProgramSubject())->setProgram(bank, prog); --(pDssiEditor->busy); return 0; } static int osc_midi ( DssiEditor *pDssiEditor, lo_arg **argv ) { static snd_midi_event_t *s_pAlsaCoder = NULL; static snd_seq_event_t s_aAlsaEvent[4]; unsigned char *data = argv[0]->m; #ifdef CONFIG_DEBUG qDebug("osc_midi: path \"%s\", midi 0x%02x 0x%02x 0x%02x 0x%02x", pDssiEditor->path, data[0], data[1], data[2], data[3]); #endif qtractorDssiPlugin *pDssiPlugin = pDssiEditor->plugin; if (pDssiPlugin == NULL) return 1; qtractorMidiManager *pMidiManager = (pDssiPlugin->list())->midiManager(); if (pMidiManager == NULL) return 1; if (s_pAlsaCoder == NULL && snd_midi_event_new(4, &s_pAlsaCoder)) return 1; snd_midi_event_reset_encode(s_pAlsaCoder); if (snd_midi_event_encode(s_pAlsaCoder, &data[1], 3, s_aAlsaEvent) < 1) return 1; // Send the event directly to snd_seq_event_t *pEvent = &s_aAlsaEvent[0]; if (snd_seq_ev_is_channel_type(pEvent)) pMidiManager->direct(pEvent); return 0; } static int osc_exiting ( DssiEditor *pDssiEditor ) { #ifdef CONFIG_DEBUG qDebug("osc_exiting: path \"%s\"", pDssiEditor->path); #endif qtractorDssiPlugin *pDssiPlugin = pDssiEditor->plugin; if (pDssiPlugin) { pDssiPlugin->clearEditor(); } pDssiEditor->plugin = NULL; if (g_dssiEditors.remove(osc_label(pDssiPlugin)) > 0) delete pDssiEditor; return 0; } static int osc_message ( const char *path, const char * /*types*/, lo_arg **argv, int /*argc*/, void *data, void * /*user_data*/ ) { QMutexLocker locker(&g_oscMutex); #ifdef CONFIG_DEBUG_0 printf("osc_message: path \"%s\"", path); for (int i = 0; i < argc; ++i) { printf(", arg %d '%c' ", i, types[i]); lo_arg_pp(lo_type(types[i]), argv[i]); } printf(", data %p, user_data %p\n", data, user_data); #endif if (::strncmp(path, "/dssi", 5)) return 1; const QString sPath = path; const QString& sLabel = sPath.section('/', 2, 2); DssiEditor *pDssiEditor = osc_find_editor(sLabel); if (pDssiEditor == NULL) return 1; if (pDssiEditor->busy > 0) return 1; lo_message message = lo_message(data); lo_address source = lo_message_get_source(message); const QString& sMethod = sPath.section('/', 3, 3); if (sMethod == "update") return osc_update(pDssiEditor, argv, source); else if (sMethod == "configure") return osc_configure(pDssiEditor, argv); else if (sMethod == "control") return osc_control(pDssiEditor, argv); else if (sMethod == "program") return osc_program(pDssiEditor, argv); else if (sMethod == "midi") return osc_midi(pDssiEditor, argv); else if (sMethod == "exiting") return osc_exiting(pDssiEditor); return 1; } static void osc_start (void) { if (g_oscThread) return; #ifdef CONFIG_DEBUG qDebug("osc_start()"); #endif // Create OSC thread... g_oscThread = lo_server_thread_new(NULL, osc_error); g_sOscPath = lo_server_thread_get_url(g_oscThread); g_sOscPath += "dssi"; lo_server_thread_add_method(g_oscThread, NULL, NULL, osc_message, NULL); lo_server_thread_start(g_oscThread); } static void osc_stop (void) { #ifdef CONFIG_DEBUG qDebug("osc_stop()"); #endif qDeleteAll(g_dssiEditors); g_dssiEditors.clear(); } static DssiEditor *osc_open_editor ( qtractorDssiPlugin *pDssiPlugin ) { QMutexLocker locker(&g_oscMutex); #ifdef CONFIG_DEBUG qDebug("osc_open_editor(\"%s\")", osc_label(pDssiPlugin).toUtf8().constData()); #endif if (g_dssiEditors.count() < 1) osc_start(); DssiEditor *pDssiEditor = new DssiEditor(pDssiPlugin); g_dssiEditors.insert(osc_label(pDssiPlugin), pDssiEditor); return pDssiEditor; } static void osc_close_editor ( DssiEditor *pDssiEditor ) { QMutexLocker locker(&g_oscMutex); #ifdef CONFIG_DEBUG qDebug("osc_close_editor(\"%s\")", osc_label(pDssiEditor->plugin).toUtf8().constData()); #endif osc_send_hide(pDssiEditor); osc_send_quit(pDssiEditor); osc_exiting(pDssiEditor); if (g_dssiEditors.count() < 1) osc_stop(); } #endif //---------------------------------------------------------------------------- // qtractorDssiPlugin::DssiMulti -- DSSI multiple instance pool entry. // static float *g_pDummyBuffer = NULL; static unsigned int g_iDummyBufferSize = 0; class DssiMulti { public: // Constructor. DssiMulti() : m_iSize(0), m_ppPlugins(NULL), m_iInstances(0), m_phInstances(NULL), m_ppEvents(NULL), m_piEvents(NULL), m_iProcess(0), m_iActivated(0), m_iRefCount(0) {} // Destructor. ~DssiMulti() { if (m_piEvents) delete [] m_piEvents; if (m_ppEvents) delete [] m_ppEvents; if (m_phInstances) delete [] m_phInstances; if (m_ppPlugins) delete [] m_ppPlugins; } // Add plugin instances to registry pool. void addPlugin(qtractorDssiPlugin *pDssiPlugin) { unsigned long iNewInstances = m_iInstances + pDssiPlugin->instances(); if (iNewInstances >= m_iSize) { m_iSize += iNewInstances; qtractorDssiPlugin **ppNewPlugins = new qtractorDssiPlugin * [m_iSize]; LADSPA_Handle *phNewInstances = new LADSPA_Handle [m_iSize]; qtractorDssiPlugin **ppOldPlugins = m_ppPlugins; LADSPA_Handle *phOldInstances = m_phInstances; if (ppOldPlugins && phOldInstances) { m_ppPlugins = NULL; m_phInstances = NULL; for (unsigned long i = 0; i < m_iInstances; ++i) { ppNewPlugins[i] = ppOldPlugins[i]; phNewInstances[i] = phOldInstances[i]; } delete [] phOldInstances; delete [] ppOldPlugins; } m_ppPlugins = ppNewPlugins; m_phInstances = phNewInstances; if (m_ppEvents) delete [] m_ppEvents; if (m_piEvents) delete [] m_piEvents; m_ppEvents = new snd_seq_event_t * [m_iSize]; m_piEvents = new unsigned long [m_iSize]; } for (unsigned long i = 0; i < pDssiPlugin->instances(); ++i) { unsigned long iInstance = m_iInstances + i; m_ppPlugins[iInstance] = pDssiPlugin; m_phInstances[iInstance] = pDssiPlugin->ladspa_handle(i); } m_iInstances = iNewInstances; if (g_iDummyBufferSize < pDssiPlugin->list()->bufferSize()) { g_iDummyBufferSize = pDssiPlugin->list()->bufferSize(); if (g_pDummyBuffer) delete [] g_pDummyBuffer; g_pDummyBuffer = new float [g_iDummyBufferSize]; } reset(pDssiPlugin); } // Remove plugin instances from registry pool. void removePlugin(qtractorDssiPlugin *pDssiPlugin) { for (unsigned long i = 0; i < m_iInstances; ++i) { unsigned long j = i; while (j < m_iInstances && m_ppPlugins[j] == pDssiPlugin) ++j; if (j > i) { unsigned long k = (j - i); for (; j < m_iInstances; ++j, ++i) { m_ppPlugins[i] = m_ppPlugins[j]; m_phInstances[i] = m_phInstances[j]; } m_iInstances -= k; break; } } } // Process registry pool. void process(const DSSI_Descriptor *pDssiDescriptor, unsigned int nframes) { // Count in only the active instances... if (++m_iProcess < m_iActivated) return; for (unsigned long i = 0; i < m_iInstances; ++i) { // Set MIDI event lists... qtractorMidiManager *pMidiManager = m_ppPlugins[i]->list()->midiManager(); if (pMidiManager) { m_ppEvents[i] = pMidiManager->events(); m_piEvents[i] = pMidiManager->count(); } else { m_ppEvents[i] = NULL; m_piEvents[i] = 0; } } (*pDssiDescriptor->run_multiple_synths)(m_iInstances, m_phInstances, nframes, m_ppEvents, m_piEvents); m_iProcess = 0; } // Activation count methods. void activate(qtractorDssiPlugin *pDssiPlugin) { m_iActivated += pDssiPlugin->instances(); } void deactivate(qtractorDssiPlugin *pDssiPlugin) { m_iActivated -= pDssiPlugin->instances(); reset(pDssiPlugin); } // Reference count methods. void addRef() { ++m_iRefCount; } void removeRef() { if (--m_iRefCount == 0) delete this; } // Reset connections. void reset(qtractorDssiPlugin *pDssiPlugin) { // One must connect the ports of all inactive // instances somewhere, otherwise it will crash... const LADSPA_Descriptor *pLadspaDescriptor = pDssiPlugin->ladspa_descriptor(); unsigned short iAudioIns = pDssiPlugin->audioIns(); unsigned short iAudioOuts = pDssiPlugin->audioOuts(); for (unsigned short i = 0; i < pDssiPlugin->instances(); ++i) { LADSPA_Handle handle = pDssiPlugin->ladspa_handle(i); for (unsigned short j = 0; j < iAudioIns; ++j) { (*pLadspaDescriptor->connect_port)(handle, pDssiPlugin->audioIn(j), g_pDummyBuffer); } for (unsigned short j = 0; j < iAudioOuts; ++j) { (*pLadspaDescriptor->connect_port)(handle, pDssiPlugin->audioOut(j), g_pDummyBuffer); } } } private: // Member variables. unsigned long m_iSize; qtractorDssiPlugin **m_ppPlugins; unsigned long m_iInstances; LADSPA_Handle *m_phInstances; snd_seq_event_t **m_ppEvents; unsigned long *m_piEvents; unsigned long m_iProcess; unsigned long m_iActivated; unsigned int m_iRefCount; }; // DSSI multiple instance pool // for each DSSI plugin implementing run_multiple_synths // one must keep a global registry of all instances here. static QHash g_dssiHash; // DSSI multiple instance key helper. static QString dssi_multi_key ( qtractorDssiPluginType *pDssiType ) { return pDssiType->filename() + '_' + pDssiType->label(); } // DSSI multiple instance entry constructor. static DssiMulti *dssi_multi_create ( qtractorDssiPluginType *pDssiType ) { const DSSI_Descriptor *pDssiDescriptor = pDssiType->dssi_descriptor(); if (pDssiDescriptor == NULL) return NULL; if (pDssiDescriptor->run_multiple_synths == NULL) return NULL; DssiMulti *pDssiMulti = NULL; const QString& sKey = dssi_multi_key(pDssiType); QHash::const_iterator iter = g_dssiHash.constFind(sKey); if (iter == g_dssiHash.constEnd()) { pDssiMulti = new DssiMulti(); g_dssiHash.insert(sKey, pDssiMulti); } else { pDssiMulti = iter.value(); } pDssiMulti->addRef(); return pDssiMulti; } // DSSI multiple instance entry destructor. void dssi_multi_destroy ( qtractorDssiPluginType *pDssiType ) { // Remove hash table entry... const QString& sKey = dssi_multi_key(pDssiType); QHash::Iterator iter = g_dssiHash.find(sKey); if (iter == g_dssiHash.end()) return; iter.value()->removeRef(); g_dssiHash.erase(iter); // On last entry deallocate dummy buffer as well... if (g_dssiHash.isEmpty() && g_pDummyBuffer) { delete [] g_pDummyBuffer; g_pDummyBuffer = NULL; g_iDummyBufferSize = 0; } } //---------------------------------------------------------------------------- // qtractorDssiPluginType -- DSSI plugin type instance. // // Derived methods. bool qtractorDssiPluginType::open (void) { // Do we have a descriptor already? if (m_pDssiDescriptor == NULL) m_pDssiDescriptor = dssi_descriptor(file(), index()); if (m_pDssiDescriptor == NULL) return false; // We're also a LADSPA one... m_pLadspaDescriptor = m_pDssiDescriptor->LADSPA_Plugin; // Let's get the it's own LADSPA stuff... if (!qtractorLadspaPluginType::open()) { m_pLadspaDescriptor = NULL; m_pDssiDescriptor = NULL; return false; } #ifdef CONFIG_DEBUG qDebug("qtractorDssiPluginType[%p]::open() filename=\"%s\" index=%lu", this, filename().toUtf8().constData(), index()); #endif // Things we have now for granted... m_bConfigure = (m_pDssiDescriptor->configure != NULL); m_iMidiIns = 1; #ifdef CONFIG_LIBLO // Check for GUI editor exacutable... QFileInfo fi(filename()); QFileInfo gi(fi.dir(), fi.baseName()); if (gi.isDir()) { QDir dir(gi.absoluteFilePath()); const QString sMask("%1_*"); QStringList names; names.append(sMask.arg(fi.baseName())); names.append(sMask.arg(m_pLadspaDescriptor->Label)); dir.setNameFilters(names); QStringList guis = dir.entryList(QDir::Files | QDir::Executable); if (!guis.isEmpty()) { gi.setFile(dir, guis.first()); // FIXME: Only the first? m_sDssiEditor = gi.absoluteFilePath(); m_bEditor = gi.isExecutable(); } } #endif return true; } void qtractorDssiPluginType::close (void) { m_pDssiDescriptor = NULL; qtractorLadspaPluginType::close(); } // Factory method (static) qtractorDssiPluginType *qtractorDssiPluginType::createType ( qtractorPluginFile *pFile, unsigned long iIndex ) { // Sanity check... if (pFile == NULL) return NULL; // Retrieve DSSI descriptor if any... const DSSI_Descriptor *pDssiDescriptor = dssi_descriptor(pFile, iIndex); if (pDssiDescriptor == NULL) return NULL; // Yep, most probably its a valid plugin descriptor... return new qtractorDssiPluginType(pFile, iIndex, pDssiDescriptor); } // Descriptor method (static) const DSSI_Descriptor *qtractorDssiPluginType::dssi_descriptor ( qtractorPluginFile *pFile, unsigned long iIndex ) { // Retrieve the DSSI descriptor function, if any... DSSI_Descriptor_Function pfnDssiDescriptor = (DSSI_Descriptor_Function) pFile->resolve("dssi_descriptor"); if (pfnDssiDescriptor == NULL) return NULL; // Retrieve DSSI descriptor if any... return (*pfnDssiDescriptor)(iIndex); } //---------------------------------------------------------------------------- // qtractorDssiPlugin -- DSSI plugin instance. // // Constructors. qtractorDssiPlugin::qtractorDssiPlugin ( qtractorPluginList *pList, qtractorDssiPluginType *pDssiType ) : qtractorLadspaPlugin(pList, pDssiType), m_pDssiMulti(NULL), m_pDssiEditor(NULL), m_bEditorVisible(false), m_pfControlOutsLast(NULL) { // Check whether we're go into a multiple instance pool. m_pDssiMulti = dssi_multi_create(pDssiType); // For tracking changes on output control ports. unsigned long iControlOuts = pDssiType->controlOuts(); if (iControlOuts > 0) { m_pfControlOutsLast = new float [iControlOuts]; for (unsigned long j = 0; j < iControlOuts; ++j) m_pfControlOutsLast[j] = 0.0f; } // Extended first instantiantion. resetChannels(); } // Destructor. qtractorDssiPlugin::~qtractorDssiPlugin (void) { // Cleanup all plugin instances... setChannels(0); // Remove reference from multiple instance pool. if (m_pDssiMulti) dssi_multi_destroy(static_cast (type())); // Remove last output control port values seen... if (m_pfControlOutsLast) delete [] m_pfControlOutsLast; } // Channel/instance number accessors. void qtractorDssiPlugin::setChannels ( unsigned short iChannels ) { // (Re)set according to existing instances... if (m_pDssiMulti) m_pDssiMulti->removePlugin(this); // Setup new instances... qtractorLadspaPlugin::setChannels(iChannels); // Epilogue... resetChannels(); } // Post-(re)initializer. void qtractorDssiPlugin::resetChannels (void) { // (Re)initialize controller port map, anyway. ::memset(m_apControllerMap, 0, 128 * sizeof(qtractorPluginParam *)); // Check how many instances are about there... unsigned short iInstances = instances(); if (iInstances < 1) return; #ifdef CONFIG_DEBUG qDebug("qtractorDssiPlugin[%p]::resetChannels() instances=%u", this, iInstances); #endif // (Re)set according to existing instances... if (m_pDssiMulti) m_pDssiMulti->addPlugin(this); // Map all existing input control ports... const DSSI_Descriptor *pDssiDescriptor = dssi_descriptor(); if (pDssiDescriptor && pDssiDescriptor->get_midi_controller_for_port) { // Only the first one instance should matter... LADSPA_Handle handle = m_phInstances[0]; const qtractorPlugin::Params& params = qtractorPlugin::params(); qtractorPlugin::Params::ConstIterator param = params.constBegin(); const qtractorPlugin::Params::ConstIterator& param_end = params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); int iController = (*pDssiDescriptor->get_midi_controller_for_port)( handle, pParam->index()); if (iController > 0 && DSSI_IS_CC(iController)) m_apControllerMap[DSSI_CC_NUMBER(iController)] = pParam; } } } // Do the actual activation. void qtractorDssiPlugin::activate (void) { // Activate as usual... if (m_pDssiMulti) m_pDssiMulti->activate(this); qtractorLadspaPlugin::activate(); } // Do the actual deactivation. void qtractorDssiPlugin::deactivate (void) { // Deactivate as usual... qtractorLadspaPlugin::deactivate(); if (m_pDssiMulti) m_pDssiMulti->deactivate(this); } // The main plugin processing procedure. void qtractorDssiPlugin::process ( float **ppIBuffer, float **ppOBuffer, unsigned int nframes ) { // Get MIDI manager access... qtractorMidiManager *pMidiManager = list()->midiManager(); if (pMidiManager == NULL) { qtractorLadspaPlugin::process(ppIBuffer, ppOBuffer, nframes); return; } if (m_phInstances == NULL) return; const LADSPA_Descriptor *pLadspaDescriptor = ladspa_descriptor(); if (pLadspaDescriptor == NULL) return; const DSSI_Descriptor *pDssiDescriptor = dssi_descriptor(); if (pDssiDescriptor == NULL) return; // We'll cross channels over instances... const unsigned short iInstances = instances(); const unsigned short iChannels = channels(); const unsigned short iAudioIns = audioIns(); const unsigned short iAudioOuts = audioOuts(); unsigned short iIChannel = 0; unsigned short iOChannel = 0; unsigned short i, j; // For each plugin instance... for (i = 0; i < iInstances; ++i) { LADSPA_Handle handle = m_phInstances[i]; // For each instance audio input port... for (j = 0; j < iAudioIns; ++j) { (*pLadspaDescriptor->connect_port)(handle, m_piAudioIns[j], ppIBuffer[iIChannel]); if (++iIChannel >= iChannels) iIChannel = 0; } // For each instance audio output port... for (j = 0; j < iAudioOuts; ++j) { (*pLadspaDescriptor->connect_port)(handle, m_piAudioOuts[j], ppOBuffer[iOChannel]); if (++iOChannel >= iChannels) iOChannel = 0; } // Care of multiple instances here... if (m_pDssiMulti) m_pDssiMulti->process(pDssiDescriptor, nframes); // Make it run... else if (pDssiDescriptor->run_synth) { (*pDssiDescriptor->run_synth)(handle, nframes, pMidiManager->events(), pMidiManager->count()); } else (*pLadspaDescriptor->run)(handle, nframes); // Wrap channels?... if (iIChannel < iChannels - 1) ++iIChannel; if (iOChannel < iChannels - 1) ++iOChannel; } } // Parameter update method. void qtractorDssiPlugin::updateParam ( qtractorPluginParam *pParam, float fValue, bool bUpdate ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorDssiPlugin[%p]::updateParam(%lu, %g, %d)", this, pParam->index(), fValue, int(bUpdate)); #endif #ifdef CONFIG_LIBLO // And update the editor too... if (bUpdate && m_pDssiEditor) osc_send_control(m_pDssiEditor, pParam->index(), fValue); #endif } // GUI Editor stuff. void qtractorDssiPlugin::openEditor ( QWidget */*pParent*/ ) { qtractorDssiPluginType *pDssiType = static_cast (type()); if (pDssiType == NULL) return; if (!pDssiType->isEditor()) return; #ifdef CONFIG_LIBLO // Are we already there? if (m_pDssiEditor) { osc_send_show(m_pDssiEditor); m_bEditorVisible = true; // Bail out. return; } // Open up a new one... m_pDssiEditor = osc_open_editor(this); const QString& sDssiEditor = pDssiType->dssi_editor(); QStringList args; args.append(g_sOscPath + '/' + osc_label(this)); args.append(QFileInfo((pDssiType->file())->filename()).fileName()); args.append(pDssiType->label()); args.append(pDssiType->name()); #ifdef CONFIG_DEBUG qDebug("qtractorDssiPlugin::openEditor() " "path=\"%s\" url=\"%s\" filename=\"%s\" label=\"%s\" name=\"%s\"", sDssiEditor.toUtf8().constData(), args[0].toUtf8().constData(), args[1].toUtf8().constData(), args[2].toUtf8().constData(), args[3].toUtf8().constData()); #endif if (!QProcess::startDetached(sDssiEditor, args)) { closeEditor(); return; } #endif m_bEditorVisible = true; if (isFormVisible()) form()->toggleEditor(true); } void qtractorDssiPlugin::closeEditor (void) { #ifdef CONFIG_LIBLO if (m_pDssiEditor) osc_close_editor(m_pDssiEditor); #else clearEditor(); #endif } // GUI editor visibility state. void qtractorDssiPlugin::setEditorVisible ( bool bVisible ) { #ifdef CONFIG_LIBLO // Check if still here... if (m_pDssiEditor == NULL) { if (bVisible) openEditor(form()); return; } // Do our deeds... if (bVisible) osc_send_show(m_pDssiEditor); else osc_send_hide(m_pDssiEditor); #endif if (isFormVisible()) form()->toggleEditor(bVisible); m_bEditorVisible = bVisible; } bool qtractorDssiPlugin::isEditorVisible (void) const { return m_bEditorVisible; } // Bank/program selector. void qtractorDssiPlugin::selectProgram ( int iBank, int iProg ) { if (iBank < 0 || iProg < 0) return; if (m_phInstances == NULL) return; const DSSI_Descriptor *pDssiDescriptor = dssi_descriptor(); if (pDssiDescriptor == NULL) return; if (pDssiDescriptor->select_program == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorDssiPlugin[%p]::selectProgram(%d, %d)", this, iBank, iProg); #endif // For each plugin instance... for (unsigned short i = 0; i < instances(); ++i) (*pDssiDescriptor->select_program)(m_phInstances[i], iBank, iProg); #ifdef CONFIG_LIBLO // And update the editor too... if (m_pDssiEditor) osc_send_program(m_pDssiEditor, iBank, iProg); #endif // Reset parameters default value... const qtractorPlugin::Params& params = qtractorPlugin::params(); qtractorPlugin::Params::ConstIterator param = params.constBegin(); const qtractorPlugin::Params::ConstIterator& param_end = params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); pParam->setDefaultValue(pParam->value()); } } // Provisional program/patch accessor. bool qtractorDssiPlugin::getProgram ( int iIndex, Program& program ) const { if (m_phInstances == NULL) return false; const DSSI_Descriptor *pDssiDescriptor = dssi_descriptor(); if (pDssiDescriptor == NULL) return false; if (pDssiDescriptor->get_program == NULL) return false; // Only first one instance should matter... const DSSI_Program_Descriptor *pDssiProgram = (*pDssiDescriptor->get_program)(m_phInstances[0], iIndex); if (pDssiProgram == NULL) return false; // Map this to that... program.bank = pDssiProgram->Bank; program.prog = pDssiProgram->Program; program.name = pDssiProgram->Name; return true; } // MIDI continuous controller handler. void qtractorDssiPlugin::setController ( int iController, int iValue ) { qtractorPluginParam *pParam = m_apControllerMap[DSSI_CC_NUMBER(iController)]; if (pParam == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorDssiPlugin[%p]::setController(%d, %d) index=%d", this, iController, iValue, int(pParam->index())); #endif float fValue = float(iValue) / 127.0f; pParam->setValue(fValue, true); } // Configuration (CLOB) stuff. void qtractorDssiPlugin::configure ( const QString& sKey, const QString& sValue ) { if (m_phInstances == NULL) return; const DSSI_Descriptor *pDssiDescriptor = dssi_descriptor(); if (pDssiDescriptor == NULL) return; if (pDssiDescriptor->configure == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorDssiPlugin[%p]::configure(\"%s\", \"%s\")", this, sKey.toUtf8().constData(), sValue.toUtf8().constData()); #endif // For each plugin instance... for (unsigned short i = 0; i < instances(); ++i) { (*pDssiDescriptor->configure)(m_phInstances[i], sKey.toUtf8().constData(), sValue.toUtf8().constData()); } #ifdef CONFIG_LIBLO if (m_pDssiEditor) { osc_send_configure(m_pDssiEditor, sKey.toUtf8().constData(), sValue.toUtf8().constData()); } #endif } // Specific accessor. const DSSI_Descriptor *qtractorDssiPlugin::dssi_descriptor (void) const { qtractorDssiPluginType *pDssiType = static_cast (type()); return (pDssiType ? pDssiType->dssi_descriptor() : NULL); } // Update all control output ports... void qtractorDssiPlugin::updateControlOuts ( bool bForce ) { #ifdef CONFIG_LIBLO if (m_pDssiEditor && m_piControlOuts && m_pfControlOuts) { unsigned long iControlOuts = type()->controlOuts(); for (unsigned long j = 0; j < iControlOuts; ++j) { // if (::fabs(m_pfControlOuts[j] - m_pfControlOutsLast[j]) > 1e-6f) { if (m_pfControlOutsLast[j] != m_pfControlOuts[j] || bForce) { osc_send_control(m_pDssiEditor, m_piControlOuts[j], m_pfControlOuts[j]); m_pfControlOutsLast[j] = m_pfControlOuts[j]; } } } #endif } // Reset(null) internal editor reference. void qtractorDssiPlugin::clearEditor (void) { m_pDssiEditor = NULL; if (isFormVisible()) form()->toggleEditor(false); m_bEditorVisible = false; } // Idle editor update (static) void qtractorDssiPlugin::idleEditorAll (void) { #ifdef CONFIG_LIBLO QHash::ConstIterator iter = g_dssiEditors.constBegin(); const QHash::ConstIterator& iter_end = g_dssiEditors.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorDssiPlugin *pDssiPlugin = iter.value()->plugin; if (pDssiPlugin) pDssiPlugin->updateControlOuts(); } #endif } #endif // CONFIG_DSSI // end of qtractorDssiPlugin.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiClip.cpp0000644000175000001440000000012312166526620021227 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134669.93608 30 ctime=1381134669.936080095 qtractor-0.5.11/src/qtractorMidiClip.cpp0000644000175000001440000007640012166526620020525 0ustar00rncbcusers00000000000000// qtractorMidiClip.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiClip.h" #include "qtractorMidiEngine.h" #include "qtractorSession.h" #include "qtractorFileList.h" #include "qtractorDocument.h" #include "qtractorMidiEditor.h" #include "qtractorMidiEditorForm.h" #include "qtractorMainForm.h" #ifdef QTRACTOR_MIDI_EDITOR_TOOL #include "qtractorOptions.h" #endif #include #include #include #include #if QT_VERSION < 0x040500 namespace Qt { const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000); } #endif //---------------------------------------------------------------------- // class qtractorMidiClip::Key -- MIDI sequence clip (hash key). // class qtractorMidiClip::Key { public: // Constructor. Key(qtractorMidiClip *pMidiClip) { update(pMidiClip); } // Key settler. void update(qtractorMidiClip *pMidiClip) { qtractorTrack *pTrack = pMidiClip->track(); m_sFilename = pMidiClip->filename();; m_iClipOffset = pMidiClip->clipOffset(); m_iClipLength = pMidiClip->clipLength(); m_iTrackChannel = pMidiClip->trackChannel(); m_iMidiChannel = (pTrack ? pTrack->midiChannel() : 0); } // Key accessors. const QString& filename() const { return m_sFilename; } unsigned long clipOffset() const { return m_iClipOffset; } unsigned long clipLength() const { return m_iClipLength; } unsigned short trackChannel() const { return m_iTrackChannel; } unsigned short midiChannel() const { return m_iMidiChannel; } // Match descriminator. bool operator== (const Key& other) const { return m_sFilename == other.filename() && m_iClipOffset == other.clipOffset() && m_iClipLength == other.clipLength() && m_iTrackChannel == other.trackChannel() && m_iMidiChannel == other.midiChannel(); } private: // Interesting variables. QString m_sFilename; unsigned long m_iClipOffset; unsigned long m_iClipLength; unsigned short m_iTrackChannel; unsigned short m_iMidiChannel; }; uint qHash ( const qtractorMidiClip::Key& key ) { return qHash(key.filename()) ^ qHash(key.clipOffset()) ^ qHash(key.clipLength()) ^ qHash(key.trackChannel()) ^ qHash(key.midiChannel()); } qtractorMidiClip::Hash qtractorMidiClip::g_hashTable; //---------------------------------------------------------------------- // class qtractorMidiClip::FileKey -- MIDI file hash key. // class qtractorMidiClip::FileKey { public: // Constructor. FileKey(qtractorMidiClip::Key *pKey) : m_sFilename(pKey->filename()), m_iTrackChannel(pKey->trackChannel()) {} // Key accessors. const QString& filename() const { return m_sFilename; } unsigned short trackChannel() const { return m_iTrackChannel; } // Match descriminator. bool operator== (const FileKey& other) const { return m_sFilename == other.filename() && m_iTrackChannel == other.trackChannel(); } private: // Interesting variables. QString m_sFilename; unsigned short m_iTrackChannel; }; uint qHash ( const qtractorMidiClip::FileKey& key ) { return qHash(key.filename()) ^ qHash(key.trackChannel()); } qtractorMidiClip::FileHash qtractorMidiClip::g_hashFiles; //---------------------------------------------------------------------- // class qtractorMidiClip -- MIDI sequence clip. // // Constructor. qtractorMidiClip::qtractorMidiClip ( qtractorTrack *pTrack ) : qtractorClip(pTrack) { m_pFile = NULL; m_pKey = NULL; m_pData = NULL; m_iTrackChannel = 0; m_iFormat = defaultFormat(); m_bSessionFlag = false; m_iRevision = 0; m_noteMin = 0; m_noteMax = 0; m_pMidiEditorForm = NULL; } // Copy constructor. qtractorMidiClip::qtractorMidiClip ( const qtractorMidiClip& clip ) : qtractorClip(clip.track()) { m_pFile = NULL; m_pKey = NULL; m_pData = NULL; setFilename(clip.filename()); setTrackChannel(clip.trackChannel()); setClipGain(clip.clipGain()); m_iFormat = clip.format(); m_bSessionFlag = false; m_iRevision = clip.revision(); m_noteMin = clip.noteMin(); m_noteMax = clip.noteMax(); m_pMidiEditorForm = NULL; } // Destructor. qtractorMidiClip::~qtractorMidiClip (void) { close(); closeMidiFile(); } // Brand new clip contents new method. bool qtractorMidiClip::createMidiFile ( const QString& sFilename, int iTrackChannel ) { closeMidiFile(); qtractorTrack *pTrack = track(); if (pTrack == NULL) return false; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return false; #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiClip[%p]::createMidiFile(\"%s\", %d)", this, sFilename.toUtf8().constData(), iTrackChannel); #endif // Self holds the SMF format, unsigned short iFormat = format(); unsigned short iTracks = 1; // Which SMF format? if (iFormat == 0) { // SMF format 0 (1 track, 1 channel) iTrackChannel = pTrack->midiChannel(); } else { // SMF format 1 (2 tracks, 1 channel) iTrackChannel = 1; ++iTracks; } // Set local properties... setFilename(sFilename); setTrackChannel(iTrackChannel); setDirty(false); // Register file path... pSession->files()->addClipItem(qtractorFileList::Midi, this, true); // Create and open up the MIDI file... m_pFile = new qtractorMidiFile(); if (!m_pFile->open(sFilename, qtractorMidiFile::Write)) { delete m_pFile; m_pFile = NULL; return false; } // Initialize MIDI event container... m_pKey = new Key(this); m_pData = new Data(); m_pData->attach(this); // Right on then... insertHashKey(); qtractorMidiSequence *pSeq = m_pData->sequence(); pSeq->clear(); pSeq->setTicksPerBeat(pSession->ticksPerBeat()); pSeq->setName(shortClipName(QFileInfo(sFilename).baseName())); pSeq->setChannel(pTrack->midiChannel()); // Make it a brand new revision... setRevision(1); // Write SMF header... if (m_pFile->writeHeader(iFormat, iTracks, pSeq->ticksPerBeat())) { // Set initial local properties... if (m_pFile->tempoMap()) { m_pFile->tempoMap()->fromTimeScale( pSession->timeScale(), pSession->tickFromFrame(clipStart())); } // Sure this is a brand new file... if (iFormat == 1) m_pFile->writeTrack(NULL); m_pFile->writeTrack(pSeq); m_pFile->close(); } // It's there now. delete m_pFile; m_pFile = NULL; // Clip name should be clear about it all. if (clipName().isEmpty()) setClipName(pSeq->name()); if (clipName().isEmpty()) setClipName(shortClipName(QFileInfo(filename()).baseName())); // Uh oh... m_playCursor.reset(pSeq); m_drawCursor.reset(pSeq); return true; } // The main use method. bool qtractorMidiClip::openMidiFile ( const QString& sFilename, int iTrackChannel, int iMode ) { closeMidiFile(); qtractorTrack *pTrack = track(); if (pTrack == NULL) return false; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return false; #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiClip[%p]::openMidiFile(\"%s\", %d, %d)", this, sFilename.toUtf8().constData(), iTrackChannel, iMode); #endif // Check file primordial state... bool bWrite = (iMode & qtractorMidiFile::Write); // Set local properties... setFilename(sFilename); setTrackChannel(iTrackChannel); setDirty(false); // Register file path... pSession->files()->addClipItem(qtractorFileList::Midi, this, bWrite); // New key-data sequence... if (!bWrite) { m_pKey = new Key(this); m_pData = g_hashTable.value(*m_pKey, NULL); if (m_pData) { m_pData->attach(this); qtractorMidiSequence *pSeq = m_pData->sequence(); // Clip name should be clear about it all. if (clipName().isEmpty()) setClipName(pSeq->name()); if (clipName().isEmpty()) setClipName(shortClipName(QFileInfo(filename()).baseName())); // Uh oh... m_playCursor.reset(pSeq); m_drawCursor.reset(pSeq); return true; } } // Create and open up the real MIDI file... m_pFile = new qtractorMidiFile(); if (!m_pFile->open(sFilename, iMode)) { delete m_pFile; m_pFile = NULL; return false; } // Initialize MIDI event container... m_pData = new Data(); m_pData->attach(this); qtractorMidiSequence *pSeq = m_pData->sequence(); pSeq->clear(); pSeq->setTicksPerBeat(pSession->ticksPerBeat()); qtractorTimeScale::Cursor cursor(pSession->timeScale()); qtractorTimeScale::Node *pNode = cursor.seekFrame(clipStart()); unsigned long t0 = pNode->tickFromFrame(clipStart()); if (clipStart() > clipOffset()) { unsigned long iOffset = clipStart() - clipOffset(); pNode = cursor.seekFrame(iOffset); pSeq->setTimeOffset(t0 - pNode->tickFromFrame(iOffset)); } else { pNode = cursor.seekFrame(clipOffset()); pSeq->setTimeOffset(pNode->tickFromFrame(clipOffset())); } unsigned long iClipEnd = clipStart() + clipLength(); pNode = cursor.seekFrame(iClipEnd); pSeq->setTimeLength(pNode->tickFromFrame(iClipEnd) - t0); // Initial statistics... pSeq->setNoteMin(m_noteMin); pSeq->setNoteMax(m_noteMax); // Are we on a pre-writing status? if (bWrite) { // On write mode, iTrackChannel holds the SMF format, // so we'll convert it here as properly. unsigned short iFormat = 0; unsigned short iTracks = 1; if (iTrackChannel == 0) { // SMF format 0 (1 track, 1 channel) iTrackChannel = pTrack->midiChannel(); } else { // SMF format 1 (2 tracks, 1 channel) iTrackChannel = 1; iFormat = 1; ++iTracks; } // That's it. setFormat(iFormat); // Write SMF header... if (m_pFile->writeHeader(iFormat, iTracks, pSeq->ticksPerBeat())) { // Set initial local properties... if (m_pFile->tempoMap()) { m_pFile->tempoMap()->fromTimeScale( pSession->timeScale(), pSeq->timeOffset()); } } // And initial clip name... pSeq->setName(shortClipName(QFileInfo(m_pFile->filename()).baseName())); pSeq->setChannel(pTrack->midiChannel()); // Nothing more as for writing... } else { // On read mode, SMF format is properly given by open file. setFormat(m_pFile->format()); // Read the event sequence in... m_pFile->readTrack(pSeq, iTrackChannel); // For immediate feedback, once... m_noteMin = pSeq->noteMin(); m_noteMax = pSeq->noteMax(); // FIXME: On demand, set session time properties from MIDI file... if (m_bSessionFlag) { #if 0 // Import eventual SysEx setup... // - take care that given track might not be currently open, // so that we'll resolve MIDI output bus somehow... qtractorMidiBus *pMidiBus = NULL; qtractorMidiEngine *pMidiEngine = pSession->midiEngine(); if (pMidiEngine) { pMidiBus = static_cast ( pMidiEngine->findOutputBus(pTrack->outputBusName())); if (pMidiBus == NULL) { for (qtractorBus *pBus = pMidiEngine->buses().first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Output) { pMidiBus = static_cast (pBus); break; } } } } // Import eventual SysEx setup... if (pMidiBus) pMidiBus->importSysexList(pSeq); #endif // Import tempo map as well... if (m_pFile->tempoMap()) { m_pFile->tempoMap()->intoTimeScale(pSession->timeScale(), t0); pSession->updateTimeScale(); } // Reset session flag now. m_bSessionFlag = false; } // We should have events, otherwise this clip is of no use... //if (m_pSeq->events().count() < 1) // return false; } // Make it a brand new revision... // setRevision(1); // Default clip length will be whole sequence duration. if (clipLength() == 0 && pSeq->timeLength() > pSeq->timeOffset()) { unsigned long t1 = t0 + (pSeq->timeLength() - pSeq->timeOffset()); pNode = cursor.seekTick(t1); setClipLength(pNode->frameFromTick(t1) - clipStart()); } // Clip name should be clear about it all. if (clipName().isEmpty()) setClipName(pSeq->name()); if (clipName().isEmpty()) setClipName(shortClipName(QFileInfo(filename()).baseName())); // Uh oh... m_playCursor.reset(pSeq); m_drawCursor.reset(pSeq); // Something might have changed... updateHashKey(); insertHashKey(); return true; } // Private cleanup. void qtractorMidiClip::closeMidiFile (void) { if (m_pMidiEditorForm) { m_pMidiEditorForm->close(); delete m_pMidiEditorForm; m_pMidiEditorForm = NULL; } if (m_pData) { m_pData->detach(this); if (m_pData->count() < 1) { removeHashKey(); delete m_pData; } m_pData = NULL; // Unregister file path... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) pSession->files()->removeClipItem(qtractorFileList::Midi, this); } if (m_pKey) { delete m_pKey; m_pKey = NULL; } if (m_pFile) { delete m_pFile; m_pFile = NULL; } } // Revisionist method. QString qtractorMidiClip::createFilePathRevision ( bool bForce ) { QString sFilename = filename(); // Check file-hash reference... if (m_iRevision > 0 && m_pKey) { FileKey fkey(m_pKey); FileHash::ConstIterator fiter = g_hashFiles.constFind(fkey); if (fiter != g_hashFiles.constEnd() && fiter.value() > 1) m_iRevision = 0; } if (m_iRevision == 0 || bForce) { qtractorTrack *pTrack = track(); qtractorSession *pSession = qtractorSession::getInstance(); if (pTrack && pSession) sFilename = pSession->createFilePath(pTrack->trackName(), "mid"); sFilename = qtractorMidiFile::createFilePathRevision(sFilename); #ifdef CONFIG_DEBUG qDebug("qtractorMidiClip::createFilePathRevision(%d): \"%s\" (%d)", int(bForce), sFilename.toUtf8().constData(), m_iRevision); #endif m_iRevision = 0; } ++m_iRevision; return sFilename; } // Sync all ref-counted filenames. void qtractorMidiClip::setFilenameEx ( const QString& sFilename ) { qtractorTrack *pTrack = track(); if (pTrack == NULL) return; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return; if (m_pData == NULL) return; removeHashKey(); QListIterator iter(m_pData->clips()); while (iter.hasNext()) { qtractorMidiClip *pMidiClip = iter.next(); pSession->files()->removeClipItem(qtractorFileList::Midi, pMidiClip); pMidiClip->setFilename(sFilename); pMidiClip->setDirty(false); pMidiClip->updateHashKey(); pMidiClip->updateEditor(true); pSession->files()->addClipItem(qtractorFileList::Midi, pMidiClip, true); } insertHashKey(); } // Sync all ref-counted clip-lengths. void qtractorMidiClip::setClipLengthEx ( unsigned long iClipLength ) { if (m_pData == NULL) return; removeHashKey(); QListIterator iter(m_pData->clips()); while (iter.hasNext()) { qtractorMidiClip *pMidiClip = iter.next(); pMidiClip->setClipLength(iClipLength); pMidiClip->updateHashKey(); } insertHashKey(); } // Sync all ref-counted clip editors. void qtractorMidiClip::updateEditorEx ( bool bSelectClear ) { if (m_pData == NULL) return; QListIterator iter(m_pData->clips()); while (iter.hasNext()) iter.next()->updateEditor(bSelectClear); } void qtractorMidiClip::resetEditorEx ( bool bSelectClear ) { if (m_pData == NULL) return; QListIterator iter(m_pData->clips()); while (iter.hasNext()) iter.next()->resetEditor(bSelectClear); } // Sync all ref-counted clip-dirtyness. void qtractorMidiClip::setDirtyEx ( bool bDirty ) { if (m_pData == NULL) return; QListIterator iter(m_pData->clips()); while (iter.hasNext()) iter.next()->setDirty(bDirty); } // Manage local hash key. void qtractorMidiClip::insertHashKey (void) { if (m_pKey) { // Increment file-hash reference... FileKey fkey(m_pKey); FileHash::Iterator fiter = g_hashFiles.find(fkey); if (fiter == g_hashFiles.end()) fiter = g_hashFiles.insert(fkey, 0); ++fiter.value(); // Insert actual clip-hash reference.... g_hashTable.insert(*m_pKey, m_pData); } } void qtractorMidiClip::updateHashKey (void) { if (m_pKey == NULL) m_pKey = new Key(this); else m_pKey->update(this); } void qtractorMidiClip::removeHashKey (void) { if (m_pKey) { // Decrement file-hash reference... FileKey fkey(m_pKey); FileHash::Iterator fiter = g_hashFiles.find(fkey); if (fiter != g_hashFiles.end()) { if (--fiter.value() < 1) g_hashFiles.remove(fkey); } // Remove actual clip-hash reference.... g_hashTable.remove(*m_pKey); } } // Unlink (clone) local hash data. void qtractorMidiClip::unlinkHashData (void) { if (m_pData == NULL) return; if (m_pData->count() < 2) return; m_pData->detach(this); Data *pNewData = new Data(); qtractorMidiSequence *pOldSeq = m_pData->sequence(); qtractorMidiSequence *pNewSeq = pNewData->sequence(); pNewSeq->setName(pOldSeq->name()); pNewSeq->setChannel(pOldSeq->channel()); pNewSeq->setBank(pOldSeq->bank()); pNewSeq->setProg(pOldSeq->prog()); pNewSeq->setTicksPerBeat(pOldSeq->ticksPerBeat()); pNewSeq->setTimeOffset(pOldSeq->timeOffset()); pNewSeq->setTimeLength(pOldSeq->timeLength()); pNewSeq->setDuration(pOldSeq->duration()); pNewSeq->setNoteMin(pOldSeq->noteMin()); pNewSeq->setNoteMax(pOldSeq->noteMax()); pNewSeq->copyEvents(pOldSeq); m_pData = pNewData; m_pData->attach(this); updateHashKey(); insertHashKey(); } // Relink local hash data. void qtractorMidiClip::relinkHashData (void) { if (m_pData == NULL) return; if (m_pData->count() > 1) return; removeHashKey(); updateHashKey(); Data *pNewData = g_hashTable.value(*m_pKey, NULL); if (pNewData == NULL) { delete m_pKey; m_pKey = NULL; } else { m_pData->detach(this); delete m_pData; m_pData = pNewData; m_pData->attach(this); } insertHashKey(); } // Whether local hash is being shared. bool qtractorMidiClip::isHashLinked (void) const { return (m_pData && m_pData->count() > 1); } // Make sure the clip hash-table gets reset. void qtractorMidiClip::clearHashTable (void) { g_hashTable.clear(); g_hashFiles.clear(); } // Intra-clip playback frame positioning. void qtractorMidiClip::seek ( unsigned long iFrame ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiClip[%p]::seek(%lu)", this, iFrame); #endif qtractorTrack *pTrack = track(); if (pTrack == NULL) return; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return; qtractorMidiSequence *pSeq = sequence(); if (pSeq == NULL) return; unsigned long t0 = pSession->tickFromFrame(clipStart()); unsigned long t1 = pSession->tickFromFrame(iFrame); // Seek for the nearest sequence event... m_playCursor.seek(pSeq, (t1 > t0 ? t1 - t0 : 0)); } // Reset clip state. void qtractorMidiClip::reset ( bool /* bLooping */ ) { qtractorMidiSequence *pSeq = sequence(); if (pSeq == NULL) return; // Reset to the first sequence event... m_playCursor.reset(pSeq); } // Loop positioning. void qtractorMidiClip::setLoop ( unsigned long /* iLoopStart */, unsigned long /* iLoopEnd */ ) { // Do nothing? } // Clip close-commit (record specific) void qtractorMidiClip::close (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiClip[%p]::close(%d)\n", this); #endif qtractorTrack *pTrack = track(); if (pTrack == NULL) return; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return; // Take pretended clip-length... unsigned long iClipLength = clipLength(); qtractorMidiSequence *pSeq = sequence(); if (pSeq) { if (iClipLength > 0) pSeq->setTimeLength(pSession->tickFromFrame(iClipLength)); // Final read statistics... m_noteMin = pSeq->noteMin(); m_noteMax = pSeq->noteMax(); // Actual sequence closure... pSeq->close(); // Commit the final clip length... if (iClipLength < 1) { iClipLength = pSession->frameFromTick(pSeq->duration()); setClipLength(iClipLength); } } // Now's time to write the whole thing... bool bNewFile = (m_pFile && m_pFile->mode() == qtractorMidiFile::Write); if (bNewFile && iClipLength > 0 && pSeq) { // Write channel tracks... if (m_iFormat == 1) m_pFile->writeTrack(NULL); // Setup track (SMF format 1). m_pFile->writeTrack(pSeq); // Channel track. m_pFile->close(); } // Just to be sure things get deallocated.. closeMidiFile(); // If proven empty, remove the file. if (bNewFile && iClipLength < 1) QFile::remove(filename()); } // MIDI clip (re)open method. void qtractorMidiClip::open (void) { // Go open the proper file... openMidiFile(filename(), m_iTrackChannel); } // Audio clip special process cycle executive. void qtractorMidiClip::process ( unsigned long iFrameStart, unsigned long iFrameEnd ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiClip[%p]::process(%lu, %lu)\n", this, iFrameStart, iFrameEnd); #endif qtractorTrack *pTrack = track(); if (pTrack == NULL) return; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return; qtractorMidiEngine *pMidiEngine = pSession->midiEngine(); if (pMidiEngine == NULL) return; qtractorMidiSequence *pSeq = sequence(); if (pSeq == NULL) return; // Track mute state... bool bMute = (pTrack->isMute() || (pSession->soloTracks() && !pTrack->isSolo())); unsigned long t0 = pSession->tickFromFrame(clipStart()); unsigned long iTimeStart = pSession->tickFromFrame(iFrameStart); unsigned long iTimeEnd = pSession->tickFromFrame(iFrameEnd); // Enqueue the requested events... qtractorMidiEvent *pEvent = m_playCursor.seek(pSeq, iTimeStart > t0 ? iTimeStart - t0 : 0); while (pEvent) { unsigned long t1 = t0 + pEvent->time(); if (t1 >= iTimeEnd) break; if (t1 >= iTimeStart && (!bMute || pEvent->type() != qtractorMidiEvent::NOTEON)) pMidiEngine->enqueue(pTrack, pEvent, t1, gain(pSession->frameFromTick(t1) - clipStart())); pEvent = pEvent->next(); } } // Audio clip paint method. void qtractorMidiClip::draw ( QPainter *pPainter, const QRect& clipRect, unsigned long iClipOffset ) { qtractorTrack *pTrack = track(); if (pTrack == NULL) return; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return; qtractorMidiSequence *pSeq = sequence(); if (pSeq == NULL) return; // Check maximum note span... int iNoteSpan = (pSeq->noteMax() - pSeq->noteMin()) + 1; if (iNoteSpan < 6) iNoteSpan = 6; unsigned long iFrameStart = clipStart() + iClipOffset; int cx = pSession->pixelFromFrame(iFrameStart); qtractorTimeScale::Cursor cursor(pSession->timeScale()); qtractorTimeScale::Node *pNode = cursor.seekFrame(clipStart()); unsigned long t0 = pNode->tickFromFrame(clipStart()); pNode = cursor.seekFrame(iFrameStart); unsigned long iTimeStart = pNode->tickFromFrame(iFrameStart); pNode = cursor.seekPixel(cx + clipRect.width()); unsigned long iTimeEnd = pNode->tickFromPixel(cx + clipRect.width()); const QColor& fg = pTrack->foreground(); pPainter->setPen(fg); pPainter->setBrush(fg.lighter()); bool bClipRecord = (pTrack->clipRecord() == this); int h1 = clipRect.height() - 3; int h = h1 / iNoteSpan; if (h < 3) h = 3; qtractorMidiEvent *pEvent = m_drawCursor.reset(pSeq, iTimeStart > t0 ? iTimeStart - t0 : 0); while (pEvent) { unsigned long t1 = t0 + pEvent->time(); if (t1 >= iTimeEnd) break; unsigned long t2 = t1 + pEvent->duration(); if (pEvent->type() == qtractorMidiEvent::NOTEON && t2 >= iTimeStart) { pNode = cursor.seekTick(t1); int x = clipRect.x() + pNode->pixelFromTick(t1) - cx; int y = clipRect.bottom() - (h1 * (pEvent->note() - pSeq->noteMin() + 1)) / iNoteSpan; int w = (pEvent->duration() > 0 || !bClipRecord ? clipRect.x() + pNode->pixelFromTick(t2) - cx : clipRect.right()) - x; // Pending note-off? (while recording) if (h > 3 && w > 3) { // if (w < 5) w = 5; pPainter->fillRect(x, y, w, h - 1, fg); pPainter->fillRect(x + 1, y + 1, w - 4, h - 4, fg.lighter()); } else { if (w < 3) w = 3; pPainter->drawRect(x, y, w, h - 1); } } pEvent = pEvent->next(); } } // Clip editor method. bool qtractorMidiClip::startEditor ( QWidget *pParent ) { qtractorTrack *pTrack = track(); if (pTrack == NULL) return false; if (m_pMidiEditorForm == NULL) { // Build up the editor form... // What style do we create tool childs? Qt::WindowFlags wflags = Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint; #ifdef QTRACTOR_MIDI_EDITOR_TOOL qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions && pOptions->bKeepToolsOnTop) wflags |= Qt::Tool; #endif // Do it... m_pMidiEditorForm = new qtractorMidiEditorForm(pParent, wflags); // Set its most standing properties... m_pMidiEditorForm->show(); m_pMidiEditorForm->setup(this); } else { // Just show up the editor form... m_pMidiEditorForm->setup(); m_pMidiEditorForm->show(); } // Get it up any way... m_pMidiEditorForm->raise(); m_pMidiEditorForm->activateWindow(); return true; } // Clip editor reset. void qtractorMidiClip::resetEditor ( bool bSelectClear ) { if (m_pMidiEditorForm) { qtractorMidiEditor *pMidiEditor = m_pMidiEditorForm->editor(); if (pMidiEditor) pMidiEditor->reset(bSelectClear); m_pMidiEditorForm->resetDirtyCount(); } } // Clip editor update. void qtractorMidiClip::updateEditor ( bool bSelectClear ) { if (m_pMidiEditorForm == NULL) return; qtractorMidiEditor *pMidiEditor = m_pMidiEditorForm->editor(); if (pMidiEditor) { pMidiEditor->reset(bSelectClear); pMidiEditor->setOffset(clipStart()); pMidiEditor->setLength(clipLength()); qtractorTrack *pTrack = track(); if (pTrack) { pMidiEditor->setForeground(pTrack->foreground()); pMidiEditor->setBackground(pTrack->background()); } pMidiEditor->updateContents(); } m_pMidiEditorForm->resetDirtyCount(); m_pMidiEditorForm->updateInstrumentNames(); m_pMidiEditorForm->stabilizeForm(); } // Clip query-close method (return true if editing is done). bool qtractorMidiClip::queryEditor (void) { if (m_pMidiEditorForm) return m_pMidiEditorForm->queryClose(); // Are any dirty changes pending commit? bool bQueryEditor = qtractorClip::queryEditor(); if (!bQueryEditor) { switch (qtractorMidiEditorForm::querySave(filename())) { case QMessageBox::Save: { // Save/replace the clip track... bQueryEditor = saveCopyFile(); break; } case QMessageBox::Discard: bQueryEditor = true; break; case QMessageBox::Cancel: bQueryEditor = false; break; } } return bQueryEditor; } // MIDI clip tool-tip. QString qtractorMidiClip::toolTip (void) const { QString sToolTip = qtractorClip::toolTip() + ' '; sToolTip += QObject::tr("(format %1)\nMIDI:\t").arg(m_iFormat); if (m_iFormat == 0) sToolTip += QObject::tr("Channel %1").arg(m_iTrackChannel + 1); else sToolTip += QObject::tr("Track %1").arg(m_iTrackChannel); if (m_pFile) { sToolTip += QObject::tr(", %1 tracks, %2 tpqn") .arg(m_pFile->tracks()) .arg(m_pFile->ticksPerBeat()); } if (clipGain() > 1.0f) sToolTip += QObject::tr(" (%1% vol)") .arg(100.0f * clipGain(), 0, 'g', 3); return sToolTip; } // Auto-save to (possible) new file revision. bool qtractorMidiClip::saveCopyFile (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // Have a new filename revision... const QString& sFilename = createFilePathRevision(); // Save/replace the clip track... if (!qtractorMidiFile::saveCopyFile( sFilename, filename(), trackChannel(), format(), sequence(), pSession->timeScale(), pSession->tickFromFrame(clipStart()))) return false; // Pre-commit dirty changes... setFilenameEx(sFilename); // Reference for immediate file addition... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->addMidiFile(sFilename); return true; } // Virtual document element methods. bool qtractorMidiClip::loadClipElement ( qtractorDocument * /* pDocument */, QDomElement *pElement ) { // Load track children... for (QDomNode nChild = pElement->firstChild(); !nChild.isNull(); nChild = nChild.nextSibling()) { // Convert node to element... QDomElement eChild = nChild.toElement(); if (eChild.isNull()) continue; // Load track state.. if (eChild.tagName() == "filename") qtractorMidiClip::setFilename(eChild.text()); else if (eChild.tagName() == "track-channel") qtractorMidiClip::setTrackChannel(eChild.text().toUShort()); else if (eChild.tagName() == "revision") qtractorMidiClip::setRevision(eChild.text().toUShort()); } return true; } bool qtractorMidiClip::saveClipElement ( qtractorDocument *pDocument, QDomElement *pElement ) const { QDomElement eMidiClip = pDocument->document()->createElement("midi-clip"); pDocument->saveTextElement("filename", qtractorMidiClip::relativeFilename(pDocument), &eMidiClip); pDocument->saveTextElement("track-channel", QString::number(qtractorMidiClip::trackChannel()), &eMidiClip); pDocument->saveTextElement("revision", QString::number(qtractorMidiClip::revision()), &eMidiClip); pElement->appendChild(eMidiClip); return true; } // MIDI clip export method. bool qtractorMidiClip::clipExport ( ClipExport pfnClipExport, void *pvArg, unsigned long iOffset, unsigned long iLength ) const { qtractorTrack *pTrack = track(); if (pTrack == NULL) return false; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return false; qtractorMidiSequence *pSeq = sequence(); if (pSeq == NULL) return false; if (iLength < 1) iLength = clipLength(); unsigned short iTicksPerBeat = pSession->ticksPerBeat(); unsigned long iTimeOffset = pSeq->timeOffset(); qtractorTimeScale::Cursor cursor(pSession->timeScale()); qtractorTimeScale::Node *pNode = cursor.seekFrame(clipStart()); unsigned long t0 = pNode->tickFromFrame(clipStart()); unsigned long f1 = clipStart() + clipOffset() + iOffset; pNode = cursor.seekFrame(f1); unsigned long t1 = pNode->tickFromFrame(f1); unsigned long iTimeStart = t1 - t0; iTimeStart = (iTimeStart > iTimeOffset ? iTimeStart - iTimeOffset : 0); pNode = cursor.seekFrame(f1 += iLength); unsigned long iTimeEnd = iTimeStart + pNode->tickFromFrame(f1) - t1; qtractorMidiSequence seq(pSeq->name(), pSeq->channel(), iTicksPerBeat); seq.setBank(pTrack->midiBank()); seq.setProg(pTrack->midiProg()); for (qtractorMidiEvent *pEvent = pSeq->events().first(); pEvent; pEvent = pEvent->next()) { unsigned long iTime = pEvent->time(); if (iTime >= iTimeStart && iTime < iTimeEnd) { qtractorMidiEvent *pNewEvent = new qtractorMidiEvent(*pEvent); pNewEvent->setTime(iTime - iTimeStart); if (pNewEvent->type() == qtractorMidiEvent::NOTEON) { pNewEvent->setVelocity((unsigned char) (clipGain() * float(pNewEvent->velocity())) & 0x7f); if (iTime + pEvent->duration() > iTimeEnd) pNewEvent->setDuration(iTimeEnd - iTime); } seq.insertEvent(pNewEvent); } } (*pfnClipExport)(&seq, pvArg); return true; } // Default MIDI file format (for capture/record) accessors. unsigned short qtractorMidiClip::g_iDefaultFormat = 0; void qtractorMidiClip::setDefaultFormat ( unsigned short iFormat ) { g_iDefaultFormat = iFormat; } unsigned short qtractorMidiClip::defaultFormat (void) { return g_iDefaultFormat; } // end of qtractorMidiClip.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditorForm.cpp0000644000175000001440000000012312166526620022412 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134670.36608 30 ctime=1381134670.366080102 qtractor-0.5.11/src/qtractorMidiEditorForm.cpp0000644000175000001440000015631012166526620021707 0ustar00rncbcusers00000000000000// qtractorMidiEditorForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiEditorForm.h" #include "qtractorMidiEditor.h" #include "qtractorMidiEditView.h" #include "qtractorMidiEditEvent.h" #include "qtractorMidiClip.h" #include "qtractorMidiEngine.h" #include "qtractorMidiMonitor.h" #include "qtractorOptions.h" #include "qtractorSession.h" #include "qtractorTracks.h" #include "qtractorTrackView.h" #include "qtractorConnections.h" #include "qtractorMainForm.h" #include "qtractorShortcutForm.h" #include "qtractorPasteRepeatForm.h" #include "qtractorClipForm.h" #include "qtractorTimeScale.h" #include "qtractorCommand.h" #include "qtractorMidiEventList.h" #include "qtractorFileList.h" #include #include #include #include #include #include #include //------------------------------------------------------------------------- // qtractorMidiEditorForm -- Main window form implementation. // Constructor. qtractorMidiEditorForm::qtractorMidiEditorForm ( QWidget */*pParent*/, Qt::WindowFlags wflags ) : QMainWindow(NULL/*pParent*/, wflags) { // Setup UI struct... m_ui.setupUi(this); m_iDirtyCount = 0; // Set our central widget. m_pMidiEditor = new qtractorMidiEditor(this); setCentralWidget(m_pMidiEditor); // Dockable widgets time. m_pMidiEventList = new qtractorMidiEventList(this); m_pMidiEventList->setEditor(m_pMidiEditor); m_pMidiEventList->hide(); // Initially hidden. // Set edit-mode action group up... m_pEditModeActionGroup = new QActionGroup(this); m_pEditModeActionGroup->setExclusive(true); m_pEditModeActionGroup->addAction(m_ui.editModeOnAction); m_pEditModeActionGroup->addAction(m_ui.editModeOffAction); // Snap-per-beat combo-box. m_pSnapPerBeatComboBox = new QComboBox(m_ui.viewToolbar); m_pSnapPerBeatComboBox->setEditable(false); // Event type selection widgets... m_pViewTypeComboBox = new QComboBox(m_ui.editViewToolbar); m_pViewTypeComboBox->setEditable(false); m_pEventTypeComboBox = new QComboBox(m_ui.editEventToolbar); m_pEventTypeComboBox->setEditable(false); m_pControllerComboBox = new QComboBox(m_ui.editEventToolbar); m_pControllerComboBox->setEditable(false); m_pControllerComboBox->setMinimumWidth(220); // Snap-to-scale/quantize selection widgets... m_pSnapToScaleKeyComboBox = new QComboBox(m_ui.snapToScaleToolbar); m_pSnapToScaleKeyComboBox->setEditable(false); m_pSnapToScaleKeyComboBox->setMinimumWidth(86); m_pSnapToScaleTypeComboBox = new QComboBox(m_ui.snapToScaleToolbar); m_pSnapToScaleKeyComboBox->setEditable(false); // View/Snap-to-beat actions initialization... int iSnap = 0; const QString sSnapObjectName("viewSnapPerBeat%1"); const QString sSnapStatusTip(tr("Set current snap to %1")); const QStringList& snapItems = qtractorTimeScale::snapItems(); QStringListIterator snapIter(snapItems); while (snapIter.hasNext()) { const QString& sSnapText = snapIter.next(); QAction *pAction = new QAction(sSnapText, this); pAction->setObjectName(sSnapObjectName.arg(iSnap)); pAction->setStatusTip(sSnapStatusTip.arg(sSnapText)); pAction->setCheckable(true); pAction->setData(iSnap++); QObject::connect(pAction, SIGNAL(triggered(bool)), SLOT(viewSnap())); m_snapPerBeatActions.append(pAction); addAction(pAction); } // Pre-fill the combo-boxes... m_pSnapPerBeatComboBox->insertItems(0, snapItems); const QIcon icon(":/images/itemProperty.png"); m_pViewTypeComboBox->addItem(icon, tr("Note On"), int(qtractorMidiEvent::NOTEON)); m_pViewTypeComboBox->addItem(icon, tr("Key Press"), int(qtractorMidiEvent::KEYPRESS)); m_pEventTypeComboBox->addItem(icon, tr("Note Velocity"), int(qtractorMidiEvent::NOTEON)); m_pEventTypeComboBox->addItem(icon, tr("Key Press"), int(qtractorMidiEvent::KEYPRESS)); m_pEventTypeComboBox->addItem(icon, tr("Controller"), int(qtractorMidiEvent::CONTROLLER)); m_pEventTypeComboBox->addItem(icon, tr("Pgm Change"), int(qtractorMidiEvent::PGMCHANGE)); m_pEventTypeComboBox->addItem(icon, tr("Chan Press"), int(qtractorMidiEvent::CHANPRESS)); m_pEventTypeComboBox->addItem(icon, tr("Pitch Bend"), int(qtractorMidiEvent::PITCHBEND)); m_pEventTypeComboBox->addItem(icon, tr("Sys Ex"), int(qtractorMidiEvent::SYSEX)); // Snap-to-scale/quantize selection widgets... QStringListIterator iter(qtractorMidiEditor::scaleKeyNames()); while (iter.hasNext()) m_pSnapToScaleKeyComboBox->addItem(icon, iter.next()); m_pSnapToScaleTypeComboBox->insertItems(0, qtractorMidiEditor::scaleTypeNames()); // updateInstrumentNames(); // Set combo-boxes tooltips... m_pSnapPerBeatComboBox->setToolTip(tr("Snap/beat")); m_pViewTypeComboBox->setToolTip(tr("Note type")); m_pEventTypeComboBox->setToolTip(tr("Value type")); m_pControllerComboBox->setToolTip(tr("Controller type")); m_pSnapToScaleKeyComboBox->setToolTip(tr("Scale key")); m_pSnapToScaleTypeComboBox->setToolTip(tr("Scale type")); // Add combo-boxes to toolbars... m_ui.viewToolbar->addSeparator(); m_ui.viewToolbar->addWidget(m_pSnapPerBeatComboBox); m_ui.editViewToolbar->addWidget(m_pViewTypeComboBox); m_ui.editEventToolbar->addWidget(m_pEventTypeComboBox); m_ui.editEventToolbar->addSeparator(); m_ui.editEventToolbar->addWidget(m_pControllerComboBox); m_ui.snapToScaleToolbar->addWidget(m_pSnapToScaleKeyComboBox); m_ui.snapToScaleToolbar->addSeparator(); m_ui.snapToScaleToolbar->addWidget(m_pSnapToScaleTypeComboBox); QStatusBar *pStatusBar = statusBar(); const QSize pad(4, 0); const QString spc(4, ' '); // Status clip/sequence name... m_pTrackNameLabel = new QLabel(spc); m_pTrackNameLabel->setAlignment(Qt::AlignLeft); m_pTrackNameLabel->setToolTip(tr("MIDI clip name")); m_pTrackNameLabel->setAutoFillBackground(true); pStatusBar->addWidget(m_pTrackNameLabel, 1); // Status filename... m_pFileNameLabel = new QLabel(spc); m_pFileNameLabel->setAlignment(Qt::AlignLeft); m_pFileNameLabel->setToolTip(tr("MIDI file name")); m_pFileNameLabel->setAutoFillBackground(true); pStatusBar->addWidget(m_pFileNameLabel, 2); // Status track/channel number... m_pTrackChannelLabel = new QLabel(spc); m_pTrackChannelLabel->setAlignment(Qt::AlignHCenter); m_pTrackChannelLabel->setToolTip(tr("MIDI track/channel")); m_pTrackChannelLabel->setAutoFillBackground(true); pStatusBar->addWidget(m_pTrackChannelLabel); // Status modification status. m_pStatusModLabel = new QLabel(tr("MOD")); m_pStatusModLabel->setAlignment(Qt::AlignHCenter); m_pStatusModLabel->setMinimumSize(m_pStatusModLabel->sizeHint() + pad); m_pStatusModLabel->setToolTip(tr("MIDI modification state")); m_pStatusModLabel->setAutoFillBackground(true); pStatusBar->addPermanentWidget(m_pStatusModLabel); // Sequence duration status. m_pDurationLabel = new QLabel(tr("00:00:00.000")); m_pDurationLabel->setAlignment(Qt::AlignHCenter); m_pDurationLabel->setMinimumSize(m_pDurationLabel->sizeHint() + pad); m_pDurationLabel->setToolTip(tr("MIDI clip duration")); m_pDurationLabel->setAutoFillBackground(true); pStatusBar->addPermanentWidget(m_pDurationLabel); // Some actions surely need those // shortcuts firmly attached... addAction(m_ui.viewMenubarAction); // Special integration ones. addAction(m_ui.transportBackwardAction); addAction(m_ui.transportLoopAction); addAction(m_ui.transportLoopSetAction); addAction(m_ui.transportStopAction); addAction(m_ui.transportPlayAction); addAction(m_ui.transportPunchAction); addAction(m_ui.transportPunchSetAction); // Make those primordially docked... addDockWidget(Qt::RightDockWidgetArea, m_pMidiEventList, Qt::Vertical); // Ah, make it stand right. setFocus(); // UI signal/slot connections... QObject::connect(m_ui.fileSaveAction, SIGNAL(triggered(bool)), SLOT(fileSave())); QObject::connect(m_ui.fileSaveAsAction, SIGNAL(triggered(bool)), SLOT(fileSaveAs())); QObject::connect(m_ui.fileUnlinkAction, SIGNAL(triggered(bool)), SLOT(fileUnlink())); QObject::connect(m_ui.fileTrackInputsAction, SIGNAL(triggered(bool)), SLOT(fileTrackInputs())); QObject::connect(m_ui.fileTrackOutputsAction, SIGNAL(triggered(bool)), SLOT(fileTrackOutputs())); QObject::connect(m_ui.fileTrackPropertiesAction, SIGNAL(triggered(bool)), SLOT(fileTrackProperties())); QObject::connect(m_ui.filePropertiesAction, SIGNAL(triggered(bool)), SLOT(fileProperties())); QObject::connect(m_ui.fileRangeSetAction, SIGNAL(triggered(bool)), SLOT(fileRangeSet())); QObject::connect(m_ui.fileLoopSetAction, SIGNAL(triggered(bool)), SLOT(fileLoopSet())); QObject::connect(m_ui.fileCloseAction, SIGNAL(triggered(bool)), SLOT(fileClose())); QObject::connect(m_ui.editUndoAction, SIGNAL(triggered(bool)), SLOT(editUndo())); QObject::connect(m_ui.editRedoAction, SIGNAL(triggered(bool)), SLOT(editRedo())); QObject::connect(m_ui.editCutAction, SIGNAL(triggered(bool)), SLOT(editCut())); QObject::connect(m_ui.editCopyAction, SIGNAL(triggered(bool)), SLOT(editCopy())); QObject::connect(m_ui.editPasteRepeatAction, SIGNAL(triggered(bool)), SLOT(editPasteRepeat())); QObject::connect(m_ui.editPasteAction, SIGNAL(triggered(bool)), SLOT(editPaste())); QObject::connect(m_ui.editDeleteAction, SIGNAL(triggered(bool)), SLOT(editDelete())); QObject::connect(m_ui.editModeOnAction, SIGNAL(triggered(bool)), SLOT(editModeOn())); QObject::connect(m_ui.editModeOffAction, SIGNAL(triggered(bool)), SLOT(editModeOff())); QObject::connect(m_ui.editModeDrawAction, SIGNAL(triggered(bool)), SLOT(editModeDraw(bool))); QObject::connect(m_ui.editSelectAllAction, SIGNAL(triggered(bool)), SLOT(editSelectAll())); QObject::connect(m_ui.editSelectNoneAction, SIGNAL(triggered(bool)), SLOT(editSelectNone())); QObject::connect(m_ui.editSelectInvertAction, SIGNAL(triggered(bool)), SLOT(editSelectInvert())); QObject::connect(m_ui.editSelectRangeAction, SIGNAL(triggered(bool)), SLOT(editSelectRange())); QObject::connect(m_ui.editInsertRangeAction, SIGNAL(triggered(bool)), SLOT(editInsertRange())); QObject::connect(m_ui.editRemoveRangeAction, SIGNAL(triggered(bool)), SLOT(editRemoveRange())); QObject::connect(m_ui.toolsQuantizeAction, SIGNAL(triggered(bool)), SLOT(toolsQuantize())); QObject::connect(m_ui.toolsTransposeAction, SIGNAL(triggered(bool)), SLOT(toolsTranspose())); QObject::connect(m_ui.toolsNormalizeAction, SIGNAL(triggered(bool)), SLOT(toolsNormalize())); QObject::connect(m_ui.toolsRandomizeAction, SIGNAL(triggered(bool)), SLOT(toolsRandomize())); QObject::connect(m_ui.toolsResizeAction, SIGNAL(triggered(bool)), SLOT(toolsResize())); QObject::connect(m_ui.toolsRescaleAction, SIGNAL(triggered(bool)), SLOT(toolsRescale())); QObject::connect(m_ui.toolsTimeshiftAction, SIGNAL(triggered(bool)), SLOT(toolsTimeshift())); QObject::connect(m_ui.viewMenubarAction, SIGNAL(triggered(bool)), SLOT(viewMenubar(bool))); QObject::connect(m_ui.viewStatusbarAction, SIGNAL(triggered(bool)), SLOT(viewStatusbar(bool))); QObject::connect(m_ui.viewToolbarFileAction, SIGNAL(triggered(bool)), SLOT(viewToolbarFile(bool))); QObject::connect(m_ui.viewToolbarEditAction, SIGNAL(triggered(bool)), SLOT(viewToolbarEdit(bool))); QObject::connect(m_ui.viewToolbarViewAction, SIGNAL(triggered(bool)), SLOT(viewToolbarView(bool))); QObject::connect(m_ui.viewToolbarTransportAction, SIGNAL(triggered(bool)), SLOT(viewToolbarTransport(bool))); QObject::connect(m_ui.viewToolbarScaleAction, SIGNAL(triggered(bool)), SLOT(viewToolbarScale(bool))); QObject::connect(m_ui.viewNoteDurationAction, SIGNAL(triggered(bool)), SLOT(viewNoteDuration(bool))); QObject::connect(m_ui.viewNoteColorAction, SIGNAL(triggered(bool)), SLOT(viewNoteColor(bool))); QObject::connect(m_ui.viewValueColorAction, SIGNAL(triggered(bool)), SLOT(viewValueColor(bool))); QObject::connect(m_ui.viewEventsAction, SIGNAL(triggered(bool)), SLOT(viewEvents(bool))); QObject::connect(m_ui.viewPreviewAction, SIGNAL(triggered(bool)), SLOT(viewPreview(bool))); QObject::connect(m_ui.viewFollowAction, SIGNAL(triggered(bool)), SLOT(viewFollow(bool))); QObject::connect(m_ui.viewZoomInAction, SIGNAL(triggered(bool)), SLOT(viewZoomIn())); QObject::connect(m_ui.viewZoomOutAction, SIGNAL(triggered(bool)), SLOT(viewZoomOut())); QObject::connect(m_ui.viewZoomResetAction, SIGNAL(triggered(bool)), SLOT(viewZoomReset())); QObject::connect(m_ui.viewZoomHorizontalAction, SIGNAL(triggered(bool)), SLOT(viewZoomHorizontal())); QObject::connect(m_ui.viewZoomVerticalAction, SIGNAL(triggered(bool)), SLOT(viewZoomVertical())); QObject::connect(m_ui.viewZoomAllAction, SIGNAL(triggered(bool)), SLOT(viewZoomAll())); QObject::connect(m_ui.viewSnapZebraAction, SIGNAL(triggered(bool)), SLOT(viewSnapZebra(bool))); QObject::connect(m_ui.viewSnapGridAction, SIGNAL(triggered(bool)), SLOT(viewSnapGrid(bool))); QObject::connect(m_ui.viewToolTipsAction, SIGNAL(triggered(bool)), SLOT(viewToolTips(bool))); QObject::connect(m_ui.viewRefreshAction, SIGNAL(triggered(bool)), SLOT(viewRefresh())); QObject::connect(m_ui.helpShortcutsAction, SIGNAL(triggered(bool)), SLOT(helpShortcuts())); QObject::connect(m_ui.helpAboutAction, SIGNAL(triggered(bool)), SLOT(helpAbout())); QObject::connect(m_ui.helpAboutQtAction, SIGNAL(triggered(bool)), SLOT(helpAboutQt())); QObject::connect(m_ui.viewZoomMenu, SIGNAL(aboutToShow()), SLOT(updateZoomMenu())); QObject::connect(m_ui.viewSnapMenu, SIGNAL(aboutToShow()), SLOT(updateSnapMenu())); QObject::connect(m_ui.viewScaleMenu, SIGNAL(aboutToShow()), SLOT(updateScaleMenu())); QObject::connect(m_pSnapPerBeatComboBox, SIGNAL(activated(int)), SLOT(snapPerBeatChanged(int))); // To handle event selection changes. QObject::connect(m_pViewTypeComboBox, SIGNAL(activated(int)), SLOT(viewTypeChanged(int))); QObject::connect(m_pEventTypeComboBox, SIGNAL(activated(int)), SLOT(eventTypeChanged(int))); QObject::connect(m_pControllerComboBox, SIGNAL(activated(int)), SLOT(controllerChanged(int))); QObject::connect(m_pSnapToScaleKeyComboBox, SIGNAL(activated(int)), SLOT(snapToScaleKeyChanged(int))); QObject::connect(m_pSnapToScaleTypeComboBox, SIGNAL(activated(int)), SLOT(snapToScaleTypeChanged(int))); QObject::connect(m_pMidiEditor, SIGNAL(selectNotifySignal(qtractorMidiEditor *)), SLOT(selectionChanged(qtractorMidiEditor *))); QObject::connect(m_pMidiEditor, SIGNAL(changeNotifySignal(qtractorMidiEditor *)), SLOT(contentsChanged(qtractorMidiEditor *))); QObject::connect(m_pMidiEventList->toggleViewAction(), SIGNAL(triggered(bool)), SLOT(stabilizeForm())); // Try to restore old editor state... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { // Initial decorations toggle state. m_ui.viewMenubarAction->setChecked(pOptions->bMidiMenubar); m_ui.viewStatusbarAction->setChecked(pOptions->bMidiStatusbar); m_ui.viewToolbarFileAction->setChecked(pOptions->bMidiFileToolbar); m_ui.viewToolbarEditAction->setChecked(pOptions->bMidiEditToolbar); m_ui.viewToolbarViewAction->setChecked(pOptions->bMidiViewToolbar); m_ui.viewToolbarTransportAction->setChecked(pOptions->bMidiTransportToolbar); m_ui.viewToolbarScaleAction->setChecked(pOptions->bMidiScaleToolbar); m_ui.viewNoteDurationAction->setChecked(pOptions->bMidiNoteDuration); m_ui.viewNoteColorAction->setChecked(pOptions->bMidiNoteColor); m_ui.viewValueColorAction->setChecked(pOptions->bMidiValueColor); m_ui.viewPreviewAction->setChecked(pOptions->bMidiPreview); m_ui.viewFollowAction->setChecked(pOptions->bMidiFollow); m_ui.viewSnapZebraAction->setChecked(pOptions->bMidiSnapZebra); m_ui.viewSnapGridAction->setChecked(pOptions->bMidiSnapGrid); m_ui.viewToolTipsAction->setChecked(pOptions->bMidiToolTips); if (pOptions->bMidiEditMode) m_ui.editModeOnAction->setChecked(true); else m_ui.editModeOffAction->setChecked(true); m_ui.editModeDrawAction->setChecked(pOptions->bMidiEditModeDraw); // Initial decorations visibility state. viewMenubar(pOptions->bMidiMenubar); viewStatusbar(pOptions->bMidiStatusbar); viewToolbarFile(pOptions->bMidiFileToolbar); viewToolbarEdit(pOptions->bMidiEditToolbar); viewToolbarView(pOptions->bMidiViewToolbar); viewToolbarTransport(pOptions->bMidiTransportToolbar); viewToolbarScale(pOptions->bMidiScaleToolbar); m_pMidiEditor->setZoomMode(pOptions->iMidiZoomMode); m_pMidiEditor->setHorizontalZoom(pOptions->iMidiHorizontalZoom); m_pMidiEditor->setVerticalZoom(pOptions->iMidiVerticalZoom); m_pMidiEditor->setSnapZebra(pOptions->bMidiSnapZebra); m_pMidiEditor->setSnapGrid(pOptions->bMidiSnapGrid); m_pMidiEditor->setToolTips(pOptions->bMidiToolTips); m_pMidiEditor->setEditMode(pOptions->bMidiEditMode); m_pMidiEditor->setEditModeDraw(pOptions->bMidiEditModeDraw); m_pMidiEditor->setNoteColor(pOptions->bMidiNoteColor); m_pMidiEditor->setValueColor(pOptions->bMidiValueColor); m_pMidiEditor->setNoteDuration(pOptions->bMidiNoteDuration); m_pMidiEditor->setSendNotes(pOptions->bMidiPreview); m_pMidiEditor->setSyncView(pOptions->bMidiFollow); m_pMidiEditor->setSnapToScaleKey(pOptions->iMidiSnapToScaleKey); m_pMidiEditor->setSnapToScaleType(pOptions->iMidiSnapToScaleType); // Default snap-per-beat setting... m_pSnapPerBeatComboBox->setCurrentIndex(pOptions->iMidiSnapPerBeat); // Default snap-to-scale settings... m_pSnapToScaleKeyComboBox->setCurrentIndex(pOptions->iMidiSnapToScaleKey); m_pSnapToScaleTypeComboBox->setCurrentIndex(pOptions->iMidiSnapToScaleType); // Restore whole dock windows state. QByteArray aDockables = pOptions->settings().value( "/MidiEditor/Layout/DockWindows").toByteArray(); if (aDockables.isEmpty()) { // Some windows are forced initially as is... insertToolBarBreak(m_ui.editViewToolbar); } else { // Make it as the last time. restoreState(aDockables); } // Try to restore old window positioning? // pOptions->loadWidgetGeometry(this, true); // Load (action) keyboard shortcuts... pOptions->loadActionShortcuts(this); } // Make last-but-not-least conections.... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) { QObject::connect(m_ui.transportBackwardAction, SIGNAL(triggered(bool)), pMainForm, SLOT(transportBackward())); QObject::connect(m_ui.transportRewindAction, SIGNAL(triggered(bool)), pMainForm, SLOT(transportRewind())); QObject::connect(m_ui.transportFastForwardAction, SIGNAL(triggered(bool)), pMainForm, SLOT(transportFastForward())); QObject::connect(m_ui.transportForwardAction, SIGNAL(triggered(bool)), pMainForm, SLOT(transportForward())); QObject::connect(m_ui.transportLoopAction, SIGNAL(triggered(bool)), pMainForm, SLOT(transportLoop())); QObject::connect(m_ui.transportLoopSetAction, SIGNAL(triggered(bool)), pMainForm, SLOT(transportLoopSet())); QObject::connect(m_ui.transportStopAction, SIGNAL(triggered(bool)), pMainForm, SLOT(transportStop())); QObject::connect(m_ui.transportPlayAction, SIGNAL(triggered(bool)), pMainForm, SLOT(transportPlay())); QObject::connect(m_ui.transportRecordAction, SIGNAL(triggered(bool)), pMainForm, SLOT(transportRecord())); QObject::connect(m_ui.transportPunchAction, SIGNAL(triggered(bool)), pMainForm, SLOT(transportPunch())); QObject::connect(m_ui.transportPunchSetAction, SIGNAL(triggered(bool)), pMainForm, SLOT(transportPunchSet())); QObject::connect(m_ui.transportPanicAction, SIGNAL(triggered(bool)), pMainForm, SLOT(transportPanic())); } eventTypeChanged(0); } // Destructor. qtractorMidiEditorForm::~qtractorMidiEditorForm (void) { // View/Snap-to-beat actions termination... qDeleteAll(m_snapPerBeatActions); m_snapPerBeatActions.clear(); // Drop any widgets around (not really necessary)... if (m_pMidiEventList) delete m_pMidiEventList; if (m_pMidiEditor) delete m_pMidiEditor; // Get edit-mode action group down. if (m_pEditModeActionGroup) delete m_pEditModeActionGroup; } //------------------------------------------------------------------------- // qtractorMidiEditorForm -- Window close event handlers. // Pre-close event handlers. bool qtractorMidiEditorForm::queryClose (void) { bool bQueryClose = true; // Are we dirty enough to prompt it? if (m_iDirtyCount > 0) { switch (querySave(filename())) { case QMessageBox::Save: bQueryClose = saveClipFile(false); // Fall thru.... case QMessageBox::Discard: break; default: // Cancel. bQueryClose = false; break; } } return bQueryClose; } // Save(as) warning message box. int qtractorMidiEditorForm::querySave ( const QString& sFilename ) { return (QMessageBox::warning( qtractorMainForm::getInstance(), tr("Warning") + " - " QTRACTOR_TITLE, tr("The current MIDI clip has been changed:\n\n" "\"%1\"\n\n" "Do you want to save the changes?").arg(sFilename), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel)); } // On-show event handler. void qtractorMidiEditorForm::showEvent ( QShowEvent *pShowEvent ) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->addEditorForm(this); QMainWindow::showEvent(pShowEvent); } // On-close event handler. void qtractorMidiEditorForm::closeEvent ( QCloseEvent *pCloseEvent ) { // Try to save current editor view state... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions && isVisible()) { // Save decorations state. pOptions->bMidiMenubar = m_ui.menuBar->isVisible(); pOptions->bMidiStatusbar = statusBar()->isVisible(); pOptions->bMidiFileToolbar = m_ui.fileToolbar->isVisible(); pOptions->bMidiEditToolbar = m_ui.editToolbar->isVisible(); pOptions->bMidiViewToolbar = m_ui.viewToolbar->isVisible(); pOptions->bMidiTransportToolbar = m_ui.transportToolbar->isVisible(); pOptions->bMidiScaleToolbar = m_ui.snapToScaleToolbar->isVisible(); pOptions->iMidiZoomMode = m_pMidiEditor->zoomMode(); pOptions->iMidiHorizontalZoom = m_pMidiEditor->horizontalZoom(); pOptions->iMidiVerticalZoom = m_pMidiEditor->verticalZoom(); pOptions->bMidiSnapZebra = m_pMidiEditor->isSnapZebra(); pOptions->bMidiSnapGrid = m_pMidiEditor->isSnapGrid(); pOptions->bMidiToolTips = m_pMidiEditor->isToolTips(); pOptions->bMidiEditMode = m_pMidiEditor->isEditMode(); pOptions->bMidiEditModeDraw = m_pMidiEditor->isEditModeDraw(); pOptions->bMidiNoteDuration = m_ui.viewNoteDurationAction->isChecked(); pOptions->bMidiNoteColor = m_ui.viewNoteColorAction->isChecked(); pOptions->bMidiValueColor = m_ui.viewValueColorAction->isChecked(); pOptions->bMidiPreview = m_ui.viewPreviewAction->isChecked(); pOptions->bMidiFollow = m_ui.viewFollowAction->isChecked(); // Save snap-per-beat setting... pOptions->iMidiSnapPerBeat = m_pSnapPerBeatComboBox->currentIndex(); // Save snap-to-scale settings... pOptions->iMidiSnapToScaleKey = m_pSnapToScaleKeyComboBox->currentIndex(); pOptions->iMidiSnapToScaleType = m_pSnapToScaleTypeComboBox->currentIndex(); // Close floating dock windows... if (m_pMidiEventList->isFloating()) m_pMidiEventList->close(); // Save the dock windows state. pOptions->settings().setValue( "/MidiEditor/Layout/DockWindows", saveState()); // And the main windows state? // pOptions->saveWidgetGeometry(this, true); } // Remove this one from main-form list... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->removeEditorForm(this); // Close it good. pCloseEvent->accept(); } //------------------------------------------------------------------------- // qtractorMidiEditorForm -- Context menu event handlers. // Context menu request. void qtractorMidiEditorForm::contextMenuEvent ( QContextMenuEvent *pContextMenuEvent ) { QMenu menu(this); menu.addAction(m_ui.editUndoAction); menu.addAction(m_ui.editRedoAction); menu.addSeparator(); menu.addAction(m_ui.editCutAction); menu.addAction(m_ui.editCopyAction); menu.addAction(m_ui.editPasteAction); menu.addAction(m_ui.editPasteRepeatAction); menu.addSeparator(); menu.addAction(m_ui.editDeleteAction); menu.addSeparator(); menu.addMenu(m_ui.editModeMenu); menu.addMenu(m_ui.editSelectMenu); menu.addSeparator(); menu.addMenu(m_ui.toolsMenu); menu.exec(pContextMenuEvent->globalPos()); } // Edit menu accessor. QMenu *qtractorMidiEditorForm::editMenu (void) const { return m_ui.editMenu; } //------------------------------------------------------------------------- // qtractorMidiEditorForm -- Central widget redirect methods. // MIDI editor widget accessor. qtractorMidiEditor *qtractorMidiEditorForm::editor (void) const { return m_pMidiEditor; } // Local time-scale accessor. qtractorTimeScale *qtractorMidiEditorForm::timeScale (void) const { return m_pMidiEditor->timeScale(); } unsigned long qtractorMidiEditorForm::timeOffset (void) const { return m_pMidiEditor->timeOffset(); } // Editing MIDI clip accessors. qtractorMidiClip *qtractorMidiEditorForm::midiClip (void) const { return m_pMidiEditor->midiClip(); } // MIDI clip property accessors. const QString& qtractorMidiEditorForm::filename (void) const { return m_pMidiEditor->filename(); } unsigned short qtractorMidiEditorForm::trackChannel (void) const { return m_pMidiEditor->trackChannel(); } unsigned short qtractorMidiEditorForm::format (void) const { return m_pMidiEditor->format(); } qtractorMidiSequence *qtractorMidiEditorForm::sequence (void) const { return m_pMidiEditor->sequence(); } // Special executive setup method. void qtractorMidiEditorForm::setup ( qtractorMidiClip *pMidiClip ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; // Get those time-scales in sync, // while keeping zoom ratios persistant... unsigned short iHorizontalZoom = m_pMidiEditor->horizontalZoom(); unsigned short iVerticalZoom = m_pMidiEditor->verticalZoom(); qtractorTimeScale *pTimeScale = m_pMidiEditor->timeScale(); pTimeScale->copy(*pSession->timeScale()); m_pMidiEditor->setHorizontalZoom(iHorizontalZoom); m_pMidiEditor->setVerticalZoom(iVerticalZoom); // Default snap-per-beat setting... pTimeScale->setSnapPerBeat( qtractorTimeScale::snapFromIndex( m_pSnapPerBeatComboBox->currentIndex())); // Note that there's two modes for this method: // whether pMidiClip is given non-null wich means // form initialization and first setup or else... if (pMidiClip) { // Set initial MIDI clip properties has seen fit... if (queryClose()) m_pMidiEditor->setMidiClip(pMidiClip); // Setup connections to main widget... QObject::connect(m_pMidiEditor, SIGNAL(changeNotifySignal(qtractorMidiEditor *)), pMainForm, SLOT(changeNotifySlot(qtractorMidiEditor *))); // This one's local but helps... QObject::connect(m_pMidiEditor, SIGNAL(sendNoteSignal(int,int)), SLOT(sendNote(int,int))); } // Reset MIDI clip length alright... else m_pMidiEditor->resetClipLength(); // Reset local dirty flag. resetDirtyCount(); // Get all those names right... updateInstrumentNames(); // Refresh and try to center (vertically) the edit-view... m_pMidiEditor->centerContents(); m_pMidiEventList->refresh(); // (Re)try to position the editor in same of track view... qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks) { unsigned long iFrame = pTimeScale->frameFromPixel( (pTracks->trackView())->contentsX()); if (iFrame > m_pMidiEditor->offset()) { iFrame -= m_pMidiEditor->offset(); } else { iFrame = 0; } int cx = pTimeScale->pixelFromFrame(iFrame); int cy = (m_pMidiEditor->editView())->contentsY(); (m_pMidiEditor->editView())->setContentsPos(cx, cy); } // (Re)sync local play/edit-head/tail (avoid follow playhead)... m_pMidiEditor->setPlayHead(pSession->playHead(), false); m_pMidiEditor->setEditHead(pSession->editHead(), false); m_pMidiEditor->setEditTail(pSession->editTail(), false); // Done. stabilizeForm(); } // Reset coomposite dirty flag. void qtractorMidiEditorForm::resetDirtyCount (void) { m_iDirtyCount = 0; // MIDI clip might be dirty already. qtractorMidiClip *pMidiClip = midiClip(); if (pMidiClip && pMidiClip->isDirty()) ++m_iDirtyCount; } //------------------------------------------------------------------------- // qtractorMidiEditorForm -- Clip Action methods. // Save current clip. bool qtractorMidiEditorForm::saveClipFile ( bool bPrompt ) { qtractorMidiClip *pMidiClip = m_pMidiEditor->midiClip(); if (pMidiClip == NULL) return false; qtractorTrack *pTrack = pMidiClip->track(); if (pTrack == NULL) return false; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return false; // Suggest a brand new filename, if there's none... QString sFilename = pMidiClip->createFilePathRevision(bPrompt); // Ask for the file to save... if (sFilename.isEmpty()) bPrompt = true; if (bPrompt) { // If none is given, assume default directory. const QString sExt("mid"); const QString& sTitle = tr("Save MIDI Clip") + " - " QTRACTOR_TITLE; const QString& sFilter = tr("MIDI files (*.%1 *.smf *.midi)").arg(sExt); #if 0//QT_VERSION < 0x040400 // Ask for the filenames to open... sFilename = QFileDialog::getSaveFileName(this, sTitle, sFilename, sFilter); #else // Construct open-files dialog... QFileDialog fileDialog(this, sTitle, sFilename, sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptSave); fileDialog.setFileMode(QFileDialog::AnyFile); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(pOptions->sMidiDir)); fileDialog.setSidebarUrls(urls); } // Show dialog... if (fileDialog.exec()) sFilename = fileDialog.selectedFiles().first(); else sFilename.clear(); #endif // Have we cancelled it? if (sFilename.isEmpty()) return false; // Enforce .mid extension... if (QFileInfo(sFilename).suffix().isEmpty()) sFilename += '.' + sExt; } // Save it right away... bool bResult = qtractorMidiFile::saveCopyFile(sFilename, filename(), trackChannel(), format(), sequence(), timeScale(), timeOffset()); // Have we done it right? if (bResult) { // Aha, but we're not dirty no more. m_iDirtyCount = 0; // Now, we avoid the linked/ref-counted instances // if we're doing a prompted save (ie. Save As...) if (bPrompt) { pSession->files()->removeClipItem(qtractorFileList::Midi, pMidiClip); pMidiClip->setFilename(sFilename); pMidiClip->setDirty(false); pMidiClip->unlinkHashData(); pMidiClip->updateEditor(true); pSession->files()->addClipItem(qtractorFileList::Midi, pMidiClip, true); } else { pMidiClip->setFilenameEx(sFilename); } // HACK: This operation is so important that // it surely deserves being in the front page... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) { pMainForm->appendMessages( tr("MIDI file save: \"%1\", track-channel: %2.") .arg(sFilename).arg(trackChannel())); pMainForm->addMidiFile(sFilename); } } // Done. stabilizeForm(); return bResult; } //------------------------------------------------------------------------- // qtractorMidiEditorForm -- File Action slots. // Save current clip. void qtractorMidiEditorForm::fileSave (void) { saveClipFile(false); } // Save current clip with another name. void qtractorMidiEditorForm::fileSaveAs (void) { saveClipFile(true); } // Unlink current clip. void qtractorMidiEditorForm::fileUnlink (void) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) { qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks) pTracks->unlinkClip(m_pMidiEditor->midiClip()); } } // File properties dialog. void qtractorMidiEditorForm::fileProperties (void) { qtractorMidiClip *pMidiClip = m_pMidiEditor->midiClip(); if (pMidiClip == NULL) return; qtractorClipForm clipForm(parentWidget()); clipForm.setClip(pMidiClip); clipForm.exec(); } // Show current MIDI clip/track input bus connections. void qtractorMidiEditorForm::fileTrackInputs (void) { qtractorMidiClip *pMidiClip = m_pMidiEditor->midiClip(); if (pMidiClip == NULL) return; qtractorTrack *pTrack = pMidiClip->track(); if (pTrack == NULL) return; if (pTrack->inputBus() == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm && pMainForm->connections()) { (pMainForm->connections())->showBus( pTrack->inputBus(), qtractorBus::Input); } } // Show current MIDI clip/track output bus connections. void qtractorMidiEditorForm::fileTrackOutputs (void) { qtractorMidiClip *pMidiClip = m_pMidiEditor->midiClip(); if (pMidiClip == NULL) return; qtractorTrack *pTrack = pMidiClip->track(); if (pTrack == NULL) return; if (pTrack->outputBus() == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm && pMainForm->connections()) { (pMainForm->connections())->showBus( pTrack->outputBus(), qtractorBus::Output); } } // Edit current MIDI clip/track properties. void qtractorMidiEditorForm::fileTrackProperties (void) { qtractorMidiClip *pMidiClip = m_pMidiEditor->midiClip(); if (pMidiClip == NULL) return; qtractorTrack *pTrack = pMidiClip->track(); if (pTrack == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm && pMainForm->tracks()) (pMainForm->tracks())->editTrack(pTrack); } // Edit-range setting to clip extents. void qtractorMidiEditorForm::fileRangeSet (void) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) { qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks) pTracks->rangeClip(m_pMidiEditor->midiClip()); } } // Loop-range setting to clip extents. void qtractorMidiEditorForm::fileLoopSet (void) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) { qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks) pTracks->loopClip(m_pMidiEditor->midiClip()); } } // Exit editing. void qtractorMidiEditorForm::fileClose (void) { // Go for close this thing. close(); } //------------------------------------------------------------------------- // qtractorMidiEditorForm -- Edit action slots. // Undo last edit command. void qtractorMidiEditorForm::editUndo (void) { m_pMidiEditor->undoCommand(); } // Redo last edit command. void qtractorMidiEditorForm::editRedo (void) { m_pMidiEditor->redoCommand(); } // Cut current selection to clipboard. void qtractorMidiEditorForm::editCut (void) { m_pMidiEditor->cutClipboard(); } // Copy current selection to clipboard. void qtractorMidiEditorForm::editCopy (void) { m_pMidiEditor->copyClipboard(); } // Paste from clipboard. void qtractorMidiEditorForm::editPaste (void) { m_pMidiEditor->pasteClipboard(); } // Paste/repeat from clipboard. void qtractorMidiEditorForm::editPasteRepeat (void) { qtractorPasteRepeatForm pasteForm(this); pasteForm.setRepeatPeriod(m_pMidiEditor->pastePeriod()); if (pasteForm.exec()) { m_pMidiEditor->pasteClipboard( pasteForm.repeatCount(), pasteForm.repeatPeriod() ); } } // Delete current selection. void qtractorMidiEditorForm::editDelete (void) { m_pMidiEditor->deleteSelect(); } // Set edit-mode on. void qtractorMidiEditorForm::editModeOn (void) { m_pMidiEditor->setEditMode(true); m_pMidiEditor->updateContents(); stabilizeForm(); } // Set edit-mode off. void qtractorMidiEditorForm::editModeOff (void) { m_pMidiEditor->setEditMode(false); m_pMidiEditor->updateContents(); stabilizeForm(); } // Toggle draw-mode (notes) void qtractorMidiEditorForm::editModeDraw ( bool bOn ) { m_pMidiEditor->setEditModeDraw(bOn); } // Select none contents. void qtractorMidiEditorForm::editSelectNone (void) { qtractorScrollView *pScrollView = m_pMidiEditor->editView(); if (m_pMidiEditor->editEvent()->hasFocus()) pScrollView = m_pMidiEditor->editEvent(); m_pMidiEditor->selectAll(pScrollView, false, false); } // Select invert contents. void qtractorMidiEditorForm::editSelectInvert (void) { qtractorScrollView *pScrollView = m_pMidiEditor->editView(); if (m_pMidiEditor->editEvent()->hasFocus()) pScrollView = m_pMidiEditor->editEvent(); m_pMidiEditor->selectAll(pScrollView, true, true); } // Select all contents. void qtractorMidiEditorForm::editSelectAll (void) { qtractorScrollView *pScrollView = m_pMidiEditor->editView(); if (m_pMidiEditor->editEvent()->hasFocus()) pScrollView = m_pMidiEditor->editEvent(); m_pMidiEditor->selectAll(pScrollView, true, false); } // Select contents range. void qtractorMidiEditorForm::editSelectRange (void) { qtractorScrollView *pScrollView = m_pMidiEditor->editView(); if (m_pMidiEditor->editEvent()->hasFocus()) pScrollView = m_pMidiEditor->editEvent(); m_pMidiEditor->selectRange(pScrollView, true, true); } // Insert range. void qtractorMidiEditorForm::editInsertRange (void) { m_pMidiEditor->insertEditRange(); } // Remove range. void qtractorMidiEditorForm::editRemoveRange (void) { m_pMidiEditor->removeEditRange(); } // Quantize tool. void qtractorMidiEditorForm::toolsQuantize (void) { m_pMidiEditor->executeTool(qtractorMidiEditor::Quantize); } // Transpose tool. void qtractorMidiEditorForm::toolsTranspose (void) { m_pMidiEditor->executeTool(qtractorMidiEditor::Transpose); } // Normalize tool. void qtractorMidiEditorForm::toolsNormalize (void) { m_pMidiEditor->executeTool(qtractorMidiEditor::Normalize); } // Randomize tool. void qtractorMidiEditorForm::toolsRandomize (void) { m_pMidiEditor->executeTool(qtractorMidiEditor::Randomize); } // Resize tool. void qtractorMidiEditorForm::toolsResize (void) { m_pMidiEditor->executeTool(qtractorMidiEditor::Resize); } // Rescale tool. void qtractorMidiEditorForm::toolsRescale (void) { m_pMidiEditor->executeTool(qtractorMidiEditor::Rescale); } // Timeshift tool. void qtractorMidiEditorForm::toolsTimeshift (void) { m_pMidiEditor->executeTool(qtractorMidiEditor::Timeshift); } //------------------------------------------------------------------------- // qtractorMidiEditorForm -- View Action slots. // Show/hide the main program window menubar. void qtractorMidiEditorForm::viewMenubar ( bool bOn ) { #if 0 if (bOn) m_ui.menuBar->show(); else m_ui.menuBar->hide(); #else m_ui.menuBar->setVisible(bOn); #endif } // Show/hide the main program window statusbar. void qtractorMidiEditorForm::viewStatusbar ( bool bOn ) { #if 0 if (bOn) statusBar()->show(); else statusBar()->hide(); #else statusBar()->setVisible(bOn); #endif } // Show/hide the file-toolbar. void qtractorMidiEditorForm::viewToolbarFile ( bool bOn ) { #if 0 if (bOn) m_ui.fileToolbar->show(); else m_ui.fileToolbar->hide(); #else m_ui.fileToolbar->setVisible(bOn); #endif } // Show/hide the edit-toolbar. void qtractorMidiEditorForm::viewToolbarEdit ( bool bOn ) { #if 0 if (bOn) m_ui.editToolbar->show(); else m_ui.editToolbar->hide(); #else m_ui.editToolbar->setVisible(bOn); #endif } // Show/hide the view-toolbar. void qtractorMidiEditorForm::viewToolbarView ( bool bOn ) { #if 0 if (bOn) m_ui.viewToolbar->show(); else m_ui.viewToolbar->hide(); #else m_ui.viewToolbar->setVisible(bOn); #endif } // Show/hide the transport-toolbar. void qtractorMidiEditorForm::viewToolbarTransport ( bool bOn ) { #if 0 if (bOn) m_ui.transportToolbar->show(); else m_ui.transportToolbar->hide(); #else m_ui.transportToolbar->setVisible(bOn); #endif } // Show/hide the scale-toolbar. void qtractorMidiEditorForm::viewToolbarScale ( bool bOn ) { #if 0 if (bOn) m_ui.snapToScaleToolbar->show(); else m_ui.snapToScaleToolbar->hide(); #else m_ui.snapToScaleToolbar->setVisible(bOn); #endif } // View note (pitch) coloring. void qtractorMidiEditorForm::viewNoteColor ( bool bOn ) { m_pMidiEditor->setNoteColor(bOn); m_pMidiEditor->updateContents(); } // View note (velocity) coloring. void qtractorMidiEditorForm::viewValueColor ( bool bOn ) { m_pMidiEditor->setValueColor(bOn); m_pMidiEditor->updateContents(); } // View duration as widths of notes void qtractorMidiEditorForm::viewNoteDuration ( bool bOn ) { m_pMidiEditor->setNoteDuration(bOn); m_pMidiEditor->updateContents(); } // Show/hide the events window view. void qtractorMidiEditorForm::viewEvents ( bool bOn ) { m_pMidiEventList->setVisible(bOn); } // View preview notes void qtractorMidiEditorForm::viewPreview ( bool bOn ) { m_pMidiEditor->setSendNotes(bOn); } // View follow playhead void qtractorMidiEditorForm::viewFollow ( bool bOn ) { m_pMidiEditor->setSyncView(bOn); } // Horizontal and/or vertical zoom-in. void qtractorMidiEditorForm::viewZoomIn (void) { m_pMidiEditor->zoomIn(); } // Horizontal and/or vertical zoom-out. void qtractorMidiEditorForm::viewZoomOut (void) { m_pMidiEditor->zoomOut(); } // Reset zoom level to default. void qtractorMidiEditorForm::viewZoomReset (void) { m_pMidiEditor->zoomReset(); } // Set horizontal zoom mode void qtractorMidiEditorForm::viewZoomHorizontal (void) { m_pMidiEditor->setZoomMode(qtractorMidiEditor::ZoomHorizontal); } // Set vertical zoom mode void qtractorMidiEditorForm::viewZoomVertical (void) { m_pMidiEditor->setZoomMode(qtractorMidiEditor::ZoomVertical); } // Set all zoom mode void qtractorMidiEditorForm::viewZoomAll (void) { m_pMidiEditor->setZoomMode(qtractorMidiEditor::ZoomAll); } // Set zebra mode void qtractorMidiEditorForm::viewSnapZebra ( bool bOn ) { m_pMidiEditor->setSnapZebra(bOn); m_pMidiEditor->updateContents(); } // Set grid mode void qtractorMidiEditorForm::viewSnapGrid ( bool bOn ) { m_pMidiEditor->setSnapGrid(bOn); m_pMidiEditor->updateContents(); } // Set floating tool-tips view mode void qtractorMidiEditorForm::viewToolTips ( bool bOn ) { m_pMidiEditor->setToolTips(bOn); } // Change snap-per-beat setting via menu. void qtractorMidiEditorForm::viewSnap (void) { // Retrieve snap-per-beat index from from action data... QAction *pAction = qobject_cast (sender()); if (pAction) { // Commit the change as usual... snapPerBeatChanged(pAction->data().toInt()); // Update the other toolbar control... qtractorTimeScale *pTimeScale = m_pMidiEditor->timeScale(); if (pTimeScale) m_pSnapPerBeatComboBox->setCurrentIndex( qtractorTimeScale::indexFromSnap(pTimeScale->snapPerBeat())); } } // Change snap-to-scale key setting via menu. void qtractorMidiEditorForm::viewScaleKey (void) { // Retrieve snap-to-scale key index from from action data... QAction *pAction = qobject_cast (sender()); if (pAction) { // Commit the change as usual... snapToScaleKeyChanged(pAction->data().toInt()); // Update the other toolbar control... m_pSnapToScaleKeyComboBox->setCurrentIndex( m_pMidiEditor->snapToScaleKey()); } } // Change snap-to-scale typesetting via menu. void qtractorMidiEditorForm::viewScaleType (void) { // Retrieve snap-to-scale type index from from action data... QAction *pAction = qobject_cast (sender()); if (pAction) { // Commit the change as usual... snapToScaleTypeChanged(pAction->data().toInt()); // Update the other toolbar control... m_pSnapToScaleTypeComboBox->setCurrentIndex( m_pMidiEditor->snapToScaleType()); } } // Refresh view display. void qtractorMidiEditorForm::viewRefresh (void) { m_pMidiEditor->updateContents(); m_pMidiEventList->refresh(); stabilizeForm(); } //------------------------------------------------------------------------- // qtractorMidiEditorForm -- Help Action slots. // Show (and edit) keyboard shortcuts. void qtractorMidiEditorForm::helpShortcuts (void) { qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; qtractorShortcutForm shortcutForm(findChildren (), this); if (shortcutForm.exec()) pOptions->saveActionShortcuts(this); } // Show information about application program. void qtractorMidiEditorForm::helpAbout (void) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->helpAbout(); } // Show information about the Qt toolkit. void qtractorMidiEditorForm::helpAboutQt (void) { QMessageBox::aboutQt(this); } //------------------------------------------------------------------------- // qtractorMidiEditorForm -- Utility methods. // Send note on/off to respective output bus. void qtractorMidiEditorForm::sendNote ( int iNote, int iVelocity ) { qtractorMidiClip *pMidiClip = m_pMidiEditor->midiClip(); if (pMidiClip == NULL) return; qtractorTrack *pTrack = pMidiClip->track(); if (pTrack == NULL) return; qtractorMidiBus *pMidiBus = static_cast (pTrack->outputBus()); if (pMidiBus == NULL) return; pMidiBus->sendNote(pTrack, iNote, iVelocity); } //------------------------------------------------------------------------- // qtractorMidiEditorForm -- Main form stabilization. void qtractorMidiEditorForm::stabilizeForm (void) { // Update the main menu state... qtractorTrack *pTrack = NULL; qtractorMidiClip *pMidiClip = m_pMidiEditor->midiClip(); if (pMidiClip) pTrack = pMidiClip->track(); m_ui.fileSaveAction->setEnabled(m_iDirtyCount > 0); m_ui.fileUnlinkAction->setEnabled(pMidiClip && pMidiClip->isHashLinked()); m_ui.fileTrackInputsAction->setEnabled(pTrack && pTrack->inputBus() != NULL); m_ui.fileTrackOutputsAction->setEnabled(pTrack && pTrack->outputBus() != NULL); m_ui.fileTrackPropertiesAction->setEnabled(pTrack != NULL); m_ui.fileRangeSetAction->setEnabled(pTrack != NULL); m_ui.fileLoopSetAction->setEnabled(pTrack != NULL); m_pMidiEditor->updateUndoAction(m_ui.editUndoAction); m_pMidiEditor->updateRedoAction(m_ui.editRedoAction); bool bSelected = m_pMidiEditor->isSelected(); bool bSelectable = m_pMidiEditor->isSelectable(); bool bClipboard = m_pMidiEditor->isClipboard(); m_ui.editCutAction->setEnabled(bSelected); m_ui.editCopyAction->setEnabled(bSelected); m_ui.editPasteAction->setEnabled(bClipboard); m_ui.editPasteRepeatAction->setEnabled(bClipboard); m_ui.editDeleteAction->setEnabled(bSelected); m_ui.editModeDrawAction->setEnabled(m_pMidiEditor->isEditMode()); m_ui.editSelectNoneAction->setEnabled(bSelected); bool bInsertable = m_pMidiEditor->isInsertable(); m_ui.editInsertRangeAction->setEnabled(bInsertable); m_ui.editRemoveRangeAction->setEnabled(bInsertable); #if 0 m_ui.toolsMenu->setEnabled(bSelected); #else m_ui.toolsQuantizeAction->setEnabled(bSelected); m_ui.toolsTransposeAction->setEnabled(bSelected); m_ui.toolsNormalizeAction->setEnabled(bSelected); m_ui.toolsRandomizeAction->setEnabled(bSelected); m_ui.toolsResizeAction->setEnabled(bSelected); m_ui.toolsRescaleAction->setEnabled(bSelected); m_ui.toolsTimeshiftAction->setEnabled(bSelected); #endif // Just having a non-null sequence will indicate // that we're editing a legal MIDI clip... qtractorMidiSequence *pSeq = sequence(); if (pSeq == NULL) { setWindowTitle(tr("MIDI Editor") + " - " QTRACTOR_TITLE); m_pFileNameLabel->clear(); m_pTrackChannelLabel->clear(); m_pTrackNameLabel->clear(); m_pStatusModLabel->clear(); m_pDurationLabel->clear(); return; } // Special display formatting... QString sTrackChannel; int k = 0; if (format() == 0) { sTrackChannel = tr("Channel %1"); ++k; } else { sTrackChannel = tr("Track %1"); } // Update the main window caption... QString sTitle = QFileInfo(filename()).fileName() + ' '; sTitle += '(' + sTrackChannel.arg(trackChannel() + k) + ')'; if (m_iDirtyCount > 0) sTitle += ' ' + tr("[modified]"); setWindowTitle(sTitle + " - " QTRACTOR_TITLE); m_ui.viewEventsAction->setChecked(m_pMidiEventList->isVisible()); m_pFileNameLabel->setText(filename()); m_pTrackChannelLabel->setText(sTrackChannel.arg(trackChannel() + k)); m_pTrackNameLabel->setText(pSeq->name()); if (m_iDirtyCount > 0) m_pStatusModLabel->setText(tr("MOD")); else m_pStatusModLabel->clear(); qtractorTimeScale *pTimeScale = m_pMidiEditor->timeScale(); m_pDurationLabel->setText(pTimeScale->textFromTick( pTimeScale->tickFromFrame(m_pMidiEditor->offset()), true, pSeq->duration())); qtractorSession *pSession = qtractorSession::getInstance(); qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pSession && pMainForm) { unsigned long iPlayHead = pSession->playHead(); bool bPlaying = pSession->isPlaying(); bool bRecording = pSession->isRecording(); bool bPunching = pSession->isPunching(); bool bLooping = pSession->isLooping(); bool bRolling = (bPlaying && bRecording); bool bBumped = (!bRolling && (iPlayHead > 0 || bPlaying)); int iRolling = pMainForm->rolling(); m_ui.transportBackwardAction->setEnabled(bBumped); m_ui.transportRewindAction->setEnabled(bBumped); m_ui.transportFastForwardAction->setEnabled(!bRolling); m_ui.transportForwardAction->setEnabled( !bRolling && (iPlayHead < pSession->sessionEnd() || iPlayHead < pSession->editHead() || iPlayHead < pSession->editTail())); m_ui.transportLoopAction->setEnabled( !bRolling && (bLooping || bSelectable)); m_ui.transportLoopSetAction->setEnabled( !bRolling && bSelectable); m_ui.transportStopAction->setEnabled(bPlaying); m_ui.transportRecordAction->setEnabled( (!bLooping || !bPunching) && pSession->recordTracks() > 0); m_ui.transportPunchAction->setEnabled(bPunching || bSelectable); m_ui.transportPunchSetAction->setEnabled(bSelectable); m_ui.transportRewindAction->setChecked(iRolling < 0); m_ui.transportFastForwardAction->setChecked(iRolling > 0); m_ui.transportLoopAction->setChecked(bLooping); m_ui.transportPlayAction->setChecked(bPlaying); m_ui.transportRecordAction->setChecked(bRecording); m_ui.transportPunchAction->setChecked(bPunching); } } // Update clip/track instrument names... void qtractorMidiEditorForm::updateInstrumentNames (void) { // Just in case... m_pMidiEditor->updateInstrumentNames(); // Update the controller names... int iOldController = m_pControllerComboBox->currentIndex(); if (iOldController < 0) iOldController = 0; const QIcon iconController(":/images/itemControllers.png"); m_pControllerComboBox->clear(); for (int i = 0; i < 128; ++i) { m_pControllerComboBox->addItem(iconController, QString::number(i) + " - " + m_pMidiEditor->controllerName(i), i); } m_pControllerComboBox->setCurrentIndex(iOldController); } //------------------------------------------------------------------------- // qtractorMidiEditorForm -- Selection widget slots. // Zoom view menu stabilizer. void qtractorMidiEditorForm::updateZoomMenu (void) { int iZoomMode = m_pMidiEditor->zoomMode(); m_ui.viewZoomHorizontalAction->setChecked( iZoomMode == qtractorMidiEditor::ZoomHorizontal); m_ui.viewZoomVerticalAction->setChecked( iZoomMode == qtractorMidiEditor::ZoomVertical); m_ui.viewZoomAllAction->setChecked( iZoomMode == qtractorMidiEditor::ZoomAll); } // Snap-per-beat view menu builder. void qtractorMidiEditorForm::updateSnapMenu (void) { m_ui.viewSnapMenu->clear(); qtractorTimeScale *pTimeScale = m_pMidiEditor->timeScale(); if (pTimeScale == NULL) return; int iSnapCurrent = qtractorTimeScale::indexFromSnap(pTimeScale->snapPerBeat()); int iSnap = 0; QListIterator iter(m_snapPerBeatActions); while (iter.hasNext()) { QAction *pAction = iter.next(); pAction->setChecked(iSnap == iSnapCurrent); m_ui.viewSnapMenu->addAction(pAction); ++iSnap; } m_ui.viewSnapMenu->addSeparator(); m_ui.viewSnapMenu->addAction(m_ui.viewSnapZebraAction); m_ui.viewSnapMenu->addAction(m_ui.viewSnapGridAction); } // Snap-to-scale view menu builder. void qtractorMidiEditorForm::updateScaleMenu (void) { m_ui.viewScaleMenu->clear(); int iSnapToScaleKey = m_pMidiEditor->snapToScaleKey(); int iScaleKey = 0; QStringListIterator iter_key(qtractorMidiEditor::scaleKeyNames()); while (iter_key.hasNext()) { QAction *pAction = m_ui.viewScaleMenu->addAction( iter_key.next(), this, SLOT(viewScaleKey())); pAction->setCheckable(true); pAction->setChecked(iScaleKey == iSnapToScaleKey); pAction->setData(iScaleKey++); } m_ui.viewScaleMenu->addSeparator(); int iSnapToScaleType = m_pMidiEditor->snapToScaleType(); int iScaleType = 0; QStringListIterator iter_type(qtractorMidiEditor::scaleTypeNames()); while (iter_type.hasNext()) { QAction *pAction = m_ui.viewScaleMenu->addAction( iter_type.next(), this, SLOT(viewScaleType())); pAction->setCheckable(true); pAction->setChecked(iScaleType == iSnapToScaleType); pAction->setData(iScaleType++); } } // Snap-per-beat spin-box change slot. void qtractorMidiEditorForm::snapPerBeatChanged ( int iSnap ) { qtractorTimeScale *pTimeScale = m_pMidiEditor->timeScale(); if (pTimeScale == NULL) return; // Avoid bogus changes... unsigned short iSnapPerBeat = qtractorTimeScale::snapFromIndex(iSnap); if (iSnapPerBeat == pTimeScale->snapPerBeat()) return; // No need to express the change as a undoable command? pTimeScale->setSnapPerBeat(iSnapPerBeat); // If showing grid, it changed a bit for sure... if (m_pMidiEditor->isSnapGrid() || m_pMidiEditor->isSnapZebra()) m_pMidiEditor->updateContents(); m_pMidiEditor->editView()->setFocus(); } // Snap-to-scale/quantize combo-box change slots. void qtractorMidiEditorForm::snapToScaleKeyChanged ( int iSnapToScaleKey ) { m_pMidiEditor->setSnapToScaleKey(iSnapToScaleKey); } void qtractorMidiEditorForm::snapToScaleTypeChanged ( int iSnapToScaleType ) { m_pMidiEditor->setSnapToScaleType(iSnapToScaleType); } // Tool selection handlers. void qtractorMidiEditorForm::viewTypeChanged ( int iIndex ) { qtractorMidiEvent::EventType eventType = qtractorMidiEvent::EventType( m_pViewTypeComboBox->itemData(iIndex).toInt()); m_pMidiEditor->editView()->setEventType(eventType); m_pMidiEditor->updateContents(); m_pMidiEventList->refresh(); stabilizeForm(); } void qtractorMidiEditorForm::eventTypeChanged ( int iIndex ) { qtractorMidiEvent::EventType eventType = qtractorMidiEvent::EventType( m_pEventTypeComboBox->itemData(iIndex).toInt()); m_pControllerComboBox->setEnabled( eventType == qtractorMidiEvent::CONTROLLER); m_pMidiEditor->editEvent()->setEventType(eventType); m_pMidiEditor->updateContents(); m_pMidiEventList->refresh(); stabilizeForm(); } void qtractorMidiEditorForm::controllerChanged ( int iIndex ) { unsigned char controller = (unsigned char) ( m_pControllerComboBox->itemData(iIndex).toInt() & 0x7f); m_pMidiEditor->editEvent()->setController(controller); m_pMidiEditor->updateContents(); m_pMidiEventList->refresh(); stabilizeForm(); } void qtractorMidiEditorForm::selectionChanged ( qtractorMidiEditor *pMidiEditor ) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->selectionNotifySlot(pMidiEditor); stabilizeForm(); } void qtractorMidiEditorForm::contentsChanged ( qtractorMidiEditor *pMidiEditor ) { ++m_iDirtyCount; selectionChanged(pMidiEditor); } // end of qtractorMidiEditorForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTrackList.cpp0000644000175000001440000000012212223304667021433 xustar000000000000000026 mtime=1380813239.49437 26 atime=1381134670.70308 30 ctime=1381134670.704080108 qtractor-0.5.11/src/qtractorTrackList.cpp0000644000175000001440000010066412223304667020732 0ustar00rncbcusers00000000000000// qtractorTrackList.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorTrackList.h" #include "qtractorTrack.h" #include "qtractorTracks.h" #include "qtractorTrackView.h" #include "qtractorTrackCommand.h" #include "qtractorTrackButton.h" #include "qtractorInstrument.h" #include "qtractorAudioEngine.h" #include "qtractorMidiEngine.h" #include "qtractorMidiBuffer.h" #include "qtractorPlugin.h" #include "qtractorRubberBand.h" #include "qtractorMainForm.h" #include "qtractorMixer.h" #include "qtractorCurve.h" #include #include #include #include #include #include #include #ifdef CONFIG_GRADIENT #include #endif //---------------------------------------------------------------------------- // qtractorCurveButton -- Track automation curve menu button. class qtractorCurveButton : public QPushButton { // Q_OBJECT public: // Constructor. qtractorCurveButton(qtractorTrack *pTrack, QWidget *pParent) : QPushButton(pParent), m_pTrack(pTrack) { QPushButton::setFocusPolicy(Qt::NoFocus); } // Button state updater. void updateTrack() { qtractorCurveList *pCurveList = m_pTrack->curveList(); if (pCurveList) { QPalette pal; if (pCurveList->isCapture()) { pal.setColor(QPalette::Button, Qt::darkRed); pal.setColor(QPalette::ButtonText, Qt::red); } else if (pCurveList->isProcess()) { pal.setColor(QPalette::Button, Qt::darkGreen); pal.setColor(QPalette::ButtonText, Qt::green); } QPushButton::setPalette(pal); QString sToolTip(QObject::tr("Automation (%1)")); qtractorSubject *pSubject = NULL; qtractorCurve *pCurrentCurve = pCurveList->currentCurve(); if (pCurrentCurve) pSubject = pCurrentCurve->subject(); if (pSubject) QPushButton::setToolTip(sToolTip.arg(pSubject->name())); else QPushButton::setToolTip(sToolTip.arg(QObject::tr("none"))); } } protected: // Virtual trap to set current track // before showing the automation menu... bool hitButton(const QPoint& pos) const { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) { qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks) pTracks->trackList()->setCurrentTrack(m_pTrack); } return QPushButton::hitButton(pos); } private: // Instance variables. qtractorTrack *m_pTrack; }; //---------------------------------------------------------------------------- // qtractorTrackListHeaderModel -- Track-list header model. // Constructor. qtractorTrackListHeaderModel::qtractorTrackListHeaderModel ( QObject *pParent ) : QAbstractListModel(pParent) { m_headerText << tr("Nr") << tr("Track Name") << tr("Bus") << tr("Ch") << tr("Patch") << tr("Instrument"); }; QVariant qtractorTrackListHeaderModel::headerData ( int section, Qt::Orientation orient, int role ) const { if (orient == Qt::Horizontal) { switch (role) { case Qt::DisplayRole: return m_headerText.at(section); case Qt::TextAlignmentRole: if (section == qtractorTrackList::Number || section == qtractorTrackList::Channel) return int(Qt::AlignHCenter | Qt::AlignVCenter); else return int(Qt::AlignLeft | Qt::AlignVCenter); } } return QVariant(); } //---------------------------------------------------------------------------- // qtractorTrackItemWidget -- Track button layout widget. // Constructor. qtractorTrackItemWidget::qtractorTrackItemWidget ( qtractorTrackList *pTrackList, qtractorTrack *pTrack ) : QWidget(pTrackList->viewport()) { QWidget::setBackgroundRole(QPalette::Window); QHBoxLayout *pHBoxLayout = new QHBoxLayout(); pHBoxLayout->setMargin(2); pHBoxLayout->setSpacing(2); const QFont& font = QWidget::font(); const QFont font2(font.family(), font.pointSize() - 2); const int iFixedHeight = QFontMetrics(font).lineSpacing() + 4; const QSize buttonSize(22, iFixedHeight); m_pRecordButton = new qtractorTrackButton(pTrack, qtractorTrack::Record); m_pRecordButton->setFixedSize(buttonSize); m_pRecordButton->setFont(font2); m_pMuteButton = new qtractorTrackButton(pTrack, qtractorTrack::Mute); m_pMuteButton->setFixedSize(buttonSize); m_pMuteButton->setFont(font2); m_pSoloButton = new qtractorTrackButton(pTrack, qtractorTrack::Solo); m_pSoloButton->setFixedSize(buttonSize); m_pSoloButton->setFont(font2); m_pCurveButton = new qtractorCurveButton(pTrack, this); m_pCurveButton->setFixedSize(QSize(32, iFixedHeight)); m_pCurveButton->setFont(font2); m_pCurveButton->setText("A"); m_pCurveButton->setToolTip(QObject::tr("Automation")); qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) m_pCurveButton->setMenu(pMainForm->trackCurveMenu()); // pHBoxLayout->addStretch(); pHBoxLayout->addWidget(m_pRecordButton); pHBoxLayout->addWidget(m_pMuteButton); pHBoxLayout->addWidget(m_pSoloButton); pHBoxLayout->addWidget(m_pCurveButton); QWidget::setLayout(pHBoxLayout); } //---------------------------------------------------------------------------- // qtractorTrackList -- Track list widget. // Constructor. qtractorTrackList::qtractorTrackList ( qtractorTracks *pTracks, QWidget *pParent ) : qtractorScrollView(pParent) { m_pTracks = pTracks; m_iCurrentTrack = -1; m_dragState = DragNone; m_iDragTrack = -1; m_iDragY = 0; m_pRubberBand = NULL; m_iUpdateContents = 0; m_pPixmap[IconAudio] = new QPixmap(":/images/trackAudio.png"); m_pPixmap[IconMidi] = new QPixmap(":/images/trackMidi.png"); // Allocate local header. m_pHeader = new QHeaderView(Qt::Horizontal, qtractorScrollView::viewport()); m_pHeader->setModel(new qtractorTrackListHeaderModel(this)); m_pHeader->setHighlightSections(false); m_pHeader->setStretchLastSection(true); m_pHeader->setSortIndicatorShown(false); // Default section sizes... m_pHeader->resizeSection(Number, 26); m_pHeader->resizeSection(Name, 120); m_pHeader->resizeSection(Channel, 24); // qtractorScrollView::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); qtractorScrollView::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); qtractorScrollView::viewport()->setFocusPolicy(Qt::ClickFocus); // qtractorScrollView::viewport()->setFocusProxy(this); // qtractorScrollView::viewport()->setAcceptDrops(true); // qtractorScrollView::setDragAutoScroll(false); qtractorScrollView::setMouseTracking(true); const QFont& font = qtractorScrollView::font(); qtractorScrollView::setFont(QFont(font.family(), font.pointSize() - 1)); QObject::connect(m_pHeader, SIGNAL(sectionResized(int,int,int)), SLOT(updateHeader())); // QObject::connect(this, SIGNAL(contentsMoving(int,int)), // this, SLOT(updatePixmap(int,int))); } // Destructor. qtractorTrackList::~qtractorTrackList (void) { delete m_pPixmap[IconAudio]; delete m_pPixmap[IconMidi]; } // Main tracks widget accessor. qtractorTracks *qtractorTrackList::tracks (void) const { return m_pTracks; } // Loacl header view accessor. QHeaderView *qtractorTrackList::header (void) const { return m_pHeader; } // Track-list model item constructor qtractorTrackList::Item::Item ( qtractorTrackList *pTrackList, qtractorTrack *pTrack ) : track(pTrack), widget(NULL) { update(pTrackList); } // Track-list model item destructor qtractorTrackList::Item::~Item (void) { if (widget) delete widget; } // Track-list model item bank/program names helper. bool qtractorTrackList::Item::updateBankProgram ( qtractorMidiManager *pMidiManager, const QString& sInstrument, QString& sBank, QString& sProgram ) const { if (pMidiManager == NULL) return false; const qtractorMidiManager::Instruments& list = pMidiManager->instruments(); if (!list.contains(sInstrument)) return false; const qtractorMidiManager::Banks& banks = list[sInstrument]; const int iBank = track->midiBank(); if (banks.contains(iBank)) { const qtractorMidiManager::Bank& bank = banks[iBank]; const int iProg = track->midiProg(); if (bank.progs.contains(iProg)) { sProgram = QString("%1 - %2").arg(iProg) .arg(bank.progs[iProg]); sBank = bank.name; } } return true; } // Track-list model item cache updater. void qtractorTrackList::Item::update ( qtractorTrackList *pTrackList ) { text.clear(); // Default initialization? if (track == NULL) return; if (widget == NULL) { widget = new qtractorTrackItemWidget(pTrackList, track); widget->lower(); } text << track->trackName(); const QString s = " - -"; QString sBusText = track->inputBusName(); if (track->inputBusName() != track->outputBusName()) sBusText += '/' + track->outputBusName(); switch (track->trackType()) { case qtractorTrack::Audio: { // Audio Bus name... text << sBusText + '\n' + QObject::tr("Audio"); // Audio channels... qtractorAudioBus *pAudioBus = static_cast (track->outputBus()); text << (pAudioBus ? QString::number(pAudioBus->channels()) : s.right(1)); // Fillers... text << s << s; break; } case qtractorTrack::Midi: { // MIDI Bus name... text << sBusText + '\n' + QObject::tr("MIDI"); qtractorMidiBus *pMidiBus = static_cast (track->outputBus()); // MIDI channels... QString sOmni; if (track->isMidiOmni()) sOmni += '*'; const unsigned short iChannel = track->midiChannel(); text << sOmni + QString::number(iChannel + 1); // Care of MIDI instrument, program and bank numbers vs.names... QString sInstrument = s; QString sProg = s; QString sBank; if (track->midiProg() >= 0) sProg = QString::number(track->midiProg() + 1) + s; if (track->midiBank() >= 0) sBank = QString::number(track->midiBank()); if (pMidiBus) { const qtractorMidiBus::Patch& patch = pMidiBus->patch(iChannel); if (!patch.instrumentName.isEmpty()) { sInstrument = patch.instrumentName; bool bMidiManager = updateBankProgram( (track->pluginList())->midiManager(), sInstrument, sBank, sProg); if (!bMidiManager && pMidiBus->pluginList_out()) { bMidiManager = updateBankProgram( (pMidiBus->pluginList_out())->midiManager(), sInstrument, sBank, sProg); } if (!bMidiManager) { qtractorInstrumentList *pInstruments = NULL; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) pInstruments = pSession->instruments(); if (pInstruments && pInstruments->contains(sInstrument)) { qtractorInstrument& instr = (*pInstruments)[sInstrument]; const qtractorInstrumentData& bank = instr.patch(track->midiBank()); if (bank.contains(track->midiProg())) { sProg = bank[track->midiProg()]; sBank = bank.name(); } } } } } // This is it, MIDI Patch/Bank... text << sProg + '\n' + sBank << sInstrument; break; } case qtractorTrack::None: default: { text << s + '\n' + QObject::tr("Unknown") << s << s << s; break; } } widget->curveButton()->updateTrack(); } // Find the list view item from track pointer reference. int qtractorTrackList::trackRow ( qtractorTrack *pTrack ) const { int iTrack = 0; QListIterator iter(m_items); while (iter.hasNext()) { if (pTrack == iter.next()->track) return iTrack; ++iTrack; } return -1; } // Find track row of given viewport point... int qtractorTrackList::trackRowAt ( const QPoint& pos ) { const int cy = qtractorScrollView::contentsY(); const int y = cy + pos.y() - m_pHeader->sizeHint().height(); const int h = qtractorScrollView::viewport()->height(); int y1, y2; y1 = y2 = 0; int iTrack = 0; QListIterator iter(m_items); while (iter.hasNext() && y2 < cy + h) { y1 = y2; y2 += (iter.next()->track)->zoomHeight(); if (y >= y1 && y < y2) return iTrack; ++iTrack; } return -1; } // Find track column of given viewport point... int qtractorTrackList::trackColumnAt ( const QPoint& pos ) { const int cy = qtractorScrollView::contentsY(); const int y = cy + pos.y() - m_pHeader->sizeHint().height(); if (y > 0 && y < qtractorScrollView::contentsHeight()) { const int cx = qtractorScrollView::contentsX(); const int x = cx + pos.x(); int x1, x2; x1 = x2 = 0; const int iColCount = m_pHeader->count(); for (int iCol = 0; iCol < iColCount; ++iCol) { x1 = x2; x2 += m_pHeader->sectionSize(iCol); if (x > x1 && x < x2) return iCol; } } return -1; } // Find the track pointer reference from list view item row. qtractorTrack *qtractorTrackList::track ( int iTrack ) const { if (iTrack < 0 || iTrack >= m_items.count()) return NULL; return m_items.at(iTrack)->track; } // Retrive the given track row rectangular (in viewport coordinates). QRect qtractorTrackList::trackRect ( int iTrack ) const { QRect rect; if (iTrack >= 0 && iTrack < m_items.count()) { rect.setX(0); rect.setWidth(qtractorScrollView::viewport()->width()); int y1, y2; y1 = y2 = m_pHeader->sizeHint().height(); QListIterator iter(m_items); while (iter.hasNext()) { y1 = y2; y2 += (iter.next()->track)->zoomHeight(); if (iTrack == 0) { rect.setY(y1 - qtractorScrollView::contentsY()); rect.setHeight(y2 - y1); break; } --iTrack; } } return rect; } // Insert a track item; return actual track row added. int qtractorTrackList::insertTrack ( int iTrack, qtractorTrack *pTrack ) { if (iTrack < 0) iTrack = m_items.count(); m_items.insert(iTrack, new Item(this, pTrack)); return iTrack; } // Remove a track item; return remaining track row. int qtractorTrackList::removeTrack ( int iTrack ) { if (iTrack < 0 || iTrack >= m_items.count()) return -1; delete m_items.at(iTrack); m_items.removeAt(iTrack); if (m_iCurrentTrack >= m_items.count()) m_iCurrentTrack = m_items.count() - 1; return (iTrack < m_items.count() ? iTrack : -1); } // Manage current track row by index. void qtractorTrackList::setCurrentTrackRow ( int iTrack ) { int iCurrentTrack = m_iCurrentTrack; if (iTrack < 0 || iTrack >= m_items.count()) iCurrentTrack = -1; else iCurrentTrack = iTrack; if (iCurrentTrack == m_iCurrentTrack) return; #ifdef CONFIG_DEBUG_0 qDebug("qtractorTrackList::setCurrentTrackRow(%d)", iCurrentTrack); #endif m_iCurrentTrack = iCurrentTrack; // Make sure the new current track is visible... if (!ensureVisibleRect(trackRect(m_iCurrentTrack))) updateContents(); emit selectionChanged(); } int qtractorTrackList::currentTrackRow (void) const { return m_iCurrentTrack; } int qtractorTrackList::trackRowCount (void) const { return m_items.count(); } // Current selected track reference. void qtractorTrackList::setCurrentTrack ( qtractorTrack *pTrack ) { setCurrentTrackRow(trackRow(pTrack)); } qtractorTrack *qtractorTrackList::currentTrack (void) const { if (m_iCurrentTrack < 0 || m_iCurrentTrack >= m_items.count()) return NULL; return m_items.at(m_iCurrentTrack)->track; } // Find the list view item from track pointer reference. void qtractorTrackList::updateTrack ( qtractorTrack *pTrack ) { QListIterator iter(m_items); while (iter.hasNext()) { Item *pItem = iter.next(); if (pTrack == NULL || pTrack == pItem->track) { // Force update the data... pItem->update(this); // Specific bail out... if (pTrack) break; } } updateContents(); } // Main table cleaner. void qtractorTrackList::clear (void) { m_iCurrentTrack = -1; m_dragState = DragNone; m_iDragTrack = -1; m_iDragY = 0; if (m_pRubberBand) delete m_pRubberBand; m_pRubberBand = NULL; qDeleteAll(m_items); m_items.clear(); } // Update all tracks item height. void qtractorTrackList::updateContentsHeight (void) { // Remember to give some room to drop something at the bottom... int iContentsHeight = m_pHeader->sizeHint().height() + (qtractorTrack::HeightBase << 1); QListIterator iter(m_items); while (iter.hasNext()) { qtractorTrack *pTrack = iter.next()->track; pTrack->updateZoomHeight(); iContentsHeight += pTrack->zoomHeight(); } qtractorScrollView::resizeContents( qtractorScrollView::contentsWidth(), iContentsHeight); // Update track view total contents height... qtractorTrackView *pTrackView = m_pTracks->trackView(); pTrackView->updateContentsHeight(); pTrackView->updateContents(); updateContents(); } // Rectangular contents update. void qtractorTrackList::updateContents ( const QRect& rect ) { if (m_iUpdateContents > 0) return; ++m_iUpdateContents; updatePixmap( qtractorScrollView::contentsX(), qtractorScrollView::contentsY()); qtractorScrollView::updateContents(rect); --m_iUpdateContents; } // Overall contents update. void qtractorTrackList::updateContents (void) { if (m_iUpdateContents > 0) return; ++m_iUpdateContents; updatePixmap( qtractorScrollView::contentsX(), qtractorScrollView::contentsY()); qtractorScrollView::updateContents(); --m_iUpdateContents; } // Resize event handler. void qtractorTrackList::resizeEvent ( QResizeEvent *pResizeEvent ) { qtractorScrollView::resizeEvent(pResizeEvent); updateHeader(); } // Update header extents. void qtractorTrackList::updateHeader (void) { // Find out wich is the largest header width // and enforce to let it know it like so... const int iColCount = m_pHeader->count() - 1; int iContentsWidth = (qtractorScrollView::viewport()->width() >> 1); for (int iCol = 0; iCol < iColCount; ++iCol) iContentsWidth += m_pHeader->sectionSize(iCol); m_pHeader->setFixedWidth(iContentsWidth); qtractorScrollView::resizeContents( iContentsWidth, qtractorScrollView::contentsHeight()); updateContents(); } // Draw table cell. void qtractorTrackList::drawCell ( QPainter *pPainter, int iRow, int iCol, const QRect& rect ) const { const QPalette& pal = qtractorScrollView::palette(); const Item *pItem = m_items.at(iRow); QColor bg, fg; if (iCol == Number) { bg = (pItem->track)->foreground().lighter(); fg = (pItem->track)->background().lighter(); } else if (m_iCurrentTrack == iRow) { bg = pal.midlight().color().darker(150); fg = pal.midlight().color().lighter(); } else { bg = pal.window().color(); fg = pal.windowText().color(); } // Draw text and decorations if any... QRect rectText(rect.topLeft() + QPoint(4, 4), rect.size() - QSize(8, 8)); #ifdef CONFIG_GRADIENT QLinearGradient grad(0, rect.top(), 0, rect.bottom()); grad.setColorAt(0.4, bg); grad.setColorAt(1.0, bg.darker(120)); pPainter->fillRect(rect, grad); #else pPainter->fillRect(rect, bg); #endif pPainter->setPen(fg); if (iCol == Number) { pPainter->drawText(rectText, Qt::AlignHCenter | Qt::AlignTop, QString::number(iRow + 1)); } else if (iCol == Channel) { pPainter->drawText(rectText, Qt::AlignHCenter | Qt::AlignTop, pItem->text.at(iCol - 1)); } else { if (iCol == Bus) { const QPixmap *pPixmap = NULL; switch ((pItem->track)->trackType()) { case qtractorTrack::Audio: pPixmap = m_pPixmap[IconAudio]; break; case qtractorTrack::Midi: pPixmap = m_pPixmap[IconMidi]; break; case qtractorTrack::None: default: break; } if (pPixmap) { pPainter->drawPixmap(rectText.x(), rectText.y(), *pPixmap); rectText.setLeft(rectText.left() + pPixmap->width() + 4); } } pPainter->drawText(rectText, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, pItem->text.at(iCol - 1)); } // Do some simple embossing... pPainter->setPen(bg.lighter(150)); pPainter->drawLine(rect.left(), rect.top(), rect.left(), rect.bottom()); pPainter->drawLine(rect.left(), rect.top(), rect.right(), rect.top()); pPainter->setPen(bg.darker(150)); pPainter->drawLine(rect.right(), rect.top(), rect.right(), rect.bottom()); pPainter->drawLine(rect.left(), rect.bottom(), rect.right(), rect.bottom()); } // (Re)create the complete view pixmap. void qtractorTrackList::updatePixmap ( int cx, int cy ) { QWidget *pViewport = qtractorScrollView::viewport(); const int w = pViewport->width(); const int h = pViewport->height(); if (w < 1 || h < 1) return; const QPalette& pal = qtractorScrollView::palette(); m_pixmap = QPixmap(w, h); m_pixmap.fill(pal.window().color()); QPainter painter(&m_pixmap); painter.initFrom(pViewport); // Update actual contents size... m_pHeader->setOffset(cx); // Draw all cells... const int iColCount = m_pHeader->count(); const int hh = m_pHeader->sizeHint().height(); // Account for the item dropping headroom... const int ch = qtractorScrollView::contentsHeight() - (qtractorTrack::HeightBase << 1); int x, y1, y2, h1; y1 = y2 = 0; int iTrack = 0; QListIterator iter(m_items); while (iter.hasNext()) { Item *pItem = iter.next(); h1 = (pItem->track)->zoomHeight(); y1 = y2; y2 += h1; if (y2 > cy && y1 < cy + h) { // Dispatch to paint this track... QRect rect(0, y1 - cy + hh, w, h1); x = 0; for (int iCol = 0; iCol < iColCount; ++iCol) { const int dx = m_pHeader->sectionSize(iCol); if (x + dx > cx && x < cx + w) { rect.setX(x - cx); rect.setWidth(dx); drawCell(&painter, iTrack, iCol, rect); if (iCol == Name && pItem->widget) { QRect rectWidget = rect; QSize sizeWidget = (pItem->widget)->sizeHint(); rectWidget.setTop(rect.bottom() - sizeWidget.height()); rectWidget.setLeft(rect.right() - sizeWidget.width()); if (rectWidget.height() < h1) { (pItem->widget)->setGeometry(rectWidget); (pItem->widget)->show(); } else { (pItem->widget)->hide(); } } } else if (iCol == Name && pItem->widget) (pItem->widget)->hide(); x += dx; } } else if (pItem->widget) (pItem->widget)->hide(); ++iTrack; } if (cy + h > ch) { painter.setPen(pal.mid().color()); painter.drawLine(0, ch - cy, w, ch - cy); painter.fillRect(0, ch - cy + 1, w, cy + h - ch, pal.dark().color()); } } // Draw the time scale. void qtractorTrackList::drawContents ( QPainter *pPainter, const QRect& rect ) { pPainter->drawPixmap(rect, m_pixmap, rect); } // To have keyline in v-sync with main view. void qtractorTrackList::contentsYMovingSlot ( int /*cx*/, int cy ) { if (qtractorScrollView::contentsY() != cy) qtractorScrollView::setContentsPos(qtractorScrollView::contentsX(), cy); } // Context menu event handler. void qtractorTrackList::contextMenuEvent ( QContextMenuEvent *pContextMenuEvent ) { // We'll need a reference for issuing commands... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->trackMenu()->exec(pContextMenuEvent->globalPos()); } // Handle mouse double-clicks. void qtractorTrackList::mouseDoubleClickEvent ( QMouseEvent * /*pMouseEvent*/ ) { // Avoid lingering mouse press/release states... resetDragState(); // We'll need a reference for issuing commands... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->trackProperties(); } // Handle item selection/dragging -- mouse button press. void qtractorTrackList::mousePressEvent ( QMouseEvent *pMouseEvent ) { const QPoint& pos = pMouseEvent->pos(); // Select current track... const int iTrack = trackRowAt(pos); setCurrentTrackRow(iTrack); // Look for the mouse hovering around some item boundary... if (iTrack >= 0) { // Special attitude, only of interest on // the first-left column (track-number)... if (trackColumnAt(pos) == Number) { m_pTracks->selectCurrentTrack((pMouseEvent->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) == 0); } if (pMouseEvent->button() == Qt::LeftButton) { // Try for drag-resize... m_posDrag = pos; if (m_iDragTrack >= 0) { m_dragState = DragResize; } else { m_iDragTrack = iTrack; m_iDragY = 0; m_dragState = DragStart; qtractorScrollView::setCursor(QCursor(Qt::PointingHandCursor)); } } } // Probably this would be done ahead, // just 'coz we're using ruberbands, which are // in fact based on real widgets (WM entities)... // qtractorScrollView::mousePressEvent(pMouseEvent); } // Handle item selection/dragging -- mouse pointer move. void qtractorTrackList::mouseMoveEvent ( QMouseEvent *pMouseEvent ) { const QPoint& pos = pMouseEvent->pos(); // We're already on some item dragging/resizing?... switch (m_dragState) { case DragMove: // Currently moving an item... if (m_iDragTrack >= 0) { const int iTrack = trackRowAt(pos); if (iTrack >= 0) { const QRect& rect = trackRect(iTrack); m_posDrag = rect.topLeft(); moveRubberBand(m_posDrag); ensureVisibleRect(rect); } else { const QRect& rect = trackRect(m_items.count() - 1); m_posDrag = rect.bottomLeft(); moveRubberBand(m_posDrag); } } break; case DragResize: // Currently resizing an item... if (m_iDragTrack >= 0) { int y = pos.y(); if (y < m_iDragY + qtractorTrack::HeightMin) y = m_iDragY + qtractorTrack::HeightMin; m_posDrag.setY(y); moveRubberBand(m_posDrag); } break; case DragStart: // About to start dragging an item... if (m_iDragTrack >= 0 && (m_posDrag - pos).manhattanLength() > QApplication::startDragDistance()) { qtractorScrollView::setCursor(QCursor(Qt::SizeVerCursor)); m_dragState = DragMove; m_posDrag = trackRect(m_iDragTrack).topLeft(); moveRubberBand(m_posDrag); } break; case DragNone: { // Look for the mouse hovering around first column item boundary... int iTrack = trackRowAt(pos); if (iTrack >= 0 && trackColumnAt(pos) == Number) { m_posDrag = pos; QRect rect = trackRect(iTrack); if (pos.y() >= rect.top() && pos.y() < rect.top() + 4) { if (--iTrack >= 0) { if (m_iDragTrack < 0) qtractorScrollView::setCursor(QCursor(Qt::SplitVCursor)); m_iDragTrack = iTrack; m_iDragY = trackRect(iTrack).top(); break; } } else if (pos.y() >= rect.bottom() - 4 && pos.y() < rect.bottom() + 4) { if (m_iDragTrack < 0) qtractorScrollView::setCursor(QCursor(Qt::SplitVCursor)); m_iDragTrack = iTrack; m_iDragY = rect.top(); break; } } // If something has been going on, turn it off... if (m_iDragTrack >= 0) { qtractorScrollView::unsetCursor(); m_iDragTrack = -1; m_iDragY = 0; } break; } default: break; } // qtractorScrollView::mouseMoveEvent(pMouseEvent); } // Handle item selection/dragging -- mouse button release. void qtractorTrackList::mouseReleaseEvent ( QMouseEvent *pMouseEvent ) { // qtractorScrollView::mouseReleaseEvent(pMouseEvent); // We'll need a reference for issuing commands... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; const QPoint& pos = pMouseEvent->pos(); // If we were resizing, now's time to let // things know that have changed somehow... switch (m_dragState) { case DragMove: if (m_iDragTrack >= 0) { qtractorTrack *pTrack = track(m_iDragTrack); if (pTrack) { qtractorTrack *pTrackDrop = NULL; const int iTrack = trackRowAt(pos); if (iTrack >= 0) pTrackDrop = track(iTrack); if (pTrack != pTrackDrop && (pTrackDrop == NULL || pTrack != pTrackDrop->prev())) { pSession->execute( new qtractorMoveTrackCommand(pTrack, pTrackDrop)); } } } break; case DragResize: if (m_iDragTrack >= 0) { int iZoomHeight = pos.y() - m_iDragY; // Check for minimum item height. if (iZoomHeight < qtractorTrack::HeightMin) iZoomHeight = qtractorTrack::HeightMin; // Go for it... qtractorTrack *pTrack = track(m_iDragTrack); if (pTrack) { pSession->execute( new qtractorResizeTrackCommand(pTrack, iZoomHeight)); } } // Fall thru... case DragStart: case DragNone: default: break; } // Force null state. resetDragState(); } // Handle zoom with mouse wheel. void qtractorTrackList::wheelEvent ( QWheelEvent *pWheelEvent ) { if (pWheelEvent->modifiers() & Qt::ControlModifier) { if (pWheelEvent->delta() > 0) m_pTracks->zoomIn(); else m_pTracks->zoomOut(); } else qtractorScrollView::wheelEvent(pWheelEvent); } // Draw a dragging separator line. void qtractorTrackList::moveRubberBand ( const QPoint& posDrag ) { // Create the rubber-band if there's none... if (m_pRubberBand == NULL) { m_pRubberBand = new qtractorRubberBand( QRubberBand::Line, qtractorScrollView::viewport()); // QPalette pal(m_pRubberBand->palette()); // pal.setColor(m_pRubberBand->foregroundRole(), Qt::blue); // m_pRubberBand->setPalette(pal); // m_pRubberBand->setBackgroundRole(QPalette::NoRole); } // Just move it m_pRubberBand->setGeometry( QRect(0, posDrag.y(), qtractorScrollView::viewport()->width(), 4)); // Ah, and make it visible, of course... if (!m_pRubberBand->isVisible()) m_pRubberBand->show(); } // Make sure the given (track) rectangle is visible. bool qtractorTrackList::ensureVisibleRect ( const QRect& rect ) { if (!rect.isValid()) return false; const int hh = m_pHeader->sizeHint().height(); const int cx = qtractorScrollView::contentsX(); const int cy = qtractorScrollView::contentsY(); if (rect.top() < hh) { qtractorScrollView::ensureVisible(cx, cy + rect.top(), 0, 24); return true; } if (rect.bottom() > qtractorScrollView::viewport()->height()) { qtractorScrollView::ensureVisible(cx, cy + rect.bottom() - hh, 0, 24); return true; } return false; } // Reset drag/select/move state. void qtractorTrackList::resetDragState (void) { // Cancel any dragging out there... // Just hide the rubber-band... if (m_pRubberBand) m_pRubberBand->hide(); // Should fallback mouse cursor... if (m_dragState != DragNone || m_iDragTrack >= 0) qtractorScrollView::unsetCursor(); // Not dragging anymore. m_dragState = DragNone; m_iDragTrack = -1; m_iDragY = 0; } // Keyboard event handler. void qtractorTrackList::keyPressEvent ( QKeyEvent *pKeyEvent ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorTrackList::keyPressEvent(%d)", pKeyEvent->key()); #endif switch (pKeyEvent->key()) { case Qt::Key_Escape: resetDragState(); break; case Qt::Key_Home: if (pKeyEvent->modifiers() & Qt::ControlModifier) { setCurrentTrackRow(0); } else { qtractorScrollView::setContentsPos( 0, qtractorScrollView::contentsY()); } break; case Qt::Key_End: if (pKeyEvent->modifiers() & Qt::ControlModifier) { setCurrentTrackRow(m_items.count() - 1); } else { qtractorScrollView::setContentsPos( qtractorScrollView::contentsWidth(), qtractorScrollView::contentsY()); } break; case Qt::Key_Left: if (pKeyEvent->modifiers() & Qt::ControlModifier) { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX() - qtractorScrollView::width(), qtractorScrollView::contentsY()); } else { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX() - 16, qtractorScrollView::contentsY()); } break; case Qt::Key_Right: if (pKeyEvent->modifiers() & Qt::ControlModifier) { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX() + qtractorScrollView::width(), qtractorScrollView::contentsY()); } else { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX() + 16, qtractorScrollView::contentsY()); } break; case Qt::Key_Up: if (m_iCurrentTrack > 0) setCurrentTrackRow(m_iCurrentTrack - 1); break; case Qt::Key_Down: if (m_iCurrentTrack < m_items.count() - 1) setCurrentTrackRow(m_iCurrentTrack + 1); break; case Qt::Key_PageUp: if (pKeyEvent->modifiers() & Qt::ControlModifier) { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX(), 0); } else { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX(), qtractorScrollView::contentsY() - qtractorScrollView::height()); } break; case Qt::Key_PageDown: if (pKeyEvent->modifiers() & Qt::ControlModifier) { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX(), qtractorScrollView::contentsHeight()); } else { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX(), qtractorScrollView::contentsY() + qtractorScrollView::height()); } break; default: qtractorScrollView::keyPressEvent(pKeyEvent); break; } } // end of qtractorTrackList.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiConnect.h0000644000175000001440000000012311563576072021404 xustar000000000000000027 mtime=1305410618.253123 26 atime=1381134667.26508 30 ctime=1381134667.265080053 qtractor-0.5.11/src/qtractorMidiConnect.h0000644000175000001440000001065011563576072020675 0ustar00rncbcusers00000000000000// qtractorMidiConnect.h // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiConnect_h #define __qtractorMidiConnect_h #include "qtractorConnect.h" #include // Forward declarations. class qtractorMidiPortItem; class qtractorMidiClientItem; class qtractorMidiClientListView; class qtractorMidiConnect; //---------------------------------------------------------------------- // qtractorMidiPortItem -- Alsa port list item. // class qtractorMidiPortItem : public qtractorPortListItem { public: // Constructor. qtractorMidiPortItem(qtractorMidiClientItem *pClientItem, const QString& sPortName, int iAlsaPort); // Default destructor. ~qtractorMidiPortItem(); // Jack handles accessors. int alsaClient() const; int alsaPort() const; private: // Instance variables. int m_iAlsaPort; }; //---------------------------------------------------------------------- // qtractorMidiClientItem -- Alsa client list item. // class qtractorMidiClientItem : public qtractorClientListItem { public: // Constructor. qtractorMidiClientItem(qtractorMidiClientListView *pClientListView, const QString& sClientName, int iAlsaClient); // Default destructor. ~qtractorMidiClientItem(); // Jack client accessors. int alsaClient() const; // Port finder by id. qtractorMidiPortItem *findPortItem(int iAlsaPort); private: // Instance variables. int m_iAlsaClient; }; //---------------------------------------------------------------------- // qtractorMidiClientListView -- Alsa client list view. // class qtractorMidiClientListView : public qtractorClientListView { public: // Constructor. qtractorMidiClientListView(QWidget *pParent = NULL); // Default destructor. ~qtractorMidiClientListView(); // Alsa sequencer accessor. snd_seq_t *alsaSeq() const; // Client finder by id. qtractorMidiClientItem *findClientItem(int iAlsaClient); // Client port finder by id. qtractorMidiPortItem *findClientPortItem(int iAlsaClient, int iAlsaPort); // Client:port refreshner (return newest item count). int updateClientPorts(); }; //---------------------------------------------------------------------------- // qtractorMidiConnect -- Connections model integrated object. // class qtractorMidiConnect : public qtractorConnect { public: // Constructor. qtractorMidiConnect( qtractorMidiClientListView *pOListView, qtractorMidiClientListView *pIListView, qtractorConnectorView *pConnectorView); // Default destructor. ~qtractorMidiConnect(); // ALSA sequencer accessor. snd_seq_t *alsaSeq() const; // icon-set array indexes. enum { ClientIn = 0, // Input client item icon. ClientOut = 1, // Output client item icon. PortIn = 2, // Input port item icon. PortOut = 3, // Output port item icon. IconCount = 4 // Number of icons in local array. }; // Common icon accessor. static const QIcon& icon(int iIcon); protected: // Virtual Connect/Disconnection primitives. bool connectPorts(qtractorPortListItem *pOPort, qtractorPortListItem *pIPort); bool disconnectPorts(qtractorPortListItem *pOPort, qtractorPortListItem *pIPort); // Update port connection references. void updateConnections(); // Update (clear) MIDI-buses connect lists (non-virtual). void disconnectPortsUpdate( qtractorPortListItem *pOPort, qtractorPortListItem *pIPort); private: // Local pixmap-set janitor methods. void createIcons(); void deleteIcons(); // Local static pixmap-set array. static QIcon *g_apIcons[IconCount]; static int g_iIconsRefCount; }; #endif // __qtractorMidiConnect_h // end of qtractorMidiConnect.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiBuffer.cpp0000644000175000001440000000012312140703725021544 xustar000000000000000027 mtime=1367574485.762649 26 atime=1381134667.43508 30 ctime=1381134667.436080056 qtractor-0.5.11/src/qtractorMidiBuffer.cpp0000644000175000001440000007243512140703725021046 0ustar00rncbcusers00000000000000// qtractorMidiBuffer.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorMidiBuffer.h" #include "qtractorSession.h" #include "qtractorPlugin.h" #include "qtractorAudioEngine.h" #include "qtractorMixer.h" #include #include #include // Specific controller definitions #define BANK_SELECT_MSB 0x00 #define BANK_SELECT_LSB 0x20 //---------------------------------------------------------------------- // class qtractorMidiManagerThread -- MIDI controller thread. // class qtractorMidiManagerThread : public QThread { public: // Constructor. qtractorMidiManagerThread(unsigned int iSyncSize = 128); // Destructor. ~qtractorMidiManagerThread(); // Thread run state accessors. void setRunState(bool bRunState); bool runState() const; // Wake from executive wait condition. void sync(qtractorMidiManager *pMidiManager = NULL); protected: // The main thread executive. void run(); private: // The thread launcher queue instance reference. unsigned int m_iSyncSize; unsigned int m_iSyncMask; qtractorMidiManager **m_ppSyncItems; volatile unsigned int m_iSyncRead; volatile unsigned int m_iSyncWrite; // Whether the thread is logically running. volatile bool m_bRunState; // Thread synchronization objects. QMutex m_mutex; QWaitCondition m_cond; }; //---------------------------------------------------------------------- // class qtractorMidiManagerThread -- MIDI output thread (singleton). // // Constructor. qtractorMidiManagerThread::qtractorMidiManagerThread ( unsigned int iSyncSize ) { m_iSyncSize = (64 << 1); while (m_iSyncSize < iSyncSize) m_iSyncSize <<= 1; m_iSyncMask = (m_iSyncSize - 1); m_ppSyncItems = new qtractorMidiManager * [m_iSyncSize]; m_iSyncRead = 0; m_iSyncWrite = 0; ::memset(m_ppSyncItems, 0, m_iSyncSize * sizeof(qtractorMidiManager *)); m_bRunState = false; } // Destructor. qtractorMidiManagerThread::~qtractorMidiManagerThread (void) { delete [] m_ppSyncItems; } // Thread run state accessors. void qtractorMidiManagerThread::setRunState ( bool bRunState ) { QMutexLocker locker(&m_mutex); m_bRunState = bRunState; } bool qtractorMidiManagerThread::runState (void) const { return m_bRunState; } // The main thread executive. void qtractorMidiManagerThread::run (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiManagerThread[%p]::run(): started...", this); #endif m_mutex.lock(); m_bRunState = true; while (m_bRunState) { // Wait for sync... m_cond.wait(&m_mutex); #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiManagerThread[%p]::run(): waked.", this); #endif // Call control process cycle. unsigned int r = m_iSyncRead; unsigned int w = m_iSyncWrite; while (r != w) { m_ppSyncItems[r]->processSync(); ++r &= m_iSyncMask; w = m_iSyncWrite; } m_iSyncRead = r; } m_mutex.unlock(); #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiManagerThread[%p]::run(): stopped.", this); #endif } // Wake from executive wait condition. void qtractorMidiManagerThread::sync ( qtractorMidiManager *pMidiManager ) { if (pMidiManager == NULL) { unsigned int r = m_iSyncRead; unsigned int w = m_iSyncWrite; while (r != w) { qtractorMidiManager *pSyncItem = m_ppSyncItems[r]; if (pSyncItem) pSyncItem->setWaitSync(false); ++r &= m_iSyncMask; w = m_iSyncWrite; } m_iSyncRead = r; } else { // !pMidiManager->isWaitSync() unsigned int n; unsigned int r = m_iSyncRead; unsigned int w = m_iSyncWrite; if (w > r) { n = ((r - w + m_iSyncSize) & m_iSyncMask) - 1; } else if (r > w) { n = (r - w) - 1; } else { n = m_iSyncSize - 1; } if (n > 0) { pMidiManager->setWaitSync(true); m_ppSyncItems[w] = pMidiManager; m_iSyncWrite = (w + 1) & m_iSyncMask; } } if (m_mutex.tryLock()) { m_cond.wakeAll(); m_mutex.unlock(); } #ifdef CONFIG_DEBUG_0 else qDebug("qtractorMidiManagerThread[%p]::sync(): tryLock() failed.", this); #endif } //---------------------------------------------------------------------- // class qtractorMidiManager -- MIDI internal plugin list manager. // qtractorMidiManagerThread *qtractorMidiManager::g_pSyncThread = NULL; unsigned int qtractorMidiManager::g_iSyncThreadRefCount = 0; bool qtractorMidiManager::g_bAudioOutputBus = false; bool qtractorMidiManager::g_bAudioOutputAutoConnect = true; // AG: Buffer size large enough to hold some sysex events. const long c_iMaxMidiData = 512; // Constructor. qtractorMidiManager::qtractorMidiManager ( qtractorPluginList *pPluginList, unsigned int iBufferSize ) : m_pPluginList(pPluginList), m_directBuffer(iBufferSize >> 1), m_queuedBuffer(iBufferSize), m_postedBuffer(iBufferSize), m_controllerBuffer(iBufferSize >> 2), m_pBuffer(NULL), m_iBuffer(0), #ifdef CONFIG_MIDI_PARSER m_pMidiParser(NULL), #endif m_iEventBuffer(0), m_bAudioOutputBus(g_bAudioOutputBus), m_bAudioOutputAutoConnect(g_bAudioOutputAutoConnect), m_pAudioOutputBus(NULL), m_iCurrentBank(-1), m_iCurrentProg(-1), m_iPendingBankMSB(-1), m_iPendingBankLSB(-1), m_iPendingProg(-1) { const unsigned int MaxMidiEvents = (bufferSize() >> 1); m_pBuffer = new snd_seq_event_t [MaxMidiEvents]; #ifdef CONFIG_MIDI_PARSER if (snd_midi_event_new(c_iMaxMidiData, &m_pMidiParser) == 0) snd_midi_event_no_status(m_pMidiParser, 1); #endif // Create_event buffers... #ifdef CONFIG_VST const unsigned int VstBufferSize = sizeof(VstEvents) + MaxMidiEvents * sizeof(VstMidiEvent *); #endif #ifdef CONFIG_LV2_EVENT const unsigned int Lv2EventBufferSize = (sizeof(LV2_Event) + 4) * MaxMidiEvents; #endif #ifdef CONFIG_LV2_ATOM const unsigned int Lv2AtomBufferSize = (sizeof(LV2_Atom_Event) + 4) * MaxMidiEvents; #endif for (unsigned short i = 0; i < 2; ++i) { #ifdef CONFIG_VST m_ppVstBuffers[i] = new unsigned char [VstBufferSize]; m_ppVstMidiBuffers[i] = new VstMidiEvent [MaxMidiEvents]; #endif #ifdef CONFIG_LV2_EVENT m_ppLv2EventBuffers[i] = lv2_event_buffer_new(Lv2EventBufferSize, LV2_EVENT_AUDIO_STAMP); #endif #ifdef CONFIG_LV2_ATOM m_ppLv2AtomBuffers[i] = lv2_atom_buffer_new(Lv2AtomBufferSize, qtractorLv2Plugin::lv2_urid_map(LV2_ATOM__Sequence), (i & 1) == 0); #endif } m_bWaitSync = false; if (++g_iSyncThreadRefCount == 1 && g_pSyncThread == NULL) { g_pSyncThread = new qtractorMidiManagerThread(); g_pSyncThread->start(); } createAudioOutputBus(); } // Destructor. qtractorMidiManager::~qtractorMidiManager (void) { deleteAudioOutputBus(); if (--g_iSyncThreadRefCount == 0 && g_pSyncThread != NULL) { // Try to wake and terminate executive thread, // but give it a bit of time to cleanup... if (g_pSyncThread->isRunning()) do { g_pSyncThread->setRunState(false); // g_pSyncThread->terminate(); g_pSyncThread->sync(); } while (!g_pSyncThread->wait(100)); delete g_pSyncThread; g_pSyncThread = NULL; } // Destroy event_buffers... for (unsigned short i = 0; i < 2; ++i) { #ifdef CONFIG_VST delete [] m_ppVstMidiBuffers[i]; delete [] m_ppVstBuffers[i]; #endif #ifdef CONFIG_LV2_EVENT ::free(m_ppLv2EventBuffers[i]); #endif #ifdef CONFIG_LV2_ATOM lv2_atom_buffer_free(m_ppLv2AtomBuffers[i]); #endif } #ifdef CONFIG_MIDI_PARSER if (m_pMidiParser) { snd_midi_event_free(m_pMidiParser); m_pMidiParser = NULL; } #endif if (m_pBuffer) delete [] m_pBuffer; } // Direct buffering. bool qtractorMidiManager::direct ( snd_seq_event_t *pEvent ) { if (pEvent->type == SND_SEQ_EVENT_CONTROLLER) { switch (pEvent->data.control.param) { case BANK_SELECT_MSB: m_iPendingBankMSB = pEvent->data.control.value; break; case BANK_SELECT_LSB: m_iPendingBankLSB = pEvent->data.control.value; break; default: m_controllerBuffer.push(pEvent); break; } } else if (pEvent->type == SND_SEQ_EVENT_PGMCHANGE) m_iPendingProg = pEvent->data.control.value; return m_directBuffer.push(pEvent); } #include "qtractorMidiEngine.h" // Queued buffering. bool qtractorMidiManager::queued ( qtractorTimeScale *pTimeScale, snd_seq_event_t *pEvent, unsigned long iTime, long iFrameStart ) { qtractorTimeScale::Cursor& cursor = pTimeScale->cursor(); qtractorTimeScale::Node *pNode = cursor.seekTick(iTime); unsigned long t0 = pNode->frameFromTick(iTime); unsigned long t1 = (long(t0) > iFrameStart ? t0 - iFrameStart : t0); if (pEvent->type == SND_SEQ_EVENT_NOTE) { snd_seq_event_t ev = *pEvent; ev.type = SND_SEQ_EVENT_NOTEON; if (!m_queuedBuffer.insert(&ev, t1)) return false; if (ev.data.note.duration > 0) { iTime += (ev.data.note.duration - 1); pNode = cursor.seekTick(iTime); t1 += (pNode->frameFromTick(iTime) - t0); } ev.type = SND_SEQ_EVENT_NOTEOFF; ev.data.note.velocity = 0; ev.data.note.duration = 0; return m_postedBuffer.insert(&ev, t1); } if (pEvent->type == SND_SEQ_EVENT_NOTEOFF) return m_postedBuffer.insert(pEvent, t1); else return m_queuedBuffer.insert(pEvent, t1); } // Clears buffers for processing. void qtractorMidiManager::clear (void) { m_iBuffer = 0; // Reset event buffers... for (unsigned short i = 0; i < 2; ++i) { #ifdef CONFIG_VST VstEvents *pVstEvents = (VstEvents *) m_ppVstBuffers[i]; ::memset(pVstEvents, 0, sizeof(VstEvents)); #endif #ifdef CONFIG_LV2_EVENT LV2_Event_Buffer *pLv2EventBuffer = m_ppLv2EventBuffers[i]; lv2_event_buffer_reset(pLv2EventBuffer, LV2_EVENT_AUDIO_STAMP, (unsigned char *) (pLv2EventBuffer + 1)); #endif #ifdef CONFIG_LV2_ATOM lv2_atom_buffer_reset(m_ppLv2AtomBuffers[i], (i & 1) == 0); #endif } m_iEventBuffer = 0; } // Process buffers (merge). void qtractorMidiManager::process ( unsigned long iTimeStart, unsigned long iTimeEnd ) { clear(); // Check for program changes and controller messages... if (g_pSyncThread && (m_iPendingProg >= 0 || !m_controllerBuffer.isEmpty())) g_pSyncThread->sync(this); // Merge events in buffer for plugin processing... snd_seq_event_t *pEv0 = m_directBuffer.peek(); snd_seq_event_t *pEv1 = m_queuedBuffer.peek(); snd_seq_event_t *pEv2 = m_postedBuffer.peek(); // Direct events... while (pEv0) { m_pBuffer[m_iBuffer++] = *pEv0; pEv0 = m_directBuffer.next(); } // Queued/posted events... while ((pEv1 && pEv1->time.tick < iTimeEnd) || (pEv2 && pEv2->time.tick < iTimeEnd)) { while (pEv1 && pEv1->time.tick < iTimeEnd && ((pEv2 && pEv2->time.tick >= pEv1->time.tick) || !pEv2)) { m_pBuffer[m_iBuffer] = *pEv1; m_pBuffer[m_iBuffer++].time.tick = (pEv1->time.tick > iTimeStart ? pEv1->time.tick - iTimeStart : 0); pEv1 = m_queuedBuffer.next(); } while (pEv2 && pEv2->time.tick < iTimeEnd && ((pEv1 && pEv1->time.tick > pEv2->time.tick) || !pEv1)) { m_pBuffer[m_iBuffer] = *pEv2; m_pBuffer[m_iBuffer++].time.tick = (pEv2->time.tick > iTimeStart ? pEv2->time.tick - iTimeStart : 0); pEv2 = m_postedBuffer.next(); } } #ifdef CONFIG_DEBUG_0 for (unsigned int i = 0; i < m_iBuffer; ++i) { snd_seq_event_t *pEv = &m_pBuffer[i]; // - show event for debug purposes... unsigned long iTime = iTimeStart + pEv->time.tick; fprintf(stderr, "MIDI Seq %06lu 0x%02x", iTime, pEv->type); if (pEv->type == SND_SEQ_EVENT_SYSEX) { fprintf(stderr, " sysex {"); unsigned char *data = (unsigned char *) pEv->data.ext.ptr; for (unsigned int i = 0; i < pEv->data.ext.len; ++i) fprintf(stderr, " %02x", data[i]); fprintf(stderr, " }\n"); } else { for (unsigned int i = 0; i < sizeof(pEv->data.raw8.d); ++i) fprintf(stderr, " %3d", pEv->data.raw8.d[i]); fprintf(stderr, "\n"); } } #endif #ifdef CONFIG_MIDI_PARSER if (m_pMidiParser) { #ifdef CONFIG_VST VstEvents *pVstEvents = (VstEvents *) m_ppVstBuffers[m_iEventBuffer & 1]; #endif #ifdef CONFIG_LV2_EVENT LV2_Event_Buffer *pLv2EventBuffer = m_ppLv2EventBuffers[m_iEventBuffer & 1]; LV2_Event_Iterator eiter; lv2_event_begin(&eiter, pLv2EventBuffer); #endif #ifdef CONFIG_LV2_ATOM LV2_Atom_Buffer *pLv2AtomBuffer = m_ppLv2AtomBuffers[m_iEventBuffer & 1]; LV2_Atom_Buffer_Iterator aiter; lv2_atom_buffer_begin(&aiter, pLv2AtomBuffer); #endif const unsigned int MaxMidiEvents = (bufferSize() << 1); unsigned int iMidiEvents = 0; // AG: Untangle treatment of VST and LV2 plugins, // so that we can use a larger buffer for the latter... #ifdef CONFIG_VST unsigned int iVstMidiEvents = 0; #endif unsigned char *pMidiData; long iMidiData; for (unsigned int i = 0; i < m_iBuffer; ++i) { snd_seq_event_t *pEv = &m_pBuffer[i]; unsigned char midiData[c_iMaxMidiData]; pMidiData = &midiData[0]; iMidiData = sizeof(midiData); iMidiData = snd_midi_event_decode(m_pMidiParser, pMidiData, iMidiData, pEv); if (iMidiData < 0) break; #ifdef CONFIG_DEBUG_0 // - show event for debug purposes... unsigned long iTime = pEv->time.tick; fprintf(stderr, "MIDI Raw %06lu {", iTime); for (long i = 0; i < iMidiData; ++i) fprintf(stderr, " %02x", pMidiData[i]); fprintf(stderr, " }\n"); #endif #ifdef CONFIG_LV2_EVENT lv2_event_write(&eiter, pEv->time.tick, 0, QTRACTOR_LV2_MIDI_EVENT_ID, iMidiData, pMidiData); #endif #ifdef CONFIG_LV2_ATOM lv2_atom_buffer_write(&aiter, pEv->time.tick, 0, QTRACTOR_LV2_MIDI_EVENT_ID, iMidiData, pMidiData); #endif #ifdef CONFIG_VST VstMidiEvent *pVstMidiBuffer = m_ppVstMidiBuffers[m_iEventBuffer & 1]; VstMidiEvent *pVstMidiEvent = &pVstMidiBuffer[iVstMidiEvents]; if (iMidiData < long(pVstMidiEvent->midiData)) { ::memset(pVstMidiEvent, 0, sizeof(VstMidiEvent)); pVstMidiEvent->type = kVstMidiType; pVstMidiEvent->byteSize = sizeof(VstMidiEvent); pVstMidiEvent->deltaFrames = pEv->time.tick; ::memcpy(&pVstMidiEvent->midiData[0], pMidiData, iMidiData); pVstEvents->events[iVstMidiEvents++] = (VstEvent *) pVstMidiEvent; } #endif if (++iMidiEvents >= MaxMidiEvents) break; } #ifdef CONFIG_VST pVstEvents->numEvents = iVstMidiEvents; // pVstEvents->reserved = 0; #endif } #endif // Now's time to process the plugins as usual... if (m_pAudioOutputBus) { unsigned int nframes = iTimeEnd - iTimeStart; if (m_bAudioOutputBus) { m_pAudioOutputBus->process_prepare(nframes); m_pPluginList->process(m_pAudioOutputBus->out(), nframes); m_pAudioOutputBus->process_commit(nframes); } else { m_pAudioOutputBus->buffer_prepare(nframes); m_pPluginList->process(m_pAudioOutputBus->buffer(), nframes); m_pAudioOutputBus->buffer_commit(nframes); } } } // Process buffers (in asynchronous controller thread). void qtractorMidiManager::processSync (void) { if (!m_bWaitSync) return; // Check for programn change... if (m_iPendingProg >= 0) { m_iCurrentBank = 0; m_iCurrentProg = m_iPendingProg; if (m_iPendingBankLSB >= 0) { if (m_iPendingBankMSB >= 0) m_iCurrentBank = (m_iPendingBankMSB << 7) + m_iPendingBankLSB; else m_iCurrentBank = m_iPendingBankLSB; } else if (m_iPendingBankMSB >= 0) m_iCurrentBank = m_iPendingBankMSB; // Make the change (should be RT safe...) qtractorPlugin *pPlugin = m_pPluginList->first(); while (pPlugin) { pPlugin->selectProgram(m_iCurrentBank, m_iCurrentProg); pPlugin = pPlugin->next(); } // Reset pending status. m_iPendingBankMSB = -1; m_iPendingBankLSB = -1; m_iPendingProg = -1; } // Have all controller events sent to plugin(s), // mostly for mere GUI update purposes... snd_seq_event_t *pEv = m_controllerBuffer.peek(); while (pEv) { if (pEv->type == SND_SEQ_EVENT_CONTROLLER) { qtractorPlugin *pPlugin = m_pPluginList->first(); while (pPlugin) { pPlugin->setController( pEv->data.control.param, pEv->data.control.value); pPlugin = pPlugin->next(); } } pEv = m_controllerBuffer.next(); } m_controllerBuffer.clear(); m_bWaitSync = false; } // Resets all buffering. void qtractorMidiManager::reset (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; pSession->lock(); m_directBuffer.clear(); m_queuedBuffer.clear(); m_postedBuffer.reset(); // formerly .clear(); clear(); #ifdef CONFIG_MIDI_PARSER if (m_pMidiParser) { snd_midi_event_reset_decode(m_pMidiParser); snd_midi_event_reset_encode(m_pMidiParser); } #endif m_pPluginList->resetBuffer(); m_controllerBuffer.clear(); m_iPendingBankMSB = -1; m_iPendingBankLSB = -1; m_iPendingProg = -1; pSession->unlock(); } // Sync thread state flags accessors. void qtractorMidiManager::setWaitSync ( bool bWaitSync ) { m_bWaitSync = bWaitSync; } bool qtractorMidiManager::isWaitSync (void) const { return m_bWaitSync; } // Factory (proxy) methods. qtractorMidiManager *qtractorMidiManager::createMidiManager ( qtractorPluginList *pPluginList ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return NULL; qtractorMidiManager *pMidiManager = new qtractorMidiManager(pPluginList); pSession->addMidiManager(pMidiManager); #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiManager::createMidiManager(%p)", pMidiManager); #endif return pMidiManager; } void qtractorMidiManager::deleteMidiManager ( qtractorMidiManager *pMidiManager ) { if (pMidiManager == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiManager::deleteMidiManager(%p)", pMidiManager); #endif pSession->removeMidiManager(pMidiManager); delete pMidiManager; } // Swap event buffers (in for out and vice-versa) void qtractorMidiManager::swapEventBuffers (void) { #ifdef CONFIG_VST ::memset(m_ppVstBuffers[m_iEventBuffer & 1], 0, sizeof(VstEvents)); #endif #ifdef CONFIG_LV2_EVENT LV2_Event_Buffer *pLv2EventBuffer = m_ppLv2EventBuffers[m_iEventBuffer & 1]; lv2_event_buffer_reset(pLv2EventBuffer, LV2_EVENT_AUDIO_STAMP, (unsigned char *) (pLv2EventBuffer + 1)); #endif #ifdef CONFIG_LV2_ATOM lv2_atom_buffer_reset(m_ppLv2AtomBuffers[m_iEventBuffer & 1], false); #endif ++m_iEventBuffer; } #ifdef CONFIG_VST // Copy VST event buffer (output)... void qtractorMidiManager::vst_events_copy ( VstEvents *pVstBuffer ) { unsigned short iEventBuffer = (m_iEventBuffer + 1) & 1; VstMidiEvent *pVstMidiBuffer = m_ppVstMidiBuffers[iEventBuffer]; VstEvents *pVstEvents = (VstEvents *) m_ppVstBuffers[iEventBuffer]; ::memset(pVstEvents, 0, sizeof(VstEvents)); const unsigned int MaxMidiEvents = (bufferSize() << 1); unsigned int iMidiEvents = pVstBuffer->numEvents; if (iMidiEvents > MaxMidiEvents) iMidiEvents = MaxMidiEvents; for (unsigned int i = 0; i < iMidiEvents; ++i) { VstMidiEvent *pOldMidiEvent = (VstMidiEvent *) pVstBuffer->events[i]; VstMidiEvent *pVstMidiEvent = &pVstMidiBuffer[i]; ::memcpy(pVstMidiEvent, pOldMidiEvent, sizeof(VstMidiEvent)); pVstEvents->events[i] = (VstEvent *) pVstMidiEvent; } pVstEvents->numEvents = iMidiEvents; } // Swap VST event buffers... void qtractorMidiManager::vst_events_swap (void) { unsigned short iEventBuffer = (m_iEventBuffer + 1) & 1; VstMidiEvent *pVstMidiBuffer = m_ppVstMidiBuffers[iEventBuffer]; VstEvents *pVstEvents = (VstEvents *) m_ppVstBuffers[iEventBuffer]; #ifdef CONFIG_LV2_EVENT LV2_Event_Buffer *pLv2EventBuffer = m_ppLv2EventBuffers[iEventBuffer]; lv2_event_buffer_reset(pLv2EventBuffer, LV2_EVENT_AUDIO_STAMP, (unsigned char *) (pLv2EventBuffer + 1)); LV2_Event_Iterator eiter; lv2_event_begin(&eiter, pLv2EventBuffer); #endif #ifdef CONFIG_LV2_ATOM LV2_Atom_Buffer *pLv2AtomBuffer = m_ppLv2AtomBuffers[iEventBuffer]; lv2_atom_buffer_reset(pLv2AtomBuffer, true); LV2_Atom_Buffer_Iterator aiter; lv2_atom_buffer_begin(&aiter, pLv2AtomBuffer); #endif unsigned int iMidiEvents = 0; const unsigned int MaxMidiEvents = (bufferSize() << 1); while (iMidiEvents < MaxMidiEvents && int(iMidiEvents) < pVstEvents->numEvents) { VstMidiEvent *pVstMidiEvent = &pVstMidiBuffer[iMidiEvents]; unsigned char *pMidiData = (unsigned char *) &pVstMidiEvent->midiData[0]; long iMidiData = sizeof(pVstMidiEvent->midiData); #ifdef CONFIG_MIDI_PARSER if (m_pMidiParser) { snd_seq_event_t *pEv = &m_pBuffer[iMidiEvents]; // snd_seq_ev_clear(pEv); iMidiData = snd_midi_event_encode(m_pMidiParser, pMidiData, iMidiData, pEv); if (iMidiData < 1 || pEv->type == SND_SEQ_EVENT_NONE) break; pEv->time.tick = pVstMidiEvent->deltaFrames; } #endif #ifdef CONFIG_LV2_EVENT lv2_event_write(&eiter, pVstMidiEvent->deltaFrames, 0, QTRACTOR_LV2_MIDI_EVENT_ID, iMidiData, pMidiData); #endif #ifdef CONFIG_LV2_ATOM lv2_atom_buffer_write(&aiter, pVstMidiEvent->deltaFrames, 0, QTRACTOR_LV2_MIDI_EVENT_ID, iMidiData, pMidiData); #endif ++iMidiEvents; } m_iBuffer = iMidiEvents; swapEventBuffers(); } #endif // CONFIG_VST #ifdef CONFIG_LV2_EVENT // Swap LV2 event buffers... void qtractorMidiManager::lv2_events_swap (void) { unsigned short iEventBuffer = (m_iEventBuffer + 1) & 1; LV2_Event_Buffer *pLv2EventBuffer = m_ppLv2EventBuffers[iEventBuffer]; #ifdef CONFIG_VST VstMidiEvent *pVstMidiBuffer = m_ppVstMidiBuffers[iEventBuffer]; VstEvents *pVstEvents = (VstEvents *) m_ppVstBuffers[iEventBuffer]; ::memset(pVstEvents, 0, sizeof(VstEvents)); #endif #ifdef CONFIG_LV2_ATOM LV2_Atom_Buffer *pLv2AtomBuffer = m_ppLv2AtomBuffers[iEventBuffer]; lv2_atom_buffer_reset(pLv2AtomBuffer, true); LV2_Atom_Buffer_Iterator aiter; lv2_atom_buffer_begin(&aiter, pLv2AtomBuffer); #endif LV2_Event_Iterator eiter; lv2_event_begin(&eiter, pLv2EventBuffer); unsigned int iMidiEvents = 0; const unsigned int MaxMidiEvents = (bufferSize() << 1); while (iMidiEvents < MaxMidiEvents && lv2_event_is_valid(&eiter)) { unsigned char *pMidiData; LV2_Event *pLv2Event = lv2_event_get(&eiter, &pMidiData); if (pLv2Event == NULL) break; if (pLv2Event->type == QTRACTOR_LV2_MIDI_EVENT_ID) { long iMidiData = pLv2Event->size; if (iMidiData < 1) break; #ifdef CONFIG_VST VstMidiEvent *pVstMidiEvent = &pVstMidiBuffer[iMidiEvents]; if (iMidiData >= long(sizeof(pVstMidiEvent->midiData))) break; #endif #ifdef CONFIG_MIDI_PARSER if (m_pMidiParser) { snd_seq_event_t *pEv = &m_pBuffer[iMidiEvents]; // snd_seq_ev_clear(pEv); iMidiData = snd_midi_event_encode(m_pMidiParser, pMidiData, iMidiData, pEv); if (iMidiData < 1 || pEv->type == SND_SEQ_EVENT_NONE) break; pEv->time.tick = pLv2Event->frames; } #endif #ifdef CONFIG_VST ::memset(pVstMidiEvent, 0, sizeof(VstMidiEvent)); pVstMidiEvent->type = kVstMidiType; pVstMidiEvent->byteSize = sizeof(VstMidiEvent); pVstMidiEvent->deltaFrames = pLv2Event->frames; ::memcpy(&pVstMidiEvent->midiData[0], pMidiData, iMidiData); pVstEvents->events[iMidiEvents] = (VstEvent *) pVstMidiEvent; #endif #ifdef CONFIG_LV2_ATOM lv2_atom_buffer_write(&aiter, pLv2Event->frames, 0, QTRACTOR_LV2_MIDI_EVENT_ID, iMidiData, pMidiData); #endif ++iMidiEvents; } lv2_event_increment(&eiter); } #ifdef CONFIG_VST pVstEvents->numEvents = iMidiEvents; #endif m_iBuffer = iMidiEvents; swapEventBuffers(); } #endif // CONFIG_LV2_EVENT #ifdef CONFIG_LV2_ATOM // Swap LV2 atom buffers... void qtractorMidiManager::lv2_atom_buffer_swap (void) { unsigned short iEventBuffer = (m_iEventBuffer + 1) & 1; LV2_Atom_Buffer *pLv2AtomBuffer = m_ppLv2AtomBuffers[iEventBuffer]; #ifdef CONFIG_VST VstMidiEvent *pVstMidiBuffer = m_ppVstMidiBuffers[iEventBuffer]; VstEvents *pVstEvents = (VstEvents *) m_ppVstBuffers[iEventBuffer]; ::memset(pVstEvents, 0, sizeof(VstEvents)); #endif #ifdef CONFIG_LV2_EVENT LV2_Event_Buffer *pLv2EventBuffer = m_ppLv2EventBuffers[iEventBuffer]; lv2_event_buffer_reset(pLv2EventBuffer, LV2_EVENT_AUDIO_STAMP, (unsigned char *) (pLv2EventBuffer + 1)); LV2_Event_Iterator eiter; lv2_event_begin(&eiter, pLv2EventBuffer); #endif LV2_Atom_Buffer_Iterator aiter; lv2_atom_buffer_begin(&aiter, pLv2AtomBuffer); unsigned int iMidiEvents = 0; const unsigned int MaxMidiEvents = (bufferSize() << 1); while (iMidiEvents < MaxMidiEvents) { unsigned char *pMidiData; LV2_Atom_Event *pLv2AtomEvent = lv2_atom_buffer_get(&aiter, &pMidiData); if (pLv2AtomEvent == NULL) break; if (pLv2AtomEvent->body.type == QTRACTOR_LV2_MIDI_EVENT_ID) { long iMidiData = pLv2AtomEvent->body.size; if (iMidiData < 1) break; #ifdef CONFIG_VST VstMidiEvent *pVstMidiEvent = &pVstMidiBuffer[iMidiEvents]; if (iMidiData >= long(sizeof(pVstMidiEvent->midiData))) break; #endif #ifdef CONFIG_MIDI_PARSER if (m_pMidiParser) { snd_seq_event_t *pEv = &m_pBuffer[iMidiEvents]; // snd_seq_ev_clear(pEv); iMidiData = snd_midi_event_encode(m_pMidiParser, pMidiData, iMidiData, pEv); if (iMidiData < 1 || pEv->type == SND_SEQ_EVENT_NONE) break; pEv->time.tick = pLv2AtomEvent->time.frames; } #endif #ifdef CONFIG_VST ::memset(pVstMidiEvent, 0, sizeof(VstMidiEvent)); pVstMidiEvent->type = kVstMidiType; pVstMidiEvent->byteSize = sizeof(VstMidiEvent); pVstMidiEvent->deltaFrames = pLv2AtomEvent->time.frames; ::memcpy(&pVstMidiEvent->midiData[0], pMidiData, iMidiData); pVstEvents->events[iMidiEvents] = (VstEvent *) pVstMidiEvent; #endif #ifdef CONFIG_LV2_EVENT lv2_event_write(&eiter, pLv2AtomEvent->time.frames, 0, QTRACTOR_LV2_MIDI_EVENT_ID, iMidiData, pMidiData); #endif ++iMidiEvents; } lv2_atom_buffer_increment(&aiter); } #ifdef CONFIG_VST pVstEvents->numEvents = iMidiEvents; #endif m_iBuffer = iMidiEvents; swapEventBuffers(); } #endif // CONFIG_LV2_ATOM // Some default factory options. void qtractorMidiManager::setDefaultAudioOutputBus ( bool bAudioOutputBus ) { g_bAudioOutputBus = bAudioOutputBus; } bool qtractorMidiManager::isDefaultAudioOutputBus (void) { return g_bAudioOutputBus; } void qtractorMidiManager::setDefaultAudioOutputAutoConnect ( bool bAudioOutputAutoConnect ) { g_bAudioOutputAutoConnect = bAudioOutputAutoConnect; } bool qtractorMidiManager::isDefaultAudioOutputAutoConnect (void) { return g_bAudioOutputAutoConnect; } // Output bus mode accessors. void qtractorMidiManager::setAudioOutputBus ( bool bAudioOutputBus ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; pSession->lock(); deleteAudioOutputBus(); m_bAudioOutputBus = bAudioOutputBus; createAudioOutputBus(); pSession->unlock(); } void qtractorMidiManager::resetAudioOutputBus (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; pSession->lock(); qtractorBus::ConnectList outputs; if (m_bAudioOutputBus && m_pAudioOutputBus) outputs.copy(m_pAudioOutputBus->outputs()); createAudioOutputBus(); if (m_bAudioOutputBus && m_pAudioOutputBus) m_pAudioOutputBus->outputs().copy(outputs); pSession->unlock(); } // Create audio output stuff... void qtractorMidiManager::createAudioOutputBus (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine == NULL) return; deleteAudioOutputBus(); // Whether audio output bus is here owned, or... if (m_bAudioOutputBus) { // Owned, not part of audio engine... m_pAudioOutputBus = new qtractorAudioBus(pAudioEngine, m_pPluginList->name(), qtractorBus::BusMode(qtractorBus::Output | qtractorBus::Ex), false, m_pPluginList->channels()); m_pAudioOutputBus->setAutoConnect(m_bAudioOutputAutoConnect); if (pAudioEngine->isActivated()) { pAudioEngine->addBusEx(m_pAudioOutputBus); if (m_pAudioOutputBus->open()) m_pAudioOutputBus->autoConnect(); } } else { // Output bus gets to be the first available output bus... for (qtractorBus *pBus = (pAudioEngine->buses()).first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Output) { m_pAudioOutputBus = static_cast (pBus); break; } } } } // Destroy audio Outputnome stuff. void qtractorMidiManager::deleteAudioOutputBus (void) { // Owned, not part of audio engine... if (m_bAudioOutputBus && m_pAudioOutputBus) { m_pAudioOutputBus->close(); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine) pAudioEngine->removeBusEx(m_pAudioOutputBus); } delete m_pAudioOutputBus; } // Done. m_pAudioOutputBus = NULL; } // Instrument map builder. void qtractorMidiManager::updateInstruments (void) { m_instruments.clear(); for (qtractorPlugin *pPlugin = m_pPluginList->first(); pPlugin; pPlugin = pPlugin->next()) { int iIndex = 0; qtractorPlugin::Program program; Banks& banks = m_instruments[(pPlugin->type())->name()]; while (pPlugin->getProgram(iIndex++, program)) { Bank& bank = banks[program.bank]; if (bank.name.isEmpty()) { bank.name = QObject::tr("%1 - Bank %2") .arg(program.bank) .arg(banks.count() - 1); } bank.progs[program.prog] = program.name.simplified(); } } } // end of qtractorMidiBuffer.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorRingBuffer.h0000644000175000001440000000012311563576072021241 xustar000000000000000027 mtime=1305410618.253123 26 atime=1381134667.26308 30 ctime=1381134667.263080053 qtractor-0.5.11/src/qtractorRingBuffer.h0000644000175000001440000001476411563576072020544 0ustar00rncbcusers00000000000000// qtractorRingBuffer.h // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorRingBuffer_h #define __qtractorRingBuffer_h #include "qtractorAtomic.h" #include #include #include //---------------------------------------------------------------------- // class qtractorRingBuffer -- Ring buffer/cache template declaration. // template class qtractorRingBuffer { public: // Constructors. qtractorRingBuffer(unsigned short iChannels, unsigned int iBufferSize = 0); // Default destructor. ~qtractorRingBuffer(); // Implementation properties. unsigned short channels() const { return m_iChannels; } unsigned int bufferSize() const { return m_iBufferSize; } unsigned int bufferMask() const { return m_iBufferMask; } // Direct ring-buffer accessor (DANGEROUS). T **buffer() const { return m_ppBuffer; } // Ring-buffer cache properties. unsigned int readable() const; unsigned int writable() const; // Buffer data read/write. int read(T **ppBuffer, unsigned int iFrames, unsigned int iOffset = 0); int write(T **ppBuffer, unsigned int iFrames, unsigned int iOffset = 0); // Reset this buffer's state. void reset(); // Next read position index accessors. void setReadIndex(unsigned int iReadIndex); unsigned int readIndex() const; // Next write position index accessors. void setWriteIndex(unsigned int iWriteIndex); unsigned int writeIndex() const; private: unsigned short m_iChannels; unsigned int m_iBufferSize; unsigned int m_iBufferMask; qtractorAtomic m_iReadIndex; qtractorAtomic m_iWriteIndex; T** m_ppBuffer; }; //---------------------------------------------------------------------- // class qtractorRingBuffer -- Ring buffer/cache method implementation. // // Constructors. template qtractorRingBuffer::qtractorRingBuffer ( unsigned short iChannels, unsigned int iBufferSize ) { m_iChannels = iChannels; // Adjust buffer size of nearest power-of-two, if necessary. const unsigned int iMinBufferSize = 4096; m_iBufferSize = iMinBufferSize; while (m_iBufferSize < iBufferSize) m_iBufferSize <<= 1; // The size overflow convenience mask and tthreshold. m_iBufferMask = (m_iBufferSize - 1); // Allocate actual buffer stuff... m_ppBuffer = new T* [m_iChannels]; for (unsigned short i = 0; i < m_iChannels; ++i) m_ppBuffer[i] = new T [m_iBufferSize]; ATOMIC_SET(&m_iReadIndex, 0); ATOMIC_SET(&m_iWriteIndex, 0); } // Default destructor. template qtractorRingBuffer::~qtractorRingBuffer (void) { // Deallocate any buffer stuff... if (m_ppBuffer) { for (unsigned short i = 0; i < m_iChannels; ++i) delete [] m_ppBuffer[i]; delete [] m_ppBuffer; } } template unsigned int qtractorRingBuffer::readable (void) const { unsigned int w = ATOMIC_GET(&m_iWriteIndex); unsigned int r = ATOMIC_GET(&m_iReadIndex); if (w > r) { return (w - r); } else { return (w - r + m_iBufferSize) & m_iBufferMask; } } template unsigned int qtractorRingBuffer::writable (void) const { unsigned int w = ATOMIC_GET(&m_iWriteIndex); unsigned int r = ATOMIC_GET(&m_iReadIndex); if (w > r){ return ((r - w + m_iBufferSize) & m_iBufferMask) - 1; } else if (r > w) { return (r - w) - 1; } else { return m_iBufferSize - 1; } } // Buffer raw data read. template int qtractorRingBuffer::read ( T **ppFrames, unsigned int iFrames, unsigned int iOffset ) { unsigned int rs = readable(); if (rs == 0) return 0; if (iFrames > rs) iFrames = rs; unsigned int r = ATOMIC_GET(&m_iReadIndex); unsigned int n1, n2; if (r + iFrames > m_iBufferSize) { n1 = (m_iBufferSize - r); n2 = (r + iFrames) & m_iBufferMask; } else { n1 = iFrames; n2 = 0; } for (unsigned short i = 0; i < m_iChannels; ++i) { ::memcpy((T *)(ppFrames[i] + iOffset), (T *)(m_ppBuffer[i] + r), n1 * sizeof(T)); if (n2) { n1 += iOffset; ::memcpy((T *)(ppFrames[i] + n1), m_ppBuffer[i], n2 * sizeof(T)); } } ATOMIC_SET(&m_iReadIndex, (r + iFrames) & m_iBufferMask); return iFrames; } // Buffer raw data write. template int qtractorRingBuffer::write ( T **ppFrames, unsigned int iFrames, unsigned int iOffset ) { unsigned int ws = writable(); if (ws == 0) return 0; if (iFrames > ws) iFrames = ws; unsigned int w = ATOMIC_GET(&m_iWriteIndex); unsigned int n1, n2; if (w + iFrames > m_iBufferSize) { n1 = (m_iBufferSize - w); n2 = (w + iFrames) & m_iBufferMask; } else { n1 = iFrames; n2 = 0; } for (unsigned short i = 0; i < m_iChannels; ++i) { ::memcpy((T *)(m_ppBuffer[i] + w), (T *)(ppFrames[i] + iOffset), n1 * sizeof(T)); if (n2 > 0) { n1 += iOffset; ::memcpy(m_ppBuffer[i], (T *)(ppFrames[i] + n1), n2 * sizeof(T)); } } ATOMIC_SET(&m_iWriteIndex, (w + iFrames) & m_iBufferMask); return iFrames; } // Reset this buffers state. template void qtractorRingBuffer::reset (void) { ATOMIC_SET(&m_iReadIndex, 0); ATOMIC_SET(&m_iWriteIndex, 0); } // Next read position index accessors. template void qtractorRingBuffer::setReadIndex ( unsigned int iReadIndex ) { ATOMIC_SET(&m_iReadIndex, (iReadIndex & m_iBufferMask)); } template unsigned int qtractorRingBuffer::readIndex (void) const { return ATOMIC_GET(&m_iReadIndex); } // Next write position index accessors. template void qtractorRingBuffer::setWriteIndex ( unsigned int iWriteIndex ) { ATOMIC_SET(&m_iWriteIndex, (iWriteIndex & m_iBufferMask)); } template unsigned int qtractorRingBuffer::writeIndex (void) const { return ATOMIC_GET(&m_iWriteIndex); } #endif // __qtractorRingBuffer_h // end of qtractorRingBuffer.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorInstrument.h0000644000175000001440000000012312073012112021331 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134668.06908 30 ctime=1381134668.069080066 qtractor-0.5.11/src/qtractorInstrument.h0000644000175000001440000002471512073012112020631 0ustar00rncbcusers00000000000000// qtractorInstrument.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorInstrument_h #define __qtractorInstrument_h #include #include // Forward declarations. class QTextStream; class QFile; class QDomElement; //---------------------------------------------------------------------- // class qtractorInstrumentData -- instrument definition data classes. // class qtractorInstrumentData { public: typedef QMap DataMap; // Constructor. qtractorInstrumentData() : m_pData(new DataRef()) {} // Copy constructor. qtractorInstrumentData(const qtractorInstrumentData& data) { attach(data); } // Destructor. ~qtractorInstrumentData() { detach(); } // Assignment operator. qtractorInstrumentData& operator= (const qtractorInstrumentData& data) { if (m_pData != data.m_pData) { detach(); attach(data); } return *this; } // Accessor operator. QString& operator[] (int iIndex) const { return m_pData->map[iIndex]; } // Property accessors. void setName(const QString& sName) { m_pData->name = sName; } const QString& name() const { return m_pData->name; } void setBasedOn(const QString& sBasedOn) { m_pData->basedOn = sBasedOn; } const QString& basedOn() const { return m_pData->basedOn; } // Indirect iterator stuff. typedef DataMap::Iterator Iterator; Iterator begin() { return m_pData->map.begin(); } Iterator end() { return m_pData->map.end(); } typedef DataMap::ConstIterator ConstIterator; ConstIterator constBegin() const { return m_pData->map.constBegin(); } ConstIterator constEnd() const { return m_pData->map.constEnd(); } unsigned int count() const { return m_pData->map.count(); } bool contains(int iKey) const { return m_pData->map.contains(iKey); } protected: // Copy/clone method. void attach(const qtractorInstrumentData& data) { m_pData = data.m_pData; ++(m_pData->refCount); } // Destroy method. void detach() { if (--(m_pData->refCount) == 0) delete m_pData; } private: // The ref-counted data. struct DataRef { // Default payload constructor. DataRef() : refCount(1) {}; // Payload members. int refCount; QString name; QString basedOn; DataMap map; } *m_pData; }; class qtractorInstrumentDataList : public QMap {}; class qtractorInstrumentPatches : public QMap {}; class qtractorInstrumentNotes : public QMap {}; class qtractorInstrumentKeys : public QMap {}; class qtractorInstrumentDrumFlags : public QMap {}; class qtractorInstrumentDrums : public QMap {}; //---------------------------------------------------------------------- // class qtractorInstrument -- instrument definition instance class. // class qtractorInstrument { public: // Constructor. qtractorInstrument() : m_pData(new DataRef()) {} // Copy constructor. qtractorInstrument(const qtractorInstrument& instr) { attach(instr); } // Destructor. ~qtractorInstrument() { detach(); } // Assignment operator. qtractorInstrument& operator= (const qtractorInstrument& instr) { if (m_pData != instr.m_pData) { detach(); attach(instr); } return *this; } // Instrument title property accessors. void setInstrumentName(const QString& sInstrumentName) { m_pData->instrumentName = sInstrumentName; } const QString& instrumentName() const { return m_pData->instrumentName; } // BankSelMethod accessors. void setBankSelMethod(int iBankSelMethod) { m_pData->bankSelMethod = iBankSelMethod; } int bankSelMethod() const { return m_pData->bankSelMethod; } void setUsesNotesAsControllers(bool bUsesNotesAsControllers) { m_pData->usesNotesAsControllers = bUsesNotesAsControllers; } bool usesNotesAsControllers() const { return m_pData->usesNotesAsControllers; } // Patch banks accessors. const qtractorInstrumentPatches& patches() const { return m_pData->patches; } const qtractorInstrumentData& patch(int iBank) const; void setPatch(int iBank, const qtractorInstrumentData& patch) { m_pData->patches[iBank] = patch; } // Control names accessors. void setControlName(const QString& sControlName) { m_pData->control.setName(sControlName); } const QString& controlName() const { return m_pData->control.name(); } void setControl(const qtractorInstrumentData& control) { m_pData->control = control; } const qtractorInstrumentData& control() const { return m_pData->control; } // RPN names accessors. void setRpnName(const QString& sRpnName) { m_pData->rpn.setName(sRpnName); } const QString& rpnName() const { return m_pData->rpn.name(); } void setRpn(const qtractorInstrumentData& rpn) { m_pData->rpn = rpn; } const qtractorInstrumentData& rpn() const { return m_pData->rpn; } // NRPN names accessors. void setNrpnName(const QString& sNrpnName) { m_pData->nrpn.setName(sNrpnName); } const QString& nrpnName() const { return m_pData->nrpn.name(); } void setNrpn(const qtractorInstrumentData& nrpn) { m_pData->nrpn = nrpn; } const qtractorInstrumentData& nrpn() const { return m_pData->nrpn; } // Keys banks accessors. const qtractorInstrumentData& notes(int iBank, int iProg) const; void setNotes(int iBank, int iProg, const qtractorInstrumentData& notes) { m_pData->keys[iBank][iProg] = notes; } const qtractorInstrumentKeys& keys() const { return m_pData->keys; } // Drumflags banks accessors. bool isDrum(int iBank, int iProg) const; void setDrum(int iBank, int iProg, bool bDrum) { m_pData->drums[iBank][iProg] = (int) bDrum; } const qtractorInstrumentDrums& drums() const { return m_pData->drums; } protected: // Copy/clone method. void attach(const qtractorInstrument& instr) { m_pData = instr.m_pData; ++(m_pData->refCount); } // Destroy method. void detach() { if (--(m_pData->refCount) == 0) delete m_pData; } private: // The ref-counted data. struct DataRef { // Default payload constructor. DataRef() : refCount(1), bankSelMethod(0), usesNotesAsControllers(false) {}; // Payload members. int refCount; int bankSelMethod; bool usesNotesAsControllers; QString instrumentName; qtractorInstrumentPatches patches; qtractorInstrumentData control; qtractorInstrumentData rpn; qtractorInstrumentData nrpn; qtractorInstrumentKeys keys; qtractorInstrumentDrums drums; } *m_pData; }; //---------------------------------------------------------------------- // class qtractorInstrumentList -- A Cakewalk .ins file container class. // class qtractorInstrumentList : public QMap { public: // Open file methods. bool load(const QString& sFilename); bool save(const QString& sFilename) const; // The official loaded file list. const QStringList& files() const; // Manage a file list (out of sync) void appendFile(const QString& sFilename) { m_files.append(sFilename); } void removeFile(const QString& sFilename) { int iFile = m_files.indexOf(sFilename); if (iFile >= 0) m_files.removeAt(iFile); } // Patch Names definition accessors. const qtractorInstrumentDataList& patches() const { return m_patches; } const qtractorInstrumentData& patches(const QString& sName) { return m_patches[sName]; } // Note Names definition accessors. const qtractorInstrumentDataList& notes() const { return m_notes; } const qtractorInstrumentData& notes(const QString& sName) { return m_notes[sName]; } // Controller Names definition accessors. const qtractorInstrumentDataList& controls() const { return m_controls; } const qtractorInstrumentData& controls(const QString& sName) { return m_controls[sName]; } // RPN Names definition accessors. const qtractorInstrumentDataList& rpns() const { return m_rpns; } const qtractorInstrumentData& rpns(const QString& sName) { return m_rpns[sName]; } // NRPN Names definition accessors. const qtractorInstrumentDataList& nrpns() const { return m_nrpns; } const qtractorInstrumentData& nrpns(const QString& sName) { return m_nrpns[sName]; } // Clear all contents. void clearAll(); // Special instrument list merge method. void merge(const qtractorInstrumentList& instruments); protected: // Internal instrument data list save method helpers. void saveDataList(QTextStream& ts, const qtractorInstrumentDataList& list) const; void saveData(QTextStream& ts, const qtractorInstrumentData& data) const; // Special instrument data list merge method. void mergeDataList(qtractorInstrumentDataList& dst, const qtractorInstrumentDataList& src); // Special SoundFont loader. bool loadSoundFont(QFile *pFile); void loadSoundFontPresets(QFile *pFile, int iSize); // Special MIDINameDocument loader. bool loadMidiNameDocument(QFile *pFile); void loadMidiDeviceNames( QDomElement *pElement); void loadMidiChannelNameSet( QDomElement *pElement, qtractorInstrument& instr); void loadMidiPatchBank( QDomElement *pElement, qtractorInstrument& instr, const QString& sName); void loadMidiPatchNameList( QDomElement *pElement, qtractorInstrument& instr, const QString& sName); void loadMidiNoteNameList( QDomElement *pElement, const QString& sName); void loadMidiControlNameList( QDomElement *pElement, const QString& sName); private: // To hold the names definition lists. qtractorInstrumentDataList m_patches; qtractorInstrumentDataList m_notes; qtractorInstrumentDataList m_controls; qtractorInstrumentDataList m_rpns; qtractorInstrumentDataList m_nrpns; // To old the official file list. QStringList m_files; }; #endif // __qtractorInstrument_h // end of qtractorInstrument.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorTrackList.h0000644000175000001440000000012312166526620021102 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134666.49608 30 ctime=1381134666.496080041 qtractor-0.5.11/src/qtractorTrackList.h0000644000175000001440000001624612166526620020402 0ustar00rncbcusers00000000000000// qtractorTrackList.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorTrackList_h #define __qtractorTrackList_h #include "qtractorScrollView.h" #include #include // Forward declarations. class qtractorTrack; class qtractorTracks; class qtractorTrackList; class qtractorTrackButton; class qtractorRubberBand; class qtractorMidiManager; class qtractorCurveButton; class QHeaderView; class QResizeEvent; class QMouseEvent; class QKeyEvent; //---------------------------------------------------------------------------- // qtractorTrackItemWidget -- Track button layout widget. class qtractorTrackItemWidget : public QWidget { // Q_OBJECT public: // Constructor. qtractorTrackItemWidget( qtractorTrackList *pTrackList, qtractorTrack *pTrack); // Local child widgets accessors. qtractorCurveButton *curveButton() const { return m_pCurveButton; } qtractorTrackButton *recordButton() const { return m_pRecordButton; } qtractorTrackButton *muteButton() const { return m_pMuteButton; } qtractorTrackButton *soloButton() const { return m_pSoloButton; } private: // The local child widgets. qtractorCurveButton *m_pCurveButton; qtractorTrackButton *m_pRecordButton; qtractorTrackButton *m_pMuteButton; qtractorTrackButton *m_pSoloButton; }; //---------------------------------------------------------------------------- // qtractorTrackList -- Track list widget. class qtractorTrackList : public qtractorScrollView { Q_OBJECT public: // Constructor. qtractorTrackList(qtractorTracks *pTracks, QWidget *pParent = 0); // Destructor. ~qtractorTrackList(); // Track list view column indexes. enum ColumnIndex { Number = 0, Name = 1, Bus = 2, Channel = 3, Patch = 4, Instrument = 5 }; // Main tracks widget accessor. qtractorTracks *tracks() const; // Header view accessor. QHeaderView *header() const; // Find the list view item from track pointer reference. int trackRow(qtractorTrack *pTrack) const; // Find track row/column of given viewport point... int trackRowAt(const QPoint& pos); int trackColumnAt(const QPoint& pos); // Find the track pointer reference from list view item row. qtractorTrack *track(int iTrack) const; // Insert/remove a track item; return actual track of incident. int insertTrack(int iTrack, qtractorTrack *pTrack); int removeTrack(int iTrack); // Manage current track row by index. void setCurrentTrackRow(int iTrack); int currentTrackRow() const; int trackRowCount() const; // Current selected track reference. void setCurrentTrack(qtractorTrack *pTrack); qtractorTrack *currentTrack() const; // Update the list view item from track pointer reference. void updateTrack(qtractorTrack *pTrack); // Main table cleaner. void clear(); // Update list content height. void updateContentsHeight(); // Rectangular contents update. void updateContents(const QRect& rect); // Overall contents update. void updateContents(); protected: // Resize event handler. void resizeEvent(QResizeEvent *pResizeEvent); // Draw the time scale. void drawContents(QPainter *pPainter, const QRect& rect); // Retrive the given track row rectangular (in contents coordinates). QRect trackRect(int iTrack) const; // Draw table cell. void drawCell(QPainter *pPainter, int iRow, int iCol, const QRect& rect) const; // Context menu request slot. void contextMenuEvent(QContextMenuEvent *pContextMenuEvent); // Handle mouse double-clicks. void mouseDoubleClickEvent(QMouseEvent *pMouseEvent); // Handle item selection with mouse. void mousePressEvent(QMouseEvent *pMouseEvent); void mouseMoveEvent(QMouseEvent *pMouseEvent); void mouseReleaseEvent(QMouseEvent *pMouseEvent); // Handle zoom with mouse wheel. void wheelEvent(QWheelEvent *pWheelEvent); // Show and move rubber-band item. void moveRubberBand(const QPoint& posDrag); // Make sure the given (track) rectangle is visible. bool ensureVisibleRect(const QRect& rect); // Keyboard event handler. void keyPressEvent(QKeyEvent *pKeyEvent); // Reset drag/select/move state. void resetDragState(); signals: // More like current row has changed. void selectionChanged(); protected slots: // To have timeline in h-sync with main track view. void contentsYMovingSlot(int cx, int cy); // (Re)create the time scale pixmap. void updatePixmap(int cx, int cy); // Update header extents. void updateHeader(); private: // The logical parent binding. qtractorTracks *m_pTracks; // Local horizontal header. QHeaderView *m_pHeader; // Local double-buffering pixmap. QPixmap m_pixmap; // Model cache item. struct Item { // Constructor Item(qtractorTrackList *pTrackList, qtractorTrack *pTrack); // Destructor. ~Item(); // Bank/program names helper. bool updateBankProgram (qtractorMidiManager *pMidiManager, const QString& sInstrument, QString& sBank, QString& sProgram ) const; // Item updater. void update(qtractorTrackList *pTrackList); // Item members. qtractorTrack *track; QStringList text; // Track-list item widget. qtractorTrackItemWidget *widget; }; // Model cache item list. QList m_items; // Current selected row. int m_iCurrentTrack; // The current selecting/dragging item stuff. enum DragState { DragNone = 0, DragStart, DragMove, DragResize } m_dragState; // For whether we're resizing or moving an item; QPoint m_posDrag; int m_iDragTrack; int m_iDragY; qtractorRubberBand *m_pRubberBand; // To avoid update reentries. int m_iUpdateContents; // Track icon pixmap stuff. enum { IconAudio = 0, IconMidi = 1, IconCount = 2 }; QPixmap *m_pPixmap[IconCount]; }; //---------------------------------------------------------------------------- // qtractorTrackListHeaderModel -- Track-list header model. class qtractorTrackListHeaderModel : public QAbstractListModel { Q_OBJECT public: // Constructor. qtractorTrackListHeaderModel(QObject *pParent = 0); QVariant headerData(int section, Qt::Orientation orient, int role) const; int rowCount(const QModelIndex&) const { return 0; } int columnCount(const QModelIndex&) const { return m_headerText.count(); } QVariant data(const QModelIndex&, int) const { return QVariant(); } private: // Model variables. QStringList m_headerText; }; #endif // __qtractorTrackList_h // end of qtractorTrackList.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorClipSelect.h0000644000175000001440000000012312214366354021231 xustar000000000000000027 mtime=1379003628.863677 26 atime=1381134667.75008 30 ctime=1381134667.750080061 qtractor-0.5.11/src/qtractorClipSelect.h0000644000175000001440000000517312214366354020526 0ustar00rncbcusers00000000000000// qtractorClipSelect.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorClipSelect_h #define __qtractorClipSelect_h #include "qtractorClip.h" #include "qtractorRubberBand.h" #include #include //------------------------------------------------------------------------- // qtractorClipSelect -- Track clip selection capsule. class qtractorClipSelect { public: // Constructor. qtractorClipSelect(); // Default constructor. ~qtractorClipSelect(); // Selection item struct. struct Item { // Item constructor. Item(const QRect& rect) : rectClip(rect), rubberBand(NULL) {} // Item destructor. ~Item() { if (rubberBand) { rubberBand->hide(); delete rubberBand; } } // Item members. QRect rectClip; qtractorRubberBand *rubberBand; }; // Selection list definition. typedef QMultiHash ItemList; // Clip selection method. void selectItem(qtractorClip *pClip, const QRect& rect, bool bSelect = true); // Clip addition (no actual selection). void addItem(qtractorClip *pClip, const QRect& rect); // The united selection rectangle. const QRect& rect() const; // Dynamic helper: // Do all selected clips belong to the same track? qtractorTrack *singleTrack(); // Selection list accessor. const ItemList& items() const; // Clip selection item lookup. Item *findItem(qtractorClip *pClip) const; // Reset clip selection. void reset(); // Clear clip selection. void clear(); private: // The clip selection list. ItemList m_items; // The united selection rectangle. QRect m_rect; // To cache single track selection. qtractorTrack *m_pTrackSingle; bool m_bTrackSingle; }; #endif // __qtractorClipSelect_h // end of qtractorClipSelect.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorTrackButton.cpp0000644000175000001440000000012212207673031021767 xustar000000000000000026 mtime=1377793561.87198 26 atime=1381134667.26408 30 ctime=1381134667.264080053 qtractor-0.5.11/src/qtractorTrackButton.cpp0000644000175000001440000001202712207673031021261 0ustar00rncbcusers00000000000000// qtractorTrackButton.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorTrackButton.h" #include "qtractorMidiControlObserverForm.h" #include "qtractorMidiControlObserver.h" //---------------------------------------------------------------------------- // qtractorMidiControlButton -- MIDI controller observer tool button. // Constructor. qtractorMidiControlButton::qtractorMidiControlButton ( QWidget *pParent ) : qtractorObserverWidget (pParent), m_pMidiControlAction(NULL) { QPushButton::setFocusPolicy(Qt::NoFocus); // QPushButton::setToolButtonStyle(Qt::ToolButtonTextOnly); QPushButton::setCheckable(true); } // MIDI controller/observer attachment (context menu) activator. void qtractorMidiControlButton::addMidiControlAction ( qtractorMidiControlObserver *pMidiObserver ) { if (m_pMidiControlAction) removeAction(m_pMidiControlAction); m_pMidiControlAction = qtractorMidiControlObserverForm::addMidiControlAction( this, this, pMidiObserver); } void qtractorMidiControlButton::midiControlActionSlot (void) { qtractorMidiControlObserverForm::midiControlAction( this, qobject_cast (sender())); } void qtractorMidiControlButton::midiControlMenuSlot ( const QPoint& pos ) { qtractorMidiControlObserverForm::midiControlMenu( qobject_cast (sender()), pos); } //---------------------------------------------------------------------------- // qtractorTrackButton -- Track tool button (observer). // Constructor. qtractorTrackButton::qtractorTrackButton ( qtractorTrack *pTrack, qtractorTrack::ToolType toolType, QWidget *pParent ) : qtractorMidiControlButton(pParent) { m_pTrack = pTrack; m_toolType = toolType; QPalette pal(QPushButton::palette()); m_rgbText = pal.buttonText().color(); m_rgbOff = pal.button().color(); switch (m_toolType) { case qtractorTrack::Record: QPushButton::setText("R"); QPushButton::setToolTip(tr("Record")); m_rgbOn = Qt::red; break; case qtractorTrack::Mute: QPushButton::setText("M"); QPushButton::setToolTip(tr("Mute")); m_rgbOn = Qt::yellow; break; case qtractorTrack::Solo: QPushButton::setText("S"); QPushButton::setToolTip(tr("Solo")); m_rgbOn = Qt::cyan; break; } updateTrack(); // Visitor setup. QObject::connect(this, SIGNAL(toggled(bool)), SLOT(toggledSlot(bool))); } // Visitors overload. void qtractorTrackButton::updateValue ( float fValue ) { bool bBlockSignals = QPushButton::blockSignals(true); bool bOn = (fValue > 0.0f); QPalette pal(QPushButton::palette()); pal.setColor(QPalette::ButtonText, bOn ? m_rgbOn.darker() : m_rgbText); pal.setColor(QPalette::Button, bOn ? m_rgbOn : m_rgbOff); QPushButton::setPalette(pal); QPushButton::setChecked(bOn); QPushButton::blockSignals(bBlockSignals); } // Special toggle slot. void qtractorTrackButton::toggledSlot ( bool bOn ) { // Just emit proper signal... m_pTrack->stateChangeNotify(m_toolType, bOn); } // Specific accessors. void qtractorTrackButton::setTrack ( qtractorTrack *pTrack ) { m_pTrack = pTrack; updateTrack(); } qtractorTrack *qtractorTrackButton::track (void) const { return m_pTrack; } qtractorTrack::ToolType qtractorTrackButton::toolType (void) const { return m_toolType; } // Track state (record, mute, solo) button setup. void qtractorTrackButton::updateTrack (void) { qtractorMidiControlObserver *pMidiObserver; switch (m_toolType) { case qtractorTrack::Record: setSubject(m_pTrack->recordSubject()); pMidiObserver = m_pTrack->recordObserver(); if (pMidiObserver) { pMidiObserver->setCurveList(m_pTrack->curveList()); addMidiControlAction(pMidiObserver); } break; case qtractorTrack::Mute: setSubject(m_pTrack->muteSubject()); pMidiObserver = m_pTrack->muteObserver(); if (pMidiObserver) { pMidiObserver->setCurveList(m_pTrack->curveList()); addMidiControlAction(pMidiObserver); } break; case qtractorTrack::Solo: setSubject(m_pTrack->soloSubject()); pMidiObserver = m_pTrack->soloObserver(); if (pMidiObserver) { pMidiObserver->setCurveList(m_pTrack->curveList()); addMidiControlAction(pMidiObserver); } break; } observer()->update(true); } // end of qtractorTrackButton.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioListView.h0000644000175000001440000000012312166526620021732 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134670.67008 30 ctime=1381134670.670080107 qtractor-0.5.11/src/qtractorAudioListView.h0000644000175000001440000000447012166526620021226 0ustar00rncbcusers00000000000000// qtractorAudioListView.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorAudioListView_h #define __qtractorAudioListView_h #include "qtractorFileListView.h" // Forward declarations. class qtractorAudioFile; class qtractorAudioListView; //---------------------------------------------------------------------- // class qtractorAudioFileItem -- MIDI file list view item. // class qtractorAudioFileItem : public qtractorFileListItem { public: // Constructor. qtractorAudioFileItem(const QString& sPath, qtractorAudioFile *pFile); protected: // Virtual tooltip renderer. QString toolTip() const; }; //---------------------------------------------------------------------------- // qtractorAudioListView -- Group/File list view, supporting drag-n-drop. // class qtractorAudioListView : public qtractorFileListView { Q_OBJECT public: // Constructor. qtractorAudioListView(QWidget *pParent = 0); // QListView::addColumn() ids. enum ItemColumn { Name = 0, Channels = 1, Frames = 2, Rate = 3, Time = 4, Path = 5, LastColumn = 6 }; protected: // Which column is the complete file path? int pathColumn() const { return Path; } // File item factory method. qtractorFileListItem *createFileItem(const QString& sPath); // Prompt for proper file list open. QStringList getOpenFileNames(); }; #endif // __qtractorAudioListView_h // end of qtractorAudioListView.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorInstrumentForm.ui0000644000175000001440000000012112067456742022371 xustar000000000000000026 mtime=1356750306.99751 26 atime=1381134667.73308 29 ctime=1381134667.73308006 qtractor-0.5.11/src/qtractorInstrumentForm.ui0000644000175000001440000002017412067456742021666 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorInstrumentForm 0 0 580 340 Instruments - Qtractor :/images/itemInstrument.png Qt::Horizontal 240 0 QAbstractItemView::NoSelection true true true Instruments Qt::Vertical 240 0 false true false true Files Path 240 0 QAbstractItemView::NoSelection true true true Names Import from instrument file &Import... :/images/formOpen.png Alt+I Remove instrument file &Remove :/images/formRemove.png Alt+R Move instrument file up on list order &Up :/images/formMoveUp.png Alt+U Move instrument file down on list order &Down :/images/formMoveDown.png Alt+D Qt::Vertical QSizePolicy::Expanding 20 20 Reload all instrument files Relo&ad :/images/formRefresh.png Alt+A Export to instrument file E&xport... :/images/formSave.png Alt+X Close this dialog Close InstrumentsListView FilesListView NamesListView ImportPushButton RemovePushButton MoveUpPushButton MoveDownPushButton ReloadPushButton ExportPushButton ClosePushButton qtractor-0.5.11/src/PaxHeaders.10084/qtractorTimeScale.h0000644000175000001440000000012312166134117021044 xustar000000000000000027 mtime=1373157455.942698 26 atime=1381134670.93108 30 ctime=1381134670.931080111 qtractor-0.5.11/src/qtractorTimeScale.h0000644000175000001440000004077512166134117020350 0ustar00rncbcusers00000000000000// qtractorTimeScale.h // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorTimeScale_h #define __qtractorTimeScale_h #include "qtractorList.h" #include #include //---------------------------------------------------------------------- // class qtractorTimeScale -- Time scale conversion helper class. // class qtractorTimeScale { public: // Available display-formats. enum DisplayFormat { Frames = 0, Time, BBT }; // Default constructor. qtractorTimeScale() : m_displayFormat(Frames), m_cursor(this), m_markerCursor(this) { clear(); } // Copy constructor. qtractorTimeScale(const qtractorTimeScale& ts) : m_cursor(this), m_markerCursor(this) { copy(ts); } // Assignment operator, qtractorTimeScale& operator=(const qtractorTimeScale& ts) { return copy(ts); } // Node list cleaner. void reset(); // (Re)nitializer method. void clear(); // Sync method. void sync(const qtractorTimeScale& ts); // Copy method. qtractorTimeScale& copy(const qtractorTimeScale& ts); // Sample rate (frames per second) void setSampleRate(unsigned int iSampleRate) { m_iSampleRate = iSampleRate; } unsigned int sampleRate() const { return m_iSampleRate; } // Resolution (ticks per quarter note; PPQN) void setTicksPerBeat(unsigned short iTicksPerBeat) { m_iTicksPerBeat = iTicksPerBeat; } unsigned short ticksPerBeat() const { return m_iTicksPerBeat; } // Pixels per beat (width). void setPixelsPerBeat(unsigned short iPixelsPerBeat) { m_iPixelsPerBeat = iPixelsPerBeat; } unsigned short pixelsPerBeat() const { return m_iPixelsPerBeat; } // Beat divisor (snap) accessors. void setSnapPerBeat(unsigned short iSnapPerBeat) { m_iSnapPerBeat = iSnapPerBeat; } unsigned short snapPerBeat(void) const { return m_iSnapPerBeat; } // Horizontal zoom factor. void setHorizontalZoom(unsigned short iHorizontalZoom) { m_iHorizontalZoom = iHorizontalZoom; } unsigned short horizontalZoom() const { return m_iHorizontalZoom; } // Vertical zoom factor. void setVerticalZoom(unsigned short iVerticalZoom) { m_iVerticalZoom = iVerticalZoom; } unsigned short verticalZoom() const { return m_iVerticalZoom; } // Fastest rounding-from-float helper. static unsigned long uroundf(float x) { return (unsigned long) (x >= 0.0f ? x + 0.5f : x - 0.5f); } // Beat divisor (snap index) accessors. static unsigned short snapFromIndex(int iSnap); static int indexFromSnap(unsigned short iSnapPerBeat); // Beat divisor (snap index) text item list. static QStringList snapItems(int iSnap = 0); // Time scale node declaration. class Node : public qtractorList::Link { public: // Constructor. Node(qtractorTimeScale *pTimeScale, unsigned long iFrame = 0, float fTempo = 120.0f, unsigned short iBeatType = 2, unsigned short iBeatsPerBar = 4, unsigned short iBeatDivisor = 2) : frame(iFrame), bar(0), beat(0), tick(0), pixel(0), tempo(fTempo), beatType(iBeatType), beatsPerBar(iBeatsPerBar), beatDivisor(iBeatDivisor), ticksPerBeat(0), ts(pTimeScale), tickRate(1.0f), beatRate(1.0f) {} // Update node scale coefficients. void update(); // Update node position metrics. void reset(Node *pNode); // Tempo accessor/convertors. void setTempoEx(float fTempo, unsigned short iBeatType = 2); float tempoEx(unsigned short iBeatType = 2) const; // Frame/bar convertors. unsigned short barFromFrame(unsigned long iFrame) const { return bar + uroundf( (beatRate * (iFrame - frame)) / (ts->frameRate() * beatsPerBar)); } unsigned long frameFromBar(unsigned short iBar) const { return frame + uroundf( (ts->frameRate() * beatsPerBar * (iBar - bar)) / beatRate); } // Frame/beat convertors. unsigned int beatFromFrame(unsigned long iFrame) const { return beat + uroundf( (beatRate * (iFrame - frame)) / ts->frameRate()); } unsigned long frameFromBeat(unsigned int iBeat) const { return frame + uroundf( (ts->frameRate() * (iBeat - beat)) / beatRate); } // Frame/tick convertors. unsigned long tickFromFrame(unsigned long iFrame) const { return tick + uroundf( (tickRate * (iFrame - frame)) / ts->frameRate()); } unsigned long frameFromTick(unsigned long iTick) const { return frame + uroundf( (ts->frameRate() * (iTick - tick)) / tickRate); } // Tick/beat convertors. unsigned int beatFromTick(unsigned long iTick) const { return beat + ((iTick - tick) / ticksPerBeat); } unsigned long tickFromBeat(unsigned int iBeat) const { return tick + (ticksPerBeat * (iBeat - beat)); } // Tick/bar convertors. unsigned short barFromTick(unsigned long iTick) const { return bar + ((iTick - tick) / (ticksPerBeat * beatsPerBar)); } unsigned long tickFromBar(unsigned short iBar) const { return tick + (ticksPerBeat * beatsPerBar * (iBar - bar)) ; } // Tick/pixel convertors. unsigned long tickFromPixel(int x) const { return tick + uroundf( (tickRate * (x - pixel)) / ts->pixelRate()); } int pixelFromTick(unsigned long iTick) const { return pixel + uroundf( (ts->pixelRate() * (iTick - tick)) / tickRate); } // Beat/pixel convertors. unsigned int beatFromPixel(int x) const { return beat + uroundf( (beatRate * (x - pixel)) / ts->pixelRate()); } int pixelFromBeat(unsigned int iBeat) const { return pixel + uroundf( (ts->pixelRate() * (iBeat - beat)) / beatRate); } // Pixel/beat rate convertor. unsigned short pixelsPerBeat() const { return uroundf(ts->pixelRate() / beatRate); } // Bar/pixel convertors. unsigned short barFromPixel(int x) const { return bar + uroundf( (beatRate * (x - pixel)) / (ts->pixelRate() * beatsPerBar)); } int pixelFromBar(unsigned short iBar) const { return pixel + uroundf( (ts->pixelRate() * beatsPerBar * (iBar - bar)) / beatRate); } // Bar/beat convertors. unsigned short barFromBeat(unsigned int iBeat) const { return bar + ((iBeat - beat) / beatsPerBar); } unsigned int beatFromBar(unsigned short iBar) const { return beat + (beatsPerBar * (iBar - bar)); } bool beatIsBar(unsigned int iBeat) const { return ((iBeat - beat) % beatsPerBar) == 0; } // Frame/bar quantizer. unsigned long frameSnapToBar(unsigned long iFrame) const { return frameFromBar(barFromFrame(iFrame)); } // Beat snap filters. unsigned long tickSnap(unsigned long iTick, unsigned short p = 1) const; unsigned long frameSnap(unsigned long iFrame) const { return frameFromTick(tickSnap(tickFromFrame(iFrame))); } int pixelSnap(int x) const { return pixelFromTick(tickSnap(tickFromPixel(x))); } // Node keys. unsigned long frame; unsigned short bar; unsigned int beat; unsigned long tick; int pixel; // Node payload. float tempo; unsigned short beatType; unsigned short beatsPerBar; unsigned short beatDivisor; unsigned short ticksPerBeat; protected: // Node owner. qtractorTimeScale *ts; // Node cached coefficients. float tickRate; float beatRate; }; // Node list accessor. const qtractorList& nodes() const { return m_nodes; } // To optimize and keep track of current frame // position, mostly like an sequence cursor/iterator. class Cursor { public: // Constructor. Cursor(qtractorTimeScale *pTimeScale) : ts(pTimeScale), node(0) {} // Time scale accessor. qtractorTimeScale *timeScale() const { return ts; } // Reset method. void reset(Node *pNode = 0); // Seek methods. Node *seekFrame(unsigned long iFrame); Node *seekBar(unsigned short iBar); Node *seekBeat(unsigned int iBeat); Node *seekTick(unsigned long iTick); Node *seekPixel(int x); protected: // Member variables. qtractorTimeScale *ts; Node *node; }; // Internal cursor accessor. Cursor& cursor() { return m_cursor; } // Node list specifics. Node *addNode( unsigned long iFrame = 0, float fTempo = 120.0f, unsigned short iBeatType = 2, unsigned short iBeatsPerBar = 4, unsigned short iBeatDivisor = 2); void updateNode(Node *pNode); void removeNode(Node *pNode); // Complete time-scale update method. void updateScale(); // Frame/pixel convertors. int pixelFromFrame(unsigned long iFrame) const { return uroundf((m_fPixelRate * iFrame) / m_fFrameRate); } unsigned long frameFromPixel(int x) const { return uroundf((m_fFrameRate * x) / m_fPixelRate); } // Frame/bar general converters. unsigned short barFromFrame(unsigned long iFrame) { Node *pNode = m_cursor.seekFrame(iFrame); return (pNode ? pNode->barFromFrame(iFrame) : 0); } unsigned long frameFromBar(unsigned short iBar) { Node *pNode = m_cursor.seekBar(iBar); return (pNode ? pNode->frameFromBar(iBar) : 0); } // Frame/beat general converters. unsigned int beatFromFrame(unsigned long iFrame) { Node *pNode = m_cursor.seekFrame(iFrame); return (pNode ? pNode->beatFromFrame(iFrame) : 0); } unsigned long frameFromBeat(unsigned int iBeat) { Node *pNode = m_cursor.seekBeat(iBeat); return (pNode ? pNode->frameFromBeat(iBeat) : 0); } // Frame/tick general converters. unsigned long tickFromFrame(unsigned long iFrame) { Node *pNode = m_cursor.seekFrame(iFrame); return (pNode ? pNode->tickFromFrame(iFrame) : 0); } unsigned long frameFromTick(unsigned long iTick) { Node *pNode = m_cursor.seekTick(iTick); return (pNode ? pNode->frameFromTick(iTick) : 0); } // Tick/pixel general converters. unsigned long tickFromPixel(int x) { Node *pNode = m_cursor.seekPixel(x); return (pNode ? pNode->tickFromPixel(x) : 0); } int pixelFromTick(unsigned long iTick) { Node *pNode = m_cursor.seekTick(iTick); return (pNode ? pNode->pixelFromTick(iTick) : 0); } // Beat/pixel composite converters. unsigned int beatFromPixel(int x) { Node *pNode = m_cursor.seekPixel(x); return (pNode ? pNode->beatFromPixel(x) : 0); } int pixelFromBeat(unsigned int iBeat) { Node *pNode = m_cursor.seekBeat(iBeat); return (pNode ? pNode->pixelFromBeat(iBeat) : 0); } // Bar/beat predicate. bool beatIsBar(unsigned int iBeat) { Node *pNode = m_cursor.seekBeat(iBeat); return (pNode ? pNode->beatIsBar(iBeat) : false); } // Snap functions. unsigned long tickSnap(unsigned long iTick) { Node *pNode = m_cursor.seekTick(iTick); return (pNode ? pNode->tickSnap(iTick) : iTick); } unsigned long frameSnap(unsigned long iFrame) { Node *pNode = m_cursor.seekFrame(iFrame); return (pNode ? pNode->frameSnap(iFrame) : iFrame); } int pixelSnap(int x) { Node *pNode = m_cursor.seekPixel(x); return (pNode ? pNode->pixelSnap(x) : x); } // Display-format accessors. void setDisplayFormat(DisplayFormat displayFormat) { m_displayFormat = displayFormat; } DisplayFormat displayFormat() const { return m_displayFormat; } // Convert frames to time string and vice-versa. QString textFromFrameEx(DisplayFormat displayFormat, unsigned long iFrame, bool bDelta = false, unsigned long iDelta = 0); QString textFromFrame( unsigned long iFrame, bool bDelta = false, unsigned long iDelta = 0); unsigned long frameFromTextEx(DisplayFormat displayFormat, const QString& sText, bool bDelta = false, unsigned long iFrame = 0); unsigned long frameFromText( const QString& sText, bool bDelta = false, unsigned long iFrame = 0); // Convert ticks to time string and vice-versa. QString textFromTick( unsigned long iTick, bool bDelta = false, unsigned long iDelta = 0); unsigned long tickFromText( const QString& sText, bool bDelta = false, unsigned long iTick = 0); // Tempo (beats per minute; BPM) void setTempo(float fTempo) { Node *pNode = m_nodes.first(); if (pNode) pNode->tempo = fTempo; } float tempo() const { Node *pNode = m_nodes.first(); return (pNode ? pNode->tempo : 120.0f); } // Tempo convertors (default's quarter notes per minute) void setTempoEx(float fTempo, unsigned short iBeatType = 2) { Node *pNode = m_nodes.first(); if (pNode) pNode->setTempoEx(fTempo, iBeatType); } float tempoEx(unsigned short iBeatType = 2) const { Node *pNode = m_nodes.first(); return (pNode ? pNode->tempoEx(iBeatType) : 120.0f); } // Tempo beat type (if not standard 2=quarter note) void setBeatType(unsigned short iBeatType) { Node *pNode = m_nodes.first(); if (pNode) pNode->beatType = iBeatType; } unsigned short beatType() const { Node *pNode = m_nodes.first(); return (pNode ? pNode->beatType : 2); } // Time signature (numerator) void setBeatsPerBar(unsigned short iBeatsPerBar) { Node *pNode = m_nodes.first(); if (pNode) pNode->beatsPerBar = iBeatsPerBar; } unsigned short beatsPerBar() const { Node *pNode = m_nodes.first(); return (pNode ? pNode->beatsPerBar : 4); } // Time signature (denominator) void setBeatDivisor(unsigned short iBeatDivisor) { Node *pNode = m_nodes.first(); if (pNode) pNode->beatDivisor = iBeatDivisor; } unsigned short beatDivisor() const { Node *pNode = m_nodes.first(); return (pNode ? pNode->beatDivisor : 2); } // Tick/Frame range conversion (delta conversion). unsigned long frameFromTickRange( unsigned long iTickStart, unsigned long iTickEnd); unsigned long tickFromFrameRange( unsigned long iFrameStart, unsigned long iFrameEnd); // Location marker declaration. class Marker : public qtractorList::Link { public: // Constructor. Marker(unsigned long iFrame, unsigned short iBar, const QString& sText, const QColor& rgbColor = Qt::darkGray) : frame(iFrame), bar(iBar), text(sText), color(rgbColor) {} // Copy constructor. Marker(const Marker& marker) : frame(marker.frame), bar(marker.bar), text(marker.text), color(marker.color) {} // Marker keys. unsigned long frame; unsigned short bar; // Marker payload. QString text; QColor color; }; // To optimize and keep track of current frame // position, mostly like an sequence cursor/iterator. class MarkerCursor { public: // Constructor. MarkerCursor(qtractorTimeScale *pTimeScale) : ts(pTimeScale), marker(0) {} // Time scale accessor. qtractorTimeScale *timeScale() const { return ts; } // Reset method. void reset(Marker *pMarker = 0); // Seek methods. Marker *seekFrame(unsigned long iFrame); Marker *seekBar(unsigned short iBar); Marker *seekBeat(unsigned int iBeat); Marker *seekTick(unsigned long iTick); Marker *seekPixel(int x); // Notable markers accessors Marker *first() const { return ts->m_markers.first(); } Marker *last() const { return ts->m_markers.last(); } protected: // Member variables. qtractorTimeScale *ts; Marker *marker; }; // Markers list accessor. MarkerCursor& markers() { return m_markerCursor; } // Marker list specifics. Marker *addMarker( unsigned long iFrame, const QString& sText, const QColor& rgbColor = Qt::darkGray); void updateMarker(Marker *pMarker); void removeMarker(Marker *pMarker); // Update markers from given node position. void updateMarkers(Node *pNode); protected: // Tempo-map independent coefficients. float pixelRate() const { return m_fPixelRate; } float frameRate() const { return m_fFrameRate; } private: unsigned short m_iSnapPerBeat; // Snap per beat (divisor). unsigned short m_iHorizontalZoom; // Horizontal zoom factor. unsigned short m_iVerticalZoom; // Vertical zoom factor. DisplayFormat m_displayFormat; // Textual display format. unsigned int m_iSampleRate; // Sample rate (frames per second) unsigned short m_iTicksPerBeat; // Tticks per quarter note (PPQN) unsigned short m_iPixelsPerBeat; // Pixels per beat (width). // Tempo-map node list. qtractorList m_nodes; // Internal node cursor. Cursor m_cursor; // Tempo-map independent coefficients. float m_fPixelRate; float m_fFrameRate; // Location marker list. qtractorList m_markers; // Internal node cursor. MarkerCursor m_markerCursor; }; #endif // __qtractorTimeScale_h // end of qtractorTimeScale.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorPluginForm.h0000644000175000001440000000012312073012112021243 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134667.12508 30 ctime=1381134667.125080051 qtractor-0.5.11/src/qtractorPluginForm.h0000644000175000001440000001007112073012112020531 0ustar00rncbcusers00000000000000// qtractorPluginForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorPluginForm_h #define __qtractorPluginForm_h #include "ui_qtractorPluginForm.h" #include #include // Forward declarations... class qtractorPlugin; class qtractorPluginParam; class qtractorPluginParamWidget; class qtractorMidiControlObserver; class qtractorObserverCheckBox; class qtractorObserverSlider; class qtractorObserverSpinBox; class qtractorPluginParamDisplay; //---------------------------------------------------------------------------- // qtractorPluginForm -- UI wrapper form. class qtractorPluginForm : public QWidget { Q_OBJECT public: // Constructor. qtractorPluginForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorPluginForm(); void setPlugin(qtractorPlugin *pPlugin); qtractorPlugin *plugin() const; void setPreset(const QString& sPreset); QString preset() const; void updateActivated(); void changeParamValue(unsigned long iIndex); void updateAudioBusName(); void activateForm(); void refresh(); void clear(); void toggleEditor(bool bOn); protected slots: void changePresetSlot(const QString& sPreset); void loadPresetSlot(const QString& sPreset); void openPresetSlot(); void savePresetSlot(); void deletePresetSlot(); void paramsSlot(bool bOn); void editSlot(bool bOn); void sendsSlot(); void returnsSlot(); void activateSlot(bool bOn); void midiControlActionSlot(); void midiControlMenuSlot(const QPoint& pos); void changeAudioBusNameSlot(const QString& sAudioBusName); void clickAudioBusNameSlot(); void updateDirectAccessParamSlot(); void changeDirectAccessParamSlot(); protected: void stabilize(); // Show insert pseudo-plugin audio bus connections. void insertPluginBus(int iBusMode); // MIDI controller/observer attachement (context menu) void addMidiControlAction( QWidget *pWidget, qtractorMidiControlObserver *pObserver); // Keyboard event handler. void keyPressEvent(QKeyEvent *); private: // The Qt-designer UI struct... Ui::qtractorPluginForm m_ui; // Instance variables... qtractorPlugin *m_pPlugin; typedef QHash ParamWidgets; ParamWidgets m_paramWidgets; QMenu *m_pDirectAccessParamMenu; int m_iDirtyCount; int m_iUpdate; }; //---------------------------------------------------------------------------- // qtractorPluginParamWidget -- Plugin port widget. // class qtractorPluginParamWidget : public QFrame { Q_OBJECT public: // Constructor. qtractorPluginParamWidget(qtractorPluginParam *pParam, QWidget *pParent = NULL); // Main properties accessors. qtractorPluginParam *param() const { return m_pParam; } // Refreshner-loader method. void refresh(); protected slots: // Parameter value change slot. void updateValue(float fValue); private: // Local forward declarations. class SliderInterface; // Instance variables. qtractorPluginParam *m_pParam; // Some possible managed widgets. qtractorObserverCheckBox *m_pCheckBox; qtractorObserverSlider *m_pSlider; qtractorObserverSpinBox *m_pSpinBox; qtractorPluginParamDisplay *m_pDisplay; }; #endif // __qtractorPluginForm_h // end of qtractorPluginForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorRubberBand.h0000644000175000001440000000012312166526620021210 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134666.76108 30 ctime=1381134666.761080045 qtractor-0.5.11/src/qtractorRubberBand.h0000644000175000001440000000411312166526620020476 0ustar00rncbcusers00000000000000// qtractorRubberBand.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorRubberBand_h #define __qtractorRubberBand_h #include #if QT_VERSION < 0x050000 #include #else #include class QWindowsStyle : public QCommonStyle {}; #endif //---------------------------------------------------------------------------- // qtractorRubberBand -- Custom rubber-band widget. class qtractorRubberBand : public QRubberBand { public: // Constructor. qtractorRubberBand(Shape shape, QWidget *widget = 0, int thick = 1); // Destructor. ~qtractorRubberBand(); // Rubberband thickness accessor. void setThickness(int thick); int thickness() const; private: // qtractorRubberBandStyle -- Custom rubber-band style. class Style : public QWindowsStyle { public: // Constructor. Style(int thick) : QWindowsStyle(), thickness(thick) {} // Custom virtual override. int styleHint( StyleHint sh, const QStyleOption *opt = 0, const QWidget *widget = 0, QStyleHintReturn *hint = 0 ) const; // Rubberband thickness. int thickness; }; // Local style instance Style *m_pStyle; }; #endif // __qtractorRubberBand_h // end of qtractorRubberBand.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorSession.cpp0000644000175000001440000000012312121562322021146 xustar000000000000000027 mtime=1363600594.061657 26 atime=1381134670.41708 30 ctime=1381134670.417080103 qtractor-0.5.11/src/qtractorSession.cpp0000644000175000001440000015225112121562322020443 0ustar00rncbcusers00000000000000// qtractorSession.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorSession.h" #include "qtractorSessionCursor.h" #include "qtractorSessionDocument.h" #include "qtractorAudioEngine.h" #include "qtractorAudioPeak.h" #include "qtractorAudioClip.h" #include "qtractorAudioBuffer.h" #include "qtractorMidiEngine.h" #include "qtractorMidiClip.h" #include "qtractorMidiBuffer.h" #include "qtractorPlugin.h" #include "qtractorCurve.h" #include "qtractorInstrument.h" #include "qtractorCommand.h" #include "qtractorFileList.h" #include "qtractorFiles.h" #include #include #include #include #include #include #include //------------------------------------------------------------------------- // qtractorSession::Properties -- Session properties structure. // Helper clear/reset method. void qtractorSession::Properties::clear (void) { sessionDir = QDir().absolutePath(); sessionName.clear(); description.clear(); timeScale.clear(); } // Helper copy method. qtractorSession::Properties& qtractorSession::Properties::copy ( const Properties& props ) { if (&props != this) { sessionDir = props.sessionDir; sessionName = props.sessionName; description = props.description; timeScale = props.timeScale; } return *this; } //------------------------------------------------------------------------- // qtractorSession -- Session container. // Singleton instance pointer. qtractorSession *qtractorSession::g_pSession = NULL; // Singleton instance accessor (static). qtractorSession *qtractorSession::getInstance (void) { // Create the singleton instance, if not already... if (g_pSession == NULL) { g_pSession = new qtractorSession(); ::atexit(Destroy); } return g_pSession; } // Singleton instance destroyer. void qtractorSession::Destroy (void) { // OK. We're done with ourselves. if (g_pSession) { delete g_pSession; g_pSession = NULL; } } // Constructor. qtractorSession::qtractorSession (void) { m_tracks.setAutoDelete(true); m_cursors.setAutoDelete(false); m_midiManagers.setAutoDelete(false); // Initial comon client name. m_sClientName = QTRACTOR_TITLE; // Singleton ownings. m_pFiles = new qtractorFileList(); m_pCommands = new qtractorCommandList(); m_pInstruments = new qtractorInstrumentList(); // The dubious permanency of the crucial device engines. m_pMidiEngine = new qtractorMidiEngine(this); m_pAudioEngine = new qtractorAudioEngine(this); m_pAudioPeakFactory = new qtractorAudioPeakFactory(); m_bAutoTimeStretch = false; m_iLoopRecordingMode = 0; clear(); } // Default destructor. qtractorSession::~qtractorSession (void) { close(); clear(); delete m_pAudioPeakFactory; delete m_pAudioEngine; delete m_pMidiEngine; delete m_pInstruments; delete m_pCommands; delete m_pFiles; } // Initialize session engine(s). bool qtractorSession::init (void) { // Lock it up... lock(); // Actually init session device engines... bool bResult = (m_pAudioEngine->init() && m_pMidiEngine->init()); // Done. unlock(); return bResult; } // Open session engine(s). bool qtractorSession::open (void) { // Lock it up... lock(); // A default MIDI master bus is always in order... const QString sMaster("Master"); if (m_pMidiEngine->buses().count() == 0) { qtractorMidiBus *pMidiMasterBus = new qtractorMidiBus(m_pMidiEngine, sMaster, qtractorBus::Duplex); m_pMidiEngine->addBus(pMidiMasterBus); } // Get over the stereo playback default master bus... if (m_pAudioEngine->buses().count() == 0) { qtractorAudioBus *pAudioMasterBus = new qtractorAudioBus(m_pAudioEngine, sMaster, qtractorBus::Duplex); pAudioMasterBus->setAutoConnect(m_pAudioEngine->isMasterAutoConnect()); m_pAudioEngine->addBus(pAudioMasterBus); } // Actually open session device engines... if (!m_pAudioEngine->open() || !m_pMidiEngine->open()) { unlock(); close(); return false; } // Open all tracks (assign buses)... qtractorTrack *pTrack = m_tracks.first(); while (pTrack) { if (!pTrack->open()) { unlock(); close(); return false; } pTrack = pTrack->next(); } // Done. unlock(); return true; } // Close session engine(s). void qtractorSession::close (void) { // Lock it up... lock(); m_pAudioEngine->close(); m_pMidiEngine->close(); // Close all tracks (unassign buses)... for (qtractorTrack *pTrack = m_tracks.first(); pTrack; pTrack = pTrack->next()) { pTrack->close(); } unlock(); m_pFiles->cleanup(true); // clear(); } // Reset session. void qtractorSession::clear (void) { ATOMIC_SET(&m_locks, 0); ATOMIC_SET(&m_mutex, 0); ATOMIC_SET(&m_busy, 0); m_pAudioPeakFactory->sync(); m_pCurrentTrack = NULL; m_tracks.clear(); m_cursors.clear(); m_props.clear(); m_midiTags.clear(); // m_midiManagers.clear(); m_pMidiEngine->clear(); m_pAudioEngine->clear(); m_pCommands->clear(); m_pFiles->clear(); qtractorAudioClip::clearHashTable(); qtractorMidiClip::clearHashTable(); m_iSessionStart = 0; m_iSessionEnd = 0; m_iRecordTracks = 0; m_iMuteTracks = 0; m_iSoloTracks = 0; m_iAudioRecord = 0; m_iMidiRecord = 0; m_iMidiTag = 0; m_iEditHead = 0; m_iEditTail = 0; m_iEditHeadTime = 0; m_iEditTailTime = 0; m_iLoopStart = 0; m_iLoopEnd = 0; m_iLoopStartTime = 0; m_iLoopEndTime = 0; m_iPunchIn = 0; m_iPunchOut = 0; m_iPunchInTime = 0; m_iPunchOutTime = 0; m_bRecording = false; updateTimeScale(); qtractorSessionCursor *pAudioCursor = m_pAudioEngine->sessionCursor(); if (pAudioCursor) { pAudioCursor->resetClips(); pAudioCursor->reset(); pAudioCursor->seek(0); m_cursors.append(pAudioCursor); } qtractorSessionCursor *pMidiCursor = m_pMidiEngine->sessionCursor(); if (pMidiCursor) { pMidiCursor->resetClips(); pMidiCursor->reset(); pMidiCursor->seek(0); m_cursors.append(pMidiCursor); } } // The global undoable command execuive. bool qtractorSession::execute ( qtractorCommand *pCommand ) { return m_pCommands->exec(pCommand); } // The global undoable command list reference. qtractorCommandList *qtractorSession::commands (void) const { return m_pCommands; } // Session instruments repository. qtractorInstrumentList *qtractorSession::instruments (void) const { return m_pInstruments; } // Session directory path accessors. void qtractorSession::setSessionDir ( const QString& sSessionDir ) { QDir sdir(sSessionDir); if (sdir.exists()) m_props.sessionDir = sdir.absolutePath(); } const QString& qtractorSession::sessionDir (void) const { return m_props.sessionDir; } // Session filename accessors. void qtractorSession::setSessionName ( const QString& sSessionName ) { m_props.sessionName = sSessionName; } const QString& qtractorSession::sessionName (void) const { return m_props.sessionName; } // Session description accessors. void qtractorSession::setDescription ( const QString& sDescription ) { m_props.description = sDescription; } const QString& qtractorSession::description (void) const { return m_props.description; } // Adjust session length to the latest and/or longer clip. void qtractorSession::updateSession ( unsigned long iSessionStart, unsigned long iSessionEnd ) { // Maybe we just don't need to know more... // (recording ongoing?) if (iSessionEnd > 0) { if (m_iSessionEnd < iSessionEnd) m_iSessionEnd = iSessionEnd; // Enough! return; } // Set initial one... m_iSessionStart = iSessionStart; m_iSessionEnd = iSessionEnd; // Find the last and longest clip frame position... int i = 0; for (qtractorTrack *pTrack = m_tracks.first(); pTrack; pTrack = pTrack->next()) { for (qtractorClip *pClip = pTrack->clips().first(); pClip; pClip = pClip->next()) { const unsigned long iClipStart = pClip->clipStart(); const unsigned long iClipEnd = iClipStart + pClip->clipLength(); if (m_iSessionStart > iClipStart || i == 0) m_iSessionStart = iClipStart; if (m_iSessionEnd < iClipEnd) m_iSessionEnd = iClipEnd; ++i; } } // Account for the last marker qtractorTimeScale::Marker *pMarker = m_props.timeScale.markers().last(); if (pMarker && m_iSessionEnd < pMarker->frame) m_iSessionEnd = pMarker->frame; } // Session start/end accessors. unsigned long qtractorSession::sessionStart (void) const { return m_iSessionStart; } unsigned long qtractorSession::sessionEnd (void) const { return m_iSessionEnd; } // Time-scale helper accessors. qtractorTimeScale *qtractorSession::timeScale (void) { return &(m_props.timeScale); } // Device engine common client name accessors. void qtractorSession::setClientName ( const QString& sClientName ) { m_sClientName = sClientName; } const QString& qtractorSession::clientName (void) const { return m_sClientName; } // Sample rate accessors. void qtractorSession::setSampleRate ( unsigned int iSampleRate ) { m_props.timeScale.setSampleRate(iSampleRate); } unsigned int qtractorSession::sampleRate (void) const { return m_props.timeScale.sampleRate(); } // Session tempo accessors. void qtractorSession::setTempo ( float fTempo ) { m_props.timeScale.setTempo(fTempo); m_props.timeScale.updateScale(); } float qtractorSession::tempo (void) const { return m_props.timeScale.tempo(); } // Tempo beat type accessors. void qtractorSession::setBeatType ( unsigned short iBeatType ) { m_props.timeScale.setBeatType(iBeatType); } unsigned short qtractorSession::beatType (void) const { return m_props.timeScale.beatType(); } // Resolution accessors. void qtractorSession::setTicksPerBeat ( unsigned short iTicksPerBeat ) { m_props.timeScale.setTicksPerBeat(iTicksPerBeat); } unsigned short qtractorSession::ticksPerBeat (void) const { return m_props.timeScale.ticksPerBeat(); } // Beats/Bar(measure) accessors. void qtractorSession::setBeatsPerBar ( unsigned short iBeatsPerBar ) { m_props.timeScale.setBeatsPerBar(iBeatsPerBar); } unsigned short qtractorSession::beatsPerBar (void) const { return m_props.timeScale.beatsPerBar(); } // Time signature (denominator) accessors. void qtractorSession::setBeatDivisor ( unsigned short iBeatDivisor ) { m_props.timeScale.setBeatDivisor(iBeatDivisor); } unsigned short qtractorSession::beatDivisor (void) const { return m_props.timeScale.beatDivisor(); } // Pixels per beat (width). void qtractorSession::setPixelsPerBeat ( unsigned short iPixelsPerBeat ) { m_props.timeScale.setPixelsPerBeat(iPixelsPerBeat); } unsigned short qtractorSession::pixelsPerBeat (void) const { return m_props.timeScale.pixelsPerBeat(); } // Horizontal zoom factor. void qtractorSession::setHorizontalZoom ( unsigned short iHorizontalZoom ) { m_props.timeScale.setHorizontalZoom(iHorizontalZoom); } unsigned short qtractorSession::horizontalZoom (void) const { return m_props.timeScale.horizontalZoom(); } // Vertical zoom factor. void qtractorSession::setVerticalZoom ( unsigned short iVerticalZoom ) { m_props.timeScale.setVerticalZoom(iVerticalZoom); } unsigned short qtractorSession::verticalZoom (void) const { return m_props.timeScale.verticalZoom(); } // Beat divisor (snap) accessors. void qtractorSession::setSnapPerBeat ( unsigned short iSnapPerBeat ) { m_props.timeScale.setSnapPerBeat(iSnapPerBeat); } unsigned short qtractorSession::snapPerBeat (void) const { return m_props.timeScale.snapPerBeat(); } // Edit-head frame accessors. void qtractorSession::setEditHead ( unsigned long iEditHead ) { m_iEditHead = iEditHead; m_iEditHeadTime = tickFromFrame(iEditHead); } unsigned long qtractorSession::editHead (void) const { return m_iEditHead; } void qtractorSession::setEditTail ( unsigned long iEditTail ) { m_iEditTail = iEditTail; m_iEditTailTime = tickFromFrame(iEditTail); } unsigned long qtractorSession::editTail (void) const { return m_iEditTail; } // Pixel/Tick number conversion. unsigned long qtractorSession::tickFromPixel ( unsigned int x ) { return m_props.timeScale.tickFromPixel(x); } unsigned int qtractorSession::pixelFromTick ( unsigned long iTick ) { return m_props.timeScale.pixelFromTick(iTick); } // Pixel/Frame number conversion. unsigned long qtractorSession::frameFromPixel ( unsigned int x ) const { return m_props.timeScale.frameFromPixel(x); } unsigned int qtractorSession::pixelFromFrame ( unsigned long iFrame ) const { return m_props.timeScale.pixelFromFrame(iFrame); } // Beat/frame conversion. unsigned long qtractorSession::frameFromBeat ( unsigned int iBeat ) { return m_props.timeScale.frameFromBeat(iBeat); } unsigned int qtractorSession::beatFromFrame ( unsigned long iFrame ) { return m_props.timeScale.beatFromFrame(iFrame); } // Tick/Frame number conversion. unsigned long qtractorSession::frameFromTick ( unsigned long iTick ) { return m_props.timeScale.frameFromTick(iTick); } unsigned long qtractorSession::tickFromFrame ( unsigned long iFrame ) { return m_props.timeScale.tickFromFrame(iFrame); } // Tick/Frame range conversion (delta conversion). unsigned long qtractorSession::frameFromTickRange ( unsigned long iTickStart, unsigned long iTickEnd ) { return m_props.timeScale.frameFromTickRange(iTickStart, iTickEnd); } unsigned long qtractorSession::tickFromFrameRange ( unsigned long iFrameStart, unsigned long iFrameEnd ) { return m_props.timeScale.tickFromFrameRange(iFrameStart, iFrameEnd); } // Beat/frame snap filters. unsigned long qtractorSession::tickSnap ( unsigned long iTick ) { return m_props.timeScale.tickSnap(iTick); } unsigned long qtractorSession::frameSnap ( unsigned long iFrame ) { return m_props.timeScale.frameSnap(iFrame); } unsigned int qtractorSession::pixelSnap ( unsigned int x ) { return m_props.timeScale.pixelSnap(x); } // Frame/locate (SMPTE) conversion. unsigned long qtractorSession::frameFromLocate ( unsigned long iLocate ) const { return (iLocate * m_props.timeScale.sampleRate()) / 30; } unsigned long qtractorSession::locateFromFrame ( unsigned long iFrame ) const { return (30 * iFrame) / m_props.timeScale.sampleRate(); } // Song position pointer (SPP=MIDI beats) to frame converters. unsigned long qtractorSession::frameFromSongPos ( unsigned short iSongPos ) { return frameFromTick((iSongPos * ticksPerBeat()) >> 2); } unsigned short qtractorSession::songPosFromFrame ( unsigned long iFrame ) { return ((tickFromFrame(iFrame) << 2) / ticksPerBeat()); } // Update scale divisor factors. void qtractorSession::updateTimeScale (void) { // Recompute scale divisor factors... m_props.timeScale.updateScale(); // Just (re)synchronize all clips to new tempo state, if any; for (qtractorTrack *pTrack = m_tracks.first(); pTrack; pTrack = pTrack->next()) { for (qtractorClip *pClip = pTrack->clips().first(); pClip; pClip = pClip->next()) { pClip->updateClipTime(); } } // Update loop points... if (m_iLoopStart < m_iLoopEnd) { m_iLoopStart = frameFromTick(m_iLoopStartTime); m_iLoopEnd = frameFromTick(m_iLoopEndTime); // Set proper loop points for every track, clip and buffer... qtractorTrack *pTrack = m_tracks.first(); while (pTrack) { pTrack->setLoop(m_iLoopStart, m_iLoopEnd); pTrack = pTrack->next(); } } // Update punch points... if (m_iPunchIn < m_iPunchOut) { m_iPunchIn = frameFromTick(m_iPunchInTime); m_iPunchOut = frameFromTick(m_iPunchOutTime); } // Do not forget those edit points too... m_iEditHead = frameFromTick(m_iEditHeadTime); m_iEditTail = frameFromTick(m_iEditTailTime); } // Update time resolution divisor factors. void qtractorSession::updateTimeResolution (void) { // Recompute scale divisor factors... m_props.timeScale.updateScale(); // Gotta (re)synchronize all MIDI clips to new resolution... for (qtractorTrack *pTrack = m_tracks.first(); pTrack; pTrack = pTrack->next()) { for (qtractorClip *pClip = pTrack->clips().first(); pClip; pClip = pClip->next()) { if (pTrack->trackType() == qtractorTrack::Midi) pClip->close(); pClip->setClipStart(pClip->clipStart()); pClip->setClipOffset(pClip->clipOffset()); pClip->setClipLength(pClip->clipLength()); if (pTrack->trackType() == qtractorTrack::Midi) pClip->open(); } } // Update loop points... if (m_iLoopStart < m_iLoopEnd) { m_iLoopStartTime = tickFromFrame(m_iLoopStart); m_iLoopEndTime = tickFromFrame(m_iLoopEnd); } // Update punch points... if (m_iPunchIn < m_iPunchOut) { m_iPunchInTime = tickFromFrame(m_iPunchIn); m_iPunchOutTime = tickFromFrame(m_iPunchOut); } // Do not forget those edit points too... m_iEditHeadTime = tickFromFrame(m_iEditHead); m_iEditTailTime = tickFromFrame(m_iEditTail); } // Update from disparate sample-rate. void qtractorSession::updateSampleRate ( unsigned int iSampleRate ) { if (iSampleRate == m_props.timeScale.sampleRate()) return; // Unfortunatelly we must close all clips first, // so let at least all audio peaks be refreshned... for (qtractorTrack *pTrack = m_tracks.first(); pTrack; pTrack = pTrack->next()) { for (qtractorClip *pClip = pTrack->clips().first(); pClip; pClip = pClip->next()) { pClip->close(); } } // Set the conversion ratio... float fRatio = float(m_props.timeScale.sampleRate()) / float(iSampleRate); // Set actual sample-rate... m_props.timeScale.setSampleRate(iSampleRate); // Give it some room for just that... stabilize(); updateTimeScale(); stabilize(); // Adjust all tracks and clips (reopening all those...) for (qtractorTrack *pTrack = m_tracks.first(); pTrack; pTrack = pTrack->next()) { // Update automation stuff... qtractorCurveList *pCurveList = pTrack->curveList(); if (pCurveList) { for (qtractorCurve *pCurve = pCurveList->first(); pCurve; pCurve = pCurve->next()) { for (qtractorCurve::Node *pNode = pCurve->nodes().first(); pNode; pNode = pNode->next()) { pNode->frame = qtractorTimeScale::uroundf( fRatio * float(pNode->frame)); } pCurve->update(); } } // Update regular clip stuff... for (qtractorClip *pClip = pTrack->clips().first(); pClip; pClip = pClip->next()) { // pClip->setClipStart(qtractorTimeScale::uroundf( // fRatio * float(pClip->clipStart()))); // pClip->setClipOffset(qtractorTimeScale::uroundf( // fRatio * float(pClip->clipOffset()))); // pClip->setClipLength(qtractorTimeScale::uroundf( // fRatio * float(pClip->clipLength()))); pClip->setFadeInLength(qtractorTimeScale::uroundf( fRatio * float(pClip->fadeInLength()))); pClip->setFadeOutLength(qtractorTimeScale::uroundf( fRatio * float(pClip->fadeOutLength()))); pClip->open(); } } } // Alternate properties accessor. qtractorSession::Properties& qtractorSession::properties (void) { return m_props; } // Track list management methods. const qtractorList& qtractorSession::tracks (void) const { return m_tracks; } void qtractorSession::addTrack ( qtractorTrack *pTrack ) { insertTrack(pTrack, m_tracks.last()); } void qtractorSession::insertTrack ( qtractorTrack *pTrack, qtractorTrack *pPrevTrack ) { // lock(); if (pTrack->trackType() == qtractorTrack::Midi) acquireMidiTag(pTrack); if (pPrevTrack) { m_tracks.insertAfter(pTrack, pPrevTrack); } else { m_tracks.prepend(pTrack); } #if 0 if (pTrack->isRecord()) setRecordTracks(true); if (pTrack->isMute()) setMuteTracks(true); if (pTrack->isSolo()) setSoloTracks(true); #endif if (pTrack->curveList()) m_curves.insert(pTrack->curveList(), pTrack); qtractorSessionCursor *pSessionCursor = m_cursors.first(); while (pSessionCursor) { pSessionCursor->addTrack(pTrack); pSessionCursor = pSessionCursor->next(); } pTrack->setLoop(m_iLoopStart, m_iLoopEnd); pTrack->open(); // unlock(); } void qtractorSession::moveTrack ( qtractorTrack *pTrack, qtractorTrack *pNextTrack ) { // lock(); m_tracks.unlink(pTrack); if (pNextTrack) m_tracks.insertBefore(pTrack, pNextTrack); else m_tracks.append(pTrack); qtractorSessionCursor *pSessionCursor = m_cursors.first(); while (pSessionCursor) { pSessionCursor->resetClips(); pSessionCursor = pSessionCursor->next(); } // unlock(); } void qtractorSession::updateTrack ( qtractorTrack *pTrack ) { // lock(); pTrack->setLoop(m_iLoopStart, m_iLoopEnd); qtractorSessionCursor *pSessionCursor = m_cursors.first(); while (pSessionCursor) { pSessionCursor->updateTrack(pTrack); pSessionCursor = pSessionCursor->next(); } // unlock(); } void qtractorSession::unlinkTrack ( qtractorTrack *pTrack ) { // lock(); pTrack->setLoop(0, 0); pTrack->close(); qtractorSessionCursor *pSessionCursor = m_cursors.first(); while (pSessionCursor) { pSessionCursor->removeTrack(pTrack); pSessionCursor = pSessionCursor->next(); } if (pTrack->isRecord()) setRecordTracks(false); if (pTrack->isMute()) setMuteTracks(false); if (pTrack->isSolo()) setSoloTracks(false); if (pTrack->curveList()) m_curves.remove(pTrack->curveList()); if (pTrack->trackType() == qtractorTrack::Midi) releaseMidiTag(pTrack); m_tracks.unlink(pTrack); // unlock(); } qtractorTrack *qtractorSession::trackAt ( int iTrack ) const { return m_tracks.at(iTrack); } // Current number of record-armed tracks. void qtractorSession::setRecordTracks ( bool bRecord ) { if (bRecord) { ++m_iRecordTracks; } else if (m_iRecordTracks > 0) { --m_iRecordTracks; } } unsigned int qtractorSession::recordTracks (void) const { return m_iRecordTracks; } // Current number of muted tracks. void qtractorSession::setMuteTracks ( bool bMute ) { if (bMute) { ++m_iMuteTracks; } else if (m_iMuteTracks > 0) { --m_iMuteTracks; } } unsigned int qtractorSession::muteTracks (void) const { return m_iMuteTracks; } // Current number of solo tracks. void qtractorSession::setSoloTracks ( bool bSolo ) { if (bSolo) { ++m_iSoloTracks; } else if (m_iSoloTracks > 0) { --m_iSoloTracks; } } unsigned int qtractorSession::soloTracks (void) const { return m_iSoloTracks; } // Temporary current track accessors. void qtractorSession::setCurrentTrack ( qtractorTrack *pTrack ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorSession::setCurrentTrack(%p)", pTrack); #endif m_pCurrentTrack = pTrack; } qtractorTrack *qtractorSession::currentTrack (void) const { return m_pCurrentTrack; } // Temporary current track predicates. bool qtractorSession::isTrackMonitor ( qtractorTrack *pTrack ) const { return pTrack->isMonitor() || pTrack == m_pCurrentTrack; } bool qtractorSession::isTrackMidiChannel ( qtractorTrack *pTrack, unsigned short iChannel ) const { return pTrack->isMidiOmni() || pTrack->midiChannel() == iChannel || pTrack == m_pCurrentTrack; } // Session cursor factory methods. qtractorSessionCursor *qtractorSession::createSessionCursor ( unsigned long iFrame, qtractorTrack::TrackType syncType ) { qtractorSessionCursor *pSessionCursor = new qtractorSessionCursor(this, iFrame, syncType); m_cursors.append(pSessionCursor); return pSessionCursor; } void qtractorSession::unlinkSessionCursor ( qtractorSessionCursor *pSessionCursor ) { m_cursors.unlink(pSessionCursor); } // Reset (reactivate) all plugin chains... void qtractorSession::resetAllPlugins (void) { // All tracks... for (qtractorTrack *pTrack = m_tracks.first(); pTrack; pTrack = pTrack->next()) { (pTrack->pluginList())->resetBuffer(); } // All audio buses... for (qtractorBus *pBus = m_pAudioEngine->buses().first(); pBus; pBus = pBus->next()) { qtractorAudioBus *pAudioBus = static_cast (pBus); if (pAudioBus) { if (pAudioBus->pluginList_in()) pAudioBus->pluginList_in()->resetBuffer(); if (pAudioBus->pluginList_out()) pAudioBus->pluginList_out()->resetBuffer(); } } } // MIDI engine accessor. qtractorMidiEngine *qtractorSession::midiEngine (void) const { return m_pMidiEngine; } // Audio engine accessor. qtractorAudioEngine *qtractorSession::audioEngine (void) const { return m_pAudioEngine; } // Wait for application stabilization. void qtractorSession::stabilize ( int msecs ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorSession::stabilize(%d)", msecs); #endif // Wait a litle bit before continue... QTime t; t.start(); while (t.elapsed() < msecs) { QThread::yieldCurrentThread(); QApplication::processEvents(/* QEventLoop::ExcludeUserInputEvents */); } } // Consolidated session engine activation status. bool qtractorSession::isActivated (void) const { return (m_pAudioEngine->isActivated() && m_pMidiEngine->isActivated()); } // Consolidated session engine start status. void qtractorSession::setPlaying ( bool bPlaying ) { ATOMIC_INC(&m_busy); // For all armed tracks... if (bPlaying && isRecording()) { // Take a snapshot on where recording // clips are about to start... unsigned long iPlayHead = playHead(); unsigned long iClipStart = iPlayHead; if (isPunching()) { unsigned long iPunchIn = punchIn(); if (iClipStart < iPunchIn) iClipStart = iPunchIn; } // Of course, mark those clips alright... for (qtractorTrack *pTrack = m_tracks.first(); pTrack; pTrack = pTrack->next()) { qtractorClip *pClipRecord = pTrack->clipRecord(); if (pClipRecord) { pClipRecord->setClipStart(iClipStart); // MIDI adjust to playing queue start... if (pTrack->trackType() == qtractorTrack::Midi && iClipStart > iPlayHead) { qtractorMidiClip *pMidiClip = static_cast (pClipRecord); if (pMidiClip) { pMidiClip->sequence()->setTimeOffset( tickFromFrame(iClipStart - iPlayHead)); } } } } } // Have all MIDI instrument plugins be shut up // if start playing, otherwise do ramping down... if (bPlaying) { qtractorMidiManager *pMidiManager = m_midiManagers.first(); while (pMidiManager) { pMidiManager->reset(); pMidiManager = pMidiManager->next(); } } // Do it. m_pAudioEngine->setPlaying(bPlaying); m_pMidiEngine->setPlaying(bPlaying); ATOMIC_DEC(&m_busy); } bool qtractorSession::isPlaying() const { return (m_pAudioEngine->isPlaying() && m_pMidiEngine->isPlaying()); } // Shutdown procedure. void qtractorSession::shutdown (void) { m_pAudioEngine->setPlaying(false); m_pMidiEngine->setPlaying(false); close(); } // (Hazardous) bi-directional locate method. void qtractorSession::seek ( unsigned long iFrame, bool bSync ) { if (bSync) resetAllPlugins(); m_pAudioEngine->sessionCursor()->seek(iFrame, bSync); m_pMidiEngine->sessionCursor()->seek(iFrame, bSync); } // Session RT-safe pseudo-locking primitives. bool qtractorSession::acquire (void) { // Are we in business? return ATOMIC_TAS(&m_mutex); } void qtractorSession::release (void) { // We're not in business anymore. ATOMIC_SET(&m_mutex, 0); } void qtractorSession::lock (void) { ATOMIC_INC(&m_busy); // Wind up as pending lock... if (ATOMIC_INC(&m_locks) == 1) { // Get lost for a while... while (!acquire()) stabilize(); } ATOMIC_DEC(&m_busy); } void qtractorSession::unlock (void) { ATOMIC_INC(&m_busy); // Unwind pending locks and force back to business... if (ATOMIC_DEC(&m_locks) < 1) { ATOMIC_SET(&m_locks, 0); release(); } ATOMIC_DEC(&m_busy); } // Re-entrancy check. bool qtractorSession::isBusy (void) const { return (ATOMIC_GET(&m_busy) > 0 || ATOMIC_GET(&m_locks) > 0); } // Playhead positioning. void qtractorSession::setPlayHead ( unsigned long iFrame ) { bool bPlaying = isPlaying(); if (bPlaying && isRecording()) return; lock(); setPlaying(false); if (m_pAudioEngine->jackClient()) jack_transport_locate(m_pAudioEngine->jackClient(), iFrame); seek(iFrame, true); // Sync all track automation... if (!bPlaying) process_curve(iFrame); setPlaying(bPlaying); unlock(); } unsigned long qtractorSession::playHead (void) const { return m_pAudioEngine->sessionCursor()->frame(); } // Session loop points accessors. void qtractorSession::setLoop ( unsigned long iLoopStart, unsigned long iLoopEnd ) { bool bPlaying = isPlaying(); if (bPlaying && isRecording()) return; lock(); setPlaying(false); // Local prepare... if (iLoopStart >= iLoopEnd) { iLoopStart = 0; iLoopEnd = 0; } // Save exact current play-head position... unsigned long iFrame = playHead(); // Set proper loop points for every track, clip and buffer... qtractorTrack *pTrack = m_tracks.first(); while (pTrack) { pTrack->setLoop(iLoopStart, iLoopEnd); pTrack = pTrack->next(); } // Local commit... m_iLoopStart = iLoopStart; m_iLoopEnd = iLoopEnd; // Time-normalized references too... m_iLoopStartTime = tickFromFrame(iLoopStart); m_iLoopEndTime = tickFromFrame(iLoopEnd); // Replace last known play-head... m_pAudioEngine->sessionCursor()->seek(iFrame, true); m_pMidiEngine->sessionCursor()->seek(iFrame, true); setPlaying(bPlaying); unlock(); } unsigned long qtractorSession::loopStart (void) const { return m_iLoopStart; } unsigned long qtractorSession::loopEnd (void) const { return m_iLoopEnd; } bool qtractorSession::isLooping (void) const { return (m_iLoopStart < m_iLoopEnd); } // Session punch points accessors. void qtractorSession::setPunch ( unsigned long iPunchIn, unsigned long iPunchOut ) { // Local prepare... if (iPunchIn >= iPunchOut) { iPunchIn = 0; iPunchOut = 0; } // Local commit... m_iPunchIn = iPunchIn; m_iPunchOut = iPunchOut; // Time-normalized references too... m_iPunchInTime = tickFromFrame(iPunchIn); m_iPunchOutTime = tickFromFrame(iPunchOut); } unsigned long qtractorSession::punchIn (void) const { return m_iPunchIn; } unsigned long qtractorSession::punchOut (void) const { return m_iPunchOut; } bool qtractorSession::isPunching (void) const { return (m_iPunchIn < m_iPunchOut); } unsigned long qtractorSession::punchInTime (void) const { return m_iPunchInTime; } unsigned long qtractorSession::punchOutTime (void) const { return m_iPunchOutTime; } unsigned long qtractorSession::frameTime (void) const { return m_pAudioEngine->sessionCursor()->frameTime(); } unsigned long qtractorSession::frameTimeEx (void) const { return m_pAudioEngine->sessionCursor()->frameTimeEx(); } // Sanitize a given name. QString qtractorSession::sanitize ( const QString& s ) { return s.simplified().replace(QRegExp("[\\s|\\.|\\-|/]+"), "_"); } // Create a brand new filename (absolute file path). QString qtractorSession::createFilePath ( const QString& sTrackName, const QString& sExt, int iClipNo ) { QString sFilename = qtractorSession::sanitize(m_props.sessionName); if (!sFilename.isEmpty()) sFilename += '-'; sFilename += qtractorSession::sanitize(sTrackName) + "-%1." + sExt; QFileInfo fi; if (iClipNo > 0) { fi.setFile(m_props.sessionDir, sFilename.arg(iClipNo)); } else do { fi.setFile(m_props.sessionDir, sFilename.arg(++iClipNo)); } while (fi.exists()); #ifdef CONFIG_DEBUG qDebug("qtractorSession::createFilePath(\"%s\")", fi.absoluteFilePath().toUtf8().constData()); #endif return fi.absoluteFilePath(); } // Consolidated session record state. void qtractorSession::setRecording ( bool bRecording ) { m_bRecording = bRecording; // For all armed tracks... unsigned long iClipStart = playHead(); if (isPunching()) { unsigned long iPunchIn = punchIn(); if (iClipStart < iPunchIn) iClipStart = iPunchIn; } unsigned long iFrameTime = frameTimeEx(); for (qtractorTrack *pTrack = m_tracks.first(); pTrack; pTrack = pTrack->next()) { if (pTrack->isRecord()) trackRecord(pTrack, bRecording, iClipStart, iFrameTime); } } bool qtractorSession::isRecording (void) const { return m_bRecording; } // Loop-recording/take mode. void qtractorSession::setLoopRecordingMode ( int iLoopRecordingMode ) { m_iLoopRecordingMode = iLoopRecordingMode; } int qtractorSession::loopRecordingMode (void) const { return m_iLoopRecordingMode; } // Loop-recording/take state. bool qtractorSession::isLoopRecording (void) const { return isLooping() && (m_iLoopRecordingMode > 0); } // Immediate track record-arming. void qtractorSession::trackRecord ( qtractorTrack *pTrack, bool bRecord, unsigned long iClipStart, unsigned long iFrameTime ) { #ifdef CONFIG_DEBUG qDebug("qtractorSession::trackRecord(\"%s\", %d, %lu, %lu)", pTrack->trackName().toUtf8().constData(), int(bRecord), iClipStart, iFrameTime); #endif // Just ditch the in-record clip... if (!bRecord) { pTrack->setClipRecord(NULL); // Check whether we set recording off... if (recordTracks() < 1) setRecording(false); // One-down current tracks in record mode. switch (pTrack->trackType()) { case qtractorTrack::Audio: --m_iAudioRecord; break; case qtractorTrack::Midi: --m_iMidiRecord; break; default: break; } #if 0 // Re-sync as appropriate... if (isPlaying()) trackMute(pTrack, false); #endif // Done. return; } switch (pTrack->trackType()) { case qtractorTrack::Audio: { qtractorAudioClip *pAudioClip = new qtractorAudioClip(pTrack); pAudioClip->setClipStart(iClipStart); pAudioClip->openAudioFile( createFilePath(pTrack->trackName(), qtractorAudioFileFactory::defaultExt()), qtractorAudioFile::Write); pTrack->setClipRecord(pAudioClip, iFrameTime); // One-up audio tracks in record mode. ++m_iAudioRecord; break; } case qtractorTrack::Midi: { qtractorMidiClip *pMidiClip = new qtractorMidiClip(pTrack); pMidiClip->setClipStart(iClipStart); pMidiClip->openMidiFile( createFilePath(pTrack->trackName(), "mid"), qtractorMidiClip::defaultFormat(), qtractorMidiFile::Write); pTrack->setClipRecord(pMidiClip, iFrameTime); // MIDI adjust to playing queue start // iif armed while already playing ... if (isPlaying()) { unsigned long iTime = pMidiClip->clipStartTime(); unsigned long iTimeStart = m_pMidiEngine->timeStart(); if (iTime > iTimeStart) pMidiClip->sequence()->setTimeOffset(iTime - iTimeStart); } // One-up MIDI tracks in record mode. ++m_iMidiRecord; break; } default: break; } #if 0 // Mute track as appropriate... if (isPlaying()) trackMute(pTrack, true); #endif } // Immediate track mute (engine indirection). void qtractorSession::trackMute ( qtractorTrack *pTrack, bool bMute ) { // For the time being, only needed for ALSA sequencer... switch (pTrack->trackType()) { case qtractorTrack::Audio: m_pAudioEngine->trackMute(pTrack, bMute); break; case qtractorTrack::Midi: m_pMidiEngine->trackMute(pTrack, bMute); break; case qtractorTrack::None: default: break; } } // Immediate track solo (engine indirection). void qtractorSession::trackSolo ( qtractorTrack *pTrack, bool bSolo ) { // Check if we're going to (un)mute all others, // due to soloing this one; if already soloing, // no need for anything ado... if ((bSolo && m_iSoloTracks > 1) || (!bSolo && m_iSoloTracks > 0)) { trackMute(pTrack, !bSolo); return; } for (qtractorTrack *pTrackMute = m_tracks.first(); pTrackMute; pTrackMute = pTrackMute->next()) { // For all other track, but this one. if (pTrackMute == pTrack || pTrackMute->isMute()) continue; // (Un)mute each other track... trackMute(pTrackMute, bSolo); } } // Track recording specifics. unsigned short qtractorSession::audioRecord (void) const { return m_iAudioRecord; } unsigned short qtractorSession::midiRecord (void) const { return m_iMidiRecord; } // Audio peak factory accessor. qtractorAudioPeakFactory *qtractorSession::audioPeakFactory (void) const { return m_pAudioPeakFactory; } // MIDI track tagging specifics. unsigned short qtractorSession::midiTag (void) const { return m_iMidiTag; } void qtractorSession::acquireMidiTag ( qtractorTrack *pTrack ) { if (pTrack->midiTag() > 0) return; if (m_midiTags.isEmpty()) { pTrack->setMidiTag(++m_iMidiTag); } else { pTrack->setMidiTag(m_midiTags.front()); m_midiTags.pop_front(); } } void qtractorSession::releaseMidiTag ( qtractorTrack *pTrack ) { unsigned short iMidiTag = pTrack->midiTag(); if (iMidiTag > 0) { m_midiTags.push_back(iMidiTag); pTrack->setMidiTag(0); } } // MIDI session/tracks instrument/controller patching (conditional). void qtractorSession::setMidiPatch ( bool bForceImmediate ) { if (!bForceImmediate || m_pMidiEngine->isResetAllControllers()) m_pMidiEngine->resetAllControllers(bForceImmediate); } // MIDI manager list accessors. void qtractorSession::addMidiManager ( qtractorMidiManager *pMidiManager ) { m_midiManagers.append(pMidiManager); } void qtractorSession::removeMidiManager ( qtractorMidiManager *pMidiManager ) { m_midiManagers.remove(pMidiManager); } const qtractorList& qtractorSession::midiManagers (void) const { return m_midiManagers; } // Auto time-stretching global flag (when tempo changes) void qtractorSession::setAutoTimeStretch ( bool bAutoTimeStretch ) { m_bAutoTimeStretch = bAutoTimeStretch; } bool qtractorSession::isAutoTimeStretch (void) const { return m_bAutoTimeStretch; } // Session special process cycle executive. void qtractorSession::process ( qtractorSessionCursor *pSessionCursor, unsigned long iFrameStart, unsigned long iFrameEnd ) { const qtractorTrack::TrackType syncType = pSessionCursor->syncType(); // Now, for every track... int iTrack = 0; qtractorTrack *pTrack = m_tracks.first(); while (pTrack) { // Track automation processing... if (syncType == qtractorTrack::Audio) { qtractorCurveList *pCurveList = pTrack->curveList(); if (pCurveList && pCurveList->isProcess()) pCurveList->process(iFrameStart); } if (syncType == pTrack->trackType()) { pTrack->process(pSessionCursor->clip(iTrack), iFrameStart, iFrameEnd); } pTrack = pTrack->next(); ++iTrack; } } // Session special process record executive (audio recording only). void qtractorSession::process_record ( unsigned long iFrameStart, unsigned long iFrameEnd ) { // Now, for every Audio track... for (qtractorTrack *pTrack = m_tracks.first(); pTrack; pTrack = pTrack->next()) { if (pTrack->trackType() == qtractorTrack::Audio && pTrack->isRecord()) pTrack->process_record(iFrameStart, iFrameEnd); } } // Session special process automation executive. void qtractorSession::process_curve ( unsigned long iFrame ) { // Now, for every track... qtractorTrack *pTrack = m_tracks.first(); while (pTrack) { pTrack->process_curve(iFrame); pTrack = pTrack->next(); } } // Find track of specific curve-list. qtractorTrack *qtractorSession::findTrack ( qtractorCurveList *pCurveList ) const { return m_curves.value(pCurveList, NULL); } // Session files registry accessor. qtractorFileList *qtractorSession::files (void) const { return m_pFiles; } // Document element methods. bool qtractorSession::loadElement ( qtractorSessionDocument *pDocument, QDomElement *pElement ) { qtractorSession::clear(); qtractorSession::lock(); // Templates have no session name... if (!pDocument->isTemplate()) qtractorSession::setSessionName(pElement->attribute("name")); // Session state should be postponed... unsigned long iLoopStart = 0; unsigned long iLoopEnd = 0; unsigned long iPunchIn = 0; unsigned long iPunchOut = 0; // Load session children... for (QDomNode nChild = pElement->firstChild(); !nChild.isNull(); nChild = nChild.nextSibling()) { // Convert node to element... QDomElement eChild = nChild.toElement(); if (eChild.isNull()) continue; // Load session properties... if (eChild.tagName() == "properties") { for (QDomNode nProp = eChild.firstChild(); !nProp.isNull(); nProp = nProp.nextSibling()) { // Convert property node to element... QDomElement eProp = nProp.toElement(); if (eProp.isNull()) continue; if (eProp.tagName() == "directory") qtractorSession::setSessionDir(eProp.text()); else if (eProp.tagName() == "description") qtractorSession::setDescription(eProp.text()); else if (eProp.tagName() == "sample-rate") qtractorSession::setSampleRate(eProp.text().toUInt()); else if (eProp.tagName() == "tempo") qtractorSession::setTempo(eProp.text().toFloat()); else if (eProp.tagName() == "ticks-per-beat") qtractorSession::setTicksPerBeat(eProp.text().toUShort()); else if (eProp.tagName() == "beats-per-bar") qtractorSession::setBeatsPerBar(eProp.text().toUShort()); else if (eProp.tagName() == "beat-divisor") qtractorSession::setBeatDivisor(eProp.text().toUShort()); } // We need to make this permanent, right now. qtractorSession::updateTimeScale(); } else if (eChild.tagName() == "state") { for (QDomNode nState = eChild.firstChild(); !nState.isNull(); nState = nState.nextSibling()) { // Convert state node to element... QDomElement eState = nState.toElement(); if (eState.isNull()) continue; if (eState.tagName() == "loop-start") iLoopStart = eState.text().toULong(); else if (eState.tagName() == "loop-end") iLoopEnd = eState.text().toULong(); else if (eState.tagName() == "punch-in") iPunchIn = eState.text().toULong(); else if (eState.tagName() == "punch-out") iPunchOut = eState.text().toULong(); } } else // Load file lists... if (eChild.tagName() == "files" && !pDocument->isTemplate()) { for (QDomNode nList = eChild.firstChild(); !nList.isNull(); nList = nList.nextSibling()) { // Convert filelist node to element... QDomElement eList = nList.toElement(); if (eList.isNull()) continue; if (eList.tagName() == "audio-list") { qtractorAudioListView *pAudioList = NULL; if (pDocument->files()) pAudioList = pDocument->files()->audioListView(); if (pAudioList == NULL) return false; if (!pAudioList->loadElement(pDocument, &eList)) return false; } else if (eList.tagName() == "midi-list") { qtractorMidiListView *pMidiList = NULL; if (pDocument->files()) pMidiList = pDocument->files()->midiListView(); if (pMidiList == NULL) return false; if (!pMidiList->loadElement(pDocument, &eList)) return false; } } // Stabilize things a bit... stabilize(); } else // Load device lists... if (eChild.tagName() == "devices") { for (QDomNode nDevice = eChild.firstChild(); !nDevice.isNull(); nDevice = nDevice.nextSibling()) { // Convert buses list node to element... QDomElement eDevice = nDevice.toElement(); if (eDevice.isNull()) continue; if (eDevice.tagName() == "audio-engine") { if (!qtractorSession::audioEngine() ->loadElement(pDocument, &eDevice)) { return false; } } else if (eDevice.tagName() == "midi-engine") { if (!qtractorSession::midiEngine() ->loadElement(pDocument, &eDevice)) { return false; } } } // Stabilize things a bit... stabilize(); } else // Load tempo/time-signature map... if (eChild.tagName() == "tempo-map") { for (QDomNode nNode = eChild.firstChild(); !nNode.isNull(); nNode = nNode.nextSibling()) { // Convert tempo node to element... QDomElement eNode = nNode.toElement(); if (eNode.isNull()) continue; // Load tempo-map... if (eNode.tagName() == "tempo-node") { unsigned long iFrame = eNode.attribute("frame").toULong(); float fTempo = 120.0f; unsigned short iBeatType = 2; unsigned short iBeatsPerBar = 4; unsigned short iBeatDivisor = 2; for (QDomNode nItem = eNode.firstChild(); !nItem.isNull(); nItem = nItem.nextSibling()) { // Convert node to element... QDomElement eItem = nItem.toElement(); if (eItem.isNull()) continue; if (eItem.tagName() == "tempo") fTempo = eItem.text().toFloat(); else if (eItem.tagName() == "beat-type") iBeatType = eItem.text().toUShort(); else if (eItem.tagName() == "beats-per-bar") iBeatsPerBar = eItem.text().toUShort(); else if (eItem.tagName() == "beat-divisor") iBeatDivisor = eItem.text().toUShort(); } // Add new node to tempo/time-signature map... qtractorSession::timeScale()->addNode(iFrame, fTempo, iBeatType, iBeatsPerBar, iBeatDivisor); } } // Again, make view/time scaling factors permanent. qtractorSession::updateTimeScale(); } else // Load location markers... if (eChild.tagName() == "markers") { for (QDomNode nMarker = eChild.firstChild(); !nMarker.isNull(); nMarker = nMarker.nextSibling()) { // Convert tempo node to element... QDomElement eMarker = nMarker.toElement(); if (eMarker.isNull()) continue; // Load markers... if (eMarker.tagName() == "marker") { unsigned long iFrame = eMarker.attribute("frame").toULong(); QString sText; QColor rgbColor = Qt::darkGray; for (QDomNode nItem = eMarker.firstChild(); !nItem.isNull(); nItem = nItem.nextSibling()) { // Convert node to element... QDomElement eItem = nItem.toElement(); if (eItem.isNull()) continue; if (eItem.tagName() == "text") sText = eItem.text(); else if (eItem.tagName() == "color") rgbColor.setNamedColor(eItem.text()); } // Add new marker... if (!sText.isEmpty()) { qtractorSession::timeScale()->addMarker( iFrame, sText, rgbColor); } } } } else // Load tracks... if (eChild.tagName() == "tracks") { for (QDomNode nTrack = eChild.firstChild(); !nTrack.isNull(); nTrack = nTrack.nextSibling()) { // Convert track node to element... QDomElement eTrack = nTrack.toElement(); if (eTrack.isNull()) continue; // Load track-view state... if (eTrack.tagName() == "view") { for (QDomNode nView = eTrack.firstChild(); !nView.isNull(); nView = nView.nextSibling()) { // Convert state node to element... QDomElement eView = nView.toElement(); if (eView.isNull()) continue; if (eView.tagName() == "pixels-per-beat") qtractorSession::setPixelsPerBeat(eView.text().toUShort()); else if (eView.tagName() == "horizontal-zoom") qtractorSession::setHorizontalZoom(eView.text().toUShort()); else if (eView.tagName() == "vertical-zoom") qtractorSession::setVerticalZoom(eView.text().toUShort()); else if (eView.tagName() == "snap-per-beat") qtractorSession::setSnapPerBeat(eView.text().toUShort()); else if (eView.tagName() == "edit-head") qtractorSession::setEditHead(eView.text().toULong()); else if (eView.tagName() == "edit-tail") qtractorSession::setEditTail(eView.text().toULong()); } // Again, make view/time scaling factors permanent. qtractorSession::updateTimeScale(); } else // Load track... if (eTrack.tagName() == "track") { qtractorTrack *pTrack = new qtractorTrack(this); if (!pTrack->loadElement(pDocument, &eTrack)) return false; qtractorSession::addTrack(pTrack); } } // Stabilize things a bit... stabilize(); } } // Just stabilize things around. qtractorSession::updateSession(); // Check whether some deferred state needs to be set... if (iLoopStart < iLoopEnd) qtractorSession::setLoop(iLoopStart, iLoopEnd); if (iPunchIn < iPunchOut) qtractorSession::setPunch(iPunchIn, iPunchOut); qtractorSession::unlock(); return true; } bool qtractorSession::saveElement ( qtractorSessionDocument *pDocument, QDomElement *pElement ) { // Templates should have no session name... if (!pDocument->isTemplate()) pElement->setAttribute("name", qtractorSession::sessionName()); pElement->setAttribute("version", PACKAGE_STRING); // Save session properties... QDomElement eProps = pDocument->document()->createElement("properties"); if (!pDocument->isArchive()) { pDocument->saveTextElement("directory", qtractorSession::sessionDir(), &eProps); } pDocument->saveTextElement("description", qtractorSession::description(), &eProps); pDocument->saveTextElement("sample-rate", QString::number(qtractorSession::sampleRate()), &eProps); pDocument->saveTextElement("tempo", QString::number(qtractorSession::tempo()), &eProps); pDocument->saveTextElement("ticks-per-beat", QString::number(qtractorSession::ticksPerBeat()), &eProps); pDocument->saveTextElement("beats-per-bar", QString::number(qtractorSession::beatsPerBar()), &eProps); pDocument->saveTextElement("beat-divisor", QString::number(qtractorSession::beatDivisor()), &eProps); pElement->appendChild(eProps); // Save session state... QDomElement eState = pDocument->document()->createElement("state"); pDocument->saveTextElement("loop-start", QString::number(qtractorSession::loopStart()), &eState); pDocument->saveTextElement("loop-end", QString::number(qtractorSession::loopEnd()), &eState); pDocument->saveTextElement("punch-in", QString::number(qtractorSession::punchIn()), &eState); pDocument->saveTextElement("punch-out", QString::number(qtractorSession::punchOut()), &eState); pElement->appendChild(eState); // Files are not saved when in template mode... if (!pDocument->isTemplate()) { // Save file lists... QDomElement eFiles = pDocument->document()->createElement("files"); // Audio files... QDomElement eAudioList = pDocument->document()->createElement("audio-list"); qtractorAudioListView *pAudioList = NULL; if (pDocument->files()) pAudioList = pDocument->files()->audioListView(); if (pAudioList == NULL) return false; if (!pAudioList->saveElement(pDocument, &eAudioList)) return false; eFiles.appendChild(eAudioList); // MIDI files... QDomElement eMidiList = pDocument->document()->createElement("midi-list"); qtractorMidiListView *pMidiList = NULL; if (pDocument->files()) pMidiList = pDocument->files()->midiListView(); if (pMidiList == NULL) return false; if (!pMidiList->saveElement(pDocument, &eMidiList)) return false; eFiles.appendChild(eMidiList); pElement->appendChild(eFiles); } // Save device lists... QDomElement eDevices = pDocument->document()->createElement("devices"); // Audio engine... QDomElement eAudioEngine = pDocument->document()->createElement("audio-engine"); if (!qtractorSession::audioEngine()->saveElement(pDocument, &eAudioEngine)) return false; eDevices.appendChild(eAudioEngine); // MIDI engine... QDomElement eMidiEngine = pDocument->document()->createElement("midi-engine"); if (!qtractorSession::midiEngine()->saveElement(pDocument, &eMidiEngine)) return false; eDevices.appendChild(eMidiEngine); pElement->appendChild(eDevices); // Save tempo/time-signature, if any... qtractorTimeScale::Node *pNode = qtractorSession::timeScale()->nodes().first(); if (pNode) pNode = pNode->next(); // Skip first anchor node. if (pNode) { QDomElement eTempoMap = pDocument->document()->createElement("tempo-map"); while (pNode) { QDomElement eNode = pDocument->document()->createElement("tempo-node"); eNode.setAttribute("bar", QString::number(pNode->bar)); eNode.setAttribute("frame", QString::number(pNode->frame)); pDocument->saveTextElement("tempo", QString::number(pNode->tempo), &eNode); pDocument->saveTextElement("beat-type", QString::number(pNode->beatType), &eNode); pDocument->saveTextElement("beats-per-bar", QString::number(pNode->beatsPerBar), &eNode); pDocument->saveTextElement("beat-divisor", QString::number(pNode->beatDivisor), &eNode); eTempoMap.appendChild(eNode); pNode = pNode->next(); } pElement->appendChild(eTempoMap); } // Save location markers, if any... qtractorTimeScale::Marker *pMarker = qtractorSession::timeScale()->markers().first(); if (pMarker) { QDomElement eMarkers = pDocument->document()->createElement("markers"); while (pMarker) { QDomElement eMarker = pDocument->document()->createElement("marker"); eMarker.setAttribute("frame", QString::number(pMarker->frame)); pDocument->saveTextElement("text", pMarker->text, &eMarker); pDocument->saveTextElement("color", pMarker->color.name(), &eMarker); eMarkers.appendChild(eMarker); pMarker = pMarker->next(); } pElement->appendChild(eMarkers); } // Save track view state... QDomElement eTracks = pDocument->document()->createElement("tracks"); QDomElement eView = pDocument->document()->createElement("view"); pDocument->saveTextElement("pixels-per-beat", QString::number(qtractorSession::pixelsPerBeat()), &eView); pDocument->saveTextElement("horizontal-zoom", QString::number(qtractorSession::horizontalZoom()), &eView); pDocument->saveTextElement("vertical-zoom", QString::number(qtractorSession::verticalZoom()), &eView); pDocument->saveTextElement("snap-per-beat", QString::number(qtractorSession::snapPerBeat()), &eView); pDocument->saveTextElement("edit-head", QString::number(qtractorSession::editHead()), &eView); pDocument->saveTextElement("edit-tail", QString::number(qtractorSession::editTail()), &eView); eTracks.appendChild(eView); // Save session tracks... for (qtractorTrack *pTrack = qtractorSession::tracks().first(); pTrack; pTrack = pTrack->next()) { // Create the new track element... QDomElement eTrack = pDocument->document()->createElement("track"); if (!pTrack->saveElement(pDocument, &eTrack)) return false; // Add this slot... eTracks.appendChild(eTrack); } pElement->appendChild(eTracks); return true; } // end of qtractorSession.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorThumbView.h0000644000175000001440000000012312157363737021124 xustar000000000000000027 mtime=1371400159.163352 26 atime=1381134667.31608 30 ctime=1381134667.316080054 qtractor-0.5.11/src/qtractorThumbView.h0000644000175000001440000000522412157363737020416 0ustar00rncbcusers00000000000000// qtractorThumbView.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorThumbView_h #define __qtractorThumbView_h #include // Forward declarations. class qtractorRubberBand; class QPaintEvent; class QResizeEvent; class QMouseEvent; class QKeyEvent; //------------------------------------------------------------------------- // qtractorThumbView -- Session track line thumb view. class qtractorThumbView : public QFrame { Q_OBJECT public: // Constructor. qtractorThumbView(QWidget *pParent = 0); // Update playhead-position. void updatePlayHead(unsigned long iPlayHead); // (Re)create the complete view pixmap. void updateContents(); public slots: // Update thumb-position. void updateThumb(int dx = 0); protected: // Update view-position. void updateView(int dx); // Set playhead-position (indirect). void setPlayHeadX(int iPlayHeadX); // Session track-line paint method. void paintEvent(QPaintEvent *pPaintEvent); // Session track-line paint method. void resizeEvent(QResizeEvent *pResizeEvent); // Handle selection with mouse. void mousePressEvent(QMouseEvent *pMouseEvent); void mouseMoveEvent(QMouseEvent *pMouseEvent); void mouseReleaseEvent(QMouseEvent *pMouseEvent); // Reset drag state. void resetDragState(); // Keyboard event handler. void keyPressEvent(QKeyEvent *pKeyEvent); private: // Local double-buffering pixmap. QPixmap m_pixmap; // Local contents length (in frames). unsigned long m_iContentsLength; // Local playhead positioning. int m_iPlayHeadX; // The thumb rubber-band widget. qtractorRubberBand *m_pRubberBand; // Thumb drag-states. enum { DragNone = 0, DragStart, DragMove, DragClick } m_dragState; QPoint m_posDrag; }; #endif // __qtractorThumbView_h // end of qtractorThumbView.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioConnect.h0000644000175000001440000000012311563576072021563 xustar000000000000000027 mtime=1305410618.253123 26 atime=1381134667.43608 30 ctime=1381134667.436080056 qtractor-0.5.11/src/qtractorAudioConnect.h0000644000175000001440000001042311563576072021052 0ustar00rncbcusers00000000000000// qtractorAudioConnect.h // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorAudioConnect_h #define __qtractorAudioConnect_h #include "qtractorConnect.h" #include // Forward declarations. class qtractorAudioPortItem; class qtractorAudioClientItem; class qtractorAudioClientListView; class qtractorAudioConnect; //---------------------------------------------------------------------- // qtractorAudioPortItem -- Jack port list item. // class qtractorAudioPortItem : public qtractorPortListItem { public: // Constructor. qtractorAudioPortItem(qtractorAudioClientItem *pClientItem, const QString& sPortName, jack_port_t *pJackPort); // Default destructor. ~qtractorAudioPortItem(); // Jack handles accessors. jack_client_t *jackClient() const; jack_port_t *jackPort() const; private: // Instance variables. jack_port_t *m_pJackPort; }; //---------------------------------------------------------------------- // qtractorAudioClientItem -- Jack client list item. // class qtractorAudioClientItem : public qtractorClientListItem { public: // Constructor. qtractorAudioClientItem(qtractorAudioClientListView *pClientListView, const QString& sClientName); // Default destructor. ~qtractorAudioClientItem(); // Jack client accessors. jack_client_t *jackClient() const; }; //---------------------------------------------------------------------- // qtractorAudioClientListView -- Jack client list view. // class qtractorAudioClientListView : public qtractorClientListView { public: // Constructor. qtractorAudioClientListView(QWidget *pParent = NULL); // Default destructor. ~qtractorAudioClientListView(); // Jack connect accessors. jack_client_t *jackClient() const; // Client:port refreshner (return newest item count). int updateClientPorts(); }; //---------------------------------------------------------------------------- // qtractorAudioConnect -- Connections model integrated object. // class qtractorAudioConnect : public qtractorConnect { public: // Constructor. qtractorAudioConnect( qtractorAudioClientListView *pOListView, qtractorAudioClientListView *pIListView, qtractorConnectorView *pConnectorView); // Default destructor. ~qtractorAudioConnect(); // JACK client accessors. jack_client_t *jackClient() const; // Icon-set array indexes. enum { ClientIn = 0, // Input client item icon. ClientOut = 1, // Output client item icon. PortIn = 2, // Input port item icon. PortOut = 3, // Output port item icon. PortPhysIn = 4, // Physical input port item icon. PortPhysOut = 5, // Physical output port item icon., IconCount = 6 // Number of icons in local array. }; // Common icon accessor. static const QIcon& icon (int iIcon); protected: // Virtual Connect/Disconnection primitives. bool connectPorts(qtractorPortListItem *pOPort, qtractorPortListItem *pIPort); bool disconnectPorts(qtractorPortListItem *pOPort, qtractorPortListItem *pIPort); // Update port connection references. void updateConnections(); // Update (clear) Audio-buses connect lists (non-virtual). void disconnectPortsUpdate( qtractorPortListItem *pOPort, qtractorPortListItem *pIPort); private: // Local pixmap-set janitor methods. void createIcons(); void deleteIcons(); // Local pixmap-set array. static QIcon *g_apIcons[IconCount]; static int g_iIconsRefCount; }; #endif // __qtractorAudioConnect_h // end of qtractorAudioConnect.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMainForm.ui0000644000175000001440000000012312164325352021075 xustar000000000000000027 mtime=1372695274.495194 26 atime=1381134670.92908 30 ctime=1381134670.930080111 qtractor-0.5.11/src/qtractorMainForm.ui0000644000175000001440000024240512164325352020373 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorMainForm 0 0 800 600 320 240 true Qtractor :/images/qtractor.png Qt::Horizontal 4 Qt::Horizontal 4 Qt::Horizontal 4 Qt::Horizontal 4 Qt::Horizontal 4 Qt::Horizontal 4 Qt::Horizontal 4 Qt::Horizontal 4 0 0 683 30 &File Open &Recent &Edit Select &Mode &Select I&nsert Remo&ve &Track &State &Navigate Mo&ve &Height Impor&t Tracks E&xport Tracks &Select M&ode A&utomation Cl&ip T&ools Ta&ke &Select &View &Toolbars &Windows :/images/viewZoomTool.png &Zoom S&nap T&ransport &Help :/images/fileNew.png &New New New session New session file Ctrl+N :/images/fileOpen.png &Open... Open Open session Open session from file Ctrl+O :/images/fileSave.png &Save Save Save session Save session to file Ctrl+S Save &As... Save As Save as Save current session with another file name &Properties... Session Properties Session properties Edit current session properties F2 E&xit Exit Exit Exit this application program :/images/editUndo.png &Undo Undo Undo Undo last action Ctrl+Z :/images/editRedo.png &Redo Redo Redo Redo last action Ctrl+Shift+Z :/images/editCut.png Cu&t Cut Cut Cut selection to clipboard Ctrl+X :/images/editCopy.png &Copy Copy Copy Copy selection to clipboard Ctrl+C :/images/editPaste.png &Paste Paste Paste Paste clipboard contents Ctrl+V Past&e Repeat... Paste Repeat Paste repeat Paste/repeat clipboard contents Ctrl+Shift+V :/images/editDelete.png &Delete Delete Delete Delete selection Del true :/images/editSelectClip.png &Clip Clip Select clip Clip selection mode true :/images/editSelectRange.png &Range Range Select range Range selection mode true :/images/editSelectRect.png R&ectangle Rect Select rectangle Rectangular selection mode true :/images/editSelectCurve.png &Automation Automation Automation Automation edit mode &All Select All Select all Mark all as selected Ctrl+A &None Select None Select none Mark all as unselected Ctrl+Shift+A &Invert Select Invert Select invert Invert selection Ctrl+I &Track Select Track Select track Mark track as selected Ctrl+T Trac&k Range Select Track Range Select track range Mark track range as selected Ctrl+Shift+R &Range Select Range Select range Mark range as selected Ctrl+R &Range... Remove Range Remove range Remove range as selected Ctrl+Del Trac&k Range Remove Track Range Remove track range Remove track range as selected Ctrl+Shift+Del &Range... Insert Range Insert range Insert range as selected Ctrl+Ins Trac&k Range Insert Track Range Insert track range Insert track range as selected Ctrl+Shift+Ins Sp&lit Split Selection Split selection Split current selection Ctrl+Y :/images/trackAdd.png &Add Track... Add Track Add track Add a new track to session Shift+Ins :/images/trackRemove.png &Remove Track Remove Track Remove track Remove current track from session Shift+Del :/images/trackProperties.png Track &Properties... Track Properties Track properties Edit current track properties Shift+F2 &Inputs Track Inputs Track inputs Show current track input bus connections &Outputs Track Outputs Track outputs Show current track output bus connections true &Record Record Track Record track Arm current track for recording true &Mute Mute Track Mute track Mute current track true &Solo Solo Track Solo track Solo current track true M&onitor Monitor Track Monitor track Monitor current track &First First Track First track Make current the first track &Previous Previous Track Previous track Make current the previous track &Next Next Track Next track Make current the next track &Last Last Track Last track Make current the last track N&one None Track None track None current track &Top Move Top Move top Move current track to top &Up Move Up Move up Move current track up &Down Move Down Move down Move current track down &Bottom Move Bottom Move bottom Move current track to bottom &Increase Increase Height Increase height Increase track height Ctrl+Shift++ &Decrease Decrease Height Decrease height Decrease track height Ctrl+Shift+- &Reset Height Reset Height reset Reset track height Ctrl+Shift+1 true Auto &Monitor Auto Monitor Auto monitor Auto-monitor current track F6 :/images/trackAudio.png &Audio... Inport Audio File Import Audio file Import tracks from Audio file :/images/trackMidi.png &MIDI... Import MIDI File Import MIDI file Import tracks from MIDI file :/images/trackAudio.png &Audio... Export Audio File Export Audio file Export tracks to Audio file :/images/trackMidi.png &MIDI... Export MIDI File Export MIDI file Export tracks to MIDI file true Log&arithmic Automation logarithmic Automation logarithmic Automation curve logarithmic scale :/images/formColor.png C&olor... Automation color Automation color Automation curve color true &Lock Automation lock Automation lock Lock automation curve :/images/trackCurveProcess.png :/images/trackCurveEnabled.png :/images/trackCurveNone.png true &Play Automation playback Automation playback Playback automation curve :/images/trackCurveCapture.png :/images/trackCurveEnabled.png :/images/trackCurveNone.png true &Record Automation record Automation record Record automation curve &Clear Automation clear Automation clear Clear automation curve true Loc&k All Automation lock all Automation lock all Lock all automation curves true Play &All Automation playback all Automation playback all Playback all automation curves true Rec&ord All Automation record all Automation record all Record all automation curves C&lear All Automation clear all Automation clear all Clear all automation curves :/images/clipNew.png &New... New Clip New clip Create new clip :/images/clipEdit.png &Edit... Edit Clip Edit clip Edit current clip F4 &Unlink Unlink Clip Unlink clip Unlink current clip &Split Split Clip Split clip Split current clip at playhead &Merge... Merge Clips Merge clips Merge selected clips N&ormalize Normalize Clip Normalize clip Normalize current clip (gain/volume) &Quantize... Quantize Clip Quantize clip events Quantize current MIDI clip events &Transpose... Transpose Clip Transpose clip events Transpose current MIDI clip events &Normalize... Normalize Clip Normalize clip events Normalize current MIDI clip events &Randomize... Randomize Clip Randomize clip events Randomize current MIDI clip events Resi&ze... Resize Clip Resize clip events Resize current MIDI clip events Re&scale... Rescale Clip Rescale clip events Rescale current MIDI clip events T&imeshift... Timeshift Clip Timeshift clip events Timeshift current MIDI clip events &Tempo... Tempo Adjust Tempo Adjust Adjust session tempo from current clip selection F7 &Range Set Clip Range Clip range Set edit-range from current clip extents &Loop Set Clip Loop Clip loop Set loop-range from current clip extents &Import... Import Clip Import clip Import clip from file(s) E&xport... Export Clip Export clip Export current clip to file &First First Take First take Select current clip first take &Previous Previous Take Previous take Select current clip previous take &Next Next Take Next take Select current clip next take Shift+T &Last Last Take Last take Select current clip last take &Reset Reset Takes Reset takes Reset (unfold) current clip takes R&ange... Take Range Take range Range (fold) current clip into takes true &Menubar Menubar Menubar Show/hide the main program window menubar Ctrl+M true &Statusbar Statusbar Statusbar Show/hide the main program window statusbar true &File File Toolbar File toolbar Show/hide main program window file toolbar true &Edit Edit Toolbar Edit toolbar Show/hide main program window edit toolbar true &Track Track Toolbar Track toolbar Show/hide main program window track toolbar true &View View Toolbar View toolbar Show/hide main program window view toolbar true &Options Options Toolbar Options toolbar Show/hide main program window options toolbar true T&ransport Transport Toolbar Transport toolbar Show/hide main program window transport toolbar true T&ime Time Toolbar Time toolbar Show/hide main program window time toolbar true Thum&b Thumb Toolbar Thumb toolbar Show/hide main program window thumb toolbar true :/images/viewFiles.png &Files Files Files Show/hide the files window true :/images/viewMessages.png M&essages Messages Messages Show/hide the messages window true :/images/viewConnections.png &Connections Connections Connections Show/hide the connections window F8 true :/images/viewMixer.png Mi&xer Mixer Mixer Show/hide the mixer window F9 :/images/viewZoomIn.png &In Zoom In Zoom in Zoom in Ctrl++ :/images/viewZoomOut.png &Out Zoom Out Zoom out Zoom out Ctrl+- &Reset Zoom Reset Zoom reset Zoom reset Ctrl+1 true &Horizontal Horizontal Zoom Horizontal zoom Horizontal zoom mode true &Vertical Vertical Zoom Vertical zoom Vertical zoom mode true &All All Zoom All zoom All zoom mode true &Grid Grid Grid Snap grid view mode true &Zebra Zebra Zebra Bar zebra view mode true Too&l Tips Tool tips Tool tips Floating tool tips view mode &Refresh Refresh Refresh Refresh views F5 :/images/itemInstrument.png &Instruments... Instruments Instruments Change instrument definitions and files :/images/itemControllers.png &Controllers... Controllers Controllers Change MIDI controllers configuration &Buses... Buses Buses Change session bus definitions Tempo M&ap / Markers... Tempo Map / Markers Tempo map / markers Change session tempo map / markers &Options... Options Options Change general application program options F12 :/images/transportBackward.png &Backward Backward Backward Transport backward Backspace true :/images/transportRewind.png Re&wind Rewind Rewind Transport rewind true :/images/transportFastForward.png F&ast Forward Fast Forward Fast forward Transport fast forward :/images/transportForward.png &Forward Forward Forward Transport forward true :/images/transportLoop.png &Loop Loop Loop Transport loop Ctrl+Shift+L Loop &Set Loop Set Loop set Transport loop set Ctrl+L :/images/transportStop.png &Stop Stop Stop Transport stop true :/images/transportPlay.png &Play Play Play Transport play/pause Space true :/images/transportRecord.png &Record Record Record Transport record true :/images/transportPunch.png &Punch Punch Punch in/out Transport punch in/out Ctrl+Shift+P Punch Se&t Punch Set Punch in/out set Transport punch in/out set Ctrl+P true :/images/transportMetro.png &Metronome Metronome Metronome Metronome true :/images/transportFollow.png F&ollow Playhead Follow Playhead Follow playhead Follow playhead true :/images/transportAutoBackward.png A&uto Backward Auto Backward Auto backward Auto backward true :/images/transportContinue.png &Continue Past End Continue Past End Continue past end Continue past end :/images/transportPanic.png Pa&nic Panic Panic All MIDI tracks shut off (panic) :/images/helpShortcuts.png &Shortcuts... Shortcuts Shortcuts Keyboard shortcuts &About... About About Show information about this application program About &Qt... About Qt About Qt Show information about the Qt toolkit qtractor-0.5.11/src/PaxHeaders.10084/qtractorFifoBuffer.h0000644000175000001440000000007011010062567021210 xustar000000000000000026 atime=1381134667.96608 30 ctime=1381134667.966080064 qtractor-0.5.11/src/qtractorFifoBuffer.h0000644000175000001440000001766511010062567020515 0ustar00rncbcusers00000000000000// qtractorFifoBuffer.h // /**************************************************************************** Copyright (C) 2005-2008, rncbc aka Rui Nuno Capela. All rights reserved. Adapted and refactored from the SoundTouch library (L)GPL, Copyright (C) 2001-2006, Olli Parviainen. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorFifoBuffer_h #define __qtractorFifoBuffer_h #include #include #include //---------------------------------------------------------------------- // class qtractorFifoBuffer -- FIFO buffer/cache template declaration. // template class qtractorFifoBuffer { public: // Constructor. qtractorFifoBuffer(unsigned short iChannels = 2); // Destructor. ~qtractorFifoBuffer(); // Implementation initializer. void setChannels(unsigned short iChannels); // Implementation properties. unsigned short channels() const { return m_iChannels; } unsigned int bufferSize() const { return m_iBufferSize; } // Write samples/frames to the end of sample frame buffer. unsigned int writeFrames( T **ppFrames, unsigned int iFrames, unsigned int iOffset = 0); // Adjusts the book-keeping to increase number of frames // in the buffer without copying any actual frames. void putFrames( T **ppFrames, unsigned int iFrames, unsigned iOffset = 0); void putFrames(unsigned int iFrames); // Read frames from beginning of the sample buffer. unsigned int readFrames( T **ppFrames, unsigned int iFrames, unsigned int iOffset = 0) const; // Adjusts book-keeping so that given number of frames are removed // from beginning of the sample buffer without copying them anywhere. unsigned int receiveFrames( T **ppFrames, unsigned int iFrames, unsigned iOffset = 0); unsigned int receiveFrames(unsigned int iFrames); // Returns number of frames currently available. unsigned int frames() const { return m_iFrameCount; } // Returns a pointer to the beginning of the output samples. T *ptrBegin(unsigned short iChannel) const { return m_ppBuffer[iChannel] + m_iFramePos; } // Returns a pointer to the end of the used part of the sample buffer. T *ptrEnd(unsigned short iChannel) const { return m_ppBuffer[iChannel] + m_iFramePos + m_iFrameCount; } // Returns nonzero if there aren't any frames available. bool isEmpty() const { return (m_iFrameCount == 0); } // Clears all the buffers. void clear() { m_iFrameCount = m_iFramePos = 0; } // Ensures that the buffer has capacity for at least this many frames. void ensureCapacity(const unsigned int iSlackCapacity); private: unsigned short m_iChannels; T **m_ppBuffer; T **m_ppBufferUnaligned; unsigned int m_iBufferSize; unsigned int m_iFrameCount; unsigned int m_iFramePos; }; //---------------------------------------------------------------------- // class qtractorFifoBuffer -- FIFO buffer/cache method implementation. // // Constructor. template qtractorFifoBuffer::qtractorFifoBuffer ( unsigned short iChannels ) : m_iChannels(0), m_ppBuffer(NULL), m_ppBufferUnaligned(NULL), m_iFrameCount(0), m_iFramePos(0) { setChannels(iChannels); } // Destructor. template qtractorFifoBuffer::~qtractorFifoBuffer (void) { if (m_ppBufferUnaligned) { for (unsigned short i = 0; i < m_iChannels; ++i) delete [] m_ppBufferUnaligned[i]; delete [] m_ppBufferUnaligned; } if (m_ppBuffer) delete [] m_ppBuffer; } // Sets number of channels, 1=mono, 2=stereo, ... template void qtractorFifoBuffer::setChannels ( unsigned short iChannels ) { if (m_iChannels == iChannels) return; m_iChannels = iChannels; m_iBufferSize = 0; ensureCapacity(1024); } // Read frames from beginning of the sample buffer. template unsigned int qtractorFifoBuffer::readFrames ( T **ppFrames, unsigned int iFrames, unsigned int iOffset ) const { unsigned int iMaxFrames = (iFrames > m_iFrameCount ? m_iFrameCount : iFrames); for (unsigned short i = 0; i < m_iChannels; ++i) ::memcpy(ppFrames[i], ptrBegin(i) + iOffset, iMaxFrames * sizeof(T)); return iMaxFrames; } // Adjusts book-keeping so that given number of frames are removed // from beginning of the sample buffer without copying them anywhere. // // Used to reduce the number of samples in the buffer when accessing // the sample buffer directly with ptrBegin() function. template unsigned int qtractorFifoBuffer::receiveFrames ( T **ppFrames, unsigned int iFrames, unsigned int iOffset ) { return receiveFrames(readFrames(ppFrames, iFrames, iOffset)); } template unsigned int qtractorFifoBuffer::receiveFrames ( unsigned int iFrames ) { if (iFrames >= m_iFrameCount) { unsigned int iFrameCount = m_iFrameCount; m_iFrameCount = 0; return iFrameCount; } m_iFrameCount -= iFrames; m_iFramePos += iFrames; return iFrames; } // Write samples/frames to the end of sample frame buffer. template unsigned int qtractorFifoBuffer::writeFrames ( T **ppFrames, unsigned int iFrames, unsigned int iOffset ) { ensureCapacity(iFrames); for (unsigned short i = 0; i < m_iChannels; ++i) ::memcpy(ptrEnd(i), ppFrames[i] + iOffset, iFrames * sizeof(T)); return iFrames; } // Adjusts the book-keeping to increase number of frames // in the buffer without copying any actual frames. // // This function is used to update the number of frames in the // sample buffer when accessing the buffer directly with ptrEnd() // function. Please be careful though. template void qtractorFifoBuffer::putFrames ( T **ppFrames, unsigned int iFrames, unsigned int iOffset ) { m_iFrameCount += writeFrames(ppFrames, iFrames, iOffset); } template void qtractorFifoBuffer::putFrames ( unsigned int iFrames ) { ensureCapacity(iFrames); m_iFrameCount += iFrames; } // Ensures that the buffer has capacity for at least this many frames. template void qtractorFifoBuffer::ensureCapacity ( const unsigned int iSlackCapacity ) { unsigned int iBufferSize = m_iFramePos + m_iFrameCount + (iSlackCapacity << 2); if (iBufferSize > m_iBufferSize) { // Enlarge the buffer in 4KB steps (round up to next 4KB boundary) unsigned int iSizeInBytes = ((iBufferSize << 1) * sizeof(T) + 4095) & -4096; // assert(iSizeInBytes % 2 == 0); float **ppTemp = new T * [m_iChannels]; float **ppTempUnaligned = new T * [m_iChannels]; m_iBufferSize = (iSizeInBytes / sizeof(T)) + (16 / sizeof(T)); for (unsigned short i = 0; i < m_iChannels; ++i) { ppTempUnaligned[i] = new T [m_iBufferSize]; ppTemp[i] = (T *) (((unsigned long) ppTempUnaligned[i] + 15) & -16); if (m_ppBuffer) { if (m_iFrameCount > 0) { ::memcpy(ppTemp[i], ptrBegin(i), m_iFrameCount * sizeof(T)); } delete [] m_ppBufferUnaligned[i]; } } if (m_ppBuffer) { delete [] m_ppBufferUnaligned; delete [] m_ppBuffer; } m_ppBufferUnaligned = ppTempUnaligned; m_ppBuffer = ppTemp; // Done realloc. m_iFramePos = 0; } else if (m_iFramePos > (m_iBufferSize >> 2)) { // Rewind the buffer by moving data... if (m_iFrameCount > 0) { for (unsigned short i = 0; i < m_iChannels; ++i) { ::memmove(m_ppBuffer[i], ptrBegin(i), m_iFrameCount * sizeof(T)); } } // Done rewind. m_iFramePos = 0; } } #endif // __qtractorFifoBuffer_h // end of qtractorFifoBuffer.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorPropertyCommand.h0000644000175000001440000000006710733016504022325 xustar000000000000000026 atime=1381134670.87608 29 ctime=1381134670.87608011 qtractor-0.5.11/src/qtractorPropertyCommand.h0000644000175000001440000000334210733016504021607 0ustar00rncbcusers00000000000000// qtractorPropertyCommand.h // /**************************************************************************** Copyright (C) 2005-2007, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorPropertyCommand_h #define __qtractorPropertyCommand_h #include "qtractorCommand.h" //---------------------------------------------------------------------- // class qtractorPropertyCommand - template declaration. // template class qtractorPropertyCommand : public qtractorCommand { public: // Constructor. qtractorPropertyCommand(const QString& sName, T& ref, const T& val) : qtractorCommand(sName), m_ref(ref), m_val(val) {} // Cannonical command methods. bool redo() { T val = m_ref; m_ref = m_val; m_val = val; return true; } bool undo() { return qtractorPropertyCommand::redo(); } private: // Instance variables. T& m_ref; T m_val; }; #endif // __qtractorPropertyCommand_h // end of qtractorPropertyCommand.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorTrackView.cpp0000644000175000001440000000012312223511102021413 xustar000000000000000027 mtime=1380880962.062114 26 atime=1381134667.83008 30 ctime=1381134667.831080062 qtractor-0.5.11/src/qtractorTrackView.cpp0000644000175000001440000042364612223511102020721 0ustar00rncbcusers00000000000000// qtractorTrackView.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorTrackView.h" #include "qtractorTrackTime.h" #include "qtractorTrackList.h" #include "qtractorSession.h" #include "qtractorTracks.h" #include "qtractorFiles.h" #include "qtractorAudioClip.h" #include "qtractorAudioFile.h" #include "qtractorMidiClip.h" #include "qtractorMidiFile.h" #include "qtractorSessionCursor.h" #include "qtractorFileListView.h" #include "qtractorClipSelect.h" #include "qtractorCurveSelect.h" #include "qtractorOptions.h" #include "qtractorClipCommand.h" #include "qtractorCurveCommand.h" #include "qtractorMainForm.h" #include "qtractorThumbView.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #include #endif //---------------------------------------------------------------------------- // qtractorTrackView::ClipBoard - Local clipaboard singleton. // Singleton declaration. qtractorTrackView::ClipBoard qtractorTrackView::g_clipboard; //---------------------------------------------------------------------------- // qtractorTrackView -- Track view widget. // Constructor. qtractorTrackView::qtractorTrackView ( qtractorTracks *pTracks, QWidget *pParent ) : qtractorScrollView(pParent) { m_pTracks = pTracks; m_pClipSelect = new qtractorClipSelect(); m_pCurveSelect = new qtractorCurveSelect(); m_pSessionCursor = NULL; m_pRubberBand = NULL; m_selectMode = SelectClip; m_bDropSpan = true; m_bSnapZebra = true; m_bSnapGrid = true; m_bToolTips = true; m_bCurveEdit = false; m_pCurveEditCommand = NULL; clear(); // Zoom tool widgets m_pHzoomIn = new QToolButton(this); m_pHzoomOut = new QToolButton(this); m_pVzoomIn = new QToolButton(this); m_pVzoomOut = new QToolButton(this); m_pXzoomReset = new QToolButton(this); const QIcon& iconZoomIn = QIcon(":/images/viewZoomIn.png"); m_pHzoomIn->setIcon(iconZoomIn); m_pVzoomIn->setIcon(iconZoomIn); const QIcon& iconZoomOut = QIcon(":/images/viewZoomOut.png"); m_pHzoomOut->setIcon(iconZoomOut); m_pVzoomOut->setIcon(iconZoomOut); m_pXzoomReset->setIcon(QIcon(":/images/viewZoomTool.png")); m_pHzoomIn->setAutoRepeat(true); m_pHzoomOut->setAutoRepeat(true); m_pVzoomIn->setAutoRepeat(true); m_pVzoomOut->setAutoRepeat(true); m_pHzoomIn->setToolTip(tr("Zoom in (horizontal)")); m_pHzoomOut->setToolTip(tr("Zoom out (horizontal)")); m_pVzoomIn->setToolTip(tr("Zoom in (vertical)")); m_pVzoomOut->setToolTip(tr("Zoom out (vertical)")); m_pXzoomReset->setToolTip(tr("Zoom reset")); int iScrollBarExtent = qtractorScrollView::style()->pixelMetric(QStyle::PM_ScrollBarExtent); m_pHzoomIn->setFixedWidth(iScrollBarExtent); m_pHzoomOut->setFixedWidth(iScrollBarExtent); qtractorScrollView::addScrollBarWidget(m_pHzoomIn, Qt::AlignRight); qtractorScrollView::addScrollBarWidget(m_pHzoomOut, Qt::AlignRight); m_pVzoomOut->setFixedHeight(iScrollBarExtent); m_pVzoomIn->setFixedHeight(iScrollBarExtent); qtractorScrollView::addScrollBarWidget(m_pVzoomOut, Qt::AlignBottom); qtractorScrollView::addScrollBarWidget(m_pVzoomIn, Qt::AlignBottom); QObject::connect(m_pHzoomIn, SIGNAL(clicked()), m_pTracks, SLOT(horizontalZoomInSlot())); QObject::connect(m_pHzoomOut, SIGNAL(clicked()), m_pTracks, SLOT(horizontalZoomOutSlot())); QObject::connect(m_pVzoomIn, SIGNAL(clicked()), m_pTracks, SLOT(verticalZoomInSlot())); QObject::connect(m_pVzoomOut, SIGNAL(clicked()), m_pTracks, SLOT(verticalZoomOutSlot())); QObject::connect(m_pXzoomReset, SIGNAL(clicked()), m_pTracks, SLOT(viewZoomResetSlot())); qtractorScrollView::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); qtractorScrollView::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); qtractorScrollView::viewport()->setFocusPolicy(Qt::StrongFocus); // qtractorScrollView::viewport()->setFocusProxy(this); qtractorScrollView::viewport()->setAcceptDrops(true); // qtractorScrollView::setDragAutoScroll(false); qtractorScrollView::setMouseTracking(true); const QFont& font = qtractorScrollView::font(); qtractorScrollView::setFont(QFont(font.family(), font.pointSize() - 1)); // QObject::connect(this, SIGNAL(contentsMoving(int,int)), // this, SLOT(updatePixmap(int,int))); // Trap for help/tool-tips events. qtractorScrollView::viewport()->installEventFilter(this); } // Destructor. qtractorTrackView::~qtractorTrackView (void) { clear(); delete m_pCurveSelect; delete m_pClipSelect; } // Track view state reset. void qtractorTrackView::clear (void) { g_clipboard.clear(); m_pClipSelect->clear(); m_pCurveSelect->clear(); m_dropType = qtractorTrack::None; m_dragState = DragNone; m_dragCursor = DragNone; m_iDragClipX = 0; m_pClipDrag = NULL; m_bDragTimer = false; m_iPlayHead = 0; m_iPlayHeadX = 0; m_iEditHeadX = 0; m_iEditTailX = 0; m_iLastRecordX = 0; m_iPasteCount = 0; m_iPastePeriod = 0; if (m_pSessionCursor) delete m_pSessionCursor; m_pSessionCursor = NULL; if (m_pRubberBand) delete m_pRubberBand; m_pRubberBand = NULL; if (m_pCurveEditCommand) delete m_pCurveEditCommand; m_pCurveEditCommand = NULL; m_bDragSingleTrack = false; m_iDragSingleTrackY = 0; m_iDragSingleTrackHeight = 0; m_pDragCurveNode = NULL; m_iDragCurveX = 0; qtractorScrollView::setContentsPos(0, 0); } // Update track view content height. void qtractorTrackView::updateContentsHeight (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Allways give some room to drop something at the bottom... int iContentsHeight = qtractorTrack::HeightBase << 1; // Compute total track height... qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack) { iContentsHeight += pTrack->zoomHeight(); pTrack = pTrack->next(); } #ifdef CONFIG_DEBUG_0 qDebug("qtractorTrackView::updateContentsHeight(%d)", iContentsHeight); #endif // Do the contents resize thing... qtractorScrollView::resizeContents( qtractorScrollView::contentsWidth(), iContentsHeight); // Keep selection (we'll update all contents anyway)... updateClipSelect(); } // Update track view content width. void qtractorTrackView::updateContentsWidth ( int iContentsWidth ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { const int iSessionWidth = pSession->pixelFromFrame(pSession->sessionEnd()); if (iContentsWidth < iSessionWidth) iContentsWidth = iSessionWidth; qtractorTimeScale::Cursor cursor(pSession->timeScale()); qtractorTimeScale::Node *pNode = cursor.seekPixel(iContentsWidth); iContentsWidth += pNode->pixelFromBeat( pNode->beat + 2 * pNode->beatsPerBar) - pNode->pixel; if (iContentsWidth < qtractorScrollView::width()) iContentsWidth += qtractorScrollView::width(); m_iPlayHeadX = pSession->pixelFromFrame(pSession->playHead()); m_iEditHeadX = pSession->pixelFromFrame(pSession->editHead()); m_iEditTailX = pSession->pixelFromFrame(pSession->editTail()); } #ifdef CONFIG_DEBUG_0 qDebug("qtractorTrackView::updateContentsWidth(%d)", iContentsWidth); #endif // Do the contents resize thing... qtractorScrollView::resizeContents( iContentsWidth, qtractorScrollView::contentsHeight()); // Keep selection (we'll update all contents anyway)... updateClipSelect(); // Force an update on the track time line too... m_pTracks->trackTime()->resizeContents( iContentsWidth + 100, m_pTracks->trackTime()->viewport()->height()); m_pTracks->trackTime()->updateContents(); } // Local rectangular contents update. void qtractorTrackView::updateContents ( const QRect& rect ) { updatePixmap( qtractorScrollView::contentsX(), qtractorScrollView::contentsY()); qtractorScrollView::updateContents(rect); } // Overall contents update. void qtractorTrackView::updateContents (void) { updatePixmap( qtractorScrollView::contentsX(), qtractorScrollView::contentsY()); qtractorScrollView::updateContents(); } // Special recording visual feedback. void qtractorTrackView::updateContentsRecord (void) { QWidget *pViewport = qtractorScrollView::viewport(); const int cx = qtractorScrollView::contentsX(); int w = m_iPlayHeadX - cx; if (w > 0 && w < pViewport->width()) { int x = 0, dx = 8; if (m_iPlayHeadX > m_iLastRecordX) { dx += (m_iPlayHeadX - m_iLastRecordX); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession && pSession->midiRecord() < 1) { w = dx; if (m_iLastRecordX > cx + dx) x = m_iLastRecordX - (cx + dx); } } else w = m_iLastRecordX - cx + dx; m_iLastRecordX = m_iPlayHeadX; pViewport->update(QRect(x, 0, w + dx, pViewport->height())); } } // Draw the track view. void qtractorTrackView::drawContents ( QPainter *pPainter, const QRect& rect ) { // Draw viewport canvas... pPainter->drawPixmap(rect, m_pixmap, rect); // Lines a-head... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; const int cx = qtractorScrollView::contentsX(); const int cy = qtractorScrollView::contentsY(); const int ch = qtractorScrollView::contentsHeight(); int x, w; // Draw track clip selection... if (isClipSelected()) { const QRect& rectView = qtractorScrollView::viewport()->rect(); const qtractorClipSelect::ItemList& items = m_pClipSelect->items(); qtractorClipSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorClipSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorClip *pClip = iter.key(); // Make sure it's a legal selection... if (pClip->track() && pClip->isClipSelected()) { qtractorClipSelect::Item *pClipItem = iter.value(); QRect rectClip(pClipItem->rectClip); rectClip.moveTopLeft( qtractorScrollView::contentsToViewport(rectClip.topLeft())); rectClip = rectClip.intersected(rectView); if (!rectClip.isEmpty()) pPainter->fillRect(rectClip, QColor(0, 0, 255, 120)); } } } // Common stuff for the job(s) ahead... unsigned long iTrackStart = 0; unsigned long iTrackEnd = 0; int y1 = 0; int y2 = 0; // On-the-fly recording clip drawing... if (pSession->isRecording() && pSession->isPlaying()) { iTrackStart = pSession->frameFromPixel(cx + rect.x()); iTrackEnd = pSession->playHead(); if (iTrackStart < iTrackEnd) { const unsigned long iFrameTime = pSession->frameTimeEx(); const unsigned long iFrameOffset = iFrameTime - iTrackEnd; const unsigned long iLoopStart = pSession->loopStart(); const unsigned long iLoopEnd = pSession->loopEnd(); qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack && y2 < ch) { y1 = y2; y2 += pTrack->zoomHeight(); // Dispatch to paint this track... qtractorClip *pClipRecord = pTrack->clipRecord(); if (pClipRecord && y2 > cy) { const int h = y2 - y1 - 2; const QRect trackRect( rect.left() - 1, y1 - cy + 1, rect.width() + 2, h); unsigned long iClipStart = pClipRecord->clipStart(); unsigned long iClipOffset = 0; if (iLoopStart < iLoopEnd && !pSession->isPunching()) { // Clip recording started within loop range: // -- adjust turn-around clip offset... if (iClipStart > iLoopStart && iClipStart < iLoopEnd) { unsigned long iHeadLength = (iLoopEnd - iClipStart); unsigned long iLoopLength = (iLoopEnd - iLoopStart); unsigned long iClipLength = (iFrameTime - pTrack->clipRecordStart()); if (iClipLength > iHeadLength) { unsigned long iLoopCount = (iClipLength - iHeadLength) / iLoopLength; iClipOffset += iHeadLength + iLoopCount * iLoopLength; iClipStart = iLoopStart; } } else // Clip recording is within loop range: // -- redraw leading/head clip segment... if (iFrameTime > iLoopStart) { unsigned long iHeadOffset = 0; if (iClipStart < iTrackStart) iHeadOffset += iTrackStart - iClipStart; x = pSession->pixelFromFrame(iClipStart) - cx; w = 0; if (iClipStart < iLoopStart) { w += pSession->pixelFromFrame(iLoopStart - iClipStart); iClipOffset += iLoopStart - iClipStart; } const QRect& headRect = QRect(x, y1 - cy + 1, w, h).intersected(trackRect); if (!headRect.isEmpty()) { pClipRecord->drawClip(pPainter, headRect, iHeadOffset); pPainter->fillRect(headRect, QColor(255, 0, 0, 120)); } iClipOffset += iFrameOffset; iClipStart = iLoopStart; } } // Clip recording rolling: // -- redraw current clip segment... if (iClipStart < iTrackStart) iClipOffset += iTrackStart - iClipStart; x = pSession->pixelFromFrame(iClipStart) - cx; w = 0; if (iClipStart < iTrackEnd) w += pSession->pixelFromFrame(iTrackEnd - iClipStart); const QRect& clipRect = QRect(x, y1 - cy + 1, w, h).intersected(trackRect); if (!clipRect.isEmpty()) { pClipRecord->drawClip(pPainter, clipRect, iClipOffset); pPainter->fillRect(clipRect, QColor(255, 0, 0, 120)); } } pTrack = pTrack->next(); } } // Make-up for next job... y1 = y2 = 0; iTrackEnd = 0; } // Automation curve drawing... pPainter->setRenderHint(QPainter::Antialiasing, true); x = rect.left(); w = rect.width(); if (w < 8) { x -= 4; if (x < 0) x = 0; w += 8; } qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack && y2 < ch) { y1 = y2; y2 += pTrack->zoomHeight(); qtractorCurve *pCurve = pTrack->currentCurve(); if (pCurve && y2 > cy) { const int h = y2 - y1 - 2; const QRect trackRect(x, y1 - cy + 1, w, h); if (iTrackStart == 0) iTrackStart = pSession->frameFromPixel(cx + x); if (iTrackEnd == 0) iTrackEnd = pSession->frameFromPixel(cx + x + w); unsigned long frame = iTrackStart; qtractorCurve::Cursor cursor(pCurve); qtractorCurve::Node *pNode = cursor.seek(frame); qtractorCurve::Mode mode = pCurve->mode(); const bool bLogarithmic = pCurve->isLogarithmic(); const bool bLocked = pCurve->isLocked(); int xc2, xc1 = trackRect.x(); int yc2, yc1 = y2 - int(cursor.scale(pNode, frame) * float(h)) - cy; int yc3, xc3 = xc1 + 4; QColor rgbCurve(pCurve->color()); QPen pen(rgbCurve); pPainter->setPen(pen); QPainterPath path; path.moveTo(xc1, yc1); while (pNode && pNode->frame < iTrackEnd) { xc2 = pSession->pixelFromFrame(pNode->frame) - cx; yc2 = y2 - int(cursor.scale(pNode) * float(h)) - cy; if (!bLocked) pPainter->drawRect(QRect(xc2 - 4, yc2 - 4, 8, 8)); switch (mode) { case qtractorCurve::Hold: path.lineTo(xc2, yc1); yc1 = yc2; break; case qtractorCurve::Linear: if (!bLogarithmic) break; // Fall thru... case qtractorCurve::Spline: default: for ( ; xc3 < xc2 - 4; xc3 += 4) { frame = pSession->frameFromPixel(cx + xc3); yc3 = y2 - int(cursor.scale(frame) * float(h)) - cy; path.lineTo(xc3, yc3); } xc3 = xc2 + 4; break; } path.lineTo(xc2, yc2); pNode = pNode->next(); } xc2 = rect.right(); frame = pSession->frameFromPixel(cx + xc2); yc2 = y2 - int(cursor.scale(frame) * float(h)) - cy; switch (mode) { case qtractorCurve::Hold: path.lineTo(xc2, yc1); break; case qtractorCurve::Linear: if (!bLogarithmic) break; // Fall thru... case qtractorCurve::Spline: default: for ( ; xc3 < xc2 - 4; xc3 += 4) { frame = pSession->frameFromPixel(cx + xc3); yc3 = y2 - int(cursor.scale(frame) * float(h)) - cy; path.lineTo(xc3, yc3); } break; } path.lineTo(xc2, yc2); // Draw line... //pen.setWidth(2); pPainter->strokePath(path, pen); // Fill semi-transparent area... rgbCurve.setAlpha(60); path.lineTo(xc2, y2 - cy); path.lineTo(xc1, y2 - cy); pPainter->fillPath(path, rgbCurve); if (m_bCurveEdit && m_pCurveSelect->isCurrentCurve(pCurve)) { const qtractorCurveSelect::ItemList& items = m_pCurveSelect->items(); qtractorCurveSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorCurveSelect::ItemList::ConstIterator iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorCurveSelect::Item *pItem = iter.value(); if (pItem->flags & 1) { QRect rectNode(pItem->rectNode); rectNode.moveTopLeft(contentsToViewport( rectNode.topLeft() + QPoint(m_iDragCurveX, 0))); pPainter->fillRect(rectNode, QColor(0, 0, 255, 80)); } } } } pTrack = pTrack->next(); } pPainter->setRenderHint(QPainter::Antialiasing, false); // Draw edit-head line... // m_iEditHeadX = pSession->pixelFromFrame(pSession->editHead()); x = m_iEditHeadX - cx; if (x >= rect.left() && x <= rect.right()) { pPainter->setPen(Qt::blue); pPainter->drawLine(x, rect.top(), x, rect.bottom()); } // Draw edit-tail line... // m_iEditTailX = pSession->pixelFromFrame(pSession->editTail()); x = m_iEditTailX - cx; if (x >= rect.left() && x <= rect.right()) { pPainter->setPen(Qt::blue); pPainter->drawLine(x, rect.top(), x, rect.bottom()); } // Draw play-head line... // m_iPlayHeadX = pSession->pixelFromFrame(pSession->playHead()); x = m_iPlayHeadX - cx; if (x >= rect.left() && x <= rect.right()) { pPainter->setPen(Qt::red); pPainter->drawLine(x, rect.top(), x, rect.bottom()); } // Show/hide a moving clip fade in/out slope lines... if (m_dragState == DragClipFadeIn || m_dragState == DragClipFadeOut) { QRect rectHandle(m_rectHandle); // Horizontal adjust... rectHandle.translate(m_iDragClipX, 0); // Convert rectangle into view coordinates... rectHandle.moveTopLeft(contentsToViewport(rectHandle.topLeft())); // Draw envelope line... QPoint vpos; QPen pen(Qt::DotLine); pen.setColor(Qt::blue); pPainter->setPen(pen); if (m_dragState == DragClipFadeIn) { vpos = contentsToViewport(m_rectDrag.bottomLeft()); pPainter->drawLine( vpos.x(), vpos.y(), rectHandle.left(), rectHandle.top()); } else if (m_dragState == DragClipFadeOut) { vpos = contentsToViewport(m_rectDrag.bottomRight()); pPainter->drawLine( rectHandle.right(), rectHandle.top(), vpos.x(), vpos.y()); } } } // Resize event handler. void qtractorTrackView::resizeEvent ( QResizeEvent *pResizeEvent ) { qtractorScrollView::resizeEvent(pResizeEvent); // Corner tool widget layout management... if (m_pXzoomReset) { const QSize& size = qtractorScrollView::size(); int h = size.height(); int w = qtractorScrollView::style()->pixelMetric( QStyle::PM_ScrollBarExtent); int x = size.width() - w - 2; m_pXzoomReset->setGeometry(x, h - w - 2, w, w); } updateContents(); // HACK: let our (single) thumb view get notified... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm && pMainForm->thumbView()) pMainForm->thumbView()->updateThumb(); } // (Re)create the complete track view pixmap. void qtractorTrackView::updatePixmap ( int cx, int cy ) { QWidget *pViewport = qtractorScrollView::viewport(); const int w = pViewport->width(); const int h = pViewport->height(); const QPalette& pal = qtractorScrollView::palette(); if (w < 1 || h < 1) return; const QColor& rgbMid = pal.mid().color(); m_pixmap = QPixmap(w, h); m_pixmap.fill(rgbMid); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorTimeScale *pTimeScale = pSession->timeScale(); if (pTimeScale == NULL) return; QPainter painter(&m_pixmap); painter.initFrom(this); // Update view session cursor location, // so that we'll start drawing clips from there... const unsigned long iTrackStart = pTimeScale->frameFromPixel(cx); const unsigned long iTrackEnd = iTrackStart + pTimeScale->frameFromPixel(w); // Create cursor now if applicable... if (m_pSessionCursor == NULL) { m_pSessionCursor = pSession->createSessionCursor(iTrackStart); } else { m_pSessionCursor->seek(iTrackStart); } const QColor& rgbLight = pal.midlight().color(); const QColor& rgbDark = rgbMid.darker(120); // Draw vertical grid lines... if (m_bSnapGrid || m_bSnapZebra) { const QBrush zebra(QColor(0, 0, 0, 20)); qtractorTimeScale::Cursor cursor(pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekPixel(cx); unsigned short iPixelsPerBeat = pNode->pixelsPerBeat(); unsigned int iBeat = pNode->beatFromPixel(cx); unsigned short iBar = pNode->barFromBeat(iBeat); int x = pNode->pixelFromBeat(iBeat) - cx; int x2 = x; while (x < w) { bool bBeatIsBar = pNode->beatIsBar(iBeat); if (bBeatIsBar) { if (m_bSnapGrid) { painter.setPen(rgbLight); painter.drawLine(x, 0, x, h); } if (m_bSnapZebra && (x > x2) && (++iBar & 1)) painter.fillRect(QRect(x2, 0, x - x2 + 1, h), zebra); x2 = x; if (iBeat == pNode->beat) iPixelsPerBeat = pNode->pixelsPerBeat(); } if (m_bSnapGrid && (bBeatIsBar || iPixelsPerBeat > 16)) { painter.setPen(rgbDark); painter.drawLine(x - 1, 0, x - 1, h); } pNode = cursor.seekBeat(++iBeat); x = pNode->pixelFromBeat(iBeat) - cx; } if (m_bSnapZebra && (x > x2) && (++iBar & 1)) painter.fillRect(QRect(x2, 0, x - x2 + 1, h), zebra); } // Draw track and horizontal lines... int y1, y2; y1 = y2 = 0; int iTrack = 0; qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack && y2 < cy + h) { y1 = y2; y2 += pTrack->zoomHeight(); if (y2 > cy) { // Dispatch to paint this track... if (y1 > cy) { painter.setPen(rgbLight); painter.drawLine(0, y1 - cy, w, y1 - cy); } const QRect trackRect(0, y1 - cy + 1, w, y2 - y1 - 2); // painter.fillRect(trackRect, rgbMid); pTrack->drawTrack(&painter, trackRect, iTrackStart, iTrackEnd, m_pSessionCursor->clip(iTrack)); painter.setPen(rgbDark); painter.drawLine(0, y2 - cy - 1, w, y2 - cy - 1); } pTrack = pTrack->next(); ++iTrack; } // Fill the empty area... if (y2 < cy + h) { painter.setPen(rgbMid); painter.drawLine(0, y2 - cy, w, y2 - cy); painter.fillRect(0, y2 - cy + 1, w, h, pal.dark().color()); } // Draw location marker lines... qtractorTimeScale::Marker *pMarker = pTimeScale->markers().seekPixel(cx); while (pMarker) { int x = pTimeScale->pixelFromFrame(pMarker->frame) - cx; if (x > w) break; painter.setPen(pMarker->color); painter.drawLine(x, 0, x, h); pMarker = pMarker->next(); } // Draw loop boundaries, if applicable... if (pSession->isLooping()) { const QBrush shade(QColor(0, 0, 0, 60)); painter.setPen(Qt::darkCyan); int x = pTimeScale->pixelFromFrame(pSession->loopStart()) - cx; if (x >= w) painter.fillRect(QRect(0, 0, w, h), shade); else if (x >= 0) { painter.fillRect(QRect(0, 0, x, h), shade); painter.drawLine(x, 0, x, h); } x = pTimeScale->pixelFromFrame(pSession->loopEnd()) - cx; if (x < 0) painter.fillRect(QRect(0, 0, w, h), shade); else if (x < w) { painter.fillRect(QRect(x, 0, w - x, h), shade); painter.drawLine(x, 0, x, h); } } // Draw punch boundaries, if applicable... if (pSession->isPunching()) { const QBrush shade(QColor(0, 0, 0, 60)); painter.setPen(Qt::darkMagenta); int x = pTimeScale->pixelFromFrame(pSession->punchIn()) - cx; if (x >= w) painter.fillRect(QRect(0, 0, w, h), shade); else if (x >= 0) { painter.fillRect(QRect(0, 0, x, h), shade); painter.drawLine(x, 0, x, h); } x = pTimeScale->pixelFromFrame(pSession->punchOut()) - cx; if (x < 0) painter.fillRect(QRect(0, 0, w, h), shade); else if (x < w) { painter.fillRect(QRect(x, 0, w - x, h), shade); painter.drawLine(x, 0, x, h); } } } // To have track view in v-sync with track list. void qtractorTrackView::contentsYMovingSlot ( int /*cx*/, int cy ) { if (qtractorScrollView::contentsY() != cy) qtractorScrollView::setContentsPos(qtractorScrollView::contentsX(), cy); } // Get track from given contents vertical position. qtractorTrack *qtractorTrackView::trackAt ( const QPoint& pos, bool bSelectTrack, qtractorTrackViewInfo *pTrackViewInfo ) const { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL || m_pSessionCursor == NULL) return NULL; int y1 = 0; int y2 = 0; int iTrack = 0; qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack) { y1 = y2; y2 += pTrack->zoomHeight(); if (y2 > pos.y()) break; pTrack = pTrack->next(); ++iTrack; } if (bSelectTrack) m_pTracks->trackList()->setCurrentTrackRow(pTrack ? iTrack : -1); if (pTrackViewInfo) { const int x = qtractorScrollView::contentsX(); const int w = qtractorScrollView::width();// View width, not contents. if (pTrack == NULL) { // Below all tracks. y1 = y2; y2 = y1 + (qtractorTrack::HeightBase * pSession->verticalZoom()) / 100; } pTrackViewInfo->trackIndex = iTrack; pTrackViewInfo->trackStart = m_pSessionCursor->frame(); pTrackViewInfo->trackEnd = pTrackViewInfo->trackStart + pSession->frameFromPixel(w); pTrackViewInfo->trackRect.setRect(x, y1 + 1, w, y2 - y1 - 2); } return pTrack; } // Get clip from given contents position. qtractorClip *qtractorTrackView::clipAtTrack ( const QPoint& pos, QRect *pClipRect, qtractorTrack *pTrack, qtractorTrackViewInfo *pTrackViewInfo ) const { if (pTrack == NULL) return NULL; qtractorSession *pSession = pTrack->session(); if (pSession == NULL || m_pSessionCursor == NULL) return NULL; qtractorClip *pClip = m_pSessionCursor->clip(pTrackViewInfo->trackIndex); if (pClip == NULL) pClip = pTrack->clips().first(); if (pClip == NULL) return NULL; qtractorClip *pClipAt = NULL; while (pClip && pClip->clipStart() < pTrackViewInfo->trackEnd) { const int x = pSession->pixelFromFrame(pClip->clipStart()); const int w = pSession->pixelFromFrame(pClip->clipLength()); if (pos.x() >= x && x + w >= pos.x()) { pClipAt = pClip; if (pClipRect) { pClipRect->setRect( x, pTrackViewInfo->trackRect.y(), w, pTrackViewInfo->trackRect.height()); } } pClip = pClip->next(); } return pClipAt; } qtractorClip *qtractorTrackView::clipAt ( const QPoint& pos, bool bSelectTrack, QRect *pClipRect ) const { qtractorTrackViewInfo tvi; qtractorTrack *pTrack = trackAt(pos, bSelectTrack, &tvi); return clipAtTrack(pos, pClipRect, pTrack, &tvi); } // Get automation curve node from given contents position. qtractorCurve::Node *qtractorTrackView::nodeAtTrack ( const QPoint& pos, qtractorTrack *pTrack, qtractorTrackViewInfo *pTrackViewInfo ) const { if (pTrack == NULL) return NULL; qtractorSession *pSession = pTrack->session(); if (pSession == NULL || m_pSessionCursor == NULL) return NULL; qtractorCurveList *pCurveList = pTrack->curveList(); if (pCurveList == NULL) return NULL; qtractorCurve *pCurve = pCurveList->currentCurve(); if (pCurve == NULL) return NULL; if (pCurve->isLocked()) return NULL; const int w = pTrackViewInfo->trackRect.width(); const int h = pTrackViewInfo->trackRect.height(); const int y2 = pTrackViewInfo->trackRect.bottom() + 1; const int cx = qtractorScrollView::contentsX(); const unsigned long frame = pSession->frameFromPixel(cx); qtractorCurve::Cursor cursor(pCurve); qtractorCurve::Node *pNode = cursor.seek(frame); while (pNode) { const int x = pSession->pixelFromFrame(pNode->frame); if (x > cx + w) // No use.... break; const int y = y2 - int(cursor.scale(pNode) * float(h)); if (QRect(x - 4, y - 4, 8, 8).contains(pos)) return pNode; // Test next... pNode = pNode->next(); } // Not found. return NULL; } qtractorCurve::Node *qtractorTrackView::nodeAt ( const QPoint& pos ) const { qtractorTrackViewInfo tvi; qtractorTrack *pTrack = trackAt(pos, false, &tvi); return nodeAtTrack(pos, pTrack, &tvi); } // Get contents visible rectangle from given track. bool qtractorTrackView::trackInfo ( qtractorTrack *pTrack, qtractorTrackViewInfo *pTrackViewInfo ) const { qtractorSession *pSession = pTrack->session(); if (pSession == NULL || m_pSessionCursor == NULL) return false; int y1, y2 = 0; int iTrack = 0; qtractorTrack *pTrackEx = pSession->tracks().first(); while (pTrackEx) { y1 = y2; y2 += pTrackEx->zoomHeight(); if (pTrackEx == pTrack) { const int x = qtractorScrollView::contentsX(); const int w = qtractorScrollView::width(); // View width, not contents. pTrackViewInfo->trackIndex = iTrack; pTrackViewInfo->trackStart = m_pSessionCursor->frame(); pTrackViewInfo->trackEnd = pTrackViewInfo->trackStart + pSession->frameFromPixel(w); pTrackViewInfo->trackRect.setRect(x, y1 + 1, w, y2 - y1 - 2); return true; } pTrackEx = pTrackEx->next(); ++iTrack; } return false; } // Get contents rectangle from given clip. bool qtractorTrackView::clipInfo ( qtractorClip *pClip, QRect *pClipRect ) const { qtractorTrack *pTrack = pClip->track(); if (pTrack == NULL) return false; qtractorTrackViewInfo tvi; if (!trackInfo(pTrack, &tvi)) return false; qtractorSession *pSession = pTrack->session(); if (pSession) { const int x = pSession->pixelFromFrame(pClip->clipStart()); const int w = pSession->pixelFromFrame(pClip->clipLength()); pClipRect->setRect(x, tvi.trackRect.y(), w, tvi.trackRect.height()); } return true; } // Selection-dragging, following the current mouse position. qtractorTrack *qtractorTrackView::dragClipMove ( const QPoint& pos, bool bKeyStep ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return NULL; // Which track we're pointing at? qtractorTrackViewInfo tvi; qtractorTrack *pTrack = trackAt(pos, true, &tvi); // May change vertically, if we've only one track selected, // and only between same track type... qtractorTrack *pSingleTrack = m_pClipSelect->singleTrack(); if (pSingleTrack && (pTrack == NULL || pSingleTrack->trackType() == pTrack->trackType())) { m_bDragSingleTrack = true; m_iDragSingleTrackY = tvi.trackRect.y(); m_iDragSingleTrackHeight = tvi.trackRect.height(); } else { m_bDragSingleTrack = false; m_iDragSingleTrackY = 0; m_iDragSingleTrackHeight = 0; } // Special update on keyboard vertical drag-stepping... if (bKeyStep) m_posStep.setY(m_posStep.y() - pos.y() + tvi.trackRect.y() + (pTrack ? (tvi.trackRect.height() >> 1) : 0)); // Always change horizontally wise... const int x = m_pClipSelect->rect().x(); int dx = (pos.x() - m_posDrag.x()); if (x + dx < 0) dx = -(x); // Force to origin (x=0). m_iDragClipX = (pSession->pixelSnap(x + dx) - x); qtractorScrollView::ensureVisible(pos.x(), pos.y(), 24, 24); showClipSelect(); // OK, we've moved it... return pTrack; } qtractorTrack *qtractorTrackView::dragClipDrop ( const QPoint& pos, bool bKeyStep, const QMimeData *pMimeData ) { // It must be a valid session... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return NULL; // Find the current pointer track... qtractorTrackViewInfo tvi; qtractorTrack *pTrack = trackAt(pos, true, &tvi); // Special update on keyboard vertical drag-stepping... if (bKeyStep) m_posStep.setY(m_posStep.y() - pos.y() + tvi.trackRect.y() + (pTrack ? (tvi.trackRect.height() >> 1) : 0)); // If we're already dragging something, if (!m_dropItems.isEmpty()) { // Adjust to target track... updateClipDropRects(tvi.trackRect.y() + 1, tvi.trackRect.height() - 2); // Always change horizontally wise... const int x = m_rectDrag.x(); int dx = (pos.x() - m_posDrag.x()); if (x + dx < 0) dx = -(x); // Force to origin (x=0). m_iDragClipX = (pSession->pixelSnap(x + dx) - x); // showDropRects(); // OK, we've moved it... return pTrack; } // Let's start from scratch... qDeleteAll(m_dropItems); m_dropItems.clear(); m_dropType = qtractorTrack::None; // Nothing more? if (pMimeData == NULL) return NULL; // Can it be single track channel (MIDI for sure)? if (qtractorFileChannelDrag::canDecode(pMimeData)) { // Let's see how many track-channels are there... const qtractorFileChannelDrag::List& items = qtractorFileChannelDrag::decode(pMimeData); QListIterator iter(items); while (iter.hasNext()) { const qtractorFileChannelDrag::Item& item = iter.next(); m_dropItems.append(new DropItem(item.path, item.channel)); } } else // Can we decode it as Audio/MIDI files? if (pMimeData->hasUrls()) { // Let's see how many files there are... QList list = pMimeData->urls(); QListIterator iter(list); while (iter.hasNext()) { const QString& sPath = iter.next().toLocalFile(); // Close current session and try to load the new one... if (!sPath.isEmpty()) m_dropItems.append(new DropItem(sPath)); } } // Nice, now we'll try to set a preview selection rectangle set... m_posDrag.setX(pSession->pixelSnap(pos.x() > 8 ? pos.x() - 8 : 0)); m_posDrag.setY(tvi.trackRect.y() + 1); m_rectDrag.setRect( m_posDrag.x(), m_posDrag.y(), 0, tvi.trackRect.height() - 2); // Now's time to add those rectangles... QMutableListIterator iter(m_dropItems); while (iter.hasNext()) { DropItem *pDropItem = iter.next(); // First test as a MIDI file... if (m_dropType == qtractorTrack::None || m_dropType == qtractorTrack::Midi) { const int x0 = m_posDrag.x(); qtractorTimeScale::Cursor cursor(pSession->timeScale()); qtractorTimeScale::Node *pNode = cursor.seekPixel(x0); unsigned long t1, t0 = pNode->tickFromPixel(x0); qtractorMidiFile file; if (file.open(pDropItem->path)) { qtractorMidiSequence seq; seq.setTicksPerBeat(pSession->ticksPerBeat()); if (pDropItem->channel < 0) { int iTracks = (file.format() == 1 ? file.tracks() : 16); for (int iTrackChannel = 0; iTrackChannel < iTracks; ++iTrackChannel) { if (file.readTrack(&seq, iTrackChannel) && seq.duration() > 0) { t1 = t0 + seq.duration(); pNode = cursor.seekTick(t1); m_rectDrag.setWidth(pNode->pixelFromTick(t1) - x0); pDropItem->rect = m_rectDrag; m_rectDrag.translate(0, m_rectDrag.height() + 4); } } if (m_dropType == qtractorTrack::None) m_dropType = qtractorTrack::Midi; } else if (file.readTrack(&seq, pDropItem->channel) && seq.duration() > 0) { t1 = t0 + seq.duration(); pNode = cursor.seekTick(t1); m_rectDrag.setWidth(pNode->pixelFromTick(t1) - x0); pDropItem->rect = m_rectDrag; m_rectDrag.translate(0, m_rectDrag.height() + 4); if (m_dropType == qtractorTrack::None) m_dropType = qtractorTrack::Midi; } else /*if (m_dropType == qtractorTrack::Midi)*/ { iter.remove(); delete pDropItem; } file.close(); continue; } else if (m_dropType == qtractorTrack::Midi) { iter.remove(); delete pDropItem; } } // Then as an Audio file ? if (m_dropType == qtractorTrack::None || m_dropType == qtractorTrack::Audio) { qtractorAudioFile *pFile = qtractorAudioFileFactory::createAudioFile(pDropItem->path); if (pFile) { if (pFile->open(pDropItem->path)) { unsigned long iFrames = pFile->frames(); if (pFile->sampleRate() > 0 && pFile->sampleRate() != pSession->sampleRate()) { iFrames = (unsigned long) (iFrames * float(pSession->sampleRate()) / float(pFile->sampleRate())); } m_rectDrag.setWidth(pSession->pixelFromFrame(iFrames)); pDropItem->rect = m_rectDrag; m_rectDrag.translate(0, m_rectDrag.height() + 4); if (m_dropType == qtractorTrack::None) m_dropType = qtractorTrack::Audio; } else if (m_dropType == qtractorTrack::Audio) { iter.remove(); delete pDropItem; } delete pFile; continue; } else if (m_dropType == qtractorTrack::Audio) { iter.remove(); delete pDropItem; } } } // Are we still here? if (m_dropItems.isEmpty() || m_dropType == qtractorTrack::None) { m_dropType = qtractorTrack::None; return NULL; } // Ok, sure we're into some drag&drop state... m_dragState = DragClipDrop; m_iDragClipX = 0; // Finally, show it to the world... updateClipDropRects(tvi.trackRect.y() + 1, tvi.trackRect.height() - 2); // showClipDropRects(); // Done. return pTrack; } qtractorTrack *qtractorTrackView::dragClipDropEvent ( QDropEvent *pDropEvent ) { return dragClipDrop( viewportToContents(pDropEvent->pos()), false, pDropEvent->mimeData()); } bool qtractorTrackView::canClipDropEvent ( QDropEvent *pDropEvent ) { // have one existing track on target? qtractorTrack *pTrack = dragClipDropEvent(pDropEvent); // Can only drop if anything... if (m_dropItems.isEmpty()) return false; // Can only drop on same type tracks... if (pTrack && pTrack->trackType() != m_dropType) return false; // Special MIDI track-channel cases... if (m_dropType == qtractorTrack::Midi) { if (m_dropItems.count() == 1 && m_dropItems.first()->channel >= 0) return true; else return (pTrack == NULL); } // Drop in the blank... return (pTrack == NULL || m_dropItems.count() == 1 || m_bDropSpan); } // Selection-dragging, following the current mouse position. void qtractorTrackView::dragCurveMove ( const QPoint& pos, bool /*bKeyStep*/ ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; const QRect& rect = m_pCurveSelect->rect(); QRect rectUpdate(rect.translated(m_iDragCurveX, 0)); // Always change horizontally wise... const int x = rect.x(); int dx = (pos.x() - m_posDrag.x()); if (x + dx < 0) dx = -(x); // Force to origin (x=0). m_iDragCurveX = (pSession->pixelSnap(x + dx) - x); qtractorScrollView::ensureVisible(pos.x(), pos.y(), 24, 24); updateRect(rectUpdate.united(rect.translated(m_iDragCurveX, 0))); } // Drag enter event handler. void qtractorTrackView::dragEnterEvent ( QDragEnterEvent *pDragEnterEvent ) { #if 0 if (canDropEvent(pDragEnterEvent)) { showDropRects(); if (!pDragEnterEvent->isAccepted()) { pDragEnterEvent->setDropAction(Qt::CopyAction); pDragEnterEvent->accept(); m_bDragTimer = false; } } else { pDragEnterEvent->ignore(); hideDropRects(); } #else // Always accept the drag-enter event, // so let we deal with it during move later... pDragEnterEvent->accept(); m_bDragTimer = false; #endif } // Drag move event handler. void qtractorTrackView::dragMoveEvent ( QDragMoveEvent *pDragMoveEvent ) { if (canClipDropEvent(pDragMoveEvent)) { showClipDropRects(); if (!pDragMoveEvent->isAccepted()) { pDragMoveEvent->setDropAction(Qt::CopyAction); pDragMoveEvent->accept(); m_bDragTimer = false; } } else { pDragMoveEvent->ignore(); hideClipDropRects(); } // Kind of auto-scroll... const QPoint& pos = viewportToContents(pDragMoveEvent->pos()); qtractorScrollView::ensureVisible(pos.x(), pos.y(), 24, 24); } // Drag leave event handler. void qtractorTrackView::dragLeaveEvent ( QDragLeaveEvent *pDragLeaveEvent ) { // Maybe we have something currently going on? if (pDragLeaveEvent->isAccepted()) { if (!m_bDragTimer) { m_bDragTimer = true; QTimer::singleShot(100, this, SLOT(dragTimeout())); } } else { // Nothing's being accepted... m_bDragTimer = false; resetDragState(); } } // Drag timeout slot. void qtractorTrackView::dragTimeout (void) { if (m_bDragTimer) { resetDragState(); m_bDragTimer = false; } } // Drop event handler. bool qtractorTrackView::dropClip ( const QPoint& pos, const QMimeData *pMimeData ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // Add new clips on proper and consecutive track locations... unsigned long iClipStart = pSession->frameSnap( pSession->frameFromPixel(m_rectDrag.x() + m_iDragClipX)); // Now check whether the drop is intra-track... qtractorTrack *pTrack = dragClipDrop(pos, false, pMimeData); // And care if we're not spanning horizontally... if (pTrack == NULL && (!m_bDropSpan || m_dropType == qtractorTrack::Midi)) { // Do we have something to drop anyway? // if yes, this is a extra-track drop... int iAddTrack = 0; if (!m_dropItems.isEmpty()) { // Prepare file list for import... QStringList files; QListIterator iter(m_dropItems); while (iter.hasNext()) { DropItem *pDropItem = iter.next(); if (m_dropType == qtractorTrack::Midi && pDropItem->channel >= 0) { m_pTracks->addMidiTrackChannel( pDropItem->path, pDropItem->channel, iClipStart); ++iAddTrack; } else { files.append(pDropItem->path); } } // Depending on import type... if (!files.isEmpty()) { switch (m_dropType) { case qtractorTrack::Audio: m_pTracks->addAudioTracks(files, iClipStart); ++iAddTrack; break; case qtractorTrack::Midi: m_pTracks->addMidiTracks(files, iClipStart); ++iAddTrack; break; default: break; } } } resetDragState(); return (iAddTrack > 0); } // Check whether we can really drop it. if (pTrack && pTrack->trackType() != m_dropType) { resetDragState(); return false; } // We'll build a composite command... QList clips; qtractorClipCommand *pClipCommand = new qtractorClipCommand(tr("add clip")); // If dropping spanned we'll need a track, sure... int iTrackClip = 0; const bool bAddTrack = (pTrack == NULL); if (bAddTrack) { pTrack = new qtractorTrack(pSession, m_dropType); // Create a new track right away... int iTrack = pSession->tracks().count() + 1; const QColor& color = qtractorTrack::trackColor(iTrack); pTrack = new qtractorTrack(pSession, m_dropType); pTrack->setBackground(color); pTrack->setForeground(color.darker()); // pTrack->setTrackName(tr("Track %1").arg(iTrack)); pClipCommand->addTrack(pTrack); } // Now's time to create the clip(s)... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); QListIterator iter(m_dropItems); while (iter.hasNext()) { DropItem *pDropItem = iter.next(); switch (pTrack->trackType()) { case qtractorTrack::Audio: { qtractorAudioClip *pAudioClip = new qtractorAudioClip(pTrack); if (pAudioClip) { pAudioClip->setFilename(pDropItem->path); pAudioClip->setClipStart(iClipStart); pClipCommand->addClip(pAudioClip, pTrack); clips.append(pAudioClip); // Don't forget to add this one to local repository. if (pMainForm) pMainForm->addAudioFile(pDropItem->path); } break; } case qtractorTrack::Midi: { qtractorMidiClip *pMidiClip = new qtractorMidiClip(pTrack); if (pMidiClip) { pMidiClip->setFilename(pDropItem->path); pMidiClip->setTrackChannel(pDropItem->channel); pMidiClip->setClipStart(iClipStart); pClipCommand->addClip(pMidiClip, pTrack); clips.append(pMidiClip); // Don't forget to add this one to local repository. if (pMainForm) pMainForm->addMidiFile(pDropItem->path); } break; } case qtractorTrack::None: default: break; } // If track's new it will need a name... if (bAddTrack && iTrackClip == 0) pTrack->setTrackName(QFileInfo(pDropItem->path).baseName()); // If multiple items, just snap/concatenate them... iClipStart = pSession->frameSnap(iClipStart + pSession->frameFromPixel(pDropItem->rect.width())); ++iTrackClip; } // Clean up. resetDragState(); // Put it in the form of an undoable command... const bool bResult = pSession->execute(pClipCommand); // Redo selection as new... if (!clips.isEmpty()) { QListIterator clip_iter(clips); while (clip_iter.hasNext()) clip_iter.next()->setClipSelected(true); updateClipSelect(); m_pTracks->selectionChangeNotify(); } return bResult; } void qtractorTrackView::dropEvent ( QDropEvent *pDropEvent ) { if (!dropClip(viewportToContents(pDropEvent->pos()), pDropEvent->mimeData())) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->dropEvent(pDropEvent); } } // Handle item selection/dragging -- mouse button press. void qtractorTrackView::mousePressEvent ( QMouseEvent *pMouseEvent ) { // Which mouse state? const QPoint& pos = viewportToContents(pMouseEvent->pos()); const Qt::KeyboardModifiers& modifiers = pMouseEvent->modifiers(); bool bModifier = (modifiers & (Qt::ShiftModifier | Qt::ControlModifier)); // Are we already step-moving or pasting something? switch (m_dragState) { case DragClipStep: // One-click change from drag-step to drag-move... m_dragState = DragClipMove; m_posDrag = m_rectDrag.center(); m_posStep = QPoint(0, 0); dragClipMove(pos + m_posStep); // Fall thru... case DragClipPaste: case DragClipPasteDrop: // qtractorScrollView::mousePressEvent(pMouseEvent); return; case DragCurveStep: // One-click change from drag-step to drag-move... m_dragState = DragCurveMove; m_posDrag = m_rectDrag.center(); m_posStep = QPoint(0, 0); dragCurveMove(pos + m_posStep); // Fall thru... case DragCurvePaste: // qtractorScrollView::mousePressEvent(pMouseEvent); return; default: break; } // Automation curve editing modes... if (pMouseEvent->button() == Qt::LeftButton) { if (m_dragCursor == DragCurveNode || (m_bCurveEdit && m_dragCursor == DragNone)) { qtractorTrackViewInfo tvi; qtractorTrack *pTrack = trackAt(pos, true, &tvi); if (pTrack && m_dragCursor == DragCurveNode) { qtractorCurve::Node *pNode = nodeAtTrack(pos, pTrack, &tvi); if (pNode) { m_pDragCurve = pTrack->currentCurve(); m_pDragCurveNode = pNode; } } } if (m_bCurveEdit) { if (!bModifier) clearSelect(); #if 0//TEST_DRAG_CURVE_NODE if ((m_dragCursor == DragCurveNode) || (m_dragCursor == DragNone && !bModifier)) if ((modifiers & Qt::ControlModifier) == 0) dragCurveNode(pos, false); #endif } #if 0//TEST_DRAG_CURVE_NODE if (m_dragCursor == DragCurveNode) { if (m_pDragCurve && m_pDragCurveNode) { m_dragState = DragStart;//DragCurveNode; m_posDrag = pos; m_pClipDrag = NULL; } #else if (m_dragCursor == DragCurveNode || (m_bCurveEdit && m_dragCursor == DragNone)) { m_dragState = DragStart;//DragCurveNode; m_posDrag = pos; m_pClipDrag = NULL; #endif // qtractorScrollView::mousePressEvent(pMouseEvent); return; } } // Force null state. m_pClipDrag = NULL; resetDragState(); // We'll need options somehow... qtractorOptions *pOptions = qtractorOptions::getInstance(); // We need a session and a location... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { // Direct snap positioning... unsigned long iFrame = pSession->frameSnap( pSession->frameFromPixel(pos.x() > 0 ? pos.x() : 0)); // Which button is being pressed? switch (pMouseEvent->button()) { case Qt::LeftButton: // Remember what and where we'll be dragging/selecting... m_dragState = DragStart; m_posDrag = pos; m_pClipDrag = clipAt(m_posDrag, true, &m_rectDrag); // Should it be selected(toggled)? if (m_pClipDrag && !dragMoveStart(pos)) { // Show that we're about to something... m_dragCursor = m_dragState; qtractorScrollView::setCursor(QCursor(Qt::PointingHandCursor)); // Make it (un)selected, right on the file view too... if (!m_bCurveEdit && m_selectMode == SelectClip) selectClipFile(!bModifier); } // Something got it started?... if (m_pClipDrag == NULL || (m_pClipDrag && !m_pClipDrag->isClipSelected())) { // Clear any selection out there? if (!m_bCurveEdit && !bModifier) clearSelect(); } break; case Qt::MidButton: // Mid-button positioning... clearSelect(); if (pOptions && pOptions->bMidButtonModifier) bModifier = !bModifier; // Reverse mid-button role... if (bModifier) { // Play-head positioning... pSession->setPlayHead(iFrame); setPlayHead(iFrame); } else { // Edit cursor (merge) positioning... setEditHead(iFrame); setEditTail(iFrame); } // Not quite a selection, but some visual feedback... m_pTracks->selectionChangeNotify(); break; case Qt::RightButton: // Have sense if pointer falls over a clip... m_pClipDrag = clipAt(pos, true); #if 0 if (m_pClipDrag == NULL) { // Right-button edit-tail positioning... setEditTail(iFrame); // Not quite a selection, but some visual feedback... m_pTracks->selectionChangeNotify(); } #endif // Fall thru... default: break; } } // qtractorScrollView::mousePressEvent(pMouseEvent); } // Handle item selection/dragging -- mouse pointer move. void qtractorTrackView::mouseMoveEvent ( QMouseEvent *pMouseEvent ) { // Are we already moving/dragging something? const QPoint& pos = viewportToContents(pMouseEvent->pos()); const Qt::KeyboardModifiers& modifiers = pMouseEvent->modifiers(); switch (m_dragState) { case DragNone: // Try to catch mouse over the fade or resize handles... dragMoveStart(pos); break; case DragClipMove: case DragClipPaste: dragClipMove(pos + m_posStep); break; case DragClipPasteDrop: dragClipDrop(pos + m_posStep); showClipDropRects(); break; case DragClipFadeIn: case DragClipFadeOut: dragClipFadeMove(pos); break; case DragClipResizeLeft: case DragClipResizeRight: dragClipResizeMove(pos); break; case DragCurveMove: case DragCurvePaste: dragCurveMove(pos + m_posStep); break; case DragCurveNode: dragCurveNode(pos, modifiers & Qt::ControlModifier); break; case DragSelect: m_rectDrag.setBottomRight(pos); moveRubberBand(&m_pRubberBand, m_rectDrag); qtractorScrollView::ensureVisible(pos.x(), pos.y(), 24, 24); if (m_bCurveEdit) { // Select all current track curve/automation // nodes that fall inside the rubber-band... selectCurveRect(m_rectDrag, SelectRect, selectFlags(modifiers)); } else { // Here we're mainly supposed to select a few bunch // of clips that fall inside the rubber-band... selectClipRect(m_rectDrag, m_selectMode, selectFlags(modifiers)); } showToolTip(m_rectDrag.normalized(), m_iDragClipX); break; case DragStart: if ((m_posDrag - pos).manhattanLength() > QApplication::startDragDistance()) { // Check if we're pointing in some fade-in/out, // resize handle or a automation curve node... if (dragMoveStart(m_posDrag)) { m_dragState = m_dragCursor; if (m_dragState == DragCurveMove) { // DragCurveMove... m_iDragCurveX = (pos.x() - m_posDrag.x()); qtractorScrollView::setCursor(QCursor(Qt::SizeHorCursor)); } else if (m_dragState == DragClipFadeIn || m_dragState == DragClipFadeOut) { // DragClipFade... m_iDragClipX = (pos.x() - m_posDrag.x()); qtractorScrollView::setCursor(QCursor(Qt::SizeHorCursor)); moveRubberBand(&m_pRubberBand, m_rectHandle); } else if (m_pClipDrag) { // DragClipResize... moveRubberBand(&m_pRubberBand, m_rectDrag, 3); } } else if (!m_bCurveEdit || (m_dragCursor != DragCurveNode && m_dragCursor != DragCurveMove)) { // We'll start dragging clip/regions alright... qtractorSession *pSession = qtractorSession::getInstance(); qtractorClipSelect::Item *pClipItem = NULL; if (m_pClipDrag && pSession) pClipItem = m_pClipSelect->findItem(m_pClipDrag); if (pClipItem && pClipItem->rectClip.contains(pos)) { int x = pSession->pixelSnap(m_rectDrag.x()); m_iDragClipX = (x - m_rectDrag.x()); m_dragState = m_dragCursor = DragClipMove; qtractorScrollView::setCursor(QCursor(Qt::SizeAllCursor)); showClipSelect(); } else { // We'll start rubber banding... m_rectDrag.setTopLeft(m_posDrag); m_rectDrag.setBottomRight(pos); m_dragState = m_dragCursor = DragSelect; // Set a proper cursor... qtractorScrollView::setCursor(QCursor( m_selectMode == SelectRange ? Qt::SizeHorCursor : Qt::CrossCursor)); // Create the rubber-band if there's none... moveRubberBand(&m_pRubberBand, m_rectDrag); } } } // Fall thru... case DragClipStep: case DragClipDrop: default: break; } // qtractorScrollView::mouseMoveEvent(pMouseEvent); } // Handle item selection/dragging -- mouse button release. void qtractorTrackView::mouseReleaseEvent ( QMouseEvent *pMouseEvent ) { // qtractorScrollView::mouseReleaseEvent(pMouseEvent); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { // Direct snap positioning... const QPoint& pos = viewportToContents(pMouseEvent->pos()); const unsigned long iFrame = pSession->frameSnap( pSession->frameFromPixel(m_posDrag.x() > 0 ? m_posDrag.x() : 0)); // Which mouse state? const Qt::KeyboardModifiers& modifiers = pMouseEvent->modifiers(); const bool bModifier = (modifiers & (Qt::ShiftModifier | Qt::ControlModifier)); switch (m_dragState) { case DragSelect: if (m_bCurveEdit) { // Select all current track curve/automation // nodes that fall inside the rubber-band... selectCurveRect(m_rectDrag, SelectRect, selectFlags(modifiers) | SelectCommit); } else { // Here we're mainly supposed to select a few bunch // of clips that fall inside the rubber-band... selectClipRect(m_rectDrag, m_selectMode, selectFlags(modifiers) | SelectCommit); } // For immediate visual feedback... m_pTracks->selectionChangeNotify(); break; case DragClipMove: // Let's move them... moveClipSelect(dragClipMove(pos + m_posStep)); break; case DragClipPaste: // Let's paste them... pasteClipSelect(dragClipMove(pos + m_posStep)); break; case DragClipPasteDrop: // Let's drop-paste them... dropClip(pos + m_posStep); break; case DragClipFadeIn: case DragClipFadeOut: dragClipFadeDrop(pos); break; case DragClipResizeLeft: case DragClipResizeRight: dragClipResizeDrop(pos, bModifier); break; case DragCurveMove: // Let's move them... moveCurveSelect(pos + m_posStep); break; case DragCurvePaste: pasteCurveSelect(pos + m_posStep); break; case DragStart: // Deferred left-button positioning... if (m_pClipDrag) { // Make it right on the file view now... if (!m_bCurveEdit && m_selectMode != SelectClip) selectClipFile(!bModifier); // Nothing more has been deferred... } else { // As long we're editing curve/automation... #if 0//TEST_DRAG_CURVE_NODE if (m_bCurveEdit && (m_dragCursor == DragCurveNode || m_dragCursor == DragCurveMove)) { if (modifiers & Qt::ControlModifier) dragCurveNode(pos, true); #else if (m_bCurveEdit) { dragCurveNode(pos, modifiers & Qt::ControlModifier); #endif } // As long we're not editing anything... if (m_dragCursor == DragNone) { // Direct play-head positioning... if (bModifier) { // First, set actual engine position... pSession->setPlayHead(iFrame); // Play-head positioning... setPlayHead(iFrame); // Done with (deferred) play-head positioning. #if 0 } else { // Deferred left-button edit-head positioning... setEditHead(iFrame); #endif } } } // Fall thru... case DragCurveNode: // Specially when editing curve nodes, // for immediate visual feedback... if (m_pCurveEditCommand && !m_pCurveEditCommand->isEmpty()) { pSession->commands()->push(m_pCurveEditCommand); m_pCurveEditCommand = NULL; m_pTracks->dirtyChangeNotify(); } else { m_pTracks->selectionChangeNotify(); } // Fall thru... case DragCurveStep: case DragClipStep: case DragClipDrop: case DragNone: default: break; } } // Force null state. resetDragState(); } // Handle item/clip editing from mouse. void qtractorTrackView::mouseDoubleClickEvent ( QMouseEvent *pMouseEvent ) { qtractorScrollView::mouseDoubleClickEvent(pMouseEvent); // By this time we should have something under... if (m_pClipDrag) m_pTracks->editClip(m_pClipDrag); else if (!m_bCurveEdit) m_pTracks->selectCurrentTrack(); } // Handle zoom with mouse wheel. void qtractorTrackView::wheelEvent ( QWheelEvent *pWheelEvent ) { if (pWheelEvent->modifiers() & Qt::ControlModifier) { const int delta = pWheelEvent->delta(); if (delta > 0) m_pTracks->zoomIn(); else m_pTracks->zoomOut(); } else qtractorScrollView::wheelEvent(pWheelEvent); } // Focus lost event. void qtractorTrackView::focusOutEvent ( QFocusEvent *pFocusEvent ) { if (m_dragState == DragClipStep || m_dragState == DragClipPaste || m_dragState == DragClipPasteDrop || m_dragState == DragCurveStep || m_dragState == DragCurvePaste) resetDragState(); qtractorScrollView::focusOutEvent(pFocusEvent); } // Trap for help/tool-tip events. bool qtractorTrackView::eventFilter ( QObject *pObject, QEvent *pEvent ) { QWidget *pViewport = qtractorScrollView::viewport(); if (static_cast (pObject) == pViewport) { if (pEvent->type() == QEvent::ToolTip && m_bToolTips) { QHelpEvent *pHelpEvent = static_cast (pEvent); if (pHelpEvent) { const QPoint& pos = qtractorScrollView::viewportToContents(pHelpEvent->pos()); qtractorTrackViewInfo tvi; qtractorTrack *pTrack = trackAt(pos, false, &tvi); if (pTrack) { qtractorCurve::Node *pNode = nodeAtTrack(pos, pTrack, &tvi); if (pNode) { qtractorCurve *pCurve = pTrack->currentCurve(); QToolTip::showText(pHelpEvent->globalPos(), nodeToolTip(pCurve, pNode), pViewport); return true; } qtractorClip *pClip = clipAtTrack(pos, NULL, pTrack, &tvi); if (pClip) { QToolTip::showText(pHelpEvent->globalPos(), pClip->toolTip(), pViewport); return true; } } } } else if (pEvent->type() == QEvent::Leave && m_dragState != DragCurvePaste && m_dragState != DragCurveStep && m_dragState != DragClipPasteDrop && m_dragState != DragClipPaste && m_dragState != DragClipStep) { m_dragCursor = DragNone; qtractorScrollView::unsetCursor(); return true; } } // Not handled here. return qtractorScrollView::eventFilter(pObject, pEvent); } // Clip file(item) selection convenience method. void qtractorTrackView::selectClipFile ( bool bReset ) { if (m_pClipDrag == NULL) return; // Reset selection (conditional)... int iUpdate = 0; QRect rectUpdate = m_pClipSelect->rect(); // Do the selection dance, first... qtractorClipSelect::Item *pClipItem = m_pClipSelect->findItem(m_pClipDrag); bool bSelect = !(pClipItem && pClipItem->rectClip.contains(m_posDrag)); if (!bReset) { m_pClipSelect->selectItem(m_pClipDrag, m_rectDrag, bSelect); ++iUpdate; } else if (bSelect || m_selectMode != SelectClip) { m_pClipSelect->clear(); if (bSelect) m_pClipSelect->selectItem(m_pClipDrag, m_rectDrag, true); ++iUpdate; } if (iUpdate > 0) { updateRect(rectUpdate.united(m_pClipSelect->rect())); m_pTracks->selectionChangeNotify(); } // Do the file view selection then... qtractorTrack *pTrack = m_pClipDrag->track(); if (pTrack == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; qtractorFiles *pFiles = pMainForm->files(); if (pFiles == NULL) return; switch (pTrack->trackType()) { case qtractorTrack::Audio: { qtractorAudioClip *pAudioClip = static_cast (m_pClipDrag); if (pAudioClip) pFiles->selectAudioFile(pAudioClip->filename()); break; } case qtractorTrack::Midi: { qtractorMidiClip *pMidiClip = static_cast (m_pClipDrag); if (pMidiClip) pFiles->selectMidiFile( pMidiClip->filename(), pMidiClip->trackChannel()); break; } default: break; } } // Convert selection flags from keyboard modifiers. int qtractorTrackView::selectFlags ( const Qt::KeyboardModifiers modifiers ) { int flags = SelectNone; if ((modifiers & (Qt::ShiftModifier | Qt::ControlModifier)) == 0) flags |= qtractorTrackView::SelectClear; if (modifiers & Qt::ControlModifier) flags |= qtractorTrackView::SelectToggle; return flags; } // Clip selection mode accessors. void qtractorTrackView::setSelectMode ( qtractorTrackView::SelectMode selectMode ) { m_selectMode = selectMode; } qtractorTrackView::SelectMode qtractorTrackView::selectMode (void) const { return m_selectMode; } // Select everything (clips) under a given (rubber-band) rectangle. void qtractorTrackView::selectClipRect ( const QRect& rectDrag, SelectMode selectMode, int flags, SelectEdit selectEdit ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; QRect rect(rectDrag.normalized()); // The precise (snapped) selection frame points... const unsigned long iSelectStart = pSession->frameSnap(pSession->frameFromPixel(rect.left())); const unsigned long iSelectEnd = pSession->frameSnap(pSession->frameFromPixel(rect.right())); // Special whole-vertical range case... QRect rectRange(0, 0, 0, qtractorScrollView::contentsHeight()); rectRange.setLeft(pSession->pixelFromFrame(iSelectStart)); rectRange.setRight(pSession->pixelFromFrame(iSelectEnd)); if (selectMode == SelectRange) { rect.setTop(rectRange.top()); rect.setBottom(rectRange.height()); } // Reset all selected clips... int iUpdate = 0; QRect rectUpdate = m_pClipSelect->rect(); if ((flags & SelectClear) && (m_pClipSelect->items().count() > 0)) { m_pClipSelect->clear(); ++iUpdate; } // Now find all the clips/regions that fall // in the given rectangular region... int y1, y2 = 0; qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack) { y1 = y2; y2 += pTrack->zoomHeight(); if (rect.bottom() < y1) break; if (y2 >= rect.top()) { const int y = y1 + 1; const int h = y2 - y1 - 2; for (qtractorClip *pClip = pTrack->clips().first(); pClip; pClip = pClip->next()) { const int x = pSession->pixelFromFrame(pClip->clipStart()); if (x > rect.right()) break; const int w = pSession->pixelFromFrame(pClip->clipLength()); // Test whether the whole clip rectangle // intersects the rubber-band range one... QRect rectClip(x, y, w, h); if (rect.intersects(rectClip)) { if (selectMode != SelectClip) rectClip = rectRange.intersected(rectClip); m_pClipSelect->selectItem(pClip, rectClip, true); if (selectMode != SelectClip) pClip->setClipSelect(iSelectStart, iSelectEnd); ++iUpdate; } } } pTrack = pTrack->next(); } // Update the screen real estate... if (iUpdate > 0) { updateRect(rectUpdate.united(m_pClipSelect->rect())); // m_pTracks->selectionChangeNotify(); } // That's all very nice but we'll also set edit-range positioning... if (selectEdit & EditHead) setEditHead(iSelectStart); if (selectEdit & EditTail) setEditTail(iSelectEnd); } // Select every clip of a given track-range. void qtractorTrackView::selectClipTrackRange ( qtractorTrack *pTrackPtr, bool bReset ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; const unsigned long iSelectStart = pSession->editHead(); const unsigned long iSelectEnd = pSession->editTail(); // Get and select the track's rectangular area // between the edit head and tail points... QRect rect(0, 0, 0, qtractorScrollView::contentsHeight()); rect.setLeft(pSession->pixelFromFrame(iSelectStart)); rect.setRight(pSession->pixelFromFrame(iSelectEnd)); // Reset selection (unconditional)... int iUpdate = 0; QRect rectUpdate = m_pClipSelect->rect(); if (bReset && m_pClipSelect->items().count() > 0) { m_pClipSelect->clear(); ++iUpdate; } int y1, y2 = 0; qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack) { y1 = y2; y2 += pTrack->zoomHeight(); if (pTrack == pTrackPtr || pTrackPtr == NULL) { const int y = y1 + 1; const int h = y2 - y1 - 2; rect.setY(y); rect.setHeight(h); for (qtractorClip *pClip = pTrack->clips().first(); pClip; pClip = pClip->next()) { const int x = pSession->pixelFromFrame(pClip->clipStart()); if (x > rect.right()) break; const int w = pSession->pixelFromFrame(pClip->clipLength()); // Test whether the track clip rectangle // intersects the rubber-band range one... QRect rectClip(x, y, w, h); if (rect.intersects(rectClip)) { rectClip = rect.intersected(rectClip); const bool bSelect = !pClip->isClipSelected(); m_pClipSelect->selectItem(pClip, rectClip, bSelect); if (bSelect) pClip->setClipSelect(iSelectStart, iSelectEnd); ++iUpdate; } } if (pTrack == pTrackPtr) break; } pTrack = pTrack->next(); } // This is most probably an overall update... if (iUpdate > 0) { updateRect(rectUpdate.united(m_pClipSelect->rect())); m_pTracks->selectionChangeNotify(); } // Make sure we keep focus... qtractorScrollView::setFocus(); } // Select every clip of a given track. void qtractorTrackView::selectClipTrack ( qtractorTrack *pTrackPtr, bool bReset ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Reset selection (conditional)... int iUpdate = 0; QRect rectUpdate = m_pClipSelect->rect(); if (bReset && m_pClipSelect->items().count() > 0) { // && m_pClipSelect->singleTrack() != pTrackPtr) { m_pClipSelect->clear(); ++iUpdate; } int y1, y2 = 0; qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack) { y1 = y2; y2 += pTrack->zoomHeight(); if (pTrack == pTrackPtr) { const int y = y1 + 1; const int h = y2 - y1 - 2; for (qtractorClip *pClip = pTrack->clips().first(); pClip; pClip = pClip->next()) { const int x = pSession->pixelFromFrame(pClip->clipStart()); const int w = pSession->pixelFromFrame(pClip->clipLength()); const bool bSelect = !pClip->isClipSelected(); m_pClipSelect->selectItem(pClip, QRect(x, y, w, h), bSelect); ++iUpdate; } break; } pTrack = pTrack->next(); } // This is most probably an overall update... if (iUpdate > 0) { updateRect(rectUpdate.united(m_pClipSelect->rect())); m_pTracks->selectionChangeNotify(); } // Make sure we keep focus... qtractorScrollView::setFocus(); } // Select all clip contents. void qtractorTrackView::selectClipAll (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Reset selection... int iUpdate = 0; QRect rectUpdate = m_pClipSelect->rect(); if (m_pClipSelect->items().count() > 0) { m_pClipSelect->clear(); ++iUpdate; } // Select all clips on all tracks... int y1, y2 = 0; qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack) { y1 = y2; y2 += pTrack->zoomHeight(); const int y = y1 + 1; const int h = y2 - y1 - 2; for (qtractorClip *pClip = pTrack->clips().first(); pClip; pClip = pClip->next()) { const int x = pSession->pixelFromFrame(pClip->clipStart()); const int w = pSession->pixelFromFrame(pClip->clipLength()); m_pClipSelect->selectItem(pClip, QRect(x, y, w, h)); ++iUpdate; } pTrack = pTrack->next(); } // This is most probably an overall update... if (iUpdate > 0) { updateRect(rectUpdate.united(m_pClipSelect->rect())); m_pTracks->selectionChangeNotify(); } // Make sure we keep focus... qtractorScrollView::setFocus(); } // Invert selection on all tracks and clips. void qtractorTrackView::selectClipInvert (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; int iUpdate = 0; QRect rectUpdate = m_pClipSelect->rect(); // Invert selection... int y1, y2 = 0; for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { y1 = y2; y2 += pTrack->zoomHeight(); const int y = y1 + 1; const int h = y2 - y1 - 2; for (qtractorClip *pClip = pTrack->clips().first(); pClip; pClip = pClip->next()) { const int x = pSession->pixelFromFrame(pClip->clipStart()); const int w = pSession->pixelFromFrame(pClip->clipLength()); const bool bSelect = !pClip->isClipSelected(); m_pClipSelect->selectItem(pClip, QRect(x, y, w, h), bSelect); ++iUpdate; } } // This is most probably an overall update... if (iUpdate > 0) { updateRect(rectUpdate.united(m_pClipSelect->rect())); m_pTracks->selectionChangeNotify(); } // Make sure we keep focus... qtractorScrollView::setFocus(); } // Select all clips of given filename and track/channel. void qtractorTrackView::selectClipFile ( qtractorTrack::TrackType trackType, const QString& sFilename, int iTrackChannel, bool bSelect ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Reset selection (conditional)... int iUpdate = 0; QRect rectUpdate = m_pClipSelect->rect(); if (m_pClipSelect->items().count() > 0 && (QApplication::keyboardModifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) == 0) { m_pClipSelect->clear(); ++iUpdate; } int x0 = qtractorScrollView::contentsWidth(); int y0 = qtractorScrollView::contentsHeight(); int y1, y2 = 0; for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { y1 = y2; y2 += pTrack->zoomHeight(); if (pTrack->trackType() != trackType) continue; const int y = y1 + 1; const int h = y2 - y1 - 2; for (qtractorClip *pClip = pTrack->clips().first(); pClip; pClip = pClip->next()) { if (pClip->filename() != sFilename) continue; if (iTrackChannel >= 0 && trackType == qtractorTrack::Midi) { qtractorMidiClip *pMidiClip = static_cast (pClip); if (pMidiClip && int(pMidiClip->trackChannel()) != iTrackChannel) continue; } const int x = pSession->pixelFromFrame(pClip->clipStart()); const int w = pSession->pixelFromFrame(pClip->clipLength()); m_pClipSelect->selectItem(pClip, QRect(x, y, w, h), bSelect); if (x0 > x) x0 = x; if (y0 > y) y0 = y; ++iUpdate; } } // This is most probably an overall update... if (iUpdate > 0) { updateRect(rectUpdate.united(m_pClipSelect->rect())); m_pTracks->selectionChangeNotify(); // Make sure the earliest is barely visible... if (isClipSelected()) qtractorScrollView::ensureVisible(x0, y0, 24, 24); } // Make sure we keep focus... (maybe not:) // qtractorScrollView::setFocus(); } // Select curve nodes under a given (rubber-band) rectangle. void qtractorTrackView::selectCurveRect ( const QRect& rectDrag, SelectMode selectMode, int flags, SelectEdit selectEdit ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; QRect rect(rectDrag.normalized()); // The precise (snapped) selection frame points... const unsigned long iSelectStart = pSession->frameSnap(pSession->frameFromPixel(rect.left())); const unsigned long iSelectEnd = pSession->frameSnap(pSession->frameFromPixel(rect.right())); // Special whole-vertical range case... rect.setLeft(pSession->pixelFromFrame(iSelectStart)); rect.setRight(pSession->pixelFromFrame(iSelectEnd)); if (selectMode == SelectRange) { rect.setTop(0); rect.setBottom(qtractorScrollView::contentsHeight()); } // Reset all selected nodes... int iUpdate = 0; QRect rectUpdate = m_pCurveSelect->rect(); if ((flags & SelectClear) && (m_pCurveSelect->items().count() > 0)) { m_pCurveSelect->clear(); ++iUpdate; } // Now find all the curve/nodes that fall // in the given rectangular region... const bool bToggle = (flags & SelectToggle); int x1 = qtractorScrollView::contentsX(); int x2 = x1 + (qtractorScrollView::viewport())->width(); if (x1 > rect.left()) x1 = rect.left(); if (x2 < rect.right()) x2 = rect.right(); int y1, y2 = 0; qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack) { y1 = y2; y2 += pTrack->zoomHeight(); if (y1 > rect.bottom()) break; if (y2 >= rect.top()) { qtractorCurve *pCurve = pTrack->currentCurve(); if (pCurve && !pCurve->isLocked()) { const int h = y2 - y1 - 2; const unsigned long iFrameStart = pSession->frameFromPixel(x1); const unsigned long iFrameEnd = pSession->frameFromPixel(x2); qtractorCurve::Cursor cursor(pCurve); qtractorCurve::Node *pNode = cursor.seek(iFrameStart); while (pNode && pNode->frame < iFrameEnd) { const int x = pSession->pixelFromFrame(pNode->frame); const int y = y2 - int(cursor.scale(pNode) * float(h)); const bool bSelect = rect.contains(x, y); m_pCurveSelect->selectItem(pCurve, pNode, QRect(x - 4, y - 4, 8, 8), bSelect, bToggle); ++iUpdate; pNode = pNode->next(); } if (m_pCurveSelect->isCurrentCurve(pCurve)) break; } } pTrack = pTrack->next(); } // Update the screen real estate... if (iUpdate > 0) { m_pCurveSelect->update(flags & SelectCommit); updateRect(rectUpdate.united(m_pCurveSelect->rect())); // m_pTracks->selectionChangeNotify(); } // That's all very nice but we'll also set edit-range positioning... if (selectEdit & EditHead) setEditHead(iSelectStart); if (selectEdit & EditTail) setEditTail(iSelectEnd); } // Select every current curve/automation node of a given track-range. void qtractorTrackView::selectCurveTrackRange ( qtractorTrack *pTrackPtr, bool bReset ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; const unsigned long iSelectStart = pSession->editHead(); const unsigned long iSelectEnd = pSession->editTail(); // Get and select the track's rectangular area // between the edit head and tail points... QRect rect(0, 0, 0, qtractorScrollView::contentsHeight()); rect.setLeft(pSession->pixelFromFrame(iSelectStart)); rect.setRight(pSession->pixelFromFrame(iSelectEnd)); // Reset selection (unconditional)... if (pTrackPtr && !bReset) bReset = !m_pCurveSelect->isCurrentCurve(pTrackPtr->currentCurve()); int iUpdate = 0; QRect rectUpdate = m_pCurveSelect->rect(); if (bReset && m_pCurveSelect->items().count() > 0) { m_pCurveSelect->clear(); ++iUpdate; } int y1, y2 = 0; qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack) { y1 = y2; y2 += pTrack->zoomHeight(); if (pTrack == pTrackPtr || pTrackPtr == NULL) { qtractorCurve *pCurve = pTrack->currentCurve(); if (pCurve && !pCurve->isLocked()) { const int h = y2 - y1 - 2; rect.setY(y1 + 1); rect.setHeight(h); qtractorCurve::Node *pNode = pCurve->nodes().first(); while (pNode) { const float s = pCurve->scaleFromValue(pNode->value); const int x = pSession->pixelFromFrame(pNode->frame); const int y = y2 - int(s * float(h)); const bool bSelect = rect.contains(x, y); m_pCurveSelect->selectItem(pCurve, pNode, QRect(x - 4, y - 4, 8, 8), bSelect, !bReset); ++iUpdate; pNode = pNode->next(); } } if (pTrackPtr || m_pCurveSelect->isCurrentCurve(pCurve)) break; } pTrack = pTrack->next(); } // This is most probably an overall update... if (iUpdate > 0) { m_pCurveSelect->update(true); updateRect(rectUpdate.united(m_pCurveSelect->rect())); m_pTracks->selectionChangeNotify(); } // Make sure we keep focus... qtractorScrollView::setFocus(); } // Select every current curve/automation node of a given track. void qtractorTrackView::selectCurveTrack ( qtractorTrack *pTrackPtr, bool bReset ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Reset selection (conditional)... if (pTrackPtr && !bReset) bReset = !m_pCurveSelect->isCurrentCurve(pTrackPtr->currentCurve()); int iUpdate = 0; QRect rectUpdate = m_pCurveSelect->rect(); if (bReset && m_pCurveSelect->items().count() > 0) { m_pCurveSelect->clear(); ++iUpdate; } int y1, y2 = 0; qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack) { y1 = y2; y2 += pTrack->zoomHeight(); if (pTrack == pTrackPtr || pTrackPtr == NULL) { qtractorCurve *pCurve = pTrack->currentCurve(); if (pCurve && !pCurve->isLocked()) { const int h = y2 - y1 - 2; qtractorCurve::Node *pNode = pCurve->nodes().first(); while (pNode) { const float s = pCurve->scaleFromValue(pNode->value); const int x = pSession->pixelFromFrame(pNode->frame); const int y = y2 - int(s * float(h)); m_pCurveSelect->selectItem(pCurve, pNode, QRect(x - 4, y - 4, 8, 8), true, !bReset); ++iUpdate; pNode = pNode->next(); } } if (pTrackPtr || m_pCurveSelect->isCurrentCurve(pCurve)) break; } pTrack = pTrack->next(); } // This is most probably an overall update... if (iUpdate > 0) { m_pCurveSelect->update(true); updateRect(rectUpdate.united(m_pCurveSelect->rect())); m_pTracks->selectionChangeNotify(); } // Make sure we keep focus... qtractorScrollView::setFocus(); } // Select all current track curve/automation nodes. void qtractorTrackView::selectCurveAll (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorTrack *pCurrentTrack = m_pTracks->currentTrack(); if (pCurrentTrack == NULL) return; int iUpdate = 0; QRect rectUpdate = m_pCurveSelect->rect(); if (m_pCurveSelect->items().count() > 0) { m_pCurveSelect->clear(); ++iUpdate; } // Select all current track/curve automation nodes... int y1, y2 = 0; qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack) { y1 = y2; y2 += pTrack->zoomHeight(); if (pCurrentTrack == pTrack) { qtractorCurve *pCurve = pTrack->currentCurve(); if (pCurve && !pCurve->isLocked()) { const int h = y2 - y1 - 2; qtractorCurve::Node *pNode = pCurve->nodes().first(); while (pNode) { const float s = pCurve->scaleFromValue(pNode->value); const int x = pSession->pixelFromFrame(pNode->frame); const int y = y2 - int(s * float(h)); m_pCurveSelect->selectItem(pCurve, pNode, QRect(x - 4, y - 4, 8, 8)); ++iUpdate; pNode = pNode->next(); } } break; } pTrack = pTrack->next(); } // This is most probably an overall update... if (iUpdate > 0) { m_pCurveSelect->update(true); updateRect(rectUpdate.united(m_pCurveSelect->rect())); m_pTracks->selectionChangeNotify(); } // Make sure we keep focus... qtractorScrollView::setFocus(); } // Invert selection on current track curve/automation nodes. void qtractorTrackView::selectCurveInvert (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; int iUpdate = 0; QRect rectUpdate = m_pCurveSelect->rect(); int y1, y2 = 0; qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack) { y1 = y2; y2 += pTrack->zoomHeight(); qtractorCurve *pCurve = pTrack->currentCurve(); if (pCurve && !pCurve->isLocked()) { const int h = y2 - y1 - 2; qtractorCurve::Node *pNode = pCurve->nodes().first(); while (pNode) { const float s = pCurve->scaleFromValue(pNode->value); const int x = pSession->pixelFromFrame(pNode->frame); const int y = y2 - int(s * float(h)); m_pCurveSelect->selectItem(pCurve, pNode, QRect(x - 4, y - 4, 8, 8), true, true); ++iUpdate; pNode = pNode->next(); } if (m_pCurveSelect->isCurrentCurve(pCurve)) break; } pTrack = pTrack->next(); } // This is most probably an overall update... if (iUpdate > 0) { m_pCurveSelect->update(true); updateRect(rectUpdate.united(m_pCurveSelect->rect())); m_pTracks->selectionChangeNotify(); } // Make sure we keep focus... qtractorScrollView::setFocus(); } // Contents update overloaded methods. void qtractorTrackView::updateRect ( const QRect& rect ) { qtractorScrollView::update( // Add some slack margin... QRect(qtractorScrollView::contentsToViewport( rect.topLeft()), rect.size() + QSize(4, 4))); } // Whether there's any clip currently editable. qtractorClip *qtractorTrackView::currentClip (void) const { qtractorClip *pClip = m_pClipDrag; if (pClip == NULL && isClipSelected()) pClip = m_pClipSelect->items().constBegin().key(); return pClip; } // Clip selection accessor. qtractorClipSelect *qtractorTrackView::clipSelect (void) const { return m_pClipSelect; } // Update whole clip selection. void qtractorTrackView::updateClipSelect (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Reset all selected clips, but don't // clear their own selection state... m_pClipSelect->reset(); // Now find all the clips/regions // that were currently selected... int y1, y2 = 0; qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack) { y1 = y2; y2 += pTrack->zoomHeight(); const int y = y1 + 1; const int h = y2 - y1 - 2; for (qtractorClip *pClip = pTrack->clips().first(); pClip; pClip = pClip->next()) { if (pClip->isClipSelected()) { const int x = pSession->pixelFromFrame(pClip->clipSelectStart()); const int w = pSession->pixelFromFrame(pClip->clipSelectEnd()) - x; m_pClipSelect->addItem(pClip, QRect(x, y, w, h)); } } pTrack = pTrack->next(); } } // Show selection tooltip... void qtractorTrackView::showToolTip ( const QRect& rect, int dx ) const { if (!m_bToolTips) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorTimeScale *pTimeScale = pSession->timeScale(); if (pTimeScale == NULL) return; const unsigned long iFrameStart = pTimeScale->frameSnap( pTimeScale->frameFromPixel(rect.left() + dx)); const unsigned long iFrameEnd = pTimeScale->frameSnap( iFrameStart + pTimeScale->frameFromPixel(rect.width())); QToolTip::showText( QCursor::pos(), tr("Start:\t%1\nEnd:\t%2\nLength:\t%3") .arg(pTimeScale->textFromFrame(iFrameStart)) .arg(pTimeScale->textFromFrame(iFrameEnd)) .arg(pTimeScale->textFromFrame(iFrameStart, true, iFrameEnd - iFrameStart)), qtractorScrollView::viewport()); } // Draw/hide the whole current clip selection. void qtractorTrackView::showClipSelect (void) const { const qtractorClipSelect::ItemList& items = m_pClipSelect->items(); qtractorClipSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorClipSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorClipSelect::Item *pClipItem = iter.value(); QRect rectClip = pClipItem->rectClip; if (m_bDragSingleTrack) { rectClip.setY(m_iDragSingleTrackY); rectClip.setHeight(m_iDragSingleTrackHeight); } moveRubberBand(&(pClipItem->rubberBand), rectClip, 3); } showToolTip(m_pClipSelect->rect(), m_iDragClipX); } void qtractorTrackView::hideClipSelect (void) const { const qtractorClipSelect::ItemList& items = m_pClipSelect->items(); qtractorClipSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorClipSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorRubberBand *pRubberBand = iter.value()->rubberBand; if (pRubberBand && pRubberBand->isVisible()) pRubberBand->hide(); } } // Draw/hide the whole drop rectagle list void qtractorTrackView::updateClipDropRects ( int y, int h ) const { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; int x = 0; const bool bDropSpan = (m_bDropSpan && m_dropType != qtractorTrack::Midi); QListIterator iter(m_dropItems); while (iter.hasNext()) { DropItem *pDropItem = iter.next(); pDropItem->rect.setY(y); pDropItem->rect.setHeight(h); if (bDropSpan) { if (x > 0) pDropItem->rect.moveLeft(x); else x = pDropItem->rect.x(); x = pSession->pixelSnap(x + pDropItem->rect.width()); } else { y += h + 4; } } } void qtractorTrackView::showClipDropRects (void) const { QRect rect; QListIterator iter(m_dropItems); while (iter.hasNext()) { DropItem *pDropItem = iter.next(); moveRubberBand(&(pDropItem->rubberBand), pDropItem->rect, 3); rect = rect.united(pDropItem->rect); } showToolTip(rect, m_iDragClipX); } void qtractorTrackView::hideClipDropRects (void) const { QListIterator iter(m_dropItems); while (iter.hasNext()) { qtractorRubberBand *pRubberBand = iter.next()->rubberBand; if (pRubberBand && pRubberBand->isVisible()) pRubberBand->hide(); } } // Show and move rubber-band item. void qtractorTrackView::moveRubberBand ( qtractorRubberBand **ppRubberBand, const QRect& rectDrag, int thick ) const { QRect rect(rectDrag.normalized()); // Horizontal adjust... rect.translate(m_iDragClipX, 0); // Convert rectangle into view coordinates... rect.moveTopLeft(qtractorScrollView::contentsToViewport(rect.topLeft())); // Make sure the rectangle doesn't get too off view, // which it would make it sluggish :) if (rect.left() < 0) rect.setLeft(-8); if (rect.right() > qtractorScrollView::width()) rect.setRight(qtractorScrollView::width() + 8); // Create the rubber-band if there's none... qtractorRubberBand *pRubberBand = *ppRubberBand; if (pRubberBand == NULL) { pRubberBand = new qtractorRubberBand( QRubberBand::Rectangle, qtractorScrollView::viewport(), thick); // QPalette pal(pRubberBand->palette()); // pal.setColor(pRubberBand->foregroundRole(), Qt::blue); // pRubberBand->setPalette(pal); // pRubberBand->setBackgroundRole(QPalette::NoRole); // Do not ever forget to set it back... *ppRubberBand = pRubberBand; } // Just move it pRubberBand->setGeometry(rect); // Ah, and make it visible, of course... if (!pRubberBand->isVisible()) pRubberBand->show(); } // Check whether we're up to drag a clip fade-in/out or resize handle. bool qtractorTrackView::dragMoveStart ( const QPoint& pos ) { qtractorTrackViewInfo tvi; qtractorTrack *pTrack = trackAt(pos, false, &tvi); if (pTrack == NULL) return false; qtractorCurve::Node *pNode = m_pDragCurveNode; if (pNode == NULL) pNode = nodeAtTrack(pos, pTrack, &tvi); if (pNode) { if (m_bCurveEdit && m_dragState == DragStart && (m_pCurveSelect->items().count() > 1) && (m_pCurveSelect->findItem(pNode))) m_dragCursor = DragCurveMove; else m_dragCursor = DragCurveNode; qtractorScrollView::setCursor(QCursor(Qt::PointingHandCursor)); return true; } qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return false; QRect rectClip; qtractorClip *pClip = clipAtTrack(pos, &rectClip, pTrack, &tvi); if (pClip) { // Fade-in handle check... m_rectHandle.setRect(rectClip.left() + 1 + pSession->pixelFromFrame(pClip->fadeInLength()), rectClip.top() + 1, 8, 8); if (m_rectHandle.contains(pos)) { m_dragCursor = DragClipFadeIn; qtractorScrollView::setCursor(QCursor(Qt::PointingHandCursor)); return true; } // Fade-out handle check... m_rectHandle.setRect(rectClip.right() - 8 - pSession->pixelFromFrame(pClip->fadeOutLength()), rectClip.top() + 1, 8, 8); if (m_rectHandle.contains(pos)) { m_dragCursor = DragClipFadeOut; qtractorScrollView::setCursor(QCursor(Qt::PointingHandCursor)); return true; } // Resize-right check... if (pos.x() >= rectClip.right() - 4) { m_dragCursor = DragClipResizeRight; qtractorScrollView::setCursor(QCursor(Qt::SizeHorCursor)); return true; } // Resize-left check... if (pos.x() < rectClip.left() + 4) { m_dragCursor = DragClipResizeLeft; qtractorScrollView::setCursor(QCursor(Qt::SizeHorCursor)); return true; } } // Reset cursor if any persist around. if (m_dragCursor != DragNone) { qtractorScrollView::unsetCursor(); m_dragCursor = DragNone; } return false; } // Clip fade-in/out handle drag-moving parts. void qtractorTrackView::dragClipFadeMove ( const QPoint& pos ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Always change horizontally wise... const int x0 = pSession->pixelSnap(pos.x()); int dx = (x0 - m_posDrag.x()); if (m_rectHandle.left() + dx < m_rectDrag.left()) dx = m_rectDrag.left() - m_rectHandle.left(); else if (m_rectHandle.right() + dx > m_rectDrag.right()) dx = m_rectDrag.right() - m_rectHandle.right(); m_iDragClipX = dx; moveRubberBand(&m_pRubberBand, m_rectHandle); qtractorScrollView::ensureVisible(pos.x(), pos.y(), 24, 24); // Prepare to update the whole view area... updateRect(m_rectDrag); // Show fade-in/out tooltip.. QRect rect(m_rectDrag); if (m_dragState == DragClipFadeIn) rect.setRight(m_rectHandle.left() + m_iDragClipX); else if (m_dragState == DragClipFadeOut) rect.setLeft(m_rectHandle.right() + m_iDragClipX); showToolTip(rect, 0); } // Clip fade-in/out handle settler. void qtractorTrackView::dragClipFadeDrop ( const QPoint& pos ) { if (m_pClipDrag == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; dragClipFadeMove(pos); // We'll build a command... qtractorClipCommand *pClipCommand = new qtractorClipCommand(tr("clip %1").arg( m_dragState == DragClipFadeIn ? tr("fade-in") : tr("fade-out"))); if (m_dragState == DragClipFadeIn) { pClipCommand->fadeInClip(m_pClipDrag, pSession->frameFromPixel( m_rectHandle.left() + m_iDragClipX - m_rectDrag.left()), m_pClipDrag->fadeInType()); } else if (m_dragState == DragClipFadeOut) { pClipCommand->fadeOutClip(m_pClipDrag, pSession->frameFromPixel( m_rectDrag.right() - m_iDragClipX - m_rectHandle.right()), m_pClipDrag->fadeOutType()); } // Reset state for proper redrawing... m_dragState = DragNone; // Put it in the form of an undoable command... pSession->execute(pClipCommand); } // Clip resize handle drag-moving parts. void qtractorTrackView::dragClipResizeMove ( const QPoint& pos ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Always change horizontally wise... int x = 0; const int dx = (pos.x() - m_posDrag.x()); QRect rect(m_rectDrag); if (m_dragState == DragClipResizeLeft) { if (rect.left() > -(dx)) x = pSession->pixelSnap(rect.left() + dx); if (x < 0) x = 0; else if (x > rect.right() - 8) x = rect.right() - 8; rect.setLeft(x); } else if (m_dragState == DragClipResizeRight) { if (rect.right() > -(dx)) x = pSession->pixelSnap(rect.right() + dx); if (x < rect.left() + 8) x = rect.left() + 8; rect.setRight(x); } moveRubberBand(&m_pRubberBand, rect, 3); showToolTip(rect, 0); qtractorScrollView::ensureVisible(pos.x(), pos.y(), 24, 24); } // Clip resize handle settler. void qtractorTrackView::dragClipResizeDrop ( const QPoint& pos, bool bTimeStretch ) { if (m_pClipDrag == NULL) return; if (!m_pClipDrag->queryEditor()) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // We'll build a command... qtractorClipCommand *pClipCommand = new qtractorClipCommand( bTimeStretch ? tr("clip stretch") : tr("clip resize")); unsigned long iClipStart = m_pClipDrag->clipStart(); unsigned long iClipOffset = m_pClipDrag->clipOffset(); unsigned long iClipLength = m_pClipDrag->clipLength(); // Always change horizontally wise... int x = 0; const int dx = (pos.x() - m_posDrag.x()); if (m_dragState == DragClipResizeLeft) { unsigned long iClipDelta; x = m_rectDrag.left() + dx; if (x < 0) x = 0; else if (x > m_rectDrag.right() - 8) x = m_rectDrag.right() - 8; iClipStart = pSession->frameSnap(pSession->frameFromPixel(x)); if (m_pClipDrag->clipStart() > iClipStart) { iClipDelta = (m_pClipDrag->clipStart() - iClipStart); if (!bTimeStretch) { if (iClipOffset > iClipDelta) iClipOffset -= iClipDelta; else iClipOffset = 0; } iClipLength += iClipDelta; } else { iClipDelta = (iClipStart - m_pClipDrag->clipStart()); if (!bTimeStretch) iClipOffset += iClipDelta; iClipLength -= iClipDelta; } } else if (m_dragState == DragClipResizeRight) { x = m_rectDrag.right() + dx; if (x < m_rectDrag.left() + 8) x = m_rectDrag.left() + 8; iClipLength = pSession->frameSnap(pSession->frameFromPixel(x)) - iClipStart; } // Time stretching... float fTimeStretch = 0.0f; if (bTimeStretch && m_pClipDrag->track()) { float fOldTimeStretch = 1.0f; if ((m_pClipDrag->track())->trackType() == qtractorTrack::Audio) { qtractorAudioClip *pAudioClip = static_cast (m_pClipDrag); if (pAudioClip) fOldTimeStretch = pAudioClip->timeStretch(); } fTimeStretch = (float(iClipLength) * fOldTimeStretch) / float(m_pClipDrag->clipLength()); } // Declare the clip resize parcel... pClipCommand->resizeClip(m_pClipDrag, iClipStart, iClipOffset, iClipLength, fTimeStretch); // Put it in the form of an undoable command... pSession->execute(pClipCommand); } // Automation curve node drag-move methods. void qtractorTrackView::dragCurveNode ( const QPoint& pos, bool bToggle ) { qtractorTrackViewInfo tvi; qtractorTrack *pTrack = trackAt(pos, false, &tvi); if (pTrack == NULL) return; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return; qtractorCurveList *pCurveList = pTrack->curveList(); if (pCurveList == NULL) return; qtractorCurve *pCurve = pCurveList->currentCurve(); if (pCurve == NULL) return; if (pCurve->isLocked()) return; if (m_pDragCurve && m_pDragCurve != pCurve) return; if (m_pCurveEditCommand == NULL) m_pCurveEditCommand = new qtractorCurveEditCommand(pCurve); qtractorCurve::Node *pNode = m_pDragCurveNode; m_pDragCurveNode = NULL; if (pNode && m_dragState == DragCurveNode) { m_pCurveSelect->removeItem(pNode); m_pCurveEditCommand->removeNode(pNode); pCurve->unlinkNode(pNode); pNode = NULL; } if (m_pDragCurve == NULL) { m_pDragCurve = pCurve; m_dragCursor = DragCurveNode; qtractorScrollView::setCursor(QCursor(Qt::PointingHandCursor)); } qtractorScrollView::ensureVisible(pos.x(), pos.y(), 24, 24); const int h = tvi.trackRect.height(); const int y2 = tvi.trackRect.bottom() + 1; if (pNode == NULL) { qtractorCurveEditList edits(pCurve); const unsigned long frame = pSession->frameSnap(pSession->frameFromPixel(pos.x())); const float value = pCurve->valueFromScale(float(y2 - pos.y()) / float(h)); pNode = pCurve->addNode(frame, value, &edits); m_pCurveEditCommand->addEditList(&edits); } if (pNode) { const float s = pCurve->scaleFromValue(pNode->value); const int x = pSession->pixelFromFrame(pNode->frame); const int y = y2 - int(s * float(h)); const QRect rectUpdate = m_pCurveSelect->rect(); m_pCurveSelect->selectItem(pCurve, pNode, QRect(x - 4, y - 4, 8, 8), true, bToggle); m_pCurveSelect->update(true); updateRect(rectUpdate.united(m_pCurveSelect->rect())); m_pDragCurveNode = pNode; if (m_bToolTips) { QWidget *pViewport = qtractorScrollView::viewport(); QToolTip::showText(pViewport->mapToGlobal(contentsToViewport(pos)), nodeToolTip(m_pDragCurve, m_pDragCurveNode), pViewport); } } } // Common tool-tip builder for automation nodes. QString qtractorTrackView::nodeToolTip ( qtractorCurve *pCurve, qtractorCurve::Node *pNode) const { QString sToolTip; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { qtractorTimeScale *pTimeScale = pSession->timeScale(); if (pTimeScale) { sToolTip = QString("(%2, %3)") .arg(pTimeScale->textFromFrame(pNode->frame)) .arg(pNode->value); if (pCurve) { qtractorSubject *pSubject = pCurve->subject(); if (pSubject) { sToolTip = QString("%1\n%2") .arg(pSubject->name()) .arg(sToolTip); } } } } return sToolTip; } // Reset drag/select/move state. void qtractorTrackView::resetDragState (void) { // To remember what we were doing... const DragState dragState = m_dragState; // Should fallback mouse cursor... if (m_dragCursor != DragNone) qtractorScrollView::unsetCursor(); if (m_dragState == DragClipStep) m_pClipSelect->clear(); if (m_dragState == DragCurveStep) m_pCurveSelect->clear(); if (m_dragState == DragClipResizeLeft || m_dragState == DragClipResizeRight || m_dragState == DragClipPasteDrop || m_dragState == DragClipPaste || m_dragState == DragClipStep || m_dragState == DragClipMove || m_dragState == DragCurvePaste || m_dragState == DragCurveStep || m_dragState == DragCurveMove) { updateContents(); } // Force null state, now. m_dragState = DragNone; m_dragCursor = DragNone; m_iDragClipX = 0; // m_pClipDrag = NULL; m_posStep = QPoint(0, 0); // No pasting nomore. m_iPasteCount = 0; m_iPastePeriod = 0; // Single track dragging reset. m_bDragSingleTrack = false; m_iDragSingleTrackY = 0; m_iDragSingleTrackHeight = 0; // Automation curve stuff reset. m_pDragCurve = NULL; m_pDragCurveNode = NULL; m_iDragCurveX = 0; if (m_pCurveEditCommand) delete m_pCurveEditCommand; m_pCurveEditCommand = NULL; // If we were moving clips around, // just hide selection, of course. hideClipSelect(); // Just hide the rubber-band... if (m_pRubberBand) { m_pRubberBand->hide(); delete m_pRubberBand; m_pRubberBand = NULL; } // If we were dragging fade-slope lines, refresh... if (dragState == DragClipFadeIn || dragState == DragClipFadeOut) updateRect(m_rectDrag); // No dropping files, whatsoever. qDeleteAll(m_dropItems); m_dropItems.clear(); m_dropType = qtractorTrack::None; } // Keyboard event handler. void qtractorTrackView::keyPressEvent ( QKeyEvent *pKeyEvent ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorTrackView::keyPressEvent(%d)", pKeyEvent->key()); #endif const int iKey = pKeyEvent->key(); switch (iKey) { case Qt::Key_Insert: // Aha, joking :) case Qt::Key_Return: if (m_dragState == DragClipStep) moveClipSelect(dragClipMove(m_posDrag + m_posStep)); else if (m_dragState == DragCurveStep) moveCurveSelect(m_posDrag + m_posStep); else { const QPoint& pos = qtractorScrollView::viewportToContents( qtractorScrollView::viewport()->mapFromGlobal(QCursor::pos())); if (m_dragState == DragClipMove) moveClipSelect(dragClipMove(pos + m_posStep)); else if (m_dragState == DragClipPaste) pasteClipSelect(dragClipMove(pos + m_posStep)); else if (m_dragState == DragClipPasteDrop) dropClip(pos + m_posStep); else if (m_dragState == DragCurveMove) moveCurveSelect(pos + m_posStep); else if (m_dragState == DragCurvePaste) pasteCurveSelect(pos + m_posStep); } // Fall thru... case Qt::Key_Escape: // HACK: Force selection clearance! m_dragState = (m_bCurveEdit ? DragCurveStep : DragClipStep); resetDragState(); break; case Qt::Key_Home: if (pKeyEvent->modifiers() & Qt::ControlModifier) { qtractorScrollView::setContentsPos(0, 0); } else { qtractorScrollView::setContentsPos( 0, qtractorScrollView::contentsY()); } break; case Qt::Key_End: if (pKeyEvent->modifiers() & Qt::ControlModifier) { qtractorScrollView::setContentsPos( qtractorScrollView::contentsWidth(), qtractorScrollView::contentsHeight()); } else { qtractorScrollView::setContentsPos( qtractorScrollView::contentsWidth(), qtractorScrollView::contentsY()); } break; case Qt::Key_Left: if (pKeyEvent->modifiers() & Qt::ControlModifier) { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX() - qtractorScrollView::width(), qtractorScrollView::contentsY()); } else if (!keyStep(iKey)) { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX() - 16, qtractorScrollView::contentsY()); } break; case Qt::Key_Right: if (pKeyEvent->modifiers() & Qt::ControlModifier) { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX() + qtractorScrollView::width(), qtractorScrollView::contentsY()); } else if (!keyStep(iKey)) { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX() + 16, qtractorScrollView::contentsY()); } break; case Qt::Key_Up: if (pKeyEvent->modifiers() & Qt::ControlModifier) { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX(), qtractorScrollView::contentsY() - qtractorScrollView::height()); } else if (!keyStep(iKey)) { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX(), qtractorScrollView::contentsY() - 16); } break; case Qt::Key_Down: if (pKeyEvent->modifiers() & Qt::ControlModifier) { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX(), qtractorScrollView::contentsY() + qtractorScrollView::height()); } else if (!keyStep(iKey)) { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX(), qtractorScrollView::contentsY() + 16); } break; case Qt::Key_PageUp: if (pKeyEvent->modifiers() & Qt::ControlModifier) { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX(), 16); } else { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX(), qtractorScrollView::contentsY() - qtractorScrollView::height()); } break; case Qt::Key_PageDown: if (pKeyEvent->modifiers() & Qt::ControlModifier) { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX(), qtractorScrollView::contentsHeight()); } else { qtractorScrollView::setContentsPos( qtractorScrollView::contentsX(), qtractorScrollView::contentsY() + qtractorScrollView::height()); } break; default: qtractorScrollView::keyPressEvent(pKeyEvent); break; } } // Keyboard step handler. bool qtractorTrackView::keyStep ( int iKey ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // Set initial bound conditions... if (m_dragState == DragNone) { if (isClipSelected() || !m_dropItems.isEmpty()) { m_dragState = m_dragCursor = DragClipStep; m_rectDrag = m_pClipSelect->rect(); m_posDrag = m_rectDrag.topLeft(); m_posStep = QPoint(0, 0); m_iDragClipX = (pSession->pixelSnap(m_rectDrag.x()) - m_rectDrag.x()); qtractorScrollView::setCursor(QCursor(Qt::SizeAllCursor)); } else if (isCurveSelected() && m_bCurveEdit && iKey != Qt::Key_Up && iKey != Qt::Key_Down) { m_dragState = m_dragCursor = DragCurveStep; m_rectDrag = m_pCurveSelect->rect(); m_posDrag = m_rectDrag.topLeft(); m_posStep = QPoint(0, 0); m_iDragCurveX = (pSession->pixelSnap(m_rectDrag.x()) - m_rectDrag.x()); qtractorScrollView::setCursor(QCursor(Qt::SizeHorCursor)); } } // Now to say the truth... const bool bClipStep = m_dragState == DragClipMove || m_dragState == DragClipStep || m_dragState == DragClipPaste || m_dragState == DragClipPasteDrop; const bool bCurveStep = m_dragState == DragCurveMove || m_dragState == DragCurveStep || m_dragState == DragCurvePaste; if (!bClipStep && !bCurveStep) return false; // Determine vertical step... if (iKey == Qt::Key_Up || iKey == Qt::Key_Down) { if (bClipStep) { int iVerticalStep = qtractorTrack::HeightMin; qtractorTrack *pTrack = m_pTracks->currentTrack(); if (pTrack) iVerticalStep += (pTrack->zoomHeight() >> 1); int y0 = m_posDrag.y(); int y1 = y0 + m_posStep.y(); if (iKey == Qt::Key_Up) y1 -= iVerticalStep; else y1 += iVerticalStep; m_posStep.setY((y1 < 0 ? 0 : y1) - y0); } } else // Determine horizontal step... if (iKey == Qt::Key_Left || iKey == Qt::Key_Right) { int iHorizontalStep = 0; const int x0 = m_posDrag.x(); int x1 = x0 + m_posStep.x(); qtractorTimeScale::Cursor cursor(pSession->timeScale()); qtractorTimeScale::Node *pNode = cursor.seekPixel(x1); const unsigned short iSnapPerBeat = pSession->snapPerBeat(); if (iSnapPerBeat > 0) iHorizontalStep = pNode->pixelsPerBeat() / iSnapPerBeat; if (iHorizontalStep < 1) iHorizontalStep = 1; if (iKey == Qt::Key_Left) x1 -= iHorizontalStep; else x1 += iHorizontalStep; m_posStep.setX(pSession->pixelSnap(x1 < 0 ? 0 : x1) - x0); } // Early sanity check... QRect rect = m_rectDrag; if (bClipStep && m_dragState != DragClipPasteDrop) rect = m_pClipSelect->rect(); else if (bCurveStep) rect = m_pCurveSelect->rect(); QPoint pos = m_posDrag; if (m_dragState != DragClipStep && m_dragState != DragCurveStep) { pos = qtractorScrollView::viewportToContents( qtractorScrollView::viewport()->mapFromGlobal(QCursor::pos())); } int x2 = - pos.x(); int y2 = - pos.y(); if (m_dragState != DragClipStep && m_dragState != DragCurveStep) { x2 += (m_posDrag.x() - rect.x()); y2 += (m_posDrag.y() - rect.y()); } if (m_posStep.x() < x2) { m_posStep.setX (x2); } else { x2 += qtractorScrollView::contentsWidth() - (rect.width() >> 1); if (m_posStep.x() > x2) m_posStep.setX (x2); } if (bClipStep) { if (m_posStep.y() < y2) { m_posStep.setY (y2); } else { y2 += qtractorScrollView::contentsHeight() - (rect.height() >> 1); if (m_posStep.y() > y2) m_posStep.setY (y2); } } // Do our deeds (flag we're key-steppin')... if (m_dragState == DragClipPasteDrop) { dragClipDrop(pos + m_posStep, true); showClipDropRects(); } else if (bClipStep) { dragClipMove(pos + m_posStep, true); } else if (bCurveStep) { dragCurveMove(pos + m_posStep, true); } return true; } // Make given frame position visible in view. void qtractorTrackView::ensureVisibleFrame ( unsigned long iFrame ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { const int x0 = qtractorScrollView::contentsX(); const int y = qtractorScrollView::contentsY(); const int w = m_pixmap.width(); const int w3 = w - (w >> 3); int x = pSession->pixelFromFrame(iFrame); if (x < x0) x -= w3; else if (x > x0 + w3) x += w3; qtractorScrollView::ensureVisible(x, y, 0, 0); // qtractorScrollView::setFocus(); } } // Session cursor accessor. qtractorSessionCursor *qtractorTrackView::sessionCursor (void) const { return m_pSessionCursor; } // Vertical line positioning. void qtractorTrackView::drawPositionX ( int& iPositionX, int x, bool bSyncView ) { // Update track-view position... const int x0 = qtractorScrollView::contentsX(); const int w = qtractorScrollView::width(); const int h = qtractorScrollView::height(); const int wm = (w >> 3); // Time-line header extents... const int h2 = m_pTracks->trackTime()->height(); const int d2 = (h2 >> 1); // Restore old position... int x1 = iPositionX - x0; if (iPositionX != x && x1 >= 0 && x1 < w + d2) { // Override old view line... qtractorScrollView::viewport()->update(QRect(x1, 0, 1, h)); ((m_pTracks->trackTime())->viewport())->update( QRect(x1 - d2, d2, h2, d2)); } // New position is in... iPositionX = x; // Force position to be in view? if (bSyncView && (x < x0 || x > x0 + w - wm) && m_dragState == DragNone && m_dragCursor == DragNone) { // Maybe we'll need some head-room... if (x < qtractorScrollView::contentsWidth() - w) { qtractorScrollView::setContentsPos( x - wm, qtractorScrollView::contentsY()); } else updateContentsWidth(x + w); } else { // Draw the line, by updating the new region... x1 = x - x0; if (x1 >= 0 && x1 < w + d2) { qtractorScrollView::viewport()->update(QRect(x1, 0, 1, h)); ((m_pTracks->trackTime())->viewport())->update( QRect(x1 - d2, d2, h2, d2)); } } } // Playhead positioning. void qtractorTrackView::setPlayHead ( unsigned long iPlayHead, bool bSyncView ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { m_iPlayHead = iPlayHead; const int iPlayHeadX = pSession->pixelFromFrame(iPlayHead); drawPositionX(m_iPlayHeadX, iPlayHeadX, bSyncView); } } unsigned long qtractorTrackView::playHead (void) const { return m_iPlayHead; } int qtractorTrackView::playHeadX (void) const { return m_iPlayHeadX; } // Edit-head positioning void qtractorTrackView::setEditHead ( unsigned long iEditHead ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { if (iEditHead > pSession->editTail()) setEditTail(iEditHead); pSession->setEditHead(iEditHead); const int iEditHeadX = pSession->pixelFromFrame(iEditHead); drawPositionX(m_iEditHeadX, iEditHeadX); } } int qtractorTrackView::editHeadX (void) const { return m_iEditHeadX; } // Edit-tail positioning void qtractorTrackView::setEditTail ( unsigned long iEditTail ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { if (iEditTail < pSession->editHead()) setEditHead(iEditTail); pSession->setEditTail(iEditTail); const int iEditTailX = pSession->pixelFromFrame(iEditTail); drawPositionX(m_iEditTailX, iEditTailX); } } int qtractorTrackView::editTailX (void) const { return m_iEditTailX; } // Clear current selection (no notify). void qtractorTrackView::clearSelect (void) { // g_clipboard.clear(); int iUpdate = 0; QRect rectUpdate = m_pClipSelect->rect(); if (m_pClipSelect->items().count() > 0) { m_pClipSelect->clear(); ++iUpdate; } if (m_pCurveSelect->items().count() > 0) { rectUpdate = rectUpdate.united(m_pCurveSelect->rect()); m_pCurveSelect->clear(); ++iUpdate; } if (iUpdate > 0) updateRect(rectUpdate); } // Whether there's any clip currently selected. bool qtractorTrackView::isClipSelected (void) const { return (m_pClipSelect->items().count() > 0); } // Whether there's any curve/automation currently selected. bool qtractorTrackView::isCurveSelected (void) const { return (m_pCurveSelect->items().count() > 0); } // Whether there's a single track selection. qtractorTrack *qtractorTrackView::singleTrackSelected (void) { return m_pClipSelect->singleTrack(); } // Whether there's any clip on clipboard. (static) bool qtractorTrackView::isClipboard (void) { return (g_clipboard.clips.count() > 0 || g_clipboard.nodes.count() > 0); } // Clipboard stuffer methods. void qtractorTrackView::ClipBoard::addClip ( qtractorClip *pClip, const QRect& clipRect, unsigned long iClipStart, unsigned long iClipOffset, unsigned long iClipLength ) { ClipItem *pClipItem = new ClipItem(pClip, clipRect, iClipStart, iClipOffset, iClipLength); if (iClipOffset == pClip->clipOffset()) pClipItem->fadeInLength = pClip->fadeInLength(); if (iClipOffset + iClipLength == pClip->clipOffset() + pClip->clipLength()) pClipItem->fadeOutLength = pClip->fadeOutLength(); clips.append(pClipItem); } void qtractorTrackView::ClipBoard::addNode ( qtractorCurve::Node *pNode, const QRect& nodeRect, unsigned long iFrame, float fValue ) { nodes.append(new NodeItem(pNode, nodeRect, iFrame, fValue)); } // Clipboard reset method. void qtractorTrackView::ClipBoard::clear (void) { qDeleteAll(clips); clips.clear(); qDeleteAll(nodes); nodes.clear(); singleTrack = NULL; frames = 0; } // Clip selection sanity check method. bool qtractorTrackView::queryClipSelect ( qtractorClip *pClip ) { // Check if anything is really selected... if (m_pClipSelect->items().count() < 1) return (pClip && pClip->queryEditor()); // Just ask whether any target clips have pending editors... const qtractorClipSelect::ItemList& items = m_pClipSelect->items(); qtractorClipSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorClipSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorClip *pClip = iter.key(); // Make sure it's a legal selection... if (pClip->track() && pClip->isClipSelected() && !pClip->queryEditor()) return false; } // If it reaches here, we can do what we will to... return true; } // Curve/automation selection executive method. void qtractorTrackView::executeCurveSelect ( qtractorTrackView::Command cmd ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorCurve *pCurve = m_pCurveSelect->curve(); if (pCurve == NULL) return; // Reset clipboard... const bool bClipboard = (cmd == Cut || cmd == Copy); if (bClipboard) { g_clipboard.clear(); g_clipboard.frames = pSession->frameFromPixel(m_pCurveSelect->rect().width()); QApplication::clipboard()->clear(); } // We'll build a composite command... qtractorCurveEditCommand *pCurveEditCommand = NULL; const QString& sCmdMask = tr("%1 automation"); QString sCmdName; switch (cmd) { case Cut: sCmdName = sCmdMask.arg(tr("cut")); break; case Delete: sCmdName = sCmdMask.arg(tr("delete")); break; default: break; } if (!sCmdName.isEmpty()) pCurveEditCommand = new qtractorCurveEditCommand(sCmdName, pCurve); const qtractorCurveSelect::ItemList& items = m_pCurveSelect->items(); qtractorCurveSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorCurveSelect::ItemList::ConstIterator iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorCurve::Node *pNode = iter.key(); if (bClipboard) { g_clipboard.addNode(pNode, iter.value()->rectNode, pNode->frame, pNode->value); } if (pCurveEditCommand) pCurveEditCommand->removeNode(pNode); } // Hint from the whole selection rectangle... g_clipboard.frames = pSession->frameFromPixel(m_pCurveSelect->rect().width()); // Put it in the form of an undoable command... if (pCurveEditCommand) pSession->execute(pCurveEditCommand); } // Clip selection executive method. void qtractorTrackView::executeClipSelect ( qtractorTrackView::Command cmd, qtractorClip *pClipEx ) { // Check if it's all about a single clip target... if (m_pClipSelect->items().count() < 1) { if (pClipEx == NULL) pClipEx = currentClip(); } else pClipEx = NULL; // Selection always takes precedence... // Check if anything is really selected and sane... if (!queryClipSelect(pClipEx)) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Reset clipboard... const bool bClipboard = (cmd == Cut || cmd == Copy); if (bClipboard) { g_clipboard.clear(); g_clipboard.singleTrack = m_pClipSelect->singleTrack(); g_clipboard.frames = pSession->frameFromPixel(m_pClipSelect->rect().width()); QApplication::clipboard()->clear(); } // We'll build a composite command... qtractorClipCommand *pClipCommand = NULL; const QString& sCmdMask = tr("%1 clip"); QString sCmdName; switch (cmd) { case Cut: sCmdName = sCmdMask.arg(tr("cut")); break; case Delete: sCmdName = sCmdMask.arg(tr("delete")); break; case Split: sCmdName = sCmdMask.arg(tr("split")); break; default: break; } if (!sCmdName.isEmpty()) pClipCommand = new qtractorClipCommand(sCmdName); if (pClipEx) { // -- Single clip... if (bClipboard) { QRect rectClip; clipInfo(pClipEx, &rectClip); g_clipboard.addClip(pClipEx, rectClip, pClipEx->clipStart(), pClipEx->clipOffset(), pClipEx->clipLength()); } if (pClipCommand && cmd != Split) pClipCommand->removeClip(pClipEx); // Done, single clip. } const qtractorClipSelect::ItemList& items = m_pClipSelect->items(); qtractorClipSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorClipSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorClip *pClip = iter.key(); qtractorTrack *pTrack = pClip->track(); // Make sure it's legal selection... if (pTrack && pClip->isClipSelected()) { // Clip parameters. const unsigned long iClipStart = pClip->clipStart(); const unsigned long iClipOffset = pClip->clipOffset(); const unsigned long iClipLength = pClip->clipLength(); const unsigned long iClipEnd = iClipStart + iClipLength; // Clip selection points. const unsigned long iSelectStart = pClip->clipSelectStart(); const unsigned long iSelectEnd = pClip->clipSelectEnd(); const unsigned long iSelectOffset = iSelectStart - iClipStart; const unsigned long iSelectLength = iSelectEnd - iSelectStart; // Determine and dispatch selected clip regions... qtractorClipSelect::Item *pClipItem = iter.value(); if (iSelectStart > iClipStart) { if (iSelectEnd < iClipEnd) { // -- Middle region... if (bClipboard) { g_clipboard.addClip(pClip, pClipItem->rectClip, iSelectStart, iClipOffset + iSelectOffset, iSelectLength); } if (pClipCommand) { // Left-clip... qtractorClip *pClipLeft = cloneClip(pClip); if (pClipLeft) { pClipLeft->setClipStart(iClipStart); pClipLeft->setClipOffset(iClipOffset); pClipLeft->setClipLength(iSelectOffset); pClipLeft->setFadeInLength(pClip->fadeInLength()); pClipCommand->addClip(pClipLeft, pTrack); } // Split(middle)-clip... if (cmd == Split) { // Middle-clip... pClipCommand->resizeClip(pClip, iSelectStart, iClipOffset + iSelectOffset, iSelectLength); // Adjust middle-clip selection... pClip->setClipSelect( iSelectStart, iSelectStart + iSelectLength); } else pClipCommand->removeClip(pClip); // Right-clip... qtractorClip *pClipRight = cloneClip(pClip); if (pClipRight) { pClipRight->setClipStart(iSelectEnd); pClipRight->setClipOffset(iClipOffset + iSelectOffset + iSelectLength); pClipRight->setClipLength(iClipEnd - iSelectEnd); pClipRight->setFadeOutLength(pClip->fadeOutLength()); pClipCommand->addClip(pClipRight, pTrack); } } // Done, middle region. } else { // -- Right region... if (bClipboard) { g_clipboard.addClip(pClip, pClipItem->rectClip, iSelectStart, iClipOffset + iSelectOffset, iSelectLength); } if (pClipCommand) { // Left-clip... qtractorClip *pClipLeft = cloneClip(pClip); if (pClipLeft) { pClipLeft->setClipStart(iClipStart); pClipLeft->setClipOffset(iClipOffset); pClipLeft->setClipLength(iSelectOffset); pClipLeft->setFadeInLength(pClip->fadeInLength()); pClipCommand->addClip(pClipLeft, pTrack); } // Split(right)-clip... if (cmd == Split) { // Right-clip... pClipCommand->resizeClip(pClip, iSelectStart, iClipOffset + iSelectOffset, iSelectLength); // Adjust middle-clip selection... pClip->setClipSelect( iSelectStart, iSelectStart + iSelectLength); } else pClipCommand->removeClip(pClip); } // Done, right region. } } else if (iSelectEnd < iClipEnd) { // -- Left region... if (bClipboard) { g_clipboard.addClip(pClip, pClipItem->rectClip, iClipStart, iClipOffset, iSelectLength); } if (pClipCommand) { // Split(left)-clip... if (cmd == Split) { // Left-clip... pClipCommand->resizeClip(pClip, iClipStart, iClipOffset, iSelectLength); // Adjust middle-clip selection... pClip->setClipSelect( iClipStart, iClipStart + iSelectLength); } else pClipCommand->removeClip(pClip); // Right-clip... qtractorClip *pClipRight = cloneClip(pClip); if (pClipRight) { pClipRight->setClipStart(iSelectEnd); pClipRight->setClipOffset(iClipOffset + iSelectLength); pClipRight->setClipLength(iClipLength - iSelectLength); pClipRight->setFadeOutLength(pClip->fadeOutLength()); pClipCommand->addClip(pClipRight, pTrack); } } // Done, left region. } else { // -- Whole clip... if (bClipboard) { g_clipboard.addClip(pClip, pClipItem->rectClip, iClipStart, iClipOffset, iClipLength); } if (pClipCommand && cmd != Split) pClipCommand->removeClip(pClip); // Done, whole clip. } } } // Hint from the whole selection rectangle... g_clipboard.frames = (pClipEx ? pClipEx->clipLength() : pSession->frameFromPixel(m_pClipSelect->rect().width())); // Reset selection on cut or delete; // put it in the form of an undoable command... if (pClipCommand) { if (cmd == Split) pClipCommand->setClearSelect(false); pSession->execute(pClipCommand); } } // Retrieve current paste period. // (as from current clipboard width) unsigned long qtractorTrackView::pastePeriod (void) const { if (g_clipboard.clips.count() < 1) return 0; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return 0; return pSession->frameSnap(g_clipboard.frames); } // Paste from clipboard (start). void qtractorTrackView::pasteClipboard ( unsigned short iPasteCount, unsigned long iPastePeriod ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorTrackView::pasteClipboard(%u, %lu)", iPasteCount, iPastePeriod); #endif qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Make sure the mouse pointer is properly located... const QPoint& pos = qtractorScrollView::viewportToContents( qtractorScrollView::viewport()->mapFromGlobal(QCursor::pos())); // Check if anything's really on clipboard... if (g_clipboard.clips.isEmpty() && g_clipboard.nodes.isEmpty()) { // System clipboard? QClipboard *pClipboard = QApplication::clipboard(); if (pClipboard && (pClipboard->mimeData())->hasUrls()) { dragClipDrop(pos, false, pClipboard->mimeData()); // Make a proper out of this (new) state? if (!m_dropItems.isEmpty()) { m_dragState = m_dragCursor = DragClipPasteDrop; // It doesn't matter which one, both pasteable views are due... qtractorScrollView::setFocus(); qtractorScrollView::setCursor( QCursor(QPixmap(":/images/editPaste.png"), 12, 12)); // Update the pasted stuff showClipDropRects(); } } // Woot! return; } // FIXME: While pasting automation/curve nodes // maybe we can only do it over the original... qtractorTrackViewInfo tvi; qtractorCurve *pCurve = NULL; if (m_bCurveEdit) { if (g_clipboard.nodes.isEmpty()) return; qtractorTrack *pTrack = m_pTracks->currentTrack(); if (pTrack == NULL || !trackInfo(pTrack, &tvi)) pTrack = trackAt(pos, true, &tvi); if (pTrack == NULL) return; pCurve = pTrack->currentCurve(); if (pCurve == NULL) return; if (pCurve->isLocked()) return; } else if (g_clipboard.clips.isEmpty()) return; // Reset any current selection, whatsoever... m_pClipSelect->clear(); m_pCurveSelect->clear(); resetDragState(); // Set paste parameters... m_iPasteCount = iPasteCount; m_iPastePeriod = iPastePeriod; if (m_iPastePeriod < 1) m_iPastePeriod = pSession->frameSnap(g_clipboard.frames); unsigned long iPasteDelta = 0; // Copy clipboard items to floating selection; if (m_bCurveEdit) { // Flag this as target current curve, // otherwise nothing will be displayed... m_pCurveSelect->setCurve(pCurve); const int h = tvi.trackRect.height(); const int y2 = tvi.trackRect.bottom() + 1; QListIterator iter(g_clipboard.nodes); for (unsigned short i = 0; i < m_iPasteCount; ++i) { iter.toFront(); while (iter.hasNext()) { NodeItem *pNodeItem = iter.next(); const int x = pSession->pixelFromFrame(pNodeItem->frame + iPasteDelta); const float s = pCurve->scaleFromValue(pNodeItem->value); const int y = y2 - int(s * float(h)); m_pCurveSelect->addItem(pNodeItem->node, QRect(x - 4, y - 4, 8, 8)); } iPasteDelta += m_iPastePeriod; } m_pCurveSelect->update(true); // We'll start a brand new floating state... m_dragState = m_dragCursor = DragCurvePaste; m_rectDrag = m_pCurveSelect->rect(); m_posDrag = m_rectDrag.topLeft(); m_posStep = QPoint(0, 0); } else { // Copy clipboard items to floating selection; // adjust clip widths/lengths just in case time // scale (horizontal zoom) has been changed... QListIterator iter(g_clipboard.clips); for (unsigned short i = 0; i < m_iPasteCount; ++i) { iter.toFront(); while (iter.hasNext()) { ClipItem *pClipItem = iter.next(); QRect rect(pClipItem->rect); rect.setX(pSession->pixelFromFrame(pClipItem->clipStart + iPasteDelta)); rect.setWidth(pSession->pixelFromFrame(pClipItem->clipLength)); m_pClipSelect->addItem(pClipItem->clip, rect); } iPasteDelta += m_iPastePeriod; } // We'll start a brand new floating state... m_dragState = m_dragCursor = DragClipPaste; m_rectDrag = m_pClipSelect->rect(); m_posDrag = m_rectDrag.topLeft(); m_posStep = QPoint(0, 0); } // It doesn't matter which one, both pasteable views are due... qtractorScrollView::setFocus(); qtractorScrollView::setCursor( QCursor(QPixmap(":/images/editPaste.png"), 12, 12)); // Let's-a go... qtractorScrollView::update(); if (m_bCurveEdit) dragCurveMove(pos + m_posStep); else dragClipMove(pos + m_posStep); } // Intra-drag-n-drop clip move method. void qtractorTrackView::moveClipSelect ( qtractorTrack *pTrack ) { // Check if anything is really selected and sane... if (!queryClipSelect()) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // We'll need this... qtractorClipCommand *pClipCommand = new qtractorClipCommand(tr("move clip")); // We can only move clips between tracks of the same type... int iTrackClip = 0; long iClipDelta = 0; const bool bAddTrack = (pTrack == NULL); qtractorTrack *pSingleTrack = m_pClipSelect->singleTrack(); if (pSingleTrack) { if (bAddTrack) { const int iTrack = pSession->tracks().count() + 1; const QColor& color = qtractorTrack::trackColor(iTrack); pTrack = new qtractorTrack(pSession, pSingleTrack->trackType()); // pTrack->setTrackName(tr("Track %1").arg(iTrack)); pTrack->setBackground(color); pTrack->setForeground(color.darker()); if (pSingleTrack->trackType() == qtractorTrack::Midi) { pTrack->setMidiChannel(pSingleTrack->midiChannel()); pTrack->setMidiBank(pSingleTrack->midiBank()); pTrack->setMidiProg(pSingleTrack->midiProg()); } pClipCommand->addTrack(pTrack); } else if (pSingleTrack->trackType() != pTrack->trackType()) return; } // We'll build a composite command... QList clips; const qtractorClipSelect::ItemList& items = m_pClipSelect->items(); qtractorClipSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorClipSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorClip *pClip = iter.key(); if (pSingleTrack == NULL) pTrack = pClip->track(); // Make sure it's legal selection... if (pTrack && pClip->isClipSelected()) { // Clip parameters. const unsigned long iClipStart = pClip->clipStart(); const unsigned long iClipOffset = pClip->clipOffset(); const unsigned long iClipLength = pClip->clipLength(); const unsigned long iClipEnd = iClipStart + iClipLength; // Clip selection points. const unsigned long iSelectStart = pClip->clipSelectStart(); const unsigned long iSelectEnd = pClip->clipSelectEnd(); const unsigned long iSelectOffset = iSelectStart - iClipStart; const unsigned long iSelectLength = iSelectEnd - iSelectStart; // Determine and keep clip regions... qtractorClipSelect::Item *pClipItem = iter.value(); if (iSelectStart > iClipStart) { // -- Left clip... qtractorClip *pClipLeft = cloneClip(pClip); pClipLeft->setClipStart(iClipStart); pClipLeft->setClipOffset(iClipOffset); pClipLeft->setClipLength(iSelectOffset); pClipLeft->setFadeInLength(pClip->fadeInLength()); pClipCommand->addClip(pClipLeft, pClipLeft->track()); // Done, left clip. } if (iSelectEnd < iClipEnd) { // -- Right clip... qtractorClip *pClipRight = cloneClip(pClip); pClipRight->setClipStart(iSelectEnd); pClipRight->setClipOffset(iClipOffset + iSelectOffset + iSelectLength); pClipRight->setClipLength(iClipEnd - iSelectEnd); pClipRight->setFadeOutLength(pClip->fadeOutLength()); pClipCommand->addClip(pClipRight, pClipRight->track()); // Done, right clip. } // Convert to precise frame positioning, // but only the first clip gets snapped... unsigned long iClipStart2 = iSelectStart; if (iTrackClip == 0) { const int x = (pClipItem->rectClip.x() + m_iDragClipX); const unsigned long iFrameStart = pSession->frameSnap( pSession->frameFromPixel(x > 0 ? x : 0)); iClipDelta = long(iFrameStart) - long(iClipStart2); iClipStart2 = iFrameStart; } else if (long(iClipStart2) + iClipDelta > 0) { iClipStart2 += iClipDelta; } else { iClipStart2 = 0; } // -- Moved clip... pClipCommand->moveClip(pClip, pTrack, iClipStart2, iClipOffset + iSelectOffset, iSelectLength); clips.append(pClip); // If track's new it will need a name... if (bAddTrack && iTrackClip == 0) pTrack->setTrackName(pClip->clipName()); ++iTrackClip; } } // Put it in the form of an undoable command... pSession->execute(pClipCommand); // Redo selection as new... if (!clips.isEmpty()) { QListIterator clip_iter(clips); while (clip_iter.hasNext()) clip_iter.next()->setClipSelected(true); updateClipSelect(); m_pTracks->selectionChangeNotify(); } } // Paste from clipboard (execute). void qtractorTrackView::pasteClipSelect ( qtractorTrack *pTrack ) { // Check if there's anything really on clipboard... if (g_clipboard.clips.count() < 1) return; // Check if anything is really selected and sane... if (!queryClipSelect()) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // We'll need this... qtractorClipCommand *pClipCommand = new qtractorClipCommand(tr("paste clip")); // We can only move clips between tracks of the same type... const bool bAddTrack = (pTrack == NULL); qtractorTrack *pSingleTrack = g_clipboard.singleTrack; if (pSingleTrack) { if (bAddTrack) { const int iTrack = pSession->tracks().count() + 1; const QColor& color = qtractorTrack::trackColor(iTrack); pTrack = new qtractorTrack(pSession, pSingleTrack->trackType()); // pTrack->setTrackName(tr("Track %1").arg(iTrack)); pTrack->setBackground(color); pTrack->setForeground(color.darker()); pClipCommand->addTrack(pTrack); } else if (pSingleTrack->trackType() != pTrack->trackType()) return; } unsigned long iPastePeriod = m_iPastePeriod; if (iPastePeriod < 1) iPastePeriod = g_clipboard.frames; long iPasteDelta = 0; if (m_iDragClipX < 0) iPasteDelta = - pSession->frameFromPixel(- m_iDragClipX); else iPasteDelta = + pSession->frameFromPixel(+ m_iDragClipX); // We'll build a composite command... QList clips; QListIterator iter(g_clipboard.clips); for (unsigned short i = 0; i < m_iPasteCount; ++i) { // Paste iteration... int iTrackClip = 0; iter.toFront(); while (iter.hasNext()) { ClipItem *pClipItem = iter.next(); qtractorClip *pClip = pClipItem->clip; if (pSingleTrack == NULL) pTrack = pClip->track(); // Convert to precise frame positioning, // but only the first clip gets snapped... unsigned long iClipStart = pClipItem->clipStart; if (long(iClipStart) + iPasteDelta > 0) iClipStart += iPasteDelta; if (iTrackClip == 0) { unsigned long iFrameStart = iClipStart; iClipStart = pSession->frameSnap(iFrameStart); iPasteDelta += long(iClipStart) - long(iFrameStart); } // Now, its imperative to make a proper copy of those clips... qtractorClip *pNewClip = cloneClip(pClip); // Add the new pasted clip... if (pNewClip) { pNewClip->setClipStart(iClipStart); pNewClip->setClipOffset(pClipItem->clipOffset); pNewClip->setClipLength(pClipItem->clipLength); pNewClip->setFadeInLength(pClipItem->fadeInLength); pNewClip->setFadeOutLength(pClipItem->fadeOutLength); pClipCommand->addClip(pNewClip, pTrack); clips.append(pNewClip); // If track's new it will need a name... if (bAddTrack && iTrackClip == 0) pTrack->setTrackName(pClip->clipName()); ++iTrackClip; } } // Set to repeat... iPasteDelta += iPastePeriod; } // Put it in the form of an undoable command... pSession->execute(pClipCommand); // Redo selection as new... if (!clips.isEmpty()) { QListIterator clip_iter(clips); while (clip_iter.hasNext()) clip_iter.next()->setClipSelected(true); updateClipSelect(); m_pTracks->selectionChangeNotify(); } } // Intra-drag-n-drop curve/automation node move method. void qtractorTrackView::moveCurveSelect ( const QPoint& pos ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; dragCurveMove(pos); qtractorTrackViewInfo tvi; qtractorTrack *pTrack = m_pTracks->currentTrack(); if (pTrack == NULL || !trackInfo(pTrack, &tvi)) pTrack = trackAt(pos, true, &tvi); if (pTrack == NULL) return; qtractorCurve *pCurve = pTrack->currentCurve(); if (pCurve == NULL) return; if (pCurve->isLocked()) return; if (!m_pCurveSelect->isCurrentCurve(pCurve)) return; const int x0 = m_pCurveSelect->rect().x(); const int x1 = x0 + m_iDragCurveX; const long delta = long(pSession->frameFromPixel(x1)) - long(pSession->frameFromPixel(x0)); qtractorCurveEditCommand *pCurveEditCommand = new qtractorCurveEditCommand(tr("move automation"), pCurve); // We'll build a composite command... QList nodes; qtractorCurveEditList edits(pCurve); const qtractorCurveSelect::ItemList& items = m_pCurveSelect->items(); qtractorCurveSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorCurveSelect::ItemList::ConstIterator iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorCurveSelect::Item *pItem = iter.value(); if (pItem->flags & 1) { qtractorCurve::Node *pNode = iter.key(); const unsigned long frame = pNode->frame + delta; const float value = pNode->value; pCurveEditCommand->removeNode(pNode); pCurve->unlinkNode(pNode); pNode = pCurve->addNode(frame, value, &edits); if (pNode) nodes.append(pNode); } } pCurveEditCommand->addEditList(&edits); // Put it in the form of an undoable command... if (pCurveEditCommand->isEmpty()) { delete pCurveEditCommand; } else { pSession->commands()->push(pCurveEditCommand); m_pTracks->dirtyChangeNotify(); } // Redo selection as new... if (!nodes.isEmpty()) { QRect rectUpdate = m_pCurveSelect->rect(); m_pCurveSelect->clear(); const int h = tvi.trackRect.height(); const int y2 = tvi.trackRect.bottom() + 1; QListIterator node_iter(nodes); while (node_iter.hasNext()) { qtractorCurve::Node *pNode = node_iter.next(); const float s = pCurve->scaleFromValue(pNode->value); const int x = pSession->pixelFromFrame(pNode->frame); const int y = y2 - int(s * float(h)); m_pCurveSelect->selectItem(pCurve, pNode, QRect(x - 4, y - 4, 8, 8)); } m_pCurveSelect->update(true); updateRect(rectUpdate.united(m_pCurveSelect->rect())); m_pTracks->selectionChangeNotify(); } } // Paste from clipboard (execute). void qtractorTrackView::pasteCurveSelect ( const QPoint& pos ) { // Check if there's anything really on clipboard... if (g_clipboard.nodes.count() < 1) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; dragCurveMove(pos); qtractorTrackViewInfo tvi; qtractorTrack *pTrack = m_pTracks->currentTrack(); if (pTrack == NULL || !trackInfo(pTrack, &tvi)) return; qtractorCurve *pCurve = pTrack->currentCurve(); if (pCurve == NULL) return; if (pCurve->isLocked()) return; // We'll need this... qtractorCurveEditCommand *pCurveEditCommand = new qtractorCurveEditCommand(tr("paste automation"), pCurve); unsigned long iPastePeriod = m_iPastePeriod; if (iPastePeriod < 1) iPastePeriod = g_clipboard.frames; long iPasteDelta = 0; if (m_iDragCurveX < 0) iPasteDelta = - pSession->frameFromPixel(- m_iDragCurveX); else iPasteDelta = + pSession->frameFromPixel(+ m_iDragCurveX); // We'll build a composite command... QList nodes; qtractorCurveEditList edits(pCurve); QListIterator iter(g_clipboard.nodes); for (unsigned short i = 0; i < m_iPasteCount; ++i) { // Paste iteration... iter.toFront(); while (iter.hasNext()) { NodeItem *pNodeItem = iter.next(); // Convert to precise frame positioning, // but only the first clip gets snapped... unsigned long iNodeFrame = pNodeItem->frame; if (long(iNodeFrame) + iPasteDelta > 0) iNodeFrame += iPasteDelta; if (nodes.isEmpty()) { unsigned long iFrameStart = iNodeFrame; iNodeFrame = pSession->frameSnap(iFrameStart); iPasteDelta += long(iNodeFrame) - long(iFrameStart); } // Now, its imperative to make a proper copy of those nodes... qtractorCurve::Node *pNode = pCurve->addNode(iNodeFrame, pNodeItem->value, &edits); if (pNode) nodes.append(pNode); } // Set to repeat... iPasteDelta += iPastePeriod; } pCurveEditCommand->addEditList(&edits); // Put it in the form of an undoable command... if (pCurveEditCommand->isEmpty()) { delete pCurveEditCommand; } else { pSession->commands()->push(pCurveEditCommand); m_pTracks->dirtyChangeNotify(); } // Redo selection as new... if (!nodes.isEmpty()) { QRect rectUpdate = m_pCurveSelect->rect(); m_pCurveSelect->clear(); const int h = tvi.trackRect.height(); const int y2 = tvi.trackRect.bottom() + 1; QListIterator node_iter(nodes); while (node_iter.hasNext()) { qtractorCurve::Node *pNode = node_iter.next(); const float s = pCurve->scaleFromValue(pNode->value); const int x = pSession->pixelFromFrame(pNode->frame); const int y = y2 - int(s * float(h)); m_pCurveSelect->selectItem(pCurve, pNode, QRect(x - 4, y - 4, 8, 8)); } m_pCurveSelect->update(true); updateRect(rectUpdate.united(m_pCurveSelect->rect())); m_pTracks->selectionChangeNotify(); } } // Clip cloner helper. qtractorClip *qtractorTrackView::cloneClip ( qtractorClip *pClip ) { if (pClip == NULL) return NULL; qtractorTrack *pTrack = pClip->track(); if (pTrack == NULL) return NULL; qtractorClip *pNewClip = NULL; switch (pTrack->trackType()) { case qtractorTrack::Audio: { qtractorAudioClip *pAudioClip = static_cast (pClip); if (pAudioClip) pNewClip = new qtractorAudioClip(*pAudioClip); break; } case qtractorTrack::Midi: { qtractorMidiClip *pMidiClip = static_cast (pClip); if (pMidiClip) pNewClip = new qtractorMidiClip(*pMidiClip); break; } case qtractorTrack::None: default: break; } return pNewClip; } // Multi-item drop mode (whether to span clips horixontally). void qtractorTrackView::setDropSpan ( bool bDropSpan ) { m_bDropSpan = bDropSpan; } bool qtractorTrackView::isDropSpan (void) const { return m_bDropSpan; } // Snap-to-bar zebra mode. void qtractorTrackView::setSnapZebra ( bool bSnapZebra ) { m_bSnapZebra = bSnapZebra; updateContents(); } bool qtractorTrackView::isSnapZebra (void) const { return m_bSnapZebra; } // Snap-to-beat grid mode. void qtractorTrackView::setSnapGrid ( bool bSnapGrid ) { m_bSnapGrid = bSnapGrid; updateContents(); } bool qtractorTrackView::isSnapGrid (void) const { return m_bSnapGrid; } // Floating tool-tips mode. void qtractorTrackView::setToolTips ( bool bToolTips ) { m_bToolTips = bToolTips; } bool qtractorTrackView::isToolTips (void) const { return m_bToolTips; } // Automation curve node editing mode. void qtractorTrackView::setCurveEdit ( bool bCurveEdit ) { if (( m_bCurveEdit && bCurveEdit) || (!m_bCurveEdit && !bCurveEdit)) return; m_bCurveEdit = bCurveEdit; g_clipboard.clear(); clearSelect(); m_pTracks->selectionChangeNotify(); } bool qtractorTrackView::isCurveEdit (void) const { return m_bCurveEdit; } // end of qtractorTrackView.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorNsmClient.cpp0000644000175000001440000000012312145664254021434 xustar000000000000000027 mtime=1368877228.984108 26 atime=1381134668.01708 30 ctime=1381134668.026080065 qtractor-0.5.11/src/qtractorNsmClient.cpp0000644000175000001440000002623112145664254020727 0ustar00rncbcusers00000000000000// qtractorNsmClient.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorNsmClient.h" #include #include #define NSM_API_VERSION_MAJOR 1 #define NSM_API_VERSION_MINOR 0 #ifdef CONFIG_LIBLO //--------------------------------------------------------------------------- // qtractorNsmClient - OSC (liblo) callback methods. static int osc_nsm_error ( const char */*path*/, const char */*types*/, lo_arg **argv, int /*argc*/, lo_message /*msg*/, void *user_data ) { qtractorNsmClient *pNsmClient = static_cast (user_data); if (pNsmClient == NULL) return -1; if (strcmp(&argv[0]->s, "/nsm/server/announce")) return -1; pNsmClient->nsm_announce_error(&argv[2]->s); return 0; } static int osc_nsm_reply ( const char */*path*/, const char */*types*/, lo_arg **argv, int /*argc*/, lo_message /*msg*/, void *user_data ) { qtractorNsmClient *pNsmClient = static_cast (user_data); if (pNsmClient == NULL) return -1; if (strcmp(&argv[0]->s, "/nsm/server/announce")) return -1; pNsmClient->nsm_announce_reply(&argv[1]->s, &argv[2]->s, &argv[3]->s); return 0; } static int osc_nsm_open ( const char */*path*/, const char */*types*/, lo_arg **argv, int /*argc*/, lo_message /*msg*/, void *user_data ) { qtractorNsmClient *pNsmClient = static_cast (user_data); if (pNsmClient == NULL) return -1; pNsmClient->nsm_open(&argv[0]->s, &argv[1]->s, &argv[2]->s); return 0; } static int osc_nsm_save ( const char */*path*/, const char */*types*/, lo_arg **/*argv*/, int /*argc*/, lo_message /*msg*/, void *user_data ) { qtractorNsmClient *pNsmClient = static_cast (user_data); if (pNsmClient == NULL) return -1; pNsmClient->nsm_save(); return 0; } static int osc_nsm_loaded ( const char */*path*/, const char */*types*/, lo_arg **/*argv*/, int /*argc*/, lo_message /*msg*/, void *user_data ) { qtractorNsmClient *pNsmClient = static_cast (user_data); if (pNsmClient == NULL) return -1; pNsmClient->nsm_loaded(); return 0; } static int osc_nsm_show ( const char */*path*/, const char */*types*/, lo_arg **/*argv*/, int /*argc*/, lo_message /*msg*/, void *user_data ) { qtractorNsmClient *pNsmClient = static_cast (user_data); if (pNsmClient == NULL) return -1; pNsmClient->nsm_show(); return 0; } static int osc_nsm_hide ( const char */*path*/, const char */*types*/, lo_arg **/*argv*/, int /*argc*/, lo_message /*msg*/, void *user_data ) { qtractorNsmClient *pNsmClient = static_cast (user_data); if (pNsmClient == NULL) return -1; pNsmClient->nsm_hide(); return 0; } #endif // CONFIG_LIBLO //--------------------------------------------------------------------------- // qtractorNsmClient - NSM OSC client agent. // Constructor. qtractorNsmClient::qtractorNsmClient ( const QString& nsm_url, QObject *pParent ) : QObject(pParent), #ifdef CONFIG_LIBLO m_address(NULL), m_thread(NULL), m_server(NULL), #endif m_active(false) { #ifdef CONFIG_LIBLO m_address = lo_address_new_from_url(nsm_url.toUtf8().constData()); int proto = lo_address_get_protocol(m_address); m_thread = lo_server_thread_new_with_proto(NULL, proto, NULL); if (m_thread) { m_server = lo_server_thread_get_server(m_thread); lo_server_thread_add_method(m_thread, "/error", "sis", osc_nsm_error, this); lo_server_thread_add_method(m_thread, "/reply", "ssss", osc_nsm_reply, this); lo_server_thread_add_method(m_thread, "/nsm/client/open", "sss", osc_nsm_open, this); lo_server_thread_add_method(m_thread, "/nsm/client/save", "", osc_nsm_save, this); lo_server_thread_add_method(m_thread, "/nsm/client/session_is_loaded", "", osc_nsm_loaded, this); lo_server_thread_add_method(m_thread, "/nsm/client/show_optional_gui", "", osc_nsm_show, this); lo_server_thread_add_method(m_thread, "/nsm/client/hide_optional_gui", "", osc_nsm_hide, this); lo_server_thread_start(m_thread); } #endif } // Destructor. qtractorNsmClient::~qtractorNsmClient (void) { #ifdef CONFIG_LIBLO if (m_thread) { lo_server_thread_stop(m_thread); lo_server_thread_free(m_thread); } if (m_address) lo_address_free(m_address); #endif } // Session clieant methods. void qtractorNsmClient::announce ( const QString& app_name, const QString& capabilities ) { #ifdef CONFIG_LIBLO if (m_address && m_server) { const QFileInfo fi(QApplication::applicationFilePath()); lo_send_from(m_address, m_server, LO_TT_IMMEDIATE, "/nsm/server/announce", "sssiii", app_name.toUtf8().constData(), capabilities.toUtf8().constData(), fi.fileName().toUtf8().constData(), NSM_API_VERSION_MAJOR, NSM_API_VERSION_MINOR, int(QApplication::applicationPid())); } #endif } // Session activation accessor. bool qtractorNsmClient::is_active (void) const { return m_active; } // Session manager accessors. const QString& qtractorNsmClient::manager (void) const { return m_manager; } const QString& qtractorNsmClient::capabilities (void) const { return m_capabilities; } // Session client accessors. const QString& qtractorNsmClient::path_name (void) const { return m_path_name; } const QString& qtractorNsmClient::display_name (void) const { return m_display_name; } const QString& qtractorNsmClient::client_id (void) const { return m_client_id; } // Session client methods. void qtractorNsmClient::dirty ( bool is_dirty ) { #ifdef CONFIG_LIBLO if (m_address && m_server && m_active) { const char *path = is_dirty ? "/nsm/client/is_dirty" : "/nsm/client/is_clean"; lo_send_from(m_address, m_server, LO_TT_IMMEDIATE, path, ""); } #endif } void qtractorNsmClient::visible ( bool is_visible ) { #ifdef CONFIG_LIBLO if (m_address && m_server && m_active) { const char *path = is_visible ? "/nsm/client/gui_is_shown" : "/nsm/client/gui_is_hidden"; lo_send_from(m_address, m_server, LO_TT_IMMEDIATE, path, ""); } #endif } void qtractorNsmClient::progress ( float percent ) { #ifdef CONFIG_LIBLO if (m_address && m_server && m_active) { lo_send_from(m_address, m_server, LO_TT_IMMEDIATE, "/nsm/client/progress", "f", percent); } #endif } void qtractorNsmClient::message ( int priority, const QString& mesg ) { #ifdef CONFIG_LIBLO if (m_address && m_server && m_active) { lo_send_from(m_address, m_server, LO_TT_IMMEDIATE, "/nsm/client/message", "is", priority, mesg.toUtf8().constData()); } #endif } // Session client reply methods. void qtractorNsmClient::open_reply ( ReplyCode reply_code ) { reply("/nsm/client/open", reply_code); } void qtractorNsmClient::save_reply ( ReplyCode reply_code ) { reply("/nsm/client/save", reply_code); } void qtractorNsmClient::reply ( const QString& path, ReplyCode reply_code ) { const char *reply_mesg; switch (reply_code) { case ERR_OK: reply_mesg = "OK"; break; case ERR_GENERAL: reply_mesg = "ERR_GENERAL"; break; case ERR_INCOMPATIBLE_API: reply_mesg = "ERR_INCOMPATIBLE_API"; break; case ERR_BLACKLISTED: reply_mesg = "ERR_BLACKLISTED"; break; case ERR_LAUNCH_FAILED: reply_mesg = "ERR_LAUNCH_FAILED"; break; case ERR_NO_SUCH_FILE: reply_mesg = "ERR_NO_SUCH_FILE"; break; case ERR_NO_SESSION_OPEN: reply_mesg = "ERR_NO_SESSION_OPEN"; break; case ERR_UNSAVED_CHANGES: reply_mesg = "ERR_UNSAVED_CHANGES"; break; case ERR_NOT_NOW: reply_mesg = "ERR_NOT_NOW"; break; default: reply_mesg = "(UNKNOWN)"; break; } #ifdef CONFIG_LIBLO if (m_address && m_server) { if (reply_code == ERR_OK) { lo_send_from(m_address, m_server, LO_TT_IMMEDIATE, "/reply", "ss", path.toUtf8().constData(), reply_mesg); } else { lo_send_from(m_address, m_server, LO_TT_IMMEDIATE, "/error", "sis", path.toUtf8().constData(), int(reply_code), reply_mesg); } } #endif } // Server announce error. void qtractorNsmClient::nsm_announce_error ( const char *mesg ) { m_active = false; m_manager.clear(); m_capabilities.clear(); m_path_name.clear(); m_display_name.clear(); m_client_id.clear(); emit active(false); qWarning("NSM: Failed to register with server: %s.", mesg); } // Server announce reply. void qtractorNsmClient::nsm_announce_reply ( const char *mesg, const char *manager, const char *capabilities ) { m_active = true; m_manager = manager; m_capabilities = capabilities; emit active(true); qWarning("NSM: Successfully registered with server: %s.", mesg); } // Client open callback. void qtractorNsmClient::nsm_open ( const char *path_name, const char *display_name, const char *client_id ) { m_path_name = path_name; m_display_name = display_name; m_client_id = client_id; #ifdef CONFIG_DEBUG qDebug("qtractorNsmClient::nsm_open: " "path_name=\"%s\" display_name=\"%s\" client_id=\"%s\".", m_path_name.toUtf8().constData(), m_display_name.toUtf8().constData(), m_client_id.toUtf8().constData()); #endif emit open(); } // Client save callback. void qtractorNsmClient::nsm_save (void) { #ifdef CONFIG_DEBUG qDebug("qtractorNsmClient::nsm_save: " "path_name=\"%s\" display_name=\"%s\" client_id=\"%s\".", m_path_name.toUtf8().constData(), m_display_name.toUtf8().constData(), m_client_id.toUtf8().constData()); #endif emit save(); } // Client loaded callback. void qtractorNsmClient::nsm_loaded (void) { #ifdef CONFIG_DEBUG qDebug("qtractorNsmClient::nsm_loaded: " "path_name=\"%s\" display_name=\"%s\" client_id=\"%s\".", m_path_name.toUtf8().constData(), m_display_name.toUtf8().constData(), m_client_id.toUtf8().constData()); #endif emit loaded(); } // Client show optional GUI. void qtractorNsmClient::nsm_show (void) { #ifdef CONFIG_DEBUG qDebug("qtractorNsmClient::nsm_show: " "path_name=\"%s\" display_name=\"%s\" client_id=\"%s\".", m_path_name.toUtf8().constData(), m_display_name.toUtf8().constData(), m_client_id.toUtf8().constData()); #endif emit show(); } // Client hide optional GUI. void qtractorNsmClient::nsm_hide (void) { #ifdef CONFIG_DEBUG qDebug("qtractorNsmClient::nsm_hide: " "path_name=\"%s\" display_name=\"%s\" client_id=\"%s\".", m_path_name.toUtf8().constData(), m_display_name.toUtf8().constData(), m_client_id.toUtf8().constData()); #endif emit hide(); } // end of qtractorNsmClient.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorClip.h0000644000175000001440000000012312166526620020071 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134666.49408 30 ctime=1381134666.494080041 qtractor-0.5.11/src/qtractorClip.h0000644000175000001440000002434112166526620017364 0ustar00rncbcusers00000000000000// qtractorClip.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorClip_h #define __qtractorClip_h #include "qtractorTrack.h" // Forward declarations. class qtractorClipCommand; class QWidget; //------------------------------------------------------------------------- // qtractorClip -- Track clip capsule. class qtractorClip : public qtractorList::Link { public: // Constructor. qtractorClip(qtractorTrack *pTrack); // Default constructor. virtual ~qtractorClip(); // Clear clip. void clear(); // Track accessor. void setTrack(qtractorTrack *pTrack) { m_pTrack = pTrack; } qtractorTrack *track() const { return m_pTrack; } // Filename properties accessors. void setFilename(const QString& sFilename); const QString& filename() const; QString relativeFilename(qtractorDocument *pDocument) const; // Clip label accessors. void setClipName(const QString& sClipName) { m_sClipName = sClipName; } const QString& clipName() const { return m_sClipName; } QString shortClipName(const QString& sClipName) const; QString clipTitle() const; // Clip start frame accessors. void setClipStart(unsigned long iClipStart); unsigned long clipStart() const { return m_iClipStart; } unsigned long clipStartTime() const { return m_iClipStartTime; } // Clip frame length accessors. void setClipLength(unsigned long iClipLength); unsigned long clipLength() const { return m_iClipLength; } unsigned long clipLengthTime() const { return m_iClipLengthTime; } // Clip offset frame accessors. void setClipOffset(unsigned long iClipOffset); unsigned long clipOffset() const { return m_iClipOffset; } unsigned long clipOffsetTime() const { return m_iClipOffsetTime; } // Clip selection accessors. void setClipSelected(bool bClipSelected); bool isClipSelected() const; void setClipSelect(unsigned long iSelectStart, unsigned long iSelectEnd); unsigned long clipSelectStart() const { return m_iSelectStart; } unsigned long clipSelectEnd() const { return m_iSelectEnd; } // Clip gain/volume accessors. void setClipGain(float fGain); float clipGain() const { return m_fGain; } // Fade modes. enum FadeMode { FadeIn = 0, FadeOut }; // Fade types. enum FadeType { Linear = 0, InQuad, OutQuad, InOutQuad, InCubic, OutCubic, InOutCubic }; // Clip fade-in type accessors void setFadeInType(FadeType fadeType); FadeType fadeInType() const { return m_fadeInType; } void setFadeInLength(unsigned long iFadeInLength); unsigned long fadeInLength() const { return m_iFadeInLength; } // Clip fade-out accessors void setFadeOutType(FadeType fadeType); FadeType fadeOutType() const { return m_fadeOutType; } void setFadeOutLength(unsigned long iFadeOutLength); unsigned long fadeOutLength() const { return m_iFadeOutLength; } // Clip time reference settler method. void updateClipTime(); // Clip paint method. void drawClip(QPainter *pPainter, const QRect& clipRect, unsigned long iClipOffset); // Clip (re)open method. virtual void open() = 0; // Intra-clip frame positioning. virtual void seek(unsigned long iFrame) = 0; // Reset clip state position. virtual void reset(bool bLooping) = 0; // Clip loop-point methods. virtual void setLoop(unsigned long iLoopStart, unsigned long iLoopEnd) = 0; // Clip close-commit (record specific) virtual void close() = 0; // Clip special process cycle executive. virtual void process(unsigned long iFrameStart, unsigned long iFrameEnd) = 0; // Clip paint method. virtual void draw(QPainter *pPainter, const QRect& clipRect, unsigned long iClipOffset) = 0; // Clip editor method. virtual bool startEditor(QWidget *pParent); virtual void resetEditor(bool bSelectClear); virtual void updateEditor(bool bSelectClear); virtual bool queryEditor(); // Clip tool-tip. virtual QString toolTip() const; // Local dirty flag. void setDirty(bool bDirty) { m_bDirty = bDirty; } bool isDirty() const { return m_bDirty; } // Compute clip gain, given current fade-in/out slopes. float gain(unsigned long iOffset) const; // Document element methods. bool loadElement(qtractorDocument *pDocument, QDomElement *pElement); bool saveElement(qtractorDocument *pDocument, QDomElement *pElement) const; // Clip fade type textual helper methods. static FadeType fadeInTypeFromText(const QString& sText); static FadeType fadeOutTypeFromText(const QString& sText); static QString textFromFadeType(FadeType fadeType); // Take(record) descriptor. // class TakeInfo { public: // Constructor. TakeInfo( unsigned long iClipStart, unsigned long iClipOffset, unsigned long iClipLength, unsigned long iTakeStart, unsigned long iTakeEnd) : m_iClipStart(iClipStart), m_iClipOffset(iClipOffset), m_iClipLength(iClipLength), m_iTakeStart(iTakeStart), m_iTakeEnd(iTakeEnd), m_iCurrentTake(-1), m_iRefCount(0) { m_apClipParts[ClipHead] = NULL; m_apClipParts[ClipTake] = NULL; } // Brainless accessors (maybe useless). unsigned long clipStart() const { return m_iClipStart; } unsigned long clipOffset() const { return m_iClipOffset; } unsigned long clipLength() const { return m_iClipLength; } unsigned long takeStart() const { return m_iTakeStart; } unsigned long takeEnd() const { return m_iTakeEnd; } void setCurrentTake(int iCurrentTake) { m_iCurrentTake = iCurrentTake; } int currentTake() const { return m_iCurrentTake; } // Estimate number of takes. int takeCount() const; // Select current take set. int select(qtractorClipCommand *pClipCommand, qtractorTrack *pTrack, int iTake = -1); // Reset(unfold) whole take set. void reset(qtractorClipCommand *pClipCommand, bool bClear = false); // Reference counting methods. void addRef() { ++m_iRefCount; } void releaseRef() { if (--m_iRefCount < 1) delete this; } // Sub-clip take parts. enum ClipPart { ClipHead = 0, ClipTake = 1, ClipParts }; void setClipPart(ClipPart cpart, qtractorClip *pClip) { m_apClipParts[cpart] = pClip; } qtractorClip *clipPart(ClipPart cpart) const { return m_apClipParts[cpart]; } ClipPart partClip(const qtractorClip *pClip) const { return (m_apClipParts[ClipHead] == pClip ? ClipHead : ClipTake); } protected: // Sub-brainfull method. void selectClipPart(qtractorClipCommand *pClipCommand, qtractorTrack *pTrack, ClipPart cpart, unsigned long iClipStart, unsigned long iClipOffset, unsigned long iClipLength); private: // Instance variables. unsigned long m_iClipStart; unsigned long m_iClipOffset; unsigned long m_iClipLength; unsigned long m_iTakeStart; unsigned long m_iTakeEnd; int m_iCurrentTake; int m_iRefCount; qtractorClip *m_apClipParts[ClipParts]; }; // Take(record) descriptor accessors. void setTakeInfo(TakeInfo *pTakeInfo); TakeInfo *takeInfo() const; // Take(record) part clip-descriptor. // class TakePart { public: // Constructor. TakePart(TakeInfo *pTakeInfo, TakeInfo::ClipPart cpart) : m_pTakeInfo(pTakeInfo), m_cpart(cpart) {} // Direct accessors. TakeInfo *takeInfo() const { return m_pTakeInfo; } TakeInfo::ClipPart cpart() const { return m_cpart; } // Delegated accessors. void setClip(qtractorClip *pClip) { m_pTakeInfo->setClipPart(m_cpart, pClip); } qtractorClip *clip() const { return m_pTakeInfo->clipPart(m_cpart); } private: // Member variables. TakeInfo *m_pTakeInfo; TakeInfo::ClipPart m_cpart; }; // Fade functor (pure abstract) class. // class FadeFunctor { public: virtual ~FadeFunctor() {} virtual float operator() (float t) const = 0; }; protected: // Fade functor factory method. // static FadeFunctor *createFadeFunctor( FadeMode fadeMode, FadeType fadeType); // Virtual document element methods. virtual bool loadClipElement( qtractorDocument *pDocument, QDomElement *pElement) = 0; virtual bool saveClipElement( qtractorDocument *pDocument, QDomElement *pElement) const = 0; // Gain fractionalizer(tm)... struct { int num, den; } m_fractGain; private: qtractorTrack *m_pTrack; // Track reference. QString m_sFilename; // Clip filename (complete path). QString m_sClipName; // Clip label. unsigned long m_iClipStart; // Clip frame start. unsigned long m_iClipLength; // Clip frame length. unsigned long m_iClipOffset; // Clip frame offset. unsigned long m_iClipStartTime; // Clip time (tick) start. unsigned long m_iClipOffsetTime;// Clip time (tick) offset. unsigned long m_iClipLengthTime;// Clip time (tick) length. unsigned long m_iSelectStart; // Clip loop start frame-offset. unsigned long m_iSelectEnd; // Clip loop end frame-offset. // Clip gain/volume. float m_fGain; // Take(record) descriptor. TakeInfo *m_pTakeInfo; // Fade-in/out stuff. unsigned long m_iFadeInLength; // Fade-in length (in frames). unsigned long m_iFadeOutLength; // Fade-out length (in frames). unsigned long m_iFadeInTime; // Fade-in length (in ticks). unsigned long m_iFadeOutTime; // Fade-out length (in ticks). FadeType m_fadeInType; // Fade-in curve type. FadeType m_fadeOutType; // Fade-out curve type. // Aproximations to exponential fade interpolation. FadeFunctor *m_pFadeInFunctor; FadeFunctor *m_pFadeOutFunctor; // Local dirty flag. bool m_bDirty; }; // Stub declarations. class qtractorTrack::TakeInfo : public qtractorClip::TakeInfo {}; #endif // __qtractorClip_h // end of qtractorClip.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorObserver.cpp0000644000175000001440000000012212161335204021312 xustar000000000000000027 mtime=1371912836.382031 26 atime=1381134670.83908 29 ctime=1381134670.87608011 qtractor-0.5.11/src/qtractorObserver.cpp0000644000175000001440000001051112161335204020600 0ustar00rncbcusers00000000000000// qtractorObserver.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorObserver.h" //--------------------------------------------------------------------------- // qtractorSubjectQueue - Update/notify subject queue. class qtractorSubjectQueue { public: struct QueueItem { qtractorSubject *subject; qtractorObserver *sender; }; qtractorSubjectQueue ( unsigned int iQueueSize = 1024 ) : m_iQueueIndex(0), m_iQueueSize(0), m_pQueueItems(NULL) { resize(iQueueSize); } ~qtractorSubjectQueue () { clear(); delete [] m_pQueueItems; } void clear() { m_iQueueIndex = 0; } bool push ( qtractorSubject *pSubject, qtractorObserver *pSender ) { if (m_iQueueIndex >= m_iQueueSize) return false; pSubject->setQueued(true); QueueItem *pItem = &m_pQueueItems[m_iQueueIndex++]; pItem->subject = pSubject; pItem->sender = pSender; return true; } bool pop (bool bUpdate) { if (m_iQueueIndex == 0) return false; QueueItem *pItem = &m_pQueueItems[--m_iQueueIndex]; qtractorSubject *pSubject = pItem->subject; pSubject->notify(pItem->sender, bUpdate); pSubject->setQueued(false); return true; } void flush (bool bUpdate) { while (pop(bUpdate)) ; } void reset () { while (m_iQueueIndex > 0) { QueueItem *pItem = &m_pQueueItems[--m_iQueueIndex]; (pItem->subject)->setQueued(false); } clear(); } void resize ( unsigned int iNewSize ) { QueueItem *pOldItems = m_pQueueItems; QueueItem *pNewItems = new QueueItem [iNewSize]; if (pOldItems) { unsigned int iOldSize = m_iQueueIndex; if (iOldSize > iNewSize) iOldSize = iNewSize; if (iOldSize > 0) ::memcpy(pNewItems, pOldItems, iOldSize * sizeof(QueueItem)); m_iQueueSize = iNewSize; m_pQueueItems = pNewItems; delete [] pOldItems; } else { m_iQueueSize = iNewSize; m_pQueueItems = pNewItems; } } private: unsigned int m_iQueueIndex; unsigned int m_iQueueSize; QueueItem *m_pQueueItems; }; // The local subject queue singleton. static qtractorSubjectQueue g_subjectQueue; //--------------------------------------------------------------------------- // qtractorSubject - Scalar parameter value model. // Constructor. qtractorSubject::qtractorSubject ( float fValue, float fDefaultValue ) : m_fValue(fValue), m_bQueued(false), m_fPrevValue(fValue), m_fMinValue(0.0f), m_fMaxValue(1.0f), m_fDefaultValue(fDefaultValue), m_bToggled(false), m_pCurve(NULL) { } // Destructor. qtractorSubject::~qtractorSubject (void) { QListIterator iter(m_observers); while (iter.hasNext()) iter.next()->setSubject(NULL); m_observers.clear(); } // Direct value accessors. void qtractorSubject::setValue ( float fValue, qtractorObserver *pSender ) { if (fValue == m_fValue) return; if (!m_bQueued) { m_fPrevValue = m_fValue; g_subjectQueue.push(this, pSender); } m_fValue = safeValue(fValue); } // Observer/view updater. void qtractorSubject::notify ( qtractorObserver *pSender, bool bUpdate ) { QListIterator iter(m_observers); while (iter.hasNext()) { qtractorObserver *pObserver = iter.next(); if (pSender && pSender == pObserver) continue; pObserver->update(bUpdate); } } // Queue flush (singleton) -- notify all pending observers. void qtractorSubject::flushQueue ( bool bUpdate ) { g_subjectQueue.flush(bUpdate); } // Queue reset (clear). void qtractorSubject::resetQueue (void) { g_subjectQueue.reset(); } // end of qtractorObserver.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorClipCommand.h0000644000175000001440000000012112165061700021356 xustar000000000000000025 mtime=1372873664.1859 26 atime=1381134667.24408 30 ctime=1381134667.244080053 qtractor-0.5.11/src/qtractorClipCommand.h0000644000175000001440000001534012165061700020652 0ustar00rncbcusers00000000000000// qtractorClipCommand.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorClipCommand_h #define __qtractorClipCommand_h #include "qtractorCommand.h" #include "qtractorClip.h" #include // Forward declarations. class qtractorTrackCommand; class qtractorSessionCommand; class qtractorCurveEditCommand; class qtractorTimeScaleNodeCommand; class qtractorTimeScaleMarkerCommand; class qtractorMidiEditCommand; class qtractorMidiClip; //---------------------------------------------------------------------- // class qtractorClipCommand - declaration. // class qtractorClipCommand : public qtractorCommand { public: // Constructor. qtractorClipCommand(const QString& sName); // Destructor. virtual ~qtractorClipCommand(); // Primitive command methods. void addClip(qtractorClip *pClip, qtractorTrack *pTrack); void removeClip(qtractorClip *pClip); // Edit clip command methods. void fileClip(qtractorClip *pClip, const QString& sFilename, unsigned short iTrackChannel = 0); void renameClip(qtractorClip *pClip, const QString& sClipName); void moveClip(qtractorClip *pClip, qtractorTrack *pTrack, unsigned long iClipStart, unsigned long iClipOffset, unsigned long iClipLength); void resizeClip(qtractorClip *pClip, unsigned long iClipStart, unsigned long iClipOffset, unsigned long iClipLength, float fTimeStretch = 0.0f, float fPitchShift = 0.0f); void gainClip(qtractorClip *pClip, float fGain); void fadeInClip(qtractorClip *pClip, unsigned long iFadeInLength, qtractorClip::FadeType fadeInType); void fadeOutClip(qtractorClip *pClip, unsigned long iFadeOutLength, qtractorClip::FadeType fadeOutType); void timeStretchClip(qtractorClip *pClip, float fTimeStretch); void pitchShiftClip(qtractorClip *pClip, float fPitchShift); void takeInfoClip(qtractorClip *pClip, qtractorClip::TakeInfo *pTakeInfo); void resetClip(qtractorClip *pClip); void reopenClip(qtractorClip *pClip, bool bClose = false); // Special clip record methods. bool addClipRecord(qtractorTrack *pTrack, unsigned long iFrameTime); bool addClipRecordTake(qtractorTrack *pTrack, qtractorClip *pClip, unsigned long iClipStart, unsigned long iClipOffset, unsigned long iClipLength, qtractorClip::TakePart *pTakePart = NULL); // When new tracks are needed. void addTrack(qtractorTrack *pTrack); // When MIDI clips are stretched. qtractorMidiEditCommand *createMidiEditCommand( qtractorMidiClip *pMidiClip, float fTimeStretch); // Composite predicate. bool isEmpty() const; // Virtual command methods. bool redo(); bool undo(); protected: // Common executive method. virtual bool execute(bool bRedo); private: // Primitive command types. enum CommandType { AddClip, RemoveClip, FileClip, RenameClip, MoveClip, ResizeClip, GainClip, FadeInClip, FadeOutClip, TimeStretchClip, PitchShiftClip, TakeInfoClip, ResetClip }; // Clip item struct. struct Item { // Item constructor. Item(CommandType cmd, qtractorClip *pClip, qtractorTrack *pTrack) : command(cmd), clip(pClip), track(pTrack), autoDelete(false), trackChannel(0), clipStart(0), clipOffset(0), clipLength(0), clipGain(0.0f), fadeInLength(0), fadeInType(qtractorClip::InQuad), fadeOutLength(0), fadeOutType(qtractorClip::OutQuad), timeStretch(0.0f), pitchShift(0.0f), editCommand(NULL), takeInfo(NULL) {} // Item members. CommandType command; qtractorClip *clip; qtractorTrack *track; bool autoDelete; QString filename; unsigned short trackChannel; QString clipName; unsigned long clipStart; unsigned long clipOffset; unsigned long clipLength; float clipGain; unsigned long fadeInLength; qtractorClip::FadeType fadeInType; unsigned long fadeOutLength; qtractorClip::FadeType fadeOutType; float timeStretch; float pitchShift; // When MIDI clips are time-stretched... qtractorMidiEditCommand *editCommand; // When clips have take(record) descriptors... qtractorClip::TakeInfo *takeInfo; }; // Instance variables. QList m_items; // When new tracks are needed. QList m_trackCommands; // When clips need to reopem. QHash m_clips; }; //---------------------------------------------------------------------- // class qtractorClipTakeCommand - declaration. // class qtractorClipTakeCommand : public qtractorClipCommand { public: // Constructor. qtractorClipTakeCommand(qtractorClip::TakeInfo *pTakeInfo, qtractorTrack *pTrack = NULL, int iCurrentTake = -1); protected: // Executive override. bool execute(bool bRedo); private: // Instance variables. qtractorClip::TakeInfo *m_pTakeInfo; int m_iCurrentTake; }; //---------------------------------------------------------------------- // class qtractorClipRangeCommand - declaration. // class qtractorClipRangeCommand : public qtractorClipCommand { public: // Constructor. qtractorClipRangeCommand(const QString& sName); // Destructor. ~qtractorClipRangeCommand(); // When Loop/Punch changes are needed. void addSessionCommand( qtractorSessionCommand *pSessionCommand); // When automation curves are needed. void addCurveEditCommand( qtractorCurveEditCommand *pCurveEditCommand); // When location markers are needed. void addTimeScaleMarkerCommand( qtractorTimeScaleMarkerCommand *pTimeScaleMarkerCommand); // When tempo-map/time-sig nodes are needed. void addTimeScaleNodeCommand( qtractorTimeScaleNodeCommand *pTimeScaleNodeCommand); protected: // Executive override. bool execute(bool bRedo); private: // Instance variables. QList m_sessionCommands; QList m_curveEditCommands; QList m_timeScaleMarkerCommands; QList m_timeScaleNodeCommands; }; #endif // __qtractorClipCommand_h // end of qtractorClipCommand.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorScrollView.h0000644000175000001440000000012311563576072021301 xustar000000000000000027 mtime=1305410618.253123 26 atime=1381134671.10808 30 ctime=1381134671.109080114 qtractor-0.5.11/src/qtractorScrollView.h0000644000175000001440000000551711563576072020600 0ustar00rncbcusers00000000000000// qtractorScrollView.h // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorScrollView_h #define __qtractorScrollView_h #include #include // Forward declarations. class QResizeEvent; class QPaintEvent; //---------------------------------------------------------------------------- // qtractorScrollView -- abstract scroll view widget. class qtractorScrollView : public QAbstractScrollArea { Q_OBJECT public: // Constructor. qtractorScrollView(QWidget *pParent); // Destructor. virtual ~qtractorScrollView(); // Virtual contents extent accessors. int contentsX() const { return m_rectContents.x(); } int contentsY() const { return m_rectContents.y(); } int contentsHeight() const { return m_rectContents.height(); } int contentsWidth() const { return m_rectContents.width(); } // Virtual contents methods. void setContentsPos(int cx, int cy); void resizeContents(int cw, int ch); // Scrolls contents so that given point is visible. void ensureVisible(int cx, int cy, int mx = 50, int my = 50); // Viewport/contents position converters. QPoint viewportToContents(const QPoint& pos) const; QPoint contentsToViewport(const QPoint& pos) const; signals: // Contents moving slot. void contentsMoving(int cx, int cy); protected: // Scrollbar stabilization. void updateScrollBars(); // Scroll area updater. void scrollContentsBy(int dx, int dy); // Specialized event handlers. void resizeEvent(QResizeEvent *pResizeEvent); void paintEvent(QPaintEvent *pPaintEvent); void wheelEvent(QWheelEvent *pWheelEvent); // Draw the virtual contents. virtual void drawContents(QPainter *pPainter, const QRect& rect) = 0; // Rectangular contents update. virtual void updateContents(const QRect& rect); // Overall contents update. virtual void updateContents(); private: // The virtual contents coordinates. QRect m_rectContents; }; #endif // __qtractorScrollView_h // end of qtractorScrollView.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorInstrument.cpp0000644000175000001440000000012312170747402021703 xustar000000000000000027 mtime=1373884162.493407 26 atime=1381134667.03408 30 ctime=1381134667.034080049 qtractor-0.5.11/src/qtractorInstrument.cpp0000644000175000001440000006546412170747402021211 0ustar00rncbcusers00000000000000// qtractorInstrument.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorInstrument.h" #include #include #include #include #include #include #include #include //---------------------------------------------------------------------- // class qtractorInstrument -- instrument definition instance class. // // Retrieve patch/program list for given bank address. const qtractorInstrumentData& qtractorInstrument::patch ( int iBank ) const { if (m_pData->patches.contains(iBank)) return m_pData->patches[iBank]; return m_pData->patches[-1]; } // Retrieve key/notes list for given (bank, prog) pair. const qtractorInstrumentData& qtractorInstrument::notes ( int iBank, int iProg ) const { if (m_pData->keys.contains(iBank)) { if (m_pData->keys[iBank].contains(iProg)) { return m_pData->keys[iBank][iProg]; } else { return m_pData->keys[iBank][-1]; } } else if (iBank >= 0) return notes(-1, iProg); return m_pData->keys[-1][-1]; } // Check if given (bank, prog) pair is a drum patch. bool qtractorInstrument::isDrum ( int iBank, int iProg ) const { if (m_pData->drums.contains(iBank)) { if (m_pData->drums[iBank].contains(iProg)) { return (bool) m_pData->drums[iBank][iProg]; } else { return (bool) m_pData->drums[iBank][-1]; } } else if (iBank >= 0) return isDrum(-1, iProg); return false; } //---------------------------------------------------------------------- // class qtractorInstrumentList -- A Cakewalk .ins file container class. // // Clear all contents. void qtractorInstrumentList::clearAll (void) { clear(); m_patches.clear(); m_notes.clear(); m_controls.clear(); m_rpns.clear(); m_nrpns.clear(); m_files.clear(); } // Special list merge method. void qtractorInstrumentList::merge ( const qtractorInstrumentList& instruments ) { // Maybe its better not merging to itself. if (this == &instruments) return; // Names data lists merge... mergeDataList(m_patches, instruments.patches()); mergeDataList(m_notes, instruments.notes()); mergeDataList(m_controls, instruments.controls()); mergeDataList(m_rpns, instruments.rpns()); mergeDataList(m_nrpns, instruments.nrpns()); // Instrument merge... qtractorInstrumentList::ConstIterator it = instruments.constBegin(); const qtractorInstrumentList::ConstIterator& it_end = instruments.constEnd(); for ( ; it != it_end; ++it) { qtractorInstrument& instr = (*this)[it.key()]; instr = it.value(); } } // Special instrument data list merge method. void qtractorInstrumentList::mergeDataList ( qtractorInstrumentDataList& dst, const qtractorInstrumentDataList& src ) { qtractorInstrumentDataList::ConstIterator it = src.constBegin(); const qtractorInstrumentDataList::ConstIterator& it_end = src.constEnd(); for ( ; it != it_end; ++it) dst[it.key()] = it.value(); } // The official loaded file list. const QStringList& qtractorInstrumentList::files (void) const { return m_files; } // File load method. bool qtractorInstrumentList::load ( const QString& sFilename ) { // Open and read from real file. QFile file(sFilename); if (!file.open(QIODevice::ReadOnly)) return false; // Check for a soundfont... if (loadSoundFont(&file)) { file.close(); appendFile(sFilename); return true; } // Check for a MIDINameDocument... if (loadMidiNameDocument(&file)) { file.close(); appendFile(sFilename); return true; } // Proceed with regulat Cakewalk .ins file... file.seek(0); enum FileSection { None = 0, PatchNames = 1, NoteNames = 2, ControlNames = 3, RpnNames = 4, NrpnNames = 5, InstrDefs = 6 } sect = None; qtractorInstrument *pInstrument = NULL; qtractorInstrumentData *pData = NULL; QRegExp rxTitle ("^\\[([^\\]]+)\\]$"); QRegExp rxData ("^([0-9]+)=(.+)$"); QRegExp rxBasedOn ("^BasedOn=(.+)$"); QRegExp rxBankSel ("^BankSelMethod=(0|1|2|3)$"); QRegExp rxUseNotes("^UsesNotesAsControllers=(0|1)$"); QRegExp rxControl ("^Control=(.+)$"); QRegExp rxRpn ("^RPN=(.+)$"); QRegExp rxNrpn ("^NRPN=(.+)$"); QRegExp rxPatch ("^Patch\\[([0-9]+|\\*)\\]=(.+)$"); QRegExp rxKey ("^Key\\[([0-9]+|\\*),([0-9]+|\\*)\\]=(.+)$"); QRegExp rxDrum ("^Drum\\[([0-9]+|\\*),([0-9]+|\\*)\\]=(0|1)$"); const QString s0_127 = "0..127"; const QString s1_128 = "1..128"; const QString s0_16383 = "0..16383"; const QString sAsterisk = "*"; // Read the file. unsigned int iLine = 0; QTextStream ts(&file); while (!ts.atEnd()) { // Read the line. ++iLine; const QString& sLine = ts.readLine().simplified(); // If not empty, nor a comment, call the server... if (sLine.isEmpty() || sLine[0] == ';') continue; // Check for section intro line... if (sLine[0] == '.') { if (sLine == ".Patch Names") { sect = PatchNames; // m_patches.clear(); m_patches[s0_127].setName(s0_127); m_patches[s1_128].setName(s1_128); } else if (sLine == ".Note Names") { sect = NoteNames; // m_notes.clear(); m_notes[s0_127].setName(s0_127); } else if (sLine == ".Controller Names") { sect = ControlNames; // m_controls.clear(); m_controls[s0_127].setName(s0_127); } else if (sLine == ".RPN Names") { sect = RpnNames; // m_rpns.clear(); m_rpns[s0_16383].setName(s0_16383); } else if (sLine == ".NRPN Names") { sect = NrpnNames; // m_nrpns.clear(); m_nrpns[s0_16383].setName(s0_16383); } else if (sLine == ".Instrument Definitions") { sect = InstrDefs; // clear(); } else { // Unknown section found... qWarning("%s(%d): %s: Unknown section.", sFilename.toUtf8().constData(), iLine, sLine.toUtf8().constData()); } // Go on... continue; } // Now it depends on the section... switch (sect) { case PatchNames: { if (rxTitle.exactMatch(sLine)) { // New patch name... const QString& sTitle = rxTitle.cap(1); pData = &(m_patches[sTitle]); pData->setName(sTitle); } else if (rxBasedOn.exactMatch(sLine)) { pData->setBasedOn(rxBasedOn.cap(1)); } else if (rxData.exactMatch(sLine)) { (*pData)[rxData.cap(1).toInt()] = rxData.cap(2); } else { qWarning("%s(%d): %s: Unknown .Patch Names entry.", sFilename.toUtf8().constData(), iLine, sLine.toUtf8().constData()); } break; } case NoteNames: { if (rxTitle.exactMatch(sLine)) { // New note name... const QString& sTitle = rxTitle.cap(1); pData = &(m_notes[sTitle]); pData->setName(sTitle); } else if (rxBasedOn.exactMatch(sLine)) { pData->setBasedOn(rxBasedOn.cap(1)); } else if (rxData.exactMatch(sLine)) { (*pData)[rxData.cap(1).toInt()] = rxData.cap(2); } else { qWarning("%s(%d): %s: Unknown .Note Names entry.", sFilename.toUtf8().constData(), iLine, sLine.toUtf8().constData()); } break; } case ControlNames: { if (rxTitle.exactMatch(sLine)) { // New controller name... const QString& sTitle = rxTitle.cap(1); pData = &(m_controls[sTitle]); pData->setName(sTitle); } else if (rxBasedOn.exactMatch(sLine)) { pData->setBasedOn(rxBasedOn.cap(1)); } else if (rxData.exactMatch(sLine)) { (*pData)[rxData.cap(1).toInt()] = rxData.cap(2); } else { qWarning("%s(%d): %s: Unknown .Controller Names entry.", sFilename.toUtf8().constData(), iLine, sLine.toUtf8().constData()); } break; } case RpnNames: { if (rxTitle.exactMatch(sLine)) { // New RPN name... const QString& sTitle = rxTitle.cap(1); pData = &(m_rpns[sTitle]); pData->setName(sTitle); } else if (rxBasedOn.exactMatch(sLine)) { pData->setBasedOn(rxBasedOn.cap(1)); } else if (rxData.exactMatch(sLine)) { (*pData)[rxData.cap(1).toInt()] = rxData.cap(2); } else { qWarning("%s(%d): %s: Unknown .RPN Names entry.", sFilename.toUtf8().constData(), iLine, sLine.toUtf8().constData()); } break; } case NrpnNames: { if (rxTitle.exactMatch(sLine)) { // New NRPN name... const QString& sTitle = rxTitle.cap(1); pData = &(m_nrpns[sTitle]); pData->setName(sTitle); } else if (rxBasedOn.exactMatch(sLine)) { pData->setBasedOn(rxBasedOn.cap(1)); } else if (rxData.exactMatch(sLine)) { (*pData)[rxData.cap(1).toInt()] = rxData.cap(2); } else { qWarning("%s(%d): %s: Unknown .NRPN Names entry.", sFilename.toUtf8().constData(), iLine, sLine.toUtf8().constData()); } break; } case InstrDefs: { if (rxTitle.exactMatch(sLine)) { // New instrument definition... const QString& sTitle = rxTitle.cap(1); pInstrument = &((*this)[sTitle]); pInstrument->setInstrumentName(sTitle); } else if (rxBankSel.exactMatch(sLine)) { pInstrument->setBankSelMethod( rxBankSel.cap(1).toInt()); } else if (rxUseNotes.exactMatch(sLine)) { pInstrument->setUsesNotesAsControllers( (bool) rxBankSel.cap(1).toInt()); } else if (rxPatch.exactMatch(sLine)) { int iBank = (rxPatch.cap(1) == sAsterisk ? -1 : rxPatch.cap(1).toInt()); pInstrument->setPatch(iBank, m_patches[rxPatch.cap(2)]); } else if (rxControl.exactMatch(sLine)) { pInstrument->setControl(m_controls[rxControl.cap(1)]); } else if (rxRpn.exactMatch(sLine)) { pInstrument->setRpn(m_rpns[rxRpn.cap(1)]); } else if (rxNrpn.exactMatch(sLine)) { pInstrument->setNrpn(m_nrpns[rxNrpn.cap(1)]); } else if (rxKey.exactMatch(sLine)) { int iBank = (rxKey.cap(1) == sAsterisk ? -1 : rxKey.cap(1).toInt()); int iProg = (rxKey.cap(2) == sAsterisk ? -1 : rxKey.cap(2).toInt()); pInstrument->setNotes(iBank, iProg, m_notes[rxKey.cap(3)]); } else if (rxDrum.exactMatch(sLine)) { int iBank = (rxDrum.cap(1) == sAsterisk ? -1 : rxDrum.cap(1).toInt()); int iProg = (rxDrum.cap(2) == sAsterisk ? -1 : rxKey.cap(2).toInt()); pInstrument->setDrum(iBank, iProg, (bool) rxDrum.cap(3).toInt()); } else { qWarning("%s(%d): %s: Unknown .Instrument Definitions entry.", sFilename.toUtf8().constData(), iLine, sLine.toUtf8().constData()); } break; } default: break; } } // Ok. We've read it all. file.close(); // We're in business... appendFile(sFilename); return true; } // File save method. bool qtractorInstrumentList::save ( const QString& sFilename ) const { // Open and write into real file. QFile file(sFilename); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) return false; // A visula separator line. const QString sepl = "; -----------------------------" "------------------------------------------------"; // Write the file. QTextStream ts(&file); ts << sepl << endl; ts << "; " << QObject::tr("Cakewalk Instrument Definition File") << endl; /* ts << ";" << endl; ts << "; " << QTRACTOR_TITLE " - " << QObject::tr(QTRACTOR_SUBTITLE) << endl; ts << "; " << QObject::tr("Version") << ": " QTRACTOR_VERSION << endl; ts << "; " << QObject::tr("Build") << ": " __DATE__ " " __TIME__ << endl; */ ts << ";" << endl; ts << "; " << QObject::tr("File") << ": " << QFileInfo(sFilename).fileName() << endl; ts << "; " << QObject::tr("Date") << ": " << QDate::currentDate().toString("MMM dd yyyy") << " " << QTime::currentTime().toString("hh:mm:ss") << endl; ts << ";" << endl; // - Patch Names... ts << sepl << endl << endl; ts << ".Patch Names" << endl; saveDataList(ts, m_patches); // - Note Names... ts << sepl << endl << endl; ts << ".Note Names" << endl; saveDataList(ts, m_notes); // - Controller Names... ts << sepl << endl << endl; ts << ".Controller Names" << endl; saveDataList(ts, m_controls); // - RPN Names... ts << sepl << endl << endl; ts << ".RPN Names" << endl; saveDataList(ts, m_rpns); // - NRPN Names... ts << sepl << endl << endl; ts << ".NRPN Names" << endl; saveDataList(ts, m_nrpns); // - Instrument Definitions... ts << sepl << endl << endl; ts << ".Instrument Definitions" << endl; ts << endl; qtractorInstrumentList::ConstIterator iter = constBegin(); const qtractorInstrumentList::ConstIterator& iter_end = constEnd(); for ( ; iter != iter_end; ++iter) { const qtractorInstrument& instr = *iter; ts << "[" << instr.instrumentName() << "]" << endl; if (instr.bankSelMethod() > 0) ts << "BankSelMethod=" << instr.bankSelMethod() << endl; if (!instr.control().name().isEmpty()) ts << "Control=" << instr.control().name() << endl; if (!instr.rpn().name().isEmpty()) ts << "RPN=" << instr.rpn().name() << endl; if (!instr.nrpn().name().isEmpty()) ts << "NRPN=" << instr.nrpn().name() << endl; // - Patches... const qtractorInstrumentPatches& patches = instr.patches(); qtractorInstrumentPatches::ConstIterator pit = patches.constBegin(); const qtractorInstrumentPatches::ConstIterator& pit_end = patches.constEnd(); for ( ; pit != pit_end; ++pit) { const QString& sPatch = pit.value().name(); if (!sPatch.isEmpty()) { int iBank = pit.key(); const QString& sBank = (iBank < 0 ? QString("*") : QString::number(iBank)); ts << "Patch[" << sBank << "]=" << sPatch << endl; } } // - Keys... const qtractorInstrumentKeys& keys = instr.keys(); qtractorInstrumentKeys::ConstIterator kit = keys.constBegin(); const qtractorInstrumentKeys::ConstIterator kit_end = keys.constEnd(); for ( ; kit != kit_end; ++kit) { int iBank = kit.key(); const QString& sBank = (iBank < 0 ? QString("*") : QString::number(iBank)); const qtractorInstrumentNotes& notes = kit.value(); qtractorInstrumentNotes::ConstIterator nit = notes.constBegin(); const qtractorInstrumentNotes::ConstIterator& nit_end = notes.constEnd(); for ( ; nit != nit_end; ++nit) { const QString& sKey = nit.value().name(); if (!sKey.isEmpty()) { int iProg = nit.key(); const QString& sProg = (iProg < 0 ? QString("*") : QString::number(iProg)); ts << "Key[" << sBank << "," << sProg << "]=" << sKey << endl; } } } // - Drums... const qtractorInstrumentDrums& drums = instr.drums(); qtractorInstrumentDrums::ConstIterator dit = drums.constBegin(); const qtractorInstrumentDrums::ConstIterator& dit_end = drums.constEnd(); for ( ; dit != dit_end; ++dit) { int iBank = dit.key(); const QString& sBank = (iBank < 0 ? QString("*") : QString::number(iBank)); const qtractorInstrumentDrumFlags& flags = dit.value(); qtractorInstrumentDrumFlags::ConstIterator fit = flags.constBegin(); const qtractorInstrumentDrumFlags::ConstIterator& fit_end = flags.constEnd(); for ( ; fit != fit_end; ++fit) { int iProg = fit.key(); const QString& sProg = (iProg < 0 ? QString("*") : QString::number(iProg)); ts << "Drum[" << sBank << "," << sProg << "]=" << fit.value() << endl; } } ts << endl; } // Done. file.close(); return true; } void qtractorInstrumentList::saveDataList ( QTextStream& ts, const qtractorInstrumentDataList& list ) const { ts << endl; qtractorInstrumentDataList::ConstIterator it = list.constBegin(); const qtractorInstrumentDataList::ConstIterator& it_end = list.constEnd(); for ( ; it != it_end; ++it) { const QString& sName = it.value().name(); if (!sName.isEmpty()) { ts << "[" << sName << "]" << endl; saveData(ts, it.value()); } } } void qtractorInstrumentList::saveData ( QTextStream& ts, const qtractorInstrumentData& data ) const { if (!data.basedOn().isEmpty()) ts << "BasedOn=" << data.basedOn() << endl; qtractorInstrumentData::ConstIterator it = data.constBegin(); const qtractorInstrumentData::ConstIterator& it_end = data.constEnd(); for ( ; it != it_end; ++it) ts << it.key() << "=" << it.value() << endl; ts << endl; } // SoundFont chunk record header. typedef struct _SoundFontChunk { char id[4]; int32_t size; } SoundFontChunk; // Special SoundFont loader. bool qtractorInstrumentList::loadSoundFont ( QFile *pFile ) { pFile->seek(0); // Check RIFF file header... SoundFontChunk chunk; pFile->read((char *) &chunk, sizeof(chunk)); if (::strncmp(chunk.id, "RIFF", 4) != 0) return false; // Check file id... pFile->read(chunk.id, sizeof(chunk.id)); if (::strncmp(chunk.id, "sfbk", 4) != 0) return false; for (;;) { pFile->read((char *) &chunk, sizeof(chunk)); if (pFile->atEnd()) break; int iSize = chunk.size; if (::strncmp(chunk.id, "LIST", 4) == 0) { // Process a list chunk. pFile->read(chunk.id, sizeof(chunk.id)); iSize -= sizeof(chunk.id); if (::strncmp(chunk.id, "pdta", 4) == 0) { loadSoundFontPresets(pFile, iSize); break; // We have enough! } } // Maybe illegal; ignored; skip it. pFile->seek(pFile->pos() + iSize); } return true; } void qtractorInstrumentList::loadSoundFontPresets ( QFile *pFile, int iSize ) { // Parse the buffer... while (iSize > 0) { // Read a sub-chunk... SoundFontChunk chunk; pFile->read((char *) &chunk, sizeof(chunk)); if (pFile->atEnd()) break; iSize -= sizeof(chunk); if (::strncmp(chunk.id, "phdr", 4) == 0) { // Instrument name based on SoundFont file name... const QString& sInstrumentName = QFileInfo(pFile->fileName()).baseName(); qtractorInstrument& instr = (*this)[sInstrumentName]; instr.setInstrumentName(sInstrumentName); // Preset header... int iDrums = 0; int iPresets = (chunk.size / 38); for (int i = 0; i < iPresets; ++i) { char name[20]; int16_t prog; int16_t bank; pFile->read(name, sizeof(name)); pFile->read((char *) &(prog), sizeof(int16_t)); pFile->read((char *) &(bank), sizeof(int16_t)); pFile->seek(pFile->pos() + 14); // Add actual preset name... if (i < iPresets - 1) { const QString& sBank = QObject::tr("%1 Bank %2") .arg(instr.instrumentName()).arg(int(bank)); qtractorInstrumentData& patch = m_patches[sBank]; patch.setName(sBank); instr.setPatch(int(bank), patch); patch[int(prog)] = QString(name).simplified(); if (bank == 128 && iDrums == 0) { instr.setDrum(128, -1, true); // Usual SF2 standard ;) ++iDrums; } } } // Enough done. break; } // Ignored; skip it. pFile->seek(pFile->pos() + chunk.size); iSize -= chunk.size; } } // Special MIDINameDocument loader. bool qtractorInstrumentList::loadMidiNameDocument ( QFile *pFile ) { pFile->seek(0); QDomDocument doc; if (!doc.setContent(pFile)) return false; QDomElement eRoot = doc.documentElement(); if (eRoot.tagName() != "MIDINameDocument") return false; for (QDomNode nItem = eRoot.firstChild(); !nItem.isNull(); nItem = nItem.nextSibling()) { // Convert item node to element... QDomElement eItem = nItem.toElement(); if (eItem.isNull()) continue; const QString& sTagName = eItem.tagName(); if (sTagName == "MasterDeviceNames") loadMidiDeviceNames(&eItem); } return true; } void qtractorInstrumentList::loadMidiDeviceNames ( QDomElement *pElement ) { QString sInstrumentName; for (QDomNode nItem = pElement->firstChild(); !nItem.isNull(); nItem = nItem.nextSibling()) { // Convert item node to element... QDomElement eItem = nItem.toElement(); if (eItem.isNull()) continue; const QString& sTagName = eItem.tagName(); const QString& sName = eItem.attribute("Name"); if (sTagName == "Manufacturer") { if (!sInstrumentName.isEmpty()) sInstrumentName += ' '; sInstrumentName += eItem.text(); } else if (sTagName == "Model") { if (!sInstrumentName.isEmpty()) sInstrumentName += ' '; sInstrumentName += eItem.text(); } else if (sTagName == "ChannelNameSet") { if (!sInstrumentName.isEmpty()) sInstrumentName += ' '; sInstrumentName += sName; qtractorInstrument& instr = (*this)[sInstrumentName]; instr.setInstrumentName(sInstrumentName); loadMidiChannelNameSet(&eItem, instr); } else if (sTagName == "PatchNameList") { qtractorInstrument& instr = (*this)[sInstrumentName]; loadMidiPatchNameList(&eItem, instr, sName); } else if (sTagName == "NoteNameList") loadMidiNoteNameList(&eItem, sName); else if (sTagName == "ControlNameList") loadMidiControlNameList(&eItem, sName); } } void qtractorInstrumentList::loadMidiChannelNameSet ( QDomElement *pElement, qtractorInstrument& instr ) { for (QDomNode nItem = pElement->firstChild(); !nItem.isNull(); nItem = nItem.nextSibling()) { QDomElement eItem = nItem.toElement(); if (eItem.isNull()) continue; const QString& sTagName = eItem.tagName(); const QString& sName = eItem.attribute("Name"); if (sTagName == "PatchBank") loadMidiPatchBank(&eItem, instr, sName); else if (sTagName == "PatchNameList") loadMidiPatchNameList(&eItem, instr, sName); else if (sTagName == "NoteNameList") loadMidiNoteNameList(&eItem, sName); else if (sTagName == "ControlNameList") loadMidiControlNameList(&eItem, sName); else if (sTagName == "UsesPatchNameList") instr.setPatch(-1, m_patches[sName]); else if (sTagName == "UsesNotesNameList") instr.setNotes(-1, -1, m_notes[sName]); else if (sTagName == "UsesControlNameList") { instr.setControl(m_controls[sName]); instr.setRpn(m_rpns[sName]); instr.setNrpn(m_nrpns[sName]); } } } void qtractorInstrumentList::loadMidiPatchBank ( QDomElement *pElement, qtractorInstrument& instr, const QString& sName ) { int iBank = -1; for (QDomNode nItem = pElement->firstChild(); !nItem.isNull(); nItem = nItem.nextSibling()) { QDomElement eItem = nItem.toElement(); if (eItem.isNull()) continue; const QString& sTagName = eItem.tagName(); QString sSubName = eItem.attribute("Name"); if (sSubName.isEmpty()) sSubName = sName; if (sTagName == "MIDICommands") { iBank = 0; for (QDomNode nCommand = eItem.firstChild(); !nCommand.isNull(); nCommand = nCommand.nextSibling()) { QDomElement eCommand = nCommand.toElement(); if (eCommand.isNull()) continue; if (eCommand.tagName() == "ControlChange") { unsigned short iControl = eCommand.attribute("Control").toUShort(); unsigned short iValue = eCommand.attribute("Value").toUShort(); if (iControl == 0) // Bank MSB. iBank |= ((iValue << 7) & 0x3f80); else if (iControl == 32) // Bank LSB. iBank |= (iValue & 0x7f); } } } else if (sTagName == "PatchNameList") { loadMidiPatchNameList(&eItem, instr, sSubName); instr.setPatch(iBank, m_patches[sSubName]); } else if (sTagName == "UsesPatchNameList") instr.setPatch(iBank, m_patches[sSubName]); } } void qtractorInstrumentList::loadMidiPatchNameList ( QDomElement *pElement, qtractorInstrument& instr, const QString& sName ) { qtractorInstrumentData& patches = m_patches[sName]; patches.setName(sName); for (QDomNode nItem = pElement->firstChild(); !nItem.isNull(); nItem = nItem.nextSibling()) { QDomElement eItem = nItem.toElement(); if (eItem.isNull()) continue; const QString& sTagName = eItem.tagName(); if (sTagName == "Patch") { const QString& sProg = eItem.attribute("Name"); int iProg = eItem.attribute("ProgramChange").toInt(); patches[iProg] = sProg; for (QDomNode nSubItem = eItem.firstChild(); !nSubItem.isNull(); nSubItem = nSubItem.nextSibling()) { QDomElement eSubItem = nSubItem.toElement(); if (eSubItem.isNull()) continue; QString sSubName = eSubItem.attribute("Name"); if (sSubName.isEmpty()) sSubName = sProg; if (sSubName.isEmpty()) sSubName = sName; const QString& sSubTagName = eSubItem.tagName(); if (sSubTagName == "NoteNameList") loadMidiNoteNameList(&eSubItem, sSubName); else if (sSubTagName == "ControlNameList") loadMidiControlNameList(&eSubItem, sSubName); else if (sSubTagName == "UsesNoteNameList") instr.setNotes(-1, iProg, m_notes[sSubName]); else if (sSubTagName == "UsesControlNameList") { instr.setControl(m_controls[sSubName]); instr.setRpn(m_rpns[sSubName]); instr.setNrpn(m_nrpns[sSubName]); } } } } } void qtractorInstrumentList::loadMidiNoteNameList ( QDomElement *pElement, const QString& sName ) { qtractorInstrumentData& notes = m_notes[sName]; notes.setName(sName); for (QDomNode nItem = pElement->firstChild(); !nItem.isNull(); nItem = nItem.nextSibling()) { QDomElement eItem = nItem.toElement(); if (eItem.isNull()) continue; const QString& sTagName = eItem.tagName(); if (sTagName == "Note") { const QString& sNote = eItem.attribute("Name"); unsigned short iNote = eItem.attribute("Number").toUShort(); notes[int(iNote)] = sNote; } else if (sTagName == "NoteGroup") { QString sSubName = eItem.attribute("Name"); if (!sSubName.isEmpty()) sSubName += ' '; for (QDomNode nSubItem = eItem.firstChild(); !nSubItem.isNull(); nSubItem = nSubItem.nextSibling()) { QDomElement eSubItem = nSubItem.toElement(); if (eSubItem.isNull()) continue; const QString& sSubTagName = eSubItem.tagName(); if (sSubTagName == "Note") { const QString& sNote = eSubItem.attribute("Name"); int iNote = eSubItem.attribute("Number").toInt(); notes[iNote] = sSubName + sNote; } } } } } void qtractorInstrumentList::loadMidiControlNameList ( QDomElement *pElement, const QString& sName ) { qtractorInstrumentData& controls = m_controls[sName]; qtractorInstrumentData& rpns = m_rpns[sName]; qtractorInstrumentData& nrpns = m_nrpns[sName]; controls.setName(sName); rpns.setName(sName); nrpns.setName(sName); for (QDomNode nItem = pElement->firstChild(); !nItem.isNull(); nItem = nItem.nextSibling()) { QDomElement eItem = nItem.toElement(); if (eItem.isNull()) continue; const QString& sTagName = eItem.tagName(); if (sTagName == "Control") { const QString& sControlType = eItem.attribute("Type"); const QString& sControl = eItem.attribute("Name"); int iControl = eItem.attribute("Number").toInt(); if (sControlType == "NRPN") nrpns[iControl] = sControl; else if (sControlType == "RPN") rpns[iControl] = sControl; else // if (sControlType == "7bit" || sControlType == "14bit") controls[iControl] = sControl; } } } // end of qtractorInstrument.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorLv2Plugin.cpp0000644000175000001440000000012312207130265021347 xustar000000000000000027 mtime=1377611957.072697 26 atime=1381134667.46008 30 ctime=1381134667.504080057 qtractor-0.5.11/src/qtractorLv2Plugin.cpp0000644000175000001440000026004012207130265020640 0ustar00rncbcusers00000000000000// qtractorLv2Plugin.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #ifdef CONFIG_LV2 #include "qtractorLv2Plugin.h" #if defined(CONFIG_LV2_EVENT) || defined(CONFIG_LV2_ATOM) #include "qtractorMidiBuffer.h" #endif #ifdef CONFIG_LV2_PRESETS // LV2 Presets: standard directory access. #include "qtractorOptions.h" // For local file vs. URI manipulations. #include #include #endif #include // URI map/unmap features. #include "lv2/lv2plug.in/ns/ext/urid/urid.h" static QHash g_uri_map; static QHash g_ids_map; static uint32_t qtractor_lv2_urid_map ( LV2_URID_Map_Handle /*handle*/, const char *uri ) { #ifdef CONFIG_LV2_EVENT if (strcmp(uri, LILV_URI_MIDI_EVENT) == 0) return QTRACTOR_LV2_MIDI_EVENT_ID; #endif return qtractorLv2Plugin::lv2_urid_map(uri); } static LV2_URID_Map g_lv2_urid_map = { NULL, qtractor_lv2_urid_map }; static const LV2_Feature g_lv2_urid_map_feature = { LV2_URID_MAP_URI, &g_lv2_urid_map }; static const char *qtractor_lv2_urid_unmap ( LV2_URID_Unmap_Handle /*handle*/, uint32_t id ) { #ifdef CONFIG_LV2_EVENT if (id == QTRACTOR_LV2_MIDI_EVENT_ID) return LILV_URI_MIDI_EVENT; #endif return qtractorLv2Plugin::lv2_urid_unmap(id); } static LV2_URID_Unmap g_lv2_urid_unmap = { NULL, qtractor_lv2_urid_unmap }; static const LV2_Feature g_lv2_urid_unmap_feature = { LV2_URID_UNMAP_URI, &g_lv2_urid_unmap }; // URI map (uri_to_id) feature (DEPRECATED) #include "lv2/lv2plug.in/ns/ext/uri-map/uri-map.h" static uint32_t qtractor_lv2_uri_to_id ( LV2_URI_Map_Callback_Data /*data*/, const char *map, const char *uri ) { #ifdef CONFIG_LV2_EVENT if ((map && strcmp(map, LV2_EVENT_URI) == 0) && strcmp(uri, LILV_URI_MIDI_EVENT) == 0) return QTRACTOR_LV2_MIDI_EVENT_ID; #endif return qtractorLv2Plugin::lv2_urid_map(uri); } static LV2_URI_Map_Feature g_lv2_uri_map = { NULL, qtractor_lv2_uri_to_id }; static const LV2_Feature g_lv2_uri_map_feature = { LV2_URI_MAP_URI, &g_lv2_uri_map }; #ifdef CONFIG_LV2_STATE static const LV2_Feature g_lv2_state_feature = { LV2_STATE_URI, NULL }; static LV2_State_Status qtractor_lv2_state_store ( LV2_State_Handle handle, uint32_t key, const void *value, size_t size, uint32_t type, uint32_t flags ) { qtractorLv2Plugin *pLv2Plugin = static_cast (handle); if (pLv2Plugin == NULL) return LV2_STATE_ERR_UNKNOWN; #ifdef CONFIG_DEBUG qDebug("qtractor_lv2_state_store(%p, %d, %d, %d, %d)", pLv2Plugin, int(key), int(size), int(type), int(flags)); #endif return pLv2Plugin->lv2_state_store(key, value, size, type, flags); } static const void *qtractor_lv2_state_retrieve ( LV2_State_Handle handle, uint32_t key, size_t *size, uint32_t *type, uint32_t *flags ) { qtractorLv2Plugin *pLv2Plugin = static_cast (handle); if (pLv2Plugin == NULL) return NULL; #ifdef CONFIG_DEBUG qDebug("qtractor_lv2_state_retrieve(%p, %d)", pLv2Plugin, int(key)); #endif return pLv2Plugin->lv2_state_retrieve(key, size, type, flags); } #endif // CONFIG_LV2_STATE // URI map helpers (static). uint32_t qtractorLv2Plugin::lv2_urid_map ( const char *uri ) { const QString sUri(uri); QHash::ConstIterator iter = g_uri_map.constFind(sUri); if (iter == g_uri_map.constEnd()) { uint32_t id = g_uri_map.size() + 1000; g_uri_map.insert(sUri, id); g_ids_map.insert(id, sUri.toUtf8()); return id; } return iter.value(); } const char *qtractorLv2Plugin::lv2_urid_unmap ( uint32_t id ) { QHash::ConstIterator iter = g_ids_map.constFind(id); if (iter == g_ids_map.constEnd()) return NULL; return iter.value().constData(); } #ifdef CONFIG_LV2_WORKER // LV2 Worker/Schedule support. #include #include #include #include //---------------------------------------------------------------------- // class qtractorLv2Worker -- LV2 Worker/Schedule item decl. // class qtractorLv2WorkerThread; class qtractorLv2Worker { public: // Constructor. qtractorLv2Worker(qtractorLv2Plugin *pLv2Plugin, const LV2_Feature *const *features); // Destructor. ~qtractorLv2Worker(); // Instance copy of worker schedule feature. LV2_Feature **lv2_features() const { return m_lv2_features; } // Schedule work. void schedule(uint32_t size, const void *data); // Respond work. void respond(uint32_t size, const void *data); // Commit work. void commit(); // Process work. void process(); // Sync thread state flags accessors. void setWaitSync(bool bWaitSync) { m_bWaitSync = bWaitSync; } bool isWaitSync() const { return m_bWaitSync; } private: // Instance members. qtractorLv2Plugin *m_pLv2Plugin; LV2_Feature **m_lv2_features; LV2_Feature m_lv2_schedule_feature; LV2_Worker_Schedule m_lv2_schedule; volatile bool m_bWaitSync; jack_ringbuffer_t *m_pRequests; jack_ringbuffer_t *m_pResponses; void *m_pResponse; static qtractorLv2WorkerThread *g_pWorkerThread; static unsigned int g_iWorkerRefCount; }; static LV2_Worker_Status qtractor_lv2_worker_schedule ( LV2_Worker_Schedule_Handle handle, uint32_t size, const void *data ) { qtractorLv2Worker *pLv2Worker = static_cast (handle); if (pLv2Worker == NULL) return LV2_WORKER_ERR_UNKNOWN; #ifdef CONFIG_DEBUG qDebug("qtractor_lv2_worker_schedule(%p, %u, %p)", pLv2Worker, size, data); #endif pLv2Worker->schedule(size, data); return LV2_WORKER_SUCCESS; } static LV2_Worker_Status qtractor_lv2_worker_respond ( LV2_Worker_Respond_Handle handle, uint32_t size, const void *data ) { qtractorLv2Worker *pLv2Worker = static_cast (handle); if (pLv2Worker == NULL) return LV2_WORKER_ERR_UNKNOWN; #ifdef CONFIG_DEBUG qDebug("qtractor_lv2_worker_respond(%p, %u, %p)", pLv2Worker, size, data); #endif pLv2Worker->respond(size, data); return LV2_WORKER_SUCCESS; } //---------------------------------------------------------------------- // class qtractorLv2WorkerThread -- LV2 Worker/Schedule thread. // class qtractorLv2WorkerThread : public QThread { public: // Constructor. qtractorLv2WorkerThread(unsigned int iSyncSize = 128); // Destructor. ~qtractorLv2WorkerThread(); // Thread run state accessors. void setRunState(bool bRunState); bool runState() const; // Wake from executive wait condition. void sync(qtractorLv2Worker *pLv2Worker = NULL); protected: // The main thread executive. void run(); private: // The peak file queue instance reference. unsigned int m_iSyncSize; unsigned int m_iSyncMask; qtractorLv2Worker **m_ppSyncItems; volatile unsigned int m_iSyncRead; volatile unsigned int m_iSyncWrite; // Whether the thread is logically running. volatile bool m_bRunState; // Thread synchronization objects. QMutex m_mutex; QWaitCondition m_cond; }; // Constructor. qtractorLv2WorkerThread::qtractorLv2WorkerThread ( unsigned int iSyncSize ) { m_iSyncSize = (64 << 1); while (m_iSyncSize < iSyncSize) m_iSyncSize <<= 1; m_iSyncMask = (m_iSyncSize - 1); m_ppSyncItems = new qtractorLv2Worker * [m_iSyncSize]; m_iSyncRead = 0; m_iSyncWrite = 0; ::memset(m_ppSyncItems, 0, m_iSyncSize * sizeof(qtractorLv2Worker *)); m_bRunState = false; } // Destructor. qtractorLv2WorkerThread::~qtractorLv2WorkerThread (void) { delete [] m_ppSyncItems; } // Run state accessor. void qtractorLv2WorkerThread::setRunState ( bool bRunState ) { QMutexLocker locker(&m_mutex); m_bRunState = bRunState; } bool qtractorLv2WorkerThread::runState (void) const { return m_bRunState; } // Wake from executive wait condition. void qtractorLv2WorkerThread::sync ( qtractorLv2Worker *pLv2Worker ) { if (pLv2Worker == NULL) { unsigned int r = m_iSyncRead; unsigned int w = m_iSyncWrite; while (r != w) { qtractorLv2Worker *pSyncItem = m_ppSyncItems[r]; if (pSyncItem) pSyncItem->setWaitSync(false); ++r &= m_iSyncMask; w = m_iSyncWrite; } // m_iSyncRead = r; } else { // !pLv2Worker->isWaitSync() unsigned int n; unsigned int r = m_iSyncRead; unsigned int w = m_iSyncWrite; if (w > r) { n = ((r - w + m_iSyncSize) & m_iSyncMask) - 1; } else if (r > w) { n = (r - w) - 1; } else { n = m_iSyncSize - 1; } if (n > 0) { pLv2Worker->setWaitSync(true); m_ppSyncItems[w] = pLv2Worker; m_iSyncWrite = (w + 1) & m_iSyncMask; } } if (m_mutex.tryLock()) { m_cond.wakeAll(); m_mutex.unlock(); } #ifdef CONFIG_DEBUG_0 else qDebug("qtractorLv2WorkerThread[%p]::sync(): tryLock() failed.", this); #endif } // The main thread executive cycle. void qtractorLv2WorkerThread::run (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorLv2WorkerThread[%p]::run(): started...", this); #endif m_mutex.lock(); m_bRunState = true; while (m_bRunState) { // Do whatever we must, then wait for more... unsigned int r = m_iSyncRead; unsigned int w = m_iSyncWrite; while (r != w) { m_ppSyncItems[r]->process(); ++r &= m_iSyncMask; w = m_iSyncWrite; } m_iSyncRead = r; // Wait for sync... m_cond.wait(&m_mutex); } m_mutex.unlock(); #ifdef CONFIG_DEBUG_0 qDebug("qtractorLv2WorkerThread[%p]::run(): stopped.\n", this); #endif } //---------------------------------------------------------------------- // class qtractorLv2Worker -- LV2 Worker/Schedule item impl. // qtractorLv2WorkerThread *qtractorLv2Worker::g_pWorkerThread = NULL; unsigned int qtractorLv2Worker::g_iWorkerRefCount = 0; // Constructor. qtractorLv2Worker::qtractorLv2Worker ( qtractorLv2Plugin *pLv2Plugin, const LV2_Feature *const *features ) { m_pLv2Plugin = pLv2Plugin; int iFeatures = 0; while (features && features[iFeatures]) { ++iFeatures; } m_lv2_features = new LV2_Feature * [iFeatures + 2]; for (int i = 0; i < iFeatures; ++i) m_lv2_features[i] = (LV2_Feature *) features[i]; m_lv2_schedule.handle = this; m_lv2_schedule.schedule_work = &qtractor_lv2_worker_schedule; m_lv2_schedule_feature.URI = LV2_WORKER__schedule; m_lv2_schedule_feature.data = &m_lv2_schedule; m_lv2_features[iFeatures++] = &m_lv2_schedule_feature; m_lv2_features[iFeatures] = NULL; m_bWaitSync = false; m_pRequests = ::jack_ringbuffer_create(1024); m_pResponses = ::jack_ringbuffer_create(1024); m_pResponse = (void *) ::malloc(1024); if (++g_iWorkerRefCount == 1) { g_pWorkerThread = new qtractorLv2WorkerThread(); g_pWorkerThread->start(); } } // Destructor. qtractorLv2Worker::~qtractorLv2Worker (void) { m_bWaitSync = false; if (--g_iWorkerRefCount == 0) { if (g_pWorkerThread->isRunning()) do { g_pWorkerThread->setRunState(false); // g_pWorkerThread->terminate(); g_pWorkerThread->sync(); } while (!g_pWorkerThread->wait(100)); delete g_pWorkerThread; g_pWorkerThread = NULL; } ::jack_ringbuffer_free(m_pRequests); ::jack_ringbuffer_free(m_pResponses); ::free(m_pResponse); delete [] m_lv2_features; } // Schedule work. void qtractorLv2Worker::schedule ( uint32_t size, const void *data ) { ::jack_ringbuffer_write(m_pRequests, (const char *) &size, sizeof(size)); ::jack_ringbuffer_write(m_pRequests, (const char *) data, size); if (g_pWorkerThread) g_pWorkerThread->sync(this); } // Response work. void qtractorLv2Worker::respond ( uint32_t size, const void *data ) { ::jack_ringbuffer_write(m_pResponses, (const char *) &size, sizeof(size)); ::jack_ringbuffer_write(m_pResponses, (const char *) data, size); } // Commit work. void qtractorLv2Worker::commit (void) { const LV2_Worker_Interface *worker = m_pLv2Plugin->lv2_worker_interface(0); if (worker == NULL) return; unsigned short i, iInstances = m_pLv2Plugin->instances(); uint32_t read_space = ::jack_ringbuffer_read_space(m_pResponses); while (read_space > 0) { uint32_t size = 0; ::jack_ringbuffer_read(m_pResponses, (char *) &size, sizeof(size)); ::jack_ringbuffer_read(m_pResponses, (char *) m_pResponse, size); if (worker->work_response) { for (i = 0; i < iInstances; ++i) { LV2_Handle handle = m_pLv2Plugin->lv2_handle(i); if (handle) (*worker->work_response)(handle, size, m_pResponse); } } read_space -= sizeof(size) + size; } if (worker->end_run) { for (i = 0; i < iInstances; ++i) { LV2_Handle handle = m_pLv2Plugin->lv2_handle(i); if (handle) (*worker->end_run)(handle); } } } // Process work. void qtractorLv2Worker::process (void) { if (!m_bWaitSync) return; const LV2_Worker_Interface *worker = m_pLv2Plugin->lv2_worker_interface(0); if (worker == NULL) return; unsigned short i, iInstances = m_pLv2Plugin->instances(); void *buf = NULL; uint32_t size = 0; uint32_t read_space = ::jack_ringbuffer_read_space(m_pRequests); if (read_space > 0) buf = ::malloc(read_space); while (read_space > 0) { ::jack_ringbuffer_read(m_pRequests, (char *) &size, sizeof(size)); ::jack_ringbuffer_read(m_pRequests, (char *) buf, size); if (worker->work) { for (i = 0; i < iInstances; ++i) { LV2_Handle handle = m_pLv2Plugin->lv2_handle(i); if (handle) (*worker->work)(handle, qtractor_lv2_worker_respond, this, size, buf); } } read_space -= sizeof(size) + size; } if (buf) ::free(buf); m_bWaitSync = false; } #endif // CONFIG_LV2_WORKER #ifdef CONFIG_LV2_STATE_FILES #include "qtractorSession.h" #include "qtractorDocument.h" #include #include static char *qtractor_lv2_state_abstract_path ( LV2_State_Map_Path_Handle handle, const char *absolute_path ) { qtractorLv2Plugin *pLv2Plugin = static_cast (handle); if (pLv2Plugin == NULL) return NULL; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return NULL; #ifdef CONFIG_DEBUG qDebug("qtractor_lv2_state_abstract_path(%p, \"%s\")", pLv2Plugin, absolute_path); #endif // abstract_path from absolute_path... const QString& sAbstractPath = qtractorDocument::addArchiveFile( QDir(pSession->sessionDir()).relativeFilePath(absolute_path)); return ::strdup(sAbstractPath.toUtf8().constData()); } static char *qtractor_lv2_state_absolute_path ( LV2_State_Map_Path_Handle handle, const char *abstract_path ) { qtractorLv2Plugin *pLv2Plugin = static_cast (handle); if (pLv2Plugin == NULL) return NULL; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return NULL; #ifdef CONFIG_DEBUG qDebug("qtractor_lv2_state_absolute_path(%p, \"%s\")", pLv2Plugin, abstract_path); #endif QFileInfo fi(abstract_path); if (fi.isRelative()) fi.setFile(QDir(pSession->sessionDir()), fi.filePath()); // absolute_path from abstract_path... const QString& sAbsolutePath = fi.absoluteFilePath(); return ::strdup(sAbsolutePath.toUtf8().constData()); } #ifdef CONFIG_LV2_STATE_MAKE_PATH static QString qtractor_lv2_state_prefix ( qtractorLv2Plugin *pLv2Plugin ) { QString sPrefix; const QString& sPresetName = pLv2Plugin->preset(); if (sPresetName.isEmpty()) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { const QString& sSessionName = pSession->sessionName(); if (!sSessionName.isEmpty()) { sPrefix += qtractorSession::sanitize(sSessionName); sPrefix += '-'; } } const QString& sListName = pLv2Plugin->list()->name(); if (!sListName.isEmpty()) { sPrefix += qtractorSession::sanitize(sListName); sPrefix += '-'; } } sPrefix += pLv2Plugin->type()->label(); sPrefix += '-'; if (sPresetName.isEmpty()) { sPrefix += QString::number(pLv2Plugin->type()->uniqueID(), 16); } else { sPrefix += qtractorSession::sanitize(sPresetName); } return sPrefix; } static char *qtractor_lv2_state_make_path ( LV2_State_Make_Path_Handle handle, const char *relative_path ) { qtractorLv2Plugin *pLv2Plugin = static_cast (handle); if (pLv2Plugin == NULL) return NULL; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return NULL; #ifdef CONFIG_DEBUG qDebug("qtractor_lv2_state_make_path(%p, \"%s\")", pLv2Plugin, relative_path); #endif QFileInfo fi(relative_path); const QDir dir(pSession->sessionDir()); if (fi.isAbsolute()) fi.setFile(dir, fi.fileName()); else fi.setFile(dir, fi.filePath()); const QString& sFilePath = fi.filePath(); if (!QDir(sFilePath).exists()) dir.mkpath(sFilePath); const QString& sFileName = qtractor_lv2_state_prefix(pLv2Plugin) + ".lv2_state"; // '.' + fi.fileName(); // make_path... const QString& sMakePath = QFileInfo(QDir(sFilePath), sFileName).filePath(); return ::strdup(sMakePath.toUtf8().constData()); } #endif // CONFIG_LV2_STATE_MAKE_PATH #endif // CONFIG_LV2_STATE_FILES #ifdef CONFIG_LV2_BUF_SIZE #include "qtractorAudioEngine.h" #include "lv2/lv2plug.in/ns/ext/buf-size/buf-size.h" static const LV2_Feature g_lv2_buf_size_feature = { LV2_BUF_SIZE__boundedBlockLength, NULL }; #endif // CONFIG_LV2_BUF_SIZE static const LV2_Feature *g_lv2_features[] = { &g_lv2_urid_map_feature, &g_lv2_urid_unmap_feature, &g_lv2_uri_map_feature, // deprecated #ifdef CONFIG_LV2_STATE &g_lv2_state_feature, #endif #ifdef CONFIG_LV2_BUF_SIZE &g_lv2_buf_size_feature, #endif NULL }; #ifdef CONFIG_LV2_UI #include "qtractorPluginForm.h" #define LV2_UI_TYPE_NONE 0 #define LV2_UI_TYPE_QT4 1 #define LV2_UI_TYPE_EXTERNAL 2 #define LV2_UI_TYPE_GTK 3 #define LV2_UI_TYPE_X11 4 #if QT_VERSION < 0x050000 #define LV2_UI_HOST_URI LV2_UI__Qt4UI #else #define LV2_UI_HOST_URI LV2_UI_PREFIX "Qt5UI" #endif static void qtractor_lv2_ui_write ( SuilController ui_controller, uint32_t port_index, uint32_t buffer_size, uint32_t protocol, const void *buffer ) { qtractorLv2Plugin *pLv2Plugin = static_cast (ui_controller); if (pLv2Plugin == NULL) return; pLv2Plugin->lv2_ui_write(port_index, buffer_size, protocol, buffer); } #ifdef CONFIG_LV2_EXTERNAL_UI static void qtractor_lv2_ui_closed ( LV2UI_Controller ui_controller ) { qtractorLv2Plugin *pLv2Plugin = static_cast (ui_controller); if (pLv2Plugin == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractor_lv2_ui_closed(%p)", pLv2Plugin); #endif // Just flag up the closure... pLv2Plugin->setEditorClosed(true); } #endif // CONFIG_LV2_EXTERNAL_UI #if QT_VERSION < 0x050000 #include class qtractorLv2Plugin::EventFilter : public QObject { public: // Constructor. EventFilter(qtractorLv2Plugin *pLv2Plugin, QWidget *pQt4Widget) : QObject(), m_pLv2Plugin(pLv2Plugin), m_pQt4Widget(pQt4Widget) { m_pQt4Widget->installEventFilter(this); } bool eventFilter(QObject *pObject, QEvent *pEvent) { if (pObject == static_cast (m_pQt4Widget)) { switch (pEvent->type()) { case QEvent::Close: { // Defer widget close! m_pQt4Widget->removeEventFilter(this); m_pQt4Widget = NULL; m_pLv2Plugin->closeEditorEx(); pEvent->ignore(); return true; } case QEvent::Resize: { // LV2 UI resize control... QResizeEvent *pResizeEvent = static_cast (pEvent); if (pResizeEvent) m_pLv2Plugin->resizeEditor(pResizeEvent->size()); // Fall thru... } default: break; } } return QObject::eventFilter(pObject, pEvent); } private: // Instance variables. qtractorLv2Plugin *m_pLv2Plugin; QWidget *m_pQt4Widget; }; #endif #endif // CONFIG_LV2_UI // LV2 World stuff (ref. counted). static LilvWorld *g_lv2_world = NULL; static LilvPlugins *g_lv2_plugins = NULL; // Supported port classes. static LilvNode *g_lv2_input_class = NULL; static LilvNode *g_lv2_output_class = NULL; static LilvNode *g_lv2_control_class = NULL; static LilvNode *g_lv2_audio_class = NULL; #ifdef CONFIG_LV2_EVENT static LilvNode *g_lv2_event_class = NULL; static LilvNode *g_lv2_midi_class = NULL; #endif #ifdef CONFIG_LV2_ATOM static LilvNode *g_lv2_atom_port_class = NULL; static uint32_t g_lv2_atom_event_type = 0; static uint32_t g_lv2_atom_sequence_type = 0; static uint32_t g_lv2_atom_string_type = 0; static uint32_t g_lv2_atom_float_type = 0; static uint32_t g_lv2_atom_int_type = 0; #endif #ifdef CONFIG_LV2_UI #ifdef CONFIG_LV2_EXTERNAL_UI static LilvNode *g_lv2_external_ui_class = NULL; #ifdef LV2_EXTERNAL_UI_DEPRECATED_URI static LilvNode *g_lv2_external_ui_deprecated_class = NULL; #endif #endif #if QT_VERSION < 0x050000 static LilvNode *g_lv2_x11_ui_class = NULL; static LilvNode *g_lv2_gtk_ui_class = NULL; static LilvNode *g_lv2_qt4_ui_class = NULL; #endif #endif // CONFIG_LV2_UI // Supported plugin features. static LilvNode *g_lv2_realtime_hint = NULL; static LilvNode *g_lv2_extension_data_hint = NULL; #ifdef CONFIG_LV2_WORKER static LilvNode *g_lv2_worker_schedule_hint = NULL; #endif #ifdef CONFIG_LV2_STATE static LilvNode *g_lv2_state_interface_hint = NULL; #endif // Supported port properties (hints). static LilvNode *g_lv2_toggled_prop = NULL; static LilvNode *g_lv2_integer_prop = NULL; static LilvNode *g_lv2_sample_rate_prop = NULL; static LilvNode *g_lv2_logarithmic_prop = NULL; #ifdef CONFIG_LV2_PROGRAMS void qtractor_lv2_program_changed ( LV2_Programs_Handle handle, int32_t index ) { qtractorLv2Plugin *pLv2Plugin = static_cast (handle); if (pLv2Plugin == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractor_lv2_program_changed(%p, %d)", pLv2Plugin, index); #endif pLv2Plugin->lv2_program_changed(index); } #endif // CONFIG_LV2_PROGRAMS #ifdef CONFIG_LV2_PRESETS // LV2 Presets: port value setter. static void qtractor_lv2_set_port_value ( const char *port_symbol, void *user_data, const void *value, uint32_t size, uint32_t type ) { qtractorLv2Plugin *pLv2Plugin = static_cast (user_data); if (pLv2Plugin == NULL) return; const LilvPlugin *plugin = pLv2Plugin->lv2_plugin(); if (plugin == NULL) return; if (size != sizeof(float) || type != g_lv2_atom_float_type) return; LilvNode *symbol = lilv_new_string(g_lv2_world, port_symbol); const LilvPort *port = lilv_plugin_get_port_by_symbol(plugin, symbol); if (port) { const float val = *(float *) value; unsigned long port_index = lilv_port_get_index(plugin, port); pLv2Plugin->updateParamValue(port_index, val, true); } lilv_node_free(symbol); } // LV2 Presets: port value getter. static const void *qtractor_lv2_get_port_value ( const char *port_symbol, void *user_data, uint32_t *size, uint32_t *type ) { const void *retv = NULL; *size = 0; *type = 0; qtractorLv2Plugin *pLv2Plugin = static_cast (user_data); if (pLv2Plugin == NULL) return retv; const LilvPlugin *plugin = pLv2Plugin->lv2_plugin(); if (plugin == NULL) return retv; LilvNode *symbol = lilv_new_string(g_lv2_world, port_symbol); const LilvPort *port = lilv_plugin_get_port_by_symbol(plugin, symbol); if (port) { unsigned long iIndex = lilv_port_get_index(plugin, port); qtractorPluginParam *pParam = pLv2Plugin->findParam(iIndex); if (pParam) { *size = sizeof(float); *type = g_lv2_atom_float_type; retv = (const void *) (pParam->subject())->data(); } } lilv_node_free(symbol); return retv; } // Remove specific dir/file path. static void qtractor_lv2_remove_dir(const QString& sDir); static void qtractor_lv2_remove_file ( const QFileInfo& info ) { if (info.exists()) { const QString& sPath = info.absoluteFilePath(); if (info.isDir()) { qtractor_lv2_remove_dir(sPath); } else { QFile::remove(sPath); } } } static void qtractor_lv2_remove_dir_list ( const QList& list ) { QListIterator iter(list); while (iter.hasNext()) qtractor_lv2_remove_file(iter.next()); } static void qtractor_lv2_remove_dir ( const QString& sDir ) { const QDir dir(sDir); qtractor_lv2_remove_dir_list( dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot)); QDir cwd = QDir::current(); if (cwd.absolutePath() == dir.absolutePath()) { cwd.cdUp(); QDir::setCurrent(cwd.path()); } dir.rmdir(sDir); } #endif // CONFIG_LV2_PRESETS #ifdef CONFIG_LV2_TIME // LV2 Time-position control structure. static struct qtractorLv2Time { enum Index { position = 0, bar, beat, beatUnit, beatsPerBar, beatsPerMinute, frame, framesPerSecond, speed, numOfMembers }; const char *uri; LilvNode *node; float value; QList *params; } g_lv2_time[] = { { LV2_TIME__position, NULL, 0.0f, NULL }, { LV2_TIME__bar, NULL, 0.0f, NULL }, { LV2_TIME__beat, NULL, 0.0f, NULL }, { LV2_TIME__beatUnit, NULL, 0.0f, NULL }, { LV2_TIME__beatsPerBar, NULL, 0.0f, NULL }, { LV2_TIME__beatsPerMinute, NULL, 0.0f, NULL }, { LV2_TIME__frame, NULL, 0.0f, NULL }, { LV2_TIME__framesPerSecond, NULL, 0.0f, NULL }, { LV2_TIME__speed, NULL, 0.0f, NULL } }; #endif // CONFIG_LV2_TIME #ifdef CONFIG_LV2_OPTIONS #ifdef CONFIG_LV2_BUF_SIZE static uint32_t g_lv2_bufsz_min_block_length = 0; static uint32_t g_lv2_bufsz_max_block_length = 0; static uint32_t g_lv2_bufsz_sequence_size = 0; #endif #endif //---------------------------------------------------------------------------- // qtractorLv2PluginType -- LV2 plugin type instance. // // Derived methods. bool qtractorLv2PluginType::open (void) { // Do we have a descriptor already? if (m_lv2_plugin == NULL) m_lv2_plugin = lv2_plugin(m_sUri); if (m_lv2_plugin == NULL) return false; #ifdef CONFIG_DEBUG qDebug("qtractorLv2PluginType[%p]::open() uri=\"%s\"", this, filename().toUtf8().constData()); #endif // Retrieve plugin type names. LilvNode *name = lilv_plugin_get_name(m_lv2_plugin); if (name) { m_sName = lilv_node_as_string(name); lilv_node_free(name); } else { m_sName = filename(); int iIndex = m_sName.lastIndexOf('/'); if (iIndex > 0) m_sName = m_sName.right(m_sName.length() - iIndex - 1); } // Sanitize plugin label. m_sLabel = m_sName.simplified().replace(QRegExp("[\\s|\\.|\\-]+"), "_"); // Retrieve plugin unique identifier. m_iUniqueID = qHash(m_sUri); // Compute and cache port counts... m_iControlIns = 0; m_iControlOuts = 0; m_iAudioIns = 0; m_iAudioOuts = 0; m_iMidiIns = 0; m_iMidiOuts = 0; #ifdef CONFIG_LV2_EVENT m_iMidiEventIns = 0; m_iMidiEventOuts = 0; #endif #ifdef CONFIG_LV2_ATOM m_iMidiAtomIns = 0; m_iMidiAtomOuts = 0; #endif unsigned long iNumPorts = lilv_plugin_get_num_ports(m_lv2_plugin); for (unsigned long i = 0; i < iNumPorts; ++i) { const LilvPort *port = lilv_plugin_get_port_by_index(m_lv2_plugin, i); if (port) { if (lilv_port_is_a(m_lv2_plugin, port, g_lv2_control_class)) { if (lilv_port_is_a(m_lv2_plugin, port, g_lv2_input_class)) ++m_iControlIns; else if (lilv_port_is_a(m_lv2_plugin, port, g_lv2_output_class)) ++m_iControlOuts; } else if (lilv_port_is_a(m_lv2_plugin, port, g_lv2_audio_class)) { if (lilv_port_is_a(m_lv2_plugin, port, g_lv2_input_class)) ++m_iAudioIns; else if (lilv_port_is_a(m_lv2_plugin, port, g_lv2_output_class)) ++m_iAudioOuts; } #ifdef CONFIG_LV2_EVENT else if (lilv_port_is_a(m_lv2_plugin, port, g_lv2_event_class) || lilv_port_is_a(m_lv2_plugin, port, g_lv2_midi_class)) { if (lilv_port_is_a(m_lv2_plugin, port, g_lv2_input_class)) ++m_iMidiEventIns; else if (lilv_port_is_a(m_lv2_plugin, port, g_lv2_output_class)) ++m_iMidiEventOuts; } #endif #ifdef CONFIG_LV2_ATOM else if (lilv_port_is_a(m_lv2_plugin, port, g_lv2_atom_port_class)) { if (lilv_port_is_a(m_lv2_plugin, port, g_lv2_input_class)) ++m_iMidiAtomIns; else if (lilv_port_is_a(m_lv2_plugin, port, g_lv2_output_class)) ++m_iMidiAtomOuts; } #endif } } #ifdef CONFIG_LV2_EVENT m_iMidiIns += m_iMidiEventIns; m_iMidiOuts += m_iMidiEventOuts; #endif #ifdef CONFIG_LV2_ATOM m_iMidiIns += m_iMidiAtomIns; m_iMidiOuts += m_iMidiAtomOuts; #endif // Cache flags. m_bRealtime = lilv_plugin_has_feature(m_lv2_plugin, g_lv2_realtime_hint); m_bConfigure = false; #ifdef CONFIG_LV2_STATE // Query for state interface extension data... LilvNodes *nodes = lilv_plugin_get_value(m_lv2_plugin, g_lv2_extension_data_hint); LILV_FOREACH(nodes, i, nodes) { const LilvNode *node = lilv_nodes_get(nodes, i); if (lilv_node_equals(node, g_lv2_state_interface_hint)) { m_bConfigure = true; break; } } #endif #ifdef CONFIG_LV2_UI // Check the UI inventory... LilvUIs *uis = lilv_plugin_get_uis(m_lv2_plugin); if (uis) { LILV_FOREACH(uis, i, uis) { const LilvUI *ui = lilv_uis_get(uis, i); #ifdef CONFIG_LV2_EXTERNAL_UI if (lilv_ui_is_a(ui, g_lv2_external_ui_class) #ifdef LV2_EXTERNAL_UI_DEPRECATED_URI || lilv_ui_is_a(ui, g_lv2_external_ui_deprecated_class) #endif ) { m_bEditor = true; break; } #endif #if QT_VERSION < 0x050000 if (lilv_ui_is_a(ui, g_lv2_x11_ui_class)) { m_bEditor = true; break; } if (lilv_ui_is_a(ui, g_lv2_gtk_ui_class)) { m_bEditor = true; break; } if (lilv_ui_is_a(ui, g_lv2_qt4_ui_class)) { m_bEditor = true; break; } #endif } lilv_uis_free(uis); } #endif // Done. return true; } void qtractorLv2PluginType::close (void) { m_lv2_plugin = NULL; } // Factory method (static) qtractorLv2PluginType *qtractorLv2PluginType::createType ( const QString& sUri, LilvPlugin *plugin ) { // Sanity check... if (sUri.isEmpty()) return NULL; if (plugin == NULL) plugin = lv2_plugin(sUri); if (plugin == NULL) return NULL; // Yep, most probably its a valid plugin descriptor... return new qtractorLv2PluginType(sUri, plugin); } // Descriptor method (static) LilvPlugin *qtractorLv2PluginType::lv2_plugin ( const QString& sUri ) { if (g_lv2_plugins == NULL) return NULL; // Retrieve plugin descriptor if any... LilvNode *uri = lilv_new_uri(g_lv2_world, sUri.toUtf8().constData()); if (uri == NULL) return NULL; LilvPlugin *plugin = const_cast ( lilv_plugins_get_by_uri(g_lv2_plugins, uri)); #if 0 LilvNodes *list = lilv_plugin_get_required_features( static_cast (plugin)); if (list) { LILV_FOREACH(nodes, iter, list) { const LilvNode *node = lilv_nodes_get(list, iter); bool bSupported = false; for (int i = 0; !bSupported && g_lv2_features[i]; ++i) { const LilvNode *impl = lilv_new_uri(g_lv2_world, g_lv2_features[i]->URI); bSupported = lilv_node_equals(impl, node); } if (!bSupported) { #ifdef CONFIG_DEBUG qDebug("qtractorLv2PluginType::lilv_plugin: node %s not supported.", lilv_node_as_string(lilv_nodes_get(node, iter))); #endif plugin = NULL; break; } } } #endif lilv_node_free(uri); return plugin; } // LV2 World stuff (ref. counted). void qtractorLv2PluginType::lv2_open (void) { if (g_lv2_plugins) return; #ifdef CONFIG_DEBUG qDebug("qtractorLv2PluginType::lv2_open()"); #endif g_lv2_world = lilv_world_new(); // Set dyn-manifest support option... LilvNode *dyn_manifest = lilv_new_bool(g_lv2_world, true); lilv_world_set_option(g_lv2_world, LILV_OPTION_DYN_MANIFEST, dyn_manifest); lilv_node_free(dyn_manifest); // Find all installed plugins. lilv_world_load_all(g_lv2_world); g_lv2_plugins = const_cast ( lilv_world_get_all_plugins(g_lv2_world)); // Set up the port classes we support. g_lv2_input_class = lilv_new_uri(g_lv2_world, LILV_URI_INPUT_PORT); g_lv2_output_class = lilv_new_uri(g_lv2_world, LILV_URI_OUTPUT_PORT); g_lv2_control_class = lilv_new_uri(g_lv2_world, LILV_URI_CONTROL_PORT); g_lv2_audio_class = lilv_new_uri(g_lv2_world, LILV_URI_AUDIO_PORT); #ifdef CONFIG_LV2_EVENT g_lv2_event_class = lilv_new_uri(g_lv2_world, LILV_URI_EVENT_PORT); g_lv2_midi_class = lilv_new_uri(g_lv2_world, LILV_URI_MIDI_EVENT); #endif #ifdef CONFIG_LV2_ATOM g_lv2_atom_port_class = lilv_new_uri(g_lv2_world, LV2_ATOM__AtomPort); g_lv2_atom_event_type = qtractorLv2Plugin::lv2_urid_map(LV2_ATOM__eventTransfer); g_lv2_atom_sequence_type = qtractorLv2Plugin::lv2_urid_map(LV2_ATOM__Sequence); g_lv2_atom_string_type = qtractorLv2Plugin::lv2_urid_map(LV2_ATOM__String); g_lv2_atom_float_type = qtractorLv2Plugin::lv2_urid_map(LV2_ATOM__Float); g_lv2_atom_int_type = qtractorLv2Plugin::lv2_urid_map(LV2_ATOM__Int); #endif #ifdef CONFIG_LV2_UI #ifdef CONFIG_LV2_EXTERNAL_UI g_lv2_external_ui_class = lilv_new_uri(g_lv2_world, LV2_EXTERNAL_UI__Widget); #ifdef LV2_EXTERNAL_UI_DEPRECATED_URI g_lv2_external_ui_deprecated_class = lilv_new_uri(g_lv2_world, LV2_EXTERNAL_UI_DEPRECATED_URI); #endif #endif #if QT_VERSION < 0x050000 g_lv2_x11_ui_class = lilv_new_uri(g_lv2_world, LV2_UI__X11UI); g_lv2_gtk_ui_class = lilv_new_uri(g_lv2_world, LV2_UI__GtkUI); g_lv2_qt4_ui_class = lilv_new_uri(g_lv2_world, LV2_UI__Qt4UI); #endif #endif // CONFIG_LV2_UI // Set up the feature we may want to know (as hints). g_lv2_realtime_hint = lilv_new_uri(g_lv2_world, LV2_CORE_PREFIX "hardRtCapable"); g_lv2_extension_data_hint = lilv_new_uri(g_lv2_world, LV2_CORE_PREFIX "extensionData"); #ifdef CONFIG_LV2_WORKER // LV2 Worker/Schedule support hints... g_lv2_worker_schedule_hint = lilv_new_uri(g_lv2_world, LV2_WORKER__schedule); #endif #ifdef CONFIG_LV2_STATE // LV2 State: set up supported interface and types... g_lv2_state_interface_hint = lilv_new_uri(g_lv2_world, LV2_STATE__interface); #endif // Set up the port properties we support (as hints). g_lv2_toggled_prop = lilv_new_uri(g_lv2_world, LV2_CORE_PREFIX "toggled"); g_lv2_integer_prop = lilv_new_uri(g_lv2_world, LV2_CORE_PREFIX "integer"); g_lv2_sample_rate_prop = lilv_new_uri(g_lv2_world, LV2_CORE_PREFIX "sampleRate"); g_lv2_logarithmic_prop = lilv_new_uri(g_lv2_world, "http://lv2plug.in/ns/dev/extportinfo#logarithmic"); #ifdef CONFIG_LV2_TIME // LV2 Time: set up supported port designations... for (int i = 0; i < int(qtractorLv2Time::numOfMembers); ++i) { qtractorLv2Time& member = g_lv2_time[i]; member.node = lilv_new_uri(g_lv2_world, member.uri); member.value = 0.0f; member.params = new QList (); } #endif #ifdef CONFIG_LV2_OPTIONS #ifdef CONFIG_LV2_BUF_SIZE g_lv2_bufsz_min_block_length = qtractorLv2Plugin::lv2_urid_map(LV2_BUF_SIZE__minBlockLength); g_lv2_bufsz_max_block_length = qtractorLv2Plugin::lv2_urid_map(LV2_BUF_SIZE__maxBlockLength); g_lv2_bufsz_sequence_size = qtractorLv2Plugin::lv2_urid_map(LV2_BUF_SIZE__sequenceSize); #endif #endif } void qtractorLv2PluginType::lv2_close (void) { if (g_lv2_plugins == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorLv2PluginType::lv2_close()"); #endif #ifdef CONFIG_LV2_OPTIONS #ifdef CONFIG_LV2_BUF_SIZE g_lv2_bufsz_min_block_length = 0; g_lv2_bufsz_max_block_length = 0; g_lv2_bufsz_sequence_size = 0; #endif #endif #ifdef CONFIG_LV2_TIME for (int i = 0; i < int(qtractorLv2Time::numOfMembers); ++i) { qtractorLv2Time& member = g_lv2_time[i]; lilv_node_free(member.node); member.node = NULL; member.value = 0.0f; delete member.params; member.params = NULL; } #endif // Clean up. lilv_node_free(g_lv2_toggled_prop); lilv_node_free(g_lv2_integer_prop); lilv_node_free(g_lv2_sample_rate_prop); lilv_node_free(g_lv2_logarithmic_prop); #ifdef CONFIG_LV2_STATE lilv_node_free(g_lv2_state_interface_hint); #endif #ifdef CONFIG_LV2_WORKER lilv_node_free(g_lv2_worker_schedule_hint); #endif lilv_node_free(g_lv2_extension_data_hint); lilv_node_free(g_lv2_realtime_hint); lilv_node_free(g_lv2_input_class); lilv_node_free(g_lv2_output_class); lilv_node_free(g_lv2_control_class); lilv_node_free(g_lv2_audio_class); #ifdef CONFIG_LV2_EVENT lilv_node_free(g_lv2_event_class); lilv_node_free(g_lv2_midi_class); #endif #ifdef CONFIG_LV2_ATOM lilv_node_free(g_lv2_atom_port_class); #endif #ifdef CONFIG_LV2_UI #ifdef CONFIG_LV2_EXTERNAL_UI lilv_node_free(g_lv2_external_ui_class); #ifdef LV2_EXTERNAL_UI_DEPRECATED_URI lilv_node_free(g_lv2_external_ui_deprecated_class); #endif #endif #if QT_VERSION < 0x050000 lilv_node_free(g_lv2_x11_ui_class); lilv_node_free(g_lv2_gtk_ui_class); lilv_node_free(g_lv2_qt4_ui_class); #endif #endif // CONFIG_LV2_UI lilv_world_free(g_lv2_world); g_lv2_input_class = NULL; g_lv2_output_class = NULL; g_lv2_control_class = NULL; g_lv2_audio_class = NULL; #ifdef CONFIG_LV2_EVENT g_lv2_event_class = NULL; g_lv2_midi_class = NULL; #endif #ifdef CONFIG_LV2_ATOM g_lv2_atom_port_class = NULL; g_lv2_atom_event_type = 0; g_lv2_atom_sequence_type = 0; g_lv2_atom_string_type = 0; g_lv2_atom_float_type = 0; g_lv2_atom_int_type = 0; #endif #ifdef CONFIG_LV2_OPTIONS #ifdef CONFIG_LV2_BUF_SIZE g_lv2_bufsz_min_block_length = 0; g_lv2_bufsz_max_block_length = 0; g_lv2_bufsz_sequence_size = 0; #endif #endif #ifdef CONFIG_LV2_UI #ifdef CONFIG_LV2_EXTERNAL_UI g_lv2_external_ui_class = NULL; #ifdef LV2_EXTERNAL_UI_DEPRECATED_URI g_lv2_external_ui_deprecated_class = NULL; #endif #endif #if QT_VERSION < 0x050000 g_lv2_x11_ui_class = NULL; g_lv2_gtk_ui_class = NULL; g_lv2_qt4_ui_class = NULL; #endif #endif g_lv2_plugins = NULL; g_lv2_world = NULL; } // Plugin type listing (static). bool qtractorLv2PluginType::getTypes ( qtractorPluginPath& path ) { if (g_lv2_plugins == NULL) return false; unsigned long iIndex = 0; LILV_FOREACH(plugins, i, g_lv2_plugins) { LilvPlugin *plugin = const_cast ( lilv_plugins_get(g_lv2_plugins, i)); const char *pszUri = lilv_node_as_uri(lilv_plugin_get_uri(plugin)); qtractorLv2PluginType *pLv2Type = qtractorLv2PluginType::createType(pszUri, plugin); if (pLv2Type) { if (pLv2Type->open()) { path.addType(pLv2Type); pLv2Type->close(); ++iIndex; } else { delete pLv2Type; } } } return (iIndex > 0); } //---------------------------------------------------------------------------- // qtractorLv2Plugin -- LV2 plugin instance. // // Dynamic singleton list of LV2 plugins with external UIs open. static QList g_lv2Plugins; // Constructors. qtractorLv2Plugin::qtractorLv2Plugin ( qtractorPluginList *pList, qtractorLv2PluginType *pLv2Type ) : qtractorPlugin(pList, pLv2Type) , m_ppInstances(NULL) , m_piControlOuts(NULL) , m_pfControlOuts(NULL) , m_pfControlOutsLast(NULL) , m_piAudioIns(NULL) , m_piAudioOuts(NULL) #ifdef CONFIG_LV2_EVENT , m_piMidiEventIns(NULL) , m_piMidiEventOuts(NULL) #endif #ifdef CONFIG_LV2_ATOM , m_piMidiAtomIns(NULL) , m_piMidiAtomOuts(NULL) , m_lv2_atom_buffer_in(NULL) , m_lv2_atom_buffer_ins(NULL) , m_lv2_atom_buffer_out(NULL) , m_lv2_atom_buffer_outs(NULL) #endif , m_lv2_features(NULL) #ifdef CONFIG_LV2_WORKER , m_lv2_worker(NULL) #endif #ifdef CONFIG_LV2_UI , m_lv2_ui_type(LV2_UI_TYPE_NONE) , m_bEditorVisible(false) , m_bEditorClosed(false) , m_lv2_uis(NULL) , m_lv2_ui(NULL) , m_lv2_ui_features(NULL) , m_suil_host(NULL) , m_suil_instance(NULL) , m_lv2_ui_widget(NULL) #ifdef CONFIG_LV2_ATOM , m_ui_events(NULL) , m_plugin_events(NULL) #endif #if QT_VERSION < 0x050000 , m_pQt4Filter(NULL) , m_pQt4Widget(NULL) #endif #endif // CONFIG_LV2_UI #ifdef CONFIG_LV2_OPTIONS #ifdef CONFIG_LV2_BUF_SIZE , m_iMinBlockLength(0) , m_iMaxBlockLength(0) , m_iSequenceSize(0) #endif #endif // CONFIG_LV2_OPTIONS { #ifdef CONFIG_DEBUG qDebug("qtractorLv2Plugin[%p] uri=\"%s\"", this, pLv2Type->filename().toUtf8().constData()); #endif int iFeatures = 0; while (g_lv2_features[iFeatures]) { ++iFeatures; } m_lv2_features = new LV2_Feature * [iFeatures + 5]; for (int i = 0; i < iFeatures; ++i) m_lv2_features[i] = (LV2_Feature *) g_lv2_features[i]; #ifdef CONFIG_LV2_STATE_FILES m_lv2_state_map_path.handle = this; m_lv2_state_map_path.abstract_path = &qtractor_lv2_state_abstract_path; m_lv2_state_map_path.absolute_path = &qtractor_lv2_state_absolute_path; m_lv2_state_map_path_feature.URI = LV2_STATE__mapPath; m_lv2_state_map_path_feature.data = &m_lv2_state_map_path; m_lv2_features[iFeatures++] = &m_lv2_state_map_path_feature; #ifdef CONFIG_LV2_STATE_MAKE_PATH m_lv2_state_make_path.handle = this; m_lv2_state_make_path.path = &qtractor_lv2_state_make_path; m_lv2_state_make_path_feature.URI = LV2_STATE__makePath; m_lv2_state_make_path_feature.data = &m_lv2_state_make_path; m_lv2_features[iFeatures++] = &m_lv2_state_make_path_feature; #endif // CONFIG_LV2_STATE_MAKE_PATH #endif // CONFIG_LV2_STATE_FILES #ifdef CONFIG_LV2_PROGRAMS m_lv2_programs_host.handle = this; m_lv2_programs_host.program_changed = &qtractor_lv2_program_changed; m_lv2_programs_host_feature.URI = LV2_PROGRAMS__Host; m_lv2_programs_host_feature.data = &m_lv2_programs_host; m_lv2_features[iFeatures++] = &m_lv2_programs_host_feature; #endif // CONFIG_LV2_PROGRAMS #ifdef CONFIG_LV2_OPTIONS #ifdef CONFIG_LV2_BUF_SIZE m_iMinBlockLength = 0; m_iMaxBlockLength = 0; m_iSequenceSize = 0; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine) m_iMaxBlockLength = pAudioEngine->bufferSize(); } qtractorMidiManager *pMidiManager = list()->midiManager(); if (pMidiManager) { const uint32_t MaxMidiEvents = (pMidiManager->bufferSize() >> 1); #ifdef CONFIG_LV2_EVENT const uint32_t Lv2EventBufferSize = (sizeof(LV2_Event) + 4) * MaxMidiEvents; if (m_iSequenceSize > Lv2EventBufferSize || m_iSequenceSize < 1) m_iSequenceSize = Lv2EventBufferSize; #endif #ifdef CONFIG_LV2_ATOM const uint32_t Lv2AtomBufferSize = (sizeof(LV2_Atom_Event) + 4) * MaxMidiEvents; if (m_iSequenceSize > Lv2AtomBufferSize || m_iSequenceSize < 1) m_iSequenceSize = Lv2AtomBufferSize; #endif } // Build options array to pass to plugin const LV2_Options_Option options[] = { { LV2_OPTIONS_INSTANCE, 0, g_lv2_bufsz_min_block_length, sizeof(int32_t), g_lv2_atom_int_type, &m_iMinBlockLength }, { LV2_OPTIONS_INSTANCE, 0, g_lv2_bufsz_max_block_length, sizeof(int32_t), g_lv2_atom_int_type, &m_iMaxBlockLength }, { LV2_OPTIONS_INSTANCE, 0, g_lv2_bufsz_sequence_size, sizeof(int32_t), g_lv2_atom_int_type, &m_iSequenceSize }, { LV2_OPTIONS_INSTANCE, 0, 0, 0, 0, NULL } }; ::memcpy(&m_lv2_options, &options, sizeof(options)); m_lv2_options_feature.URI = LV2_OPTIONS__options; m_lv2_options_feature.data = &m_lv2_options; m_lv2_features[iFeatures++] = &m_lv2_options_feature; #endif // CONFIG_LV2_BUF_SIZE #endif // CONFIG_LV2_OPTIONS m_lv2_features[iFeatures] = NULL; // Get some structural data first... const LilvPlugin *plugin = pLv2Type->lv2_plugin(); if (plugin) { unsigned short iControlOuts = pLv2Type->controlOuts(); unsigned short iAudioIns = pLv2Type->audioIns(); unsigned short iAudioOuts = pLv2Type->audioOuts(); if (iAudioIns > 0) m_piAudioIns = new unsigned long [iAudioIns]; if (iAudioOuts > 0) m_piAudioOuts = new unsigned long [iAudioOuts]; if (iControlOuts > 0) { m_piControlOuts = new unsigned long [iControlOuts]; m_pfControlOuts = new float [iControlOuts]; m_pfControlOutsLast = new float [iControlOuts]; } iControlOuts = iAudioIns = iAudioOuts = 0; #ifdef CONFIG_LV2_EVENT unsigned short iMidiEventIns = pLv2Type->midiEventIns(); unsigned short iMidiEventOuts = pLv2Type->midiEventOuts(); if (iMidiEventIns > 0) m_piMidiEventIns = new unsigned long [iMidiEventIns]; if (iMidiEventOuts > 0) m_piMidiEventOuts = new unsigned long [iMidiEventOuts]; iMidiEventIns = iMidiEventOuts = 0; #endif // CONFIG_LV2_EVENT #ifdef CONFIG_LV2_ATOM const unsigned int MaxBufferCapacity = 1024; unsigned short iMidiAtomIns = pLv2Type->midiAtomIns(); unsigned short iMidiAtomOuts = pLv2Type->midiAtomOuts(); if (iMidiAtomIns > 0) { m_piMidiAtomIns = new unsigned long [iMidiAtomIns]; m_lv2_atom_buffer_in = lv2_atom_buffer_new(MaxBufferCapacity, g_lv2_atom_sequence_type, true); m_lv2_atom_buffer_ins = new LV2_Atom_Buffer * [iMidiAtomIns]; for (unsigned long j = 0; j < iMidiAtomIns; ++j) m_lv2_atom_buffer_ins[j] = m_lv2_atom_buffer_in; } if (iMidiAtomOuts > 0) { m_piMidiAtomOuts = new unsigned long [iMidiAtomOuts]; m_lv2_atom_buffer_out = lv2_atom_buffer_new(MaxBufferCapacity, g_lv2_atom_sequence_type, false); m_lv2_atom_buffer_outs = new LV2_Atom_Buffer * [iMidiAtomOuts]; for (unsigned long j = 0; j < iMidiAtomOuts; ++j) m_lv2_atom_buffer_outs[j] = m_lv2_atom_buffer_out; } #ifdef CONFIG_LV2_UI m_ui_events = ::jack_ringbuffer_create(MaxBufferCapacity); m_plugin_events = ::jack_ringbuffer_create(MaxBufferCapacity); #endif iMidiAtomIns = iMidiAtomOuts = 0; #endif // CONFIG_LV2_ATOM unsigned long iNumPorts = lilv_plugin_get_num_ports(plugin); for (unsigned long i = 0; i < iNumPorts; ++i) { const LilvPort *port = lilv_plugin_get_port_by_index(plugin, i); if (port) { if (lilv_port_is_a(plugin, port, g_lv2_input_class)) { if (lilv_port_is_a(plugin, port, g_lv2_audio_class)) m_piAudioIns[iAudioIns++] = i; else #ifdef CONFIG_LV2_EVENT if (lilv_port_is_a(plugin, port, g_lv2_event_class) || lilv_port_is_a(plugin, port, g_lv2_midi_class)) m_piMidiEventIns[iMidiEventIns++] = i; else #endif #ifdef CONFIG_LV2_ATOM if (lilv_port_is_a(plugin, port, g_lv2_atom_port_class)) m_piMidiAtomIns[iMidiAtomIns++] = i; else #endif if (lilv_port_is_a(plugin, port, g_lv2_control_class)) addParam(new qtractorLv2PluginParam(this, i)); } else if (lilv_port_is_a(plugin, port, g_lv2_output_class)) { if (lilv_port_is_a(plugin, port, g_lv2_audio_class)) m_piAudioOuts[iAudioOuts++] = i; else #ifdef CONFIG_LV2_EVENT if (lilv_port_is_a(plugin, port, g_lv2_event_class) || lilv_port_is_a(plugin, port, g_lv2_midi_class)) m_piMidiEventOuts[iMidiEventOuts++] = i; else #endif #ifdef CONFIG_LV2_ATOM if (lilv_port_is_a(plugin, port, g_lv2_atom_port_class)) m_piMidiAtomOuts[iMidiAtomOuts++] = i; else #endif if (lilv_port_is_a(plugin, port, g_lv2_control_class)) { m_piControlOuts[iControlOuts] = i; m_pfControlOuts[iControlOuts] = 0.0f; m_pfControlOutsLast[iControlOuts] = 0.0f; ++iControlOuts; } } } } #ifdef CONFIG_LV2_PRESETS LilvNode *label_uri = lilv_new_uri(g_lv2_world, LILV_NS_RDFS "label"); LilvNode *preset_uri = lilv_new_uri(g_lv2_world, LV2_PRESETS__Preset); LilvNodes *presets = lilv_plugin_get_related(lv2_plugin(), preset_uri); if (presets) { LILV_FOREACH(nodes, i, presets) { const LilvNode *preset = lilv_nodes_get(presets, i); lilv_world_load_resource(g_lv2_world, preset); LilvNodes *labels = lilv_world_find_nodes( g_lv2_world, preset, label_uri, NULL); if (labels) { const LilvNode *label = lilv_nodes_get_first(labels); const QString sPreset(lilv_node_as_string(label)); const QString sUri(lilv_node_as_string(preset)); m_lv2_presets.insert(sPreset, sUri); lilv_nodes_free(labels); } } lilv_nodes_free(presets); } lilv_node_free(preset_uri); lilv_node_free(label_uri); #endif // CONFIG_LV2_PRESETS #ifdef CONFIG_LV2_TIME // Set up time-pos designated port indexes, if any... for (int i = 0; i < int(qtractorLv2Time::numOfMembers); ++i) { qtractorLv2Time& member = g_lv2_time[i]; if (member.node) { const LilvPort *port = lilv_plugin_get_port_by_designation( plugin, g_lv2_input_class, member.node); if (port) { unsigned long index = lilv_port_get_index(plugin, port); qtractorLv2PluginParam *pParam = static_cast (findParam(index)); if (pParam) { m_lv2_time_ports.insert(index, i); member.params->append(pParam); } } } } #endif // CONFIG_LV2_TIME // FIXME: instantiate each instance properly... qtractorLv2Plugin::setChannels(channels()); } } // Destructor. qtractorLv2Plugin::~qtractorLv2Plugin (void) { // Cleanup all plugin instances... setChannels(0); #ifdef CONFIG_LV2_TIME // Unsubscribe mapped params... QHash::ConstIterator iter = m_lv2_time_ports.constBegin(); const QHash::ConstIterator& iter_end = m_lv2_time_ports.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorLv2PluginParam *pParam = static_cast (findParam(iter.key())); if (pParam) g_lv2_time[iter.value()].params->removeAll(pParam); } #endif // CONFIG_LV2_TIME // Free up all the rest... #ifdef CONFIG_LV2_ATOM if (m_lv2_atom_buffer_outs) delete [] m_lv2_atom_buffer_outs; if (m_lv2_atom_buffer_ins) delete [] m_lv2_atom_buffer_ins; if (m_lv2_atom_buffer_out) lv2_atom_buffer_free(m_lv2_atom_buffer_out); if (m_lv2_atom_buffer_in) lv2_atom_buffer_free(m_lv2_atom_buffer_in); #ifdef CONFIG_LV2_UI if (m_plugin_events) ::jack_ringbuffer_free(m_plugin_events); if (m_ui_events) ::jack_ringbuffer_free(m_ui_events); #endif if (m_piMidiAtomOuts) delete [] m_piMidiAtomOuts; if (m_piMidiAtomIns) delete [] m_piMidiAtomIns; #endif // CONFIG_LV2_ATOM #ifdef CONFIG_LV2_EVENT if (m_piMidiEventOuts) delete [] m_piMidiEventOuts; if (m_piMidiEventIns) delete [] m_piMidiEventIns; #endif // CONFIG_LV2_EVENT if (m_piAudioOuts) delete [] m_piAudioOuts; if (m_piAudioIns) delete [] m_piAudioIns; if (m_piControlOuts) delete [] m_piControlOuts; if (m_pfControlOuts) delete [] m_pfControlOuts; if (m_pfControlOutsLast) delete [] m_pfControlOutsLast; if (m_lv2_features) delete [] m_lv2_features; } // Channel/instance number accessors. void qtractorLv2Plugin::setChannels ( unsigned short iChannels ) { // Check our type... qtractorPluginType *pType = type(); if (pType == NULL) return; // Estimate the (new) number of instances... unsigned short iOldInstances = instances(); unsigned short iInstances = pType->instances(iChannels, list()->isMidi()); // Now see if instance count changed anyhow... if (iInstances == iOldInstances) return; const LilvPlugin *plugin = lv2_plugin(); if (plugin == NULL) return; // Gotta go for a while... bool bActivated = isActivated(); setActivated(false); // Set new instance number... setInstances(iInstances); // Close old instances, all the way... #ifdef CONFIG_LV2_WORKER if (m_lv2_worker) { delete m_lv2_worker; m_lv2_worker = NULL; } #endif if (m_ppInstances) { for (unsigned short i = 0; i < iOldInstances; ++i) { LilvInstance *instance = m_ppInstances[i]; if (instance) lilv_instance_free(instance); } delete [] m_ppInstances; m_ppInstances = NULL; } // Bail out, if none are about to be created... if (iInstances < 1) { setActivated(bActivated); return; } #ifdef CONFIG_DEBUG qDebug("qtractorLv2Plugin[%p]::setChannels(%u) instances=%u", this, iChannels, iInstances); #endif #ifdef CONFIG_LV2_WORKER if (lilv_plugin_has_feature(lv2_plugin(), g_lv2_worker_schedule_hint)) m_lv2_worker = new qtractorLv2Worker(this, m_lv2_features); #endif LV2_Feature **features = m_lv2_features; #ifdef CONFIG_LV2_WORKER if (m_lv2_worker) features = m_lv2_worker->lv2_features(); #endif // We'll need output control (not dummy anymore) port indexes... unsigned short iControlOuts = pType->controlOuts(); // Allocate new instances... m_ppInstances = new LilvInstance * [iInstances]; for (unsigned short i = 0; i < iInstances; ++i) { // Instantiate them properly first... LilvInstance *instance = lilv_plugin_instantiate(plugin, sampleRate(), features); if (instance) { // (Dis)connect all ports... unsigned long iNumPorts = lilv_plugin_get_num_ports(plugin); for (unsigned long k = 0; k < iNumPorts; ++k) lilv_instance_connect_port(instance, k, NULL); // Connect all existing input control ports... const qtractorPlugin::Params& params = qtractorPlugin::params(); qtractorPlugin::Params::ConstIterator param = params.constBegin(); const qtractorPlugin::Params::ConstIterator& param_end = params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); lilv_instance_connect_port(instance, pParam->index(), pParam->subject()->data()); } // Connect all existing output control ports... for (unsigned short j = 0; j < iControlOuts; ++j) { lilv_instance_connect_port(instance, m_piControlOuts[j], &m_pfControlOuts[j]); } #if 0//def CONFIG_LV2_TIME // Connect time-pos designated ports, if any... QHash::ConstIterator iter = m_lv2_time_ports.constBegin(); const QHash::ConstIterator& iter_end = m_lv2_time_ports.constEnd(); for ( ; iter != iter_end; ++iter) { lilv_instance_connect_port(instance, iter.key(), &(g_lv2_time[iter.value()].data)); } #endif } #ifdef CONFIG_DEBUG qDebug("qtractorLv2Plugin[%p]::setChannels(%u) instance[%u]=%p", this, iChannels, i, instance); #endif // This is it... m_ppInstances[i] = instance; } // (Re)issue all configuration as needed... realizeConfigs(); realizeValues(); // But won't need it anymore. releaseConfigs(); releaseValues(); // (Re)activate instance if necessary... setActivated(bActivated); } // Specific accessors. LilvPlugin *qtractorLv2Plugin::lv2_plugin (void) const { qtractorLv2PluginType *pLv2Type = static_cast (type()); return (pLv2Type ? pLv2Type->lv2_plugin() : NULL); } LilvInstance *qtractorLv2Plugin::lv2_instance ( unsigned short iInstance ) const { return (m_ppInstances ? m_ppInstances[iInstance] : NULL); } LV2_Handle qtractorLv2Plugin::lv2_handle ( unsigned short iInstance ) const { const LilvInstance *instance = lv2_instance(iInstance); return (instance ? lilv_instance_get_handle(instance) : NULL); } // Do the actual activation. void qtractorLv2Plugin::activate (void) { if (m_ppInstances) { for (unsigned short i = 0; i < instances(); ++i) { LilvInstance *instance = m_ppInstances[i]; if (instance) lilv_instance_activate(instance); } } } // Do the actual deactivation. void qtractorLv2Plugin::deactivate (void) { if (m_ppInstances) { for (unsigned short i = 0; i < instances(); ++i) { LilvInstance *instance = m_ppInstances[i]; if (instance) lilv_instance_deactivate(instance); } } } // The main plugin processing procedure. void qtractorLv2Plugin::process ( float **ppIBuffer, float **ppOBuffer, unsigned int nframes ) { if (m_ppInstances == NULL) return; const LilvPlugin *plugin = lv2_plugin(); if (plugin == NULL) return; #if defined(CONFIG_LV2_EVENT) || defined(CONFIG_LV2_ATOM) qtractorMidiManager *pMidiManager = NULL; qtractorLv2PluginType *pLv2Type = static_cast (type()); if (pLv2Type->midiIns() > 0) pMidiManager = list()->midiManager(); #ifdef CONFIG_LV2_EVENT const unsigned short iMidiEventIns = pLv2Type->midiEventIns(); const unsigned short iMidiEventOuts = pLv2Type->midiEventOuts(); #endif #ifdef CONFIG_LV2_ATOM const unsigned short iMidiAtomIns = pLv2Type->midiAtomIns(); const unsigned short iMidiAtomOuts = pLv2Type->midiAtomOuts(); #endif #endif // We'll cross channels over instances... const unsigned short iInstances = instances(); const unsigned short iChannels = channels(); const unsigned short iAudioIns = audioIns(); const unsigned short iAudioOuts = audioOuts(); unsigned short iIChannel = 0; unsigned short iOChannel = 0; unsigned short i, j; // For each plugin instance... for (i = 0; i < iInstances; ++i) { LilvInstance *instance = m_ppInstances[i]; if (instance) { // For each instance audio input port... for (j = 0; j < iAudioIns; ++j) { lilv_instance_connect_port(instance, m_piAudioIns[j], ppIBuffer[iIChannel]); if (++iIChannel >= iChannels) iIChannel = 0; } // For each instance audio output port... for (j = 0; j < iAudioOuts; ++j) { lilv_instance_connect_port(instance, m_piAudioOuts[j], ppOBuffer[iOChannel]); if (++iOChannel >= iChannels) iOChannel = 0; } #ifdef CONFIG_LV2_EVENT // Connect all existing input event/MIDI ports... if (pMidiManager) { for (j = 0; j < iMidiEventIns; ++j) { lilv_instance_connect_port(instance, m_piMidiEventIns[j], pMidiManager->lv2_events_in()); } for (j = 0; j < iMidiEventOuts; ++j) { lilv_instance_connect_port(instance, m_piMidiEventOuts[j], pMidiManager->lv2_events_out()); } } #endif #ifdef CONFIG_LV2_ATOM // Connect all existing input atom/MIDI ports... for (j = 0; j < iMidiAtomIns; ++j) { if (pMidiManager) m_lv2_atom_buffer_ins[j] = pMidiManager->lv2_atom_buffer_in(); else lv2_atom_buffer_reset(m_lv2_atom_buffer_ins[j], true); lilv_instance_connect_port(instance, m_piMidiAtomIns[j], &m_lv2_atom_buffer_ins[j]->atoms); } for (j = 0; j < iMidiAtomOuts; ++j) { if (pMidiManager) m_lv2_atom_buffer_outs[j] = pMidiManager->lv2_atom_buffer_out(); else lv2_atom_buffer_reset(m_lv2_atom_buffer_outs[j], false); lilv_instance_connect_port(instance, m_piMidiAtomOuts[j], &m_lv2_atom_buffer_outs[j]->atoms); } #ifdef CONFIG_LV2_UI // Read and apply control change events from UI... if (m_lv2_ui_widget) { uint32_t read_space = ::jack_ringbuffer_read_space(m_ui_events); while (read_space > 0) { ControlEvent ev; ::jack_ringbuffer_read(m_ui_events, (char *) &ev, sizeof(ev)); char buf[ev.size]; if (::jack_ringbuffer_read(m_ui_events, buf, ev.size) < ev.size) break; if (ev.protocol == g_lv2_atom_event_type) { for (j = 0; j < iMidiAtomIns; ++j) { if (m_piMidiAtomIns[j] == ev.index) { LV2_Atom_Buffer_Iterator aiter; lv2_atom_buffer_end(&aiter, m_lv2_atom_buffer_ins[j]); const LV2_Atom *atom = (const LV2_Atom *) buf; lv2_atom_buffer_write(&aiter, nframes, 0, atom->type, atom->size, (const uint8_t *) LV2_ATOM_BODY(atom)); break; } } } read_space -= sizeof(ev) + ev.size; } } #endif // CONFIG_LV2_UI #endif // CONFIG_LV2_ATOM // Make it run... lilv_instance_run(instance, nframes); // Done. // Wrap channels?... if (iIChannel < iChannels - 1) ++iIChannel; if (iOChannel < iChannels - 1) ++iOChannel; } } #ifdef CONFIG_LV2_WORKER if (m_lv2_worker) m_lv2_worker->commit(); #endif #ifdef CONFIG_LV2_ATOM #ifdef CONFIG_LV2_UI for (j = 0; j < iMidiAtomOuts; ++j) { LV2_Atom_Buffer_Iterator aiter; lv2_atom_buffer_begin(&aiter, m_lv2_atom_buffer_outs[j]); while (true) { uint8_t *data; LV2_Atom_Event *pLv2AtomEvent = lv2_atom_buffer_get(&aiter, &data); if (pLv2AtomEvent == NULL) break; if (pLv2AtomEvent->body.type != QTRACTOR_LV2_MIDI_EVENT_ID) { char buf[sizeof(ControlEvent) + sizeof(LV2_Atom)]; const uint32_t type = pLv2AtomEvent->body.type; const uint32_t size = pLv2AtomEvent->body.size; ControlEvent *ev = (ControlEvent *) buf; ev->index = m_piMidiAtomOuts[j]; ev->protocol = g_lv2_atom_event_type; ev->size = sizeof(LV2_Atom) + size; LV2_Atom *atom = (LV2_Atom *) ev->body; atom->type = type; atom->size = size; if (::jack_ringbuffer_write_space(m_plugin_events) < sizeof(buf) + size) break; ::jack_ringbuffer_write(m_plugin_events, (const char *) buf, sizeof(buf)); ::jack_ringbuffer_write(m_plugin_events, (const char *) data, size); } lv2_atom_buffer_increment(&aiter); } } #endif // CONFIG_LV2_UI #endif // CONFIG_LV2_ATOM #ifdef CONFIG_LV2_EVENT if (pMidiManager && iMidiEventOuts > 0) pMidiManager->lv2_events_swap(); #endif #ifdef CONFIG_LV2_ATOM if (pMidiManager && iMidiAtomOuts > 0) pMidiManager->lv2_atom_buffer_swap(); #endif } #ifdef CONFIG_LV2_UI // Open editor. void qtractorLv2Plugin::openEditor ( QWidget */*pParent*/ ) { if (m_lv2_ui_widget) { setEditorVisible(true); return; } qtractorLv2PluginType *pLv2Type = static_cast (type()); if (pLv2Type == NULL) return; // Check the UI inventory... m_lv2_uis = lilv_plugin_get_uis(pLv2Type->lv2_plugin()); if (m_lv2_uis == NULL) return; QMap ui_map; LILV_FOREACH(uis, i, m_lv2_uis) { LilvUI *ui = const_cast (lilv_uis_get(m_lv2_uis, i)); #ifdef CONFIG_LV2_EXTERNAL_UI if (lilv_ui_is_a(ui, g_lv2_external_ui_class) #ifdef LV2_EXTERNAL_UI_DEPRECATED_URI || lilv_ui_is_a(ui, g_lv2_external_ui_deprecated_class) #endif ) ui_map.insert(LV2_UI_TYPE_EXTERNAL, ui); #if QT_VERSION < 0x050000 else #endif #endif #if QT_VERSION < 0x050000 if (lilv_ui_is_a(ui, g_lv2_x11_ui_class)) ui_map.insert(LV2_UI_TYPE_X11, ui); else if (lilv_ui_is_a(ui, g_lv2_gtk_ui_class)) ui_map.insert(LV2_UI_TYPE_GTK, ui); else if (lilv_ui_is_a(ui, g_lv2_qt4_ui_class)) ui_map.insert(LV2_UI_TYPE_QT4, ui); #endif } if (ui_map.isEmpty()) return; QMap::ConstIterator ui_iter = ui_map.constBegin(); m_lv2_ui_type = ui_iter.key(); m_lv2_ui = ui_iter.value(); const LilvInstance *instance = lv2_instance(0); if (instance == NULL) return; const LV2_Descriptor *descriptor = lilv_instance_get_descriptor(instance); if (descriptor == NULL) return; updateEditorTitle(); int iFeatures = 0; while (m_lv2_features[iFeatures]) { ++iFeatures; } m_lv2_ui_features = new LV2_Feature * [iFeatures + 5]; for (int i = 0; i < iFeatures; ++i) m_lv2_ui_features[i] = (LV2_Feature *) m_lv2_features[i]; m_lv2_data_access.data_access = descriptor->extension_data; m_lv2_data_access_feature.URI = LV2_DATA_ACCESS_URI; m_lv2_data_access_feature.data = &m_lv2_data_access; m_lv2_ui_features[iFeatures++] = &m_lv2_data_access_feature; m_lv2_instance_access_feature.URI = LV2_INSTANCE_ACCESS_URI; m_lv2_instance_access_feature.data = lilv_instance_get_handle(instance); m_lv2_ui_features[iFeatures++] = &m_lv2_instance_access_feature; #ifdef CONFIG_LV2_EXTERNAL_UI m_lv2_ui_external_host.ui_closed = qtractor_lv2_ui_closed; m_lv2_ui_external_host.plugin_human_id = m_aEditorTitle.constData(); m_lv2_ui_external_feature.URI = LV2_EXTERNAL_UI__Host; m_lv2_ui_external_feature.data = &m_lv2_ui_external_host; m_lv2_ui_features[iFeatures++] = &m_lv2_ui_external_feature; #ifdef LV2_EXTERNAL_UI_DEPRECATED_URI m_lv2_ui_external_deprecated_feature.URI = LV2_EXTERNAL_UI_DEPRECATED_URI; m_lv2_ui_external_deprecated_feature.data = &m_lv2_ui_external_host; m_lv2_ui_features[iFeatures++] = &m_lv2_ui_external_deprecated_feature; #endif #endif m_lv2_ui_features[iFeatures] = NULL; const char *ui_type_uri = NULL; switch (m_lv2_ui_type) { #ifdef CONFIG_LV2_EXTERNAL_UI case LV2_UI_TYPE_EXTERNAL: #ifdef LV2_EXTERNAL_UI_DEPRECATED_URI if (lilv_ui_is_a(m_lv2_ui, g_lv2_external_ui_deprecated_class)) ui_type_uri = LV2_EXTERNAL_UI_DEPRECATED_URI; else #endif ui_type_uri = LV2_EXTERNAL_UI__Widget; break; #endif #if QT_VERSION < 0x050000 case LV2_UI_TYPE_X11: ui_type_uri = LV2_UI__X11UI; break; case LV2_UI_TYPE_GTK: ui_type_uri = LV2_UI__GtkUI; break; case LV2_UI_TYPE_QT4: ui_type_uri = LV2_UI__Qt4UI; break; #endif default: break; } #ifdef CONFIG_DEBUG qDebug("qtractorLv2Plugin[%p]::openEditor(\"%s\")", this, ui_type_uri); #endif m_suil_host = suil_host_new(qtractor_lv2_ui_write, NULL, NULL, NULL); m_suil_instance = suil_instance_new(m_suil_host, this, LV2_UI_HOST_URI, lilv_node_as_uri(lilv_plugin_get_uri(pLv2Type->lv2_plugin())), lilv_node_as_uri(lilv_ui_get_uri(m_lv2_ui)), ui_type_uri, lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_bundle_uri(m_lv2_ui))), lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_binary_uri(m_lv2_ui))), m_lv2_ui_features); if (m_suil_instance) { const qtractorPlugin::Params& params = qtractorPlugin::params(); qtractorPlugin::Params::ConstIterator param = params.constBegin(); const qtractorPlugin::Params::ConstIterator& param_end = params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); float fValue = pParam->value(); suil_instance_port_event(m_suil_instance, pParam->index(), sizeof(float), 0, &fValue); } unsigned long iControlOuts = pLv2Type->controlOuts(); for (unsigned long j = 0; j < iControlOuts; ++j) { suil_instance_port_event(m_suil_instance, m_piControlOuts[j], sizeof(float), 0, &m_pfControlOuts[j]); } m_lv2_ui_widget = suil_instance_get_widget(m_suil_instance); #if QT_VERSION < 0x050000 if (m_lv2_ui_widget && m_lv2_ui_type != LV2_UI_TYPE_EXTERNAL) { m_pQt4Widget = static_cast (m_lv2_ui_widget); m_pQt4Widget->setWindowTitle(m_aEditorTitle.constData()); m_pQt4Filter = new EventFilter(this, m_pQt4Widget); // LV2 UI resize control... resizeEditor(m_pQt4Widget->sizeHint()); // m_pQt4Widget->show(); } #endif g_lv2Plugins.append(this); } setEditorVisible(true); // idleEditor(); } // Close editor. void qtractorLv2Plugin::closeEditor (void) { if (m_lv2_ui_widget == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorLv2Plugin[%p]::closeEditor()", this); #endif setEditorVisible(false); m_ui_params.clear(); #if QT_VERSION < 0x050000 if (m_pQt4Filter) { delete m_pQt4Filter; m_pQt4Filter = NULL; } if (m_pQt4Widget) { // delete m_pQt4Widget; m_pQt4Widget = NULL; } #endif m_lv2_ui_type = LV2_UI_TYPE_NONE; int iLv2Plugin = g_lv2Plugins.indexOf(this); if (iLv2Plugin >= 0) g_lv2Plugins.removeAt(iLv2Plugin); if (m_suil_instance) { suil_instance_free(m_suil_instance); m_suil_instance = NULL; } if (m_suil_host) { suil_host_free(m_suil_host); m_suil_host = NULL; } m_lv2_ui_widget = NULL; if (m_lv2_ui_features) { delete [] m_lv2_ui_features; m_lv2_ui_features = NULL; } if (m_lv2_uis) { lilv_uis_free(m_lv2_uis); m_lv2_uis = NULL; m_lv2_ui = NULL; } } // Idle editor. void qtractorLv2Plugin::idleEditor (void) { if (m_lv2_ui_widget == NULL) return; // Do we need some clean-up...? if (isEditorClosed()) { setEditorClosed(false); if (isFormVisible()) form()->toggleEditor(false); m_bEditorVisible = false; // Do really close now. closeEditor(); return; } if (m_piControlOuts && m_pfControlOuts && m_pfControlOutsLast) { if (m_suil_instance) { unsigned long iControlOuts = type()->controlOuts(); for (unsigned short j = 0; j < iControlOuts; ++j) { if (m_pfControlOutsLast[j] != m_pfControlOuts[j]) { suil_instance_port_event(m_suil_instance, m_piControlOuts[j], sizeof(float), 0, &m_pfControlOuts[j]); m_pfControlOutsLast[j] = m_pfControlOuts[j]; } } } } #ifdef CONFIG_LV2_EXTERNAL_UI if (m_lv2_ui_type == LV2_UI_TYPE_EXTERNAL) LV2_EXTERNAL_UI_RUN((LV2_External_UI_Widget *) m_lv2_ui_widget); #endif #ifdef CONFIG_LV2_ATOM uint32_t read_space = ::jack_ringbuffer_read_space(m_plugin_events); while (read_space > 0) { ControlEvent ev; ::jack_ringbuffer_read(m_plugin_events, (char *) &ev, sizeof(ev)); char buf[ev.size]; if (::jack_ringbuffer_read(m_plugin_events, buf, ev.size) < ev.size) break; if (m_suil_instance) { suil_instance_port_event(m_suil_instance, ev.index, ev.size, ev.protocol, buf); } read_space -= sizeof(ev) + ev.size; } #endif // CONFIG_LV2_ATOM #ifdef CONFIG_LV2_UI if (m_ui_params.count() > 0) { QHash::ConstIterator iter = m_ui_params.constBegin(); const QHash::ConstIterator& iter_end = m_ui_params.constEnd(); for ( ; iter != iter_end; ++iter) { unsigned long iIndex = iter.key(); float fValue = iter.value(); #if 0//def CONFIG_LV2_TIME int i = m_lv2_time_ports.value(iIndex, -1); if (i >= 0) g_lv2_time[i].value = fValue; #endif updateParamValue(iIndex, fValue, false); } m_ui_params.clear(); } #endif // CONFIG_LV2_UI } void qtractorLv2Plugin::closeEditorEx (void) { #ifdef CONFIG_DEBUG qDebug("qtractorLv2Plugin[%p]::closeEditorEx()", this); #endif #if QT_VERSION < 0x050000 if (m_pQt4Widget) { m_pQt4Widget = NULL; setEditorClosed(true); } #endif } // GUI editor visibility state. void qtractorLv2Plugin::setEditorVisible ( bool bVisible ) { if (m_lv2_ui_widget == NULL) return; if (/*!m_bEditorVisible && */bVisible) { #ifdef CONFIG_LV2_EXTERNAL_UI if (m_lv2_ui_type == LV2_UI_TYPE_EXTERNAL) LV2_EXTERNAL_UI_SHOW((LV2_External_UI_Widget *) m_lv2_ui_widget); #endif #if QT_VERSION < 0x050000 if (m_pQt4Widget) { // Guaranteeing a reasonable window type: // ie. not Qt::Dialog or Qt::Popup from the seemingly good choices. if (m_lv2_ui_type == LV2_UI_TYPE_QT4) { const Qt::WindowFlags wflags = m_pQt4Widget->windowFlags() & ~Qt::WindowType_Mask; m_pQt4Widget->setWindowFlags(wflags | Qt::Widget); } m_pQt4Widget->show(); m_pQt4Widget->raise(); m_pQt4Widget->activateWindow(); } #endif m_bEditorVisible = true; } else if (/*m_bEditorVisible && */!bVisible) { #ifdef CONFIG_LV2_EXTERNAL_UI if (m_lv2_ui_type == LV2_UI_TYPE_EXTERNAL) LV2_EXTERNAL_UI_HIDE((LV2_External_UI_Widget *) m_lv2_ui_widget); #endif #if QT_VERSION < 0x050000 if (m_pQt4Widget) m_pQt4Widget->hide(); #endif m_bEditorVisible = false; } if (isFormVisible()) form()->toggleEditor(m_bEditorVisible); } bool qtractorLv2Plugin::isEditorVisible (void) const { return m_bEditorVisible; } // Update editor widget caption. void qtractorLv2Plugin::setEditorTitle ( const QString& sTitle ) { qtractorPlugin::setEditorTitle(sTitle); m_aEditorTitle = editorTitle().toUtf8(); #ifdef CONFIG_LV2_EXTERNAL_UI m_lv2_ui_external_host.plugin_human_id = m_aEditorTitle.constData(); #endif #if QT_VERSION < 0x050000 if (m_pQt4Widget) m_pQt4Widget->setWindowTitle(m_aEditorTitle.constData()); #endif } // Parameter update method. void qtractorLv2Plugin::updateParam ( qtractorPluginParam *pParam, float fValue, bool bUpdate ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorLv2Plugin[%p]::updateParam(%lu, %g, %d)", this, pParam->index(), fValue, int(bUpdate)); #endif if (bUpdate && m_suil_instance) { suil_instance_port_event(m_suil_instance, pParam->index(), sizeof(float), 0, &fValue); } } // Idle editor (static). void qtractorLv2Plugin::idleEditorAll (void) { QListIterator iter(g_lv2Plugins); while (iter.hasNext()) iter.next()->idleEditor(); } // LV2 UI control change method. void qtractorLv2Plugin::lv2_ui_write ( uint32_t port_index, uint32_t buffer_size, uint32_t protocol, const void *buffer ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorLv2Plugin[%p]::lv2_ui_write(%u, %u, %u, %p)", this, port_index, buffer_size, protocol, buffer); #endif #ifdef CONFIG_LV2_ATOM if (protocol == g_lv2_atom_event_type) { char buf[sizeof(ControlEvent) + buffer_size]; ControlEvent* ev = (ControlEvent *) buf; ev->index = port_index; ev->protocol = protocol; ev->size = buffer_size; ::memcpy(ev->body, buffer, buffer_size); ::jack_ringbuffer_write(m_ui_events, buf, sizeof(buf)); return; } #endif if (buffer_size != sizeof(float) || protocol != 0) return; float val = *(float *) buffer; // FIXME: Update plugin params... // updateParamValue(port_index, val, false); m_ui_params.insert(port_index, val); } // LV2 UI resize control (host->ui). void qtractorLv2Plugin::resizeEditor ( const QSize& size ) const { #ifdef CONFIG_DEBUG_0 qDebug("qtractorLv2Plugin[%p]::resizeEditor(%d, %d)", this, size.width(), size.height()); #endif if (m_suil_instance) { const LV2UI_Resize *resize = (const LV2UI_Resize *) suil_instance_extension_data( m_suil_instance, LV2_UI__resize); if (resize && resize->ui_resize) { (*resize->ui_resize)(resize->handle, size.width(), size.height()); } } } #endif // CONFIG_LV2_UI // Plugin configuration/state (save) snapshot. void qtractorLv2Plugin::freezeConfigs (void) { if (!type()->isConfigure()) return; #ifdef CONFIG_LV2_STATE for (unsigned short i = 0; i < instances(); ++i) { const LV2_State_Interface *state = lv2_state_interface(i); if (state) { LV2_Handle handle = lv2_handle(i); if (handle) (*state->save)(handle, qtractor_lv2_state_store, this, LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE, m_lv2_features); } } #endif // CONFIG_LV2_STATE } // Plugin configuration/state (load) realization. void qtractorLv2Plugin::realizeConfigs (void) { if (!type()->isConfigure()) return; #ifdef CONFIG_LV2_STATE m_lv2_state_configs.clear(); m_lv2_state_ctypes.clear(); const Configs& configs = qtractorPlugin::configs(); const ConfigTypes& ctypes = qtractorPlugin::configTypes(); Configs::ConstIterator config = configs.constBegin(); const Configs::ConstIterator& config_end = configs.constEnd(); for ( ; config != config_end; ++config) { const QString& sKey = config.key(); QByteArray aType; ConfigTypes::ConstIterator ctype = ctypes.constFind(sKey); if (ctype != ctypes.constEnd()) aType = ctype.value().toUtf8(); const char *pszType = aType.constData(); if (aType.isEmpty() || ::strcmp(pszType, LV2_ATOM__Path) == 0 || ::strcmp(pszType, LV2_ATOM__String) == 0) { m_lv2_state_configs.insert(sKey, config.value().toUtf8()); } else { m_lv2_state_configs.insert(sKey, qUncompress( QByteArray::fromBase64(config.value().toUtf8()))); m_lv2_state_ctypes.insert(sKey, lv2_urid_map(pszType)); } } for (unsigned short i = 0; i < instances(); ++i) { const LV2_State_Interface *state = lv2_state_interface(i); if (state) { LV2_Handle handle = lv2_handle(i); if (handle) (*state->restore)(handle, qtractor_lv2_state_retrieve, this, LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE, m_lv2_features); } } #endif // CONFIG_LV2_STATE qtractorPlugin::realizeConfigs(); } // Plugin configuration/state release. void qtractorLv2Plugin::releaseConfigs (void) { if (!type()->isConfigure()) return; #ifdef CONFIG_LV2_STATE m_lv2_state_configs.clear(); m_lv2_state_ctypes.clear(); #endif qtractorPlugin::releaseConfigs(); } #ifdef CONFIG_LV2_WORKER // LV2 Worker/Schedule extension data interface accessor. const LV2_Worker_Interface *qtractorLv2Plugin::lv2_worker_interface ( unsigned short iInstance ) const { const LilvInstance *instance = lv2_instance(iInstance); if (instance == NULL) return NULL; const LV2_Descriptor *descriptor = lilv_instance_get_descriptor(instance); if (descriptor == NULL) return NULL; if (descriptor->extension_data == NULL) return NULL; return (const LV2_Worker_Interface *) (*descriptor->extension_data)(LV2_WORKER__interface); } #endif // CONFIG_LV2_WORKER #ifdef CONFIG_LV2_STATE // LV2 State extension data descriptor accessor. const LV2_State_Interface *qtractorLv2Plugin::lv2_state_interface ( unsigned short iInstance ) const { const LilvInstance *instance = lv2_instance(iInstance); if (instance == NULL) return NULL; const LV2_Descriptor *descriptor = lilv_instance_get_descriptor(instance); if (descriptor == NULL) return NULL; if (descriptor->extension_data == NULL) return NULL; return (const LV2_State_Interface *) (*descriptor->extension_data)(LV2_STATE__interface); } LV2_State_Status qtractorLv2Plugin::lv2_state_store ( uint32_t key, const void *value, size_t size, uint32_t type, uint32_t flags ) { if ((flags & (LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE)) == 0) return LV2_STATE_ERR_BAD_FLAGS; const char *pszKey = lv2_urid_unmap(key); if (pszKey == NULL) return LV2_STATE_ERR_UNKNOWN; const char *pszType = lv2_urid_unmap(type); if (pszType == NULL) return LV2_STATE_ERR_BAD_TYPE; const char *pchValue = (const char *) value; if (pchValue == NULL) return LV2_STATE_ERR_UNKNOWN; const QString& sKey = QString::fromUtf8(pszKey); if (::strcmp(pszType, LV2_ATOM__Path) == 0 || ::strcmp(pszType, LV2_ATOM__String) == 0) { setConfig(sKey, QString::fromUtf8(pchValue, ::strlen(pchValue))); } else { QByteArray data = qCompress( QByteArray(pchValue, size)).toBase64(); for (int i = data.size() - (data.size() % 72); i >= 0; i -= 72) data.insert(i, "\n "); // Indentation. setConfig(sKey, data.constData()); setConfigType(sKey, QString::fromUtf8(pszType)); } return LV2_STATE_SUCCESS; } const void *qtractorLv2Plugin::lv2_state_retrieve ( uint32_t key, size_t *size, uint32_t *type, uint32_t *flags ) { const char *pszKey = lv2_urid_unmap(key); if (pszKey == NULL) return NULL; const QString& sKey = QString::fromUtf8(pszKey); if (sKey.isEmpty()) return NULL; QHash::ConstIterator iter = m_lv2_state_configs.constFind(sKey); if (iter == m_lv2_state_configs.constEnd()) return NULL; const QByteArray& data = iter.value(); if (size) *size = data.size(); if (type) { QHash::ConstIterator ctype = m_lv2_state_ctypes.constFind(sKey); if (ctype != m_lv2_state_ctypes.constEnd()) *type = ctype.value(); else *type = g_lv2_atom_string_type; } if (flags) *flags = LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE; return data.constData(); } #endif // CONFIG_LV2_STATE #ifdef CONFIG_LV2_PROGRAMS // LV2 Programs extension data descriptor accessor. const LV2_Programs_Interface *qtractorLv2Plugin::lv2_programs_descriptor ( unsigned short iInstance ) const { const LilvInstance *instance = lv2_instance(iInstance); if (instance == NULL) return NULL; const LV2_Descriptor *descriptor = lilv_instance_get_descriptor(instance); if (descriptor == NULL) return NULL; if (descriptor->extension_data == NULL) return NULL; return (const LV2_Programs_Interface *) (*descriptor->extension_data)(LV2_PROGRAMS__Interface); } // Bank/program selector. void qtractorLv2Plugin::selectProgram ( int iBank, int iProg ) { if (iBank < 0 || iProg < 0) return; #ifdef CONFIG_DEBUG qDebug("qtractorLv2Plugin[%p]::selectProgram(%d, %d)", this, iBank, iProg); #endif // For each plugin instance... for (unsigned short i = 0; i < instances(); ++i) { const LV2_Programs_Interface *programs = lv2_programs_descriptor(i); if (programs && programs->select_program) { LV2_Handle handle = lv2_handle(i); if (handle) { (*programs->select_program)(handle, iBank, iProg); } } } #ifdef CONFIG_LV2_UI if (m_suil_instance) { const LV2_Programs_UI_Interface *ui_programs = (const LV2_Programs_UI_Interface *) suil_instance_extension_data( m_suil_instance, LV2_PROGRAMS__UIInterface); if (ui_programs && ui_programs->select_program) { #ifdef CONFIG_SUIL_INSTANCE_GET_HANDLE LV2UI_Handle ui_handle = (LV2UI_Handle) suil_instance_get_handle(m_suil_instance); #else struct SuilInstanceHead { // HACK! void *ui_lib_handle; const LV2UI_Descriptor *ui_descriptor; LV2UI_Handle ui_handle; } *suil_instance_head = (SuilInstanceHead *) m_suil_instance; LV2UI_Handle ui_handle = suil_instance_head->ui_handle; #endif // CONFIG_SUIL_INSTANCE_GET_HANDLE #ifdef CONFIG_DEBUG qDebug("qtractorLv2Plugin[%p]::selectProgram(%d, %d)" " LV2UI_Handle=%p", this, iBank, iProg, ui_handle); #endif if (ui_handle) { (*ui_programs->select_program)(ui_handle, iBank, iProg); } } } #endif // CONFIG_LV2_UI // Reset parameters default value... const qtractorPlugin::Params& params = qtractorPlugin::params(); qtractorPlugin::Params::ConstIterator param = params.constBegin(); const qtractorPlugin::Params::ConstIterator& param_end = params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); pParam->setDefaultValue(pParam->value()); } } // Provisional program/patch accessor. bool qtractorLv2Plugin::getProgram ( int iIndex, Program& program ) const { // Only first one instance should matter... const LV2_Programs_Interface *programs = lv2_programs_descriptor(0); if (programs == NULL) return false; if (programs->get_program == NULL) return false; LV2_Handle handle = lv2_handle(0); if (handle == NULL) return false; const LV2_Program_Descriptor *pLv2Program = (*programs->get_program)(handle, iIndex); if (pLv2Program == NULL) return false; // Map this to that... program.bank = pLv2Program->bank; program.prog = pLv2Program->program; program.name = pLv2Program->name; return true; } // Program/patch notification. void qtractorLv2Plugin::lv2_program_changed ( int iIndex ) { qtractorPluginList *pList = list(); if (iIndex < 0) { qtractorMidiManager *pMidiManager = pList->midiManager(); if (pMidiManager) pMidiManager->updateInstruments(); } else { qtractorPlugin::Program program; if (getProgram(iIndex, program)) { qtractorPluginList::MidiProgramSubject *pMidiProgramSubject = pList->midiProgramSubject(); if (pMidiProgramSubject) pMidiProgramSubject->setProgram(program.bank, program.prog); } } } #endif // CONFIG_LV2_PROGRAMS #ifdef CONFIG_LV2_TIME // Update LV2 Time from JACK transport position. (static) inline void qtractor_lv2_time_update ( int i, float fValue ) { qtractorLv2Time& member = g_lv2_time[i]; if (member.value != fValue && member.params && member.params->count() > 0) { member.value = fValue; QListIterator iter(*member.params); while (iter.hasNext()) iter.next()->setValue(fValue, true); } } void qtractorLv2Plugin::updateTime ( const jack_transport_state_t state, const jack_position_t *pPos ) { qtractor_lv2_time_update( qtractorLv2Time::position, float(pPos->tick)); qtractor_lv2_time_update( qtractorLv2Time::bar, float(pPos->bar)); qtractor_lv2_time_update( qtractorLv2Time::beat, float(pPos->beat)); qtractor_lv2_time_update( qtractorLv2Time::beatUnit, float(pPos->beat_type)); qtractor_lv2_time_update( qtractorLv2Time::beatsPerBar, float(pPos->beats_per_bar)); qtractor_lv2_time_update( qtractorLv2Time::beatsPerMinute, float(pPos->beats_per_minute)); qtractor_lv2_time_update( qtractorLv2Time::frame, float(pPos->frame)); qtractor_lv2_time_update( qtractorLv2Time::framesPerSecond, float(pPos->frame_rate)); qtractor_lv2_time_update( qtractorLv2Time::speed, float(state == JackTransportRolling)); } #endif // CONFIG_LV2_TIME #ifdef CONFIG_LV2_PRESETS // Refresh and load preset labels listing. (virtual) QStringList qtractorLv2Plugin::presetList (void) const { QStringList list(qtractorPlugin::presetList()); QHash::ConstIterator iter = m_lv2_presets.constBegin(); const QHash::ConstIterator& iter_end = m_lv2_presets.constEnd(); for ( ; iter != iter_end; ++iter) list.append(iter.key()); return list; } // Load plugin state from a named preset. bool qtractorLv2Plugin::loadPreset ( const QString& sPreset ) { const QString& sUri = m_lv2_presets.value(sPreset); if (sUri.isEmpty()) return false; LilvNode *preset = lilv_new_uri(g_lv2_world, sUri.toUtf8().constData()); LilvState *state = NULL; const QString& sPath = QUrl(sUri).toLocalFile(); if (!sPath.isEmpty() && QFileInfo(sPath).exists()) { state = lilv_state_new_from_file(g_lv2_world, &g_lv2_urid_map, preset, sPath.toUtf8().constData()); } else { state = lilv_state_new_from_world(g_lv2_world, &g_lv2_urid_map, preset); } if (state == NULL) { lilv_node_free(preset); return false; } for (unsigned short i = 0; i < instances(); ++i) { lilv_state_restore(state, m_ppInstances[i], qtractor_lv2_set_port_value, this, 0, NULL); } lilv_state_free(state); lilv_node_free(preset); return true; } // Save current plugin state as a named preset. bool qtractorLv2Plugin::savePreset ( const QString& sPreset ) { qtractorLv2PluginType *pLv2Type = static_cast (type()); if (pLv2Type == NULL) return false; LilvState *state = lilv_state_new_from_instance( lv2_plugin(), m_ppInstances[0], &g_lv2_urid_map, NULL, NULL, NULL, NULL, qtractor_lv2_get_port_value, this, LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE, m_lv2_features); if (state == NULL) return false; lilv_state_set_label(state, sPreset.toUtf8().constData()); const QString sDotLv2(".lv2"); const QString& sep = QDir::separator(); QString sDir; qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) sDir = pOptions->sLv2PresetDir; if (sDir.isEmpty()) sDir = QDir::homePath() + sep + sDotLv2; sDir += sep + pLv2Type->label(); sDir += '_' + QString::number(pLv2Type->uniqueID(), 16); sDir += '-' + sPreset + sDotLv2; const QString& sFile = sPreset + ".ttl"; int ret = lilv_state_save(g_lv2_world, &g_lv2_urid_map, &g_lv2_urid_unmap, state, NULL, sDir.toUtf8().constData(), sFile.toUtf8().constData()); lilv_state_free(state); if (ret == 0) { m_lv2_presets.insert(sPreset, QUrl::fromLocalFile(sDir + sep + sFile).toString()); } return (ret == 0); } // Delete plugin state preset (from file-system). bool qtractorLv2Plugin::deletePreset ( const QString& sPreset ) { const QString& sUri = m_lv2_presets.value(sPreset); if (sUri.isEmpty()) return false; const QString& sPath = QUrl(sUri).toLocalFile(); if (!sPath.isEmpty()) { QFileInfo info(sPath); if (!info.isDir()) info.setFile(info.absolutePath()); qtractor_lv2_remove_file(info); m_lv2_presets.remove(sPreset); } return true; } // Whether given preset is internal/read-only. bool qtractorLv2Plugin::isReadOnlyPreset ( const QString& sPreset ) const { const QString& sUri = m_lv2_presets.value(sPreset); if (sUri.isEmpty()) return false; const QString& sPath = QUrl(sUri).toLocalFile(); if (sPath.isEmpty()) return true; const QFileInfo info(sPath); return !info.exists() || !info.isWritable(); } #endif // CONFIG_LV2_PRESETS //---------------------------------------------------------------------------- // qtractorLv2PluginParam -- LV2 plugin control input port instance. // // Constructors. qtractorLv2PluginParam::qtractorLv2PluginParam ( qtractorLv2Plugin *pLv2Plugin, unsigned long iIndex ) : qtractorPluginParam(pLv2Plugin, iIndex), m_iPortHints(None) { const LilvPlugin *plugin = pLv2Plugin->lv2_plugin(); const LilvPort *port = lilv_plugin_get_port_by_index(plugin, iIndex); // Set nominal parameter name... LilvNode *name = lilv_port_get_name(plugin, port); setName(lilv_node_as_string(name)); lilv_node_free(name); // Get port properties and set hints... if (lilv_port_has_property(plugin, port, g_lv2_toggled_prop)) m_iPortHints |= Toggled; if (lilv_port_has_property(plugin, port, g_lv2_integer_prop)) m_iPortHints |= Integer; if (lilv_port_has_property(plugin, port, g_lv2_sample_rate_prop)) m_iPortHints |= SampleRate; if (lilv_port_has_property(plugin, port, g_lv2_logarithmic_prop)) m_iPortHints |= Logarithmic; // Initialize range values... LilvNode *vdef; LilvNode *vmin; LilvNode *vmax; lilv_port_get_range(plugin, port, &vdef, &vmin, &vmax); setMinValue(vmin ? lilv_node_as_float(vmin) : 0.0f); setMaxValue(vmax ? lilv_node_as_float(vmax) : 1.0f); setDefaultValue(vdef ? lilv_node_as_float(vdef) : 0.0f); if (vdef) lilv_node_free(vdef); if (vmin) lilv_node_free(vmin); if (vmax) lilv_node_free(vmax); // Have scale points (display values) // m_display.clear(); LilvScalePoints *points = lilv_port_get_scale_points(plugin, port); if (points) { LILV_FOREACH(scale_points, i, points) { const LilvScalePoint *point = lilv_scale_points_get(points, i); const LilvNode *value = lilv_scale_point_get_value(point); const LilvNode *label = lilv_scale_point_get_label(point); if (value && label) { float fValue = lilv_node_as_float(value); QString sLabel = lilv_node_as_string(label); m_display.insert(QString::number(fValue), sLabel); } } lilv_scale_points_free(points); } // Initialize port value... reset(); } // Destructor. qtractorLv2PluginParam::~qtractorLv2PluginParam (void) { } // Port range hints predicate methods. bool qtractorLv2PluginParam::isBoundedBelow (void) const { return true; } bool qtractorLv2PluginParam::isBoundedAbove (void) const { return true; } bool qtractorLv2PluginParam::isDefaultValue (void) const { return true; } bool qtractorLv2PluginParam::isLogarithmic (void) const { return (m_iPortHints & Logarithmic); } bool qtractorLv2PluginParam::isSampleRate (void) const { return (m_iPortHints & SampleRate); } bool qtractorLv2PluginParam::isInteger (void) const { return (m_iPortHints & Integer); } bool qtractorLv2PluginParam::isToggled (void) const { return (m_iPortHints & Toggled); } bool qtractorLv2PluginParam::isDisplay (void) const { return !m_display.isEmpty(); } // Current display value. QString qtractorLv2PluginParam::display (void) const { // Check if current value is mapped... if (isDisplay()) { float fValue = value(); if (isInteger()) fValue = ::rintf(fValue); const QString& sValue = QString::number(fValue); if (m_display.contains(sValue)) return m_display.value(sValue); } // Default parameter display value... return qtractorPluginParam::display(); } #endif // CONFIG_LV2 // end of qtractorLv2Plugin.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioFile.cpp0000644000175000001440000000012312073012112021355 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134666.81708 30 ctime=1381134666.818080046 qtractor-0.5.11/src/qtractorAudioFile.cpp0000644000175000001440000002166312073012112020654 0ustar00rncbcusers00000000000000// qtractorAudioFile.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorAudioFile.h" #include "qtractorAudioSndFile.h" #include "qtractorAudioVorbisFile.h" #include "qtractorAudioMadFile.h" #include #include #include //---------------------------------------------------------------------- // class qtractorAudioFileFactory -- Audio file factory (singleton). // // Initialize singleton instance pointer. qtractorAudioFileFactory *qtractorAudioFileFactory::g_pInstance = NULL; // Singleton instance accessor. qtractorAudioFileFactory& qtractorAudioFileFactory::getInstance (void) { // Create the singleton instance, if not already... if (g_pInstance == NULL) { g_pInstance = new qtractorAudioFileFactory(); ::atexit(Destroy); } return *g_pInstance; } // Singleton instance destroyer. void qtractorAudioFileFactory::Destroy (void) { // OK. We're done with ourselves. if (g_pInstance) { qDeleteAll(g_pInstance->m_formats); g_pInstance->m_formats.clear(); g_pInstance->m_filters.clear(); g_pInstance->m_types.clear(); delete g_pInstance; g_pInstance = NULL; } } // Constructor. qtractorAudioFileFactory::qtractorAudioFileFactory (void) { // Default file format/type (for capture/record) m_pDefaultFormat = NULL; m_iDefaultFormat = SF_FORMAT_PCM_16; m_iDefaultQuality = 4; // Second for libsndfile stuff... FileFormat *pFormat; const QString sExtMask("*.%1"); const QString sFilterMask("%1 (%2)"); SF_FORMAT_INFO sffinfo; int iCount = 0; ::sf_command(NULL, SFC_GET_FORMAT_MAJOR_COUNT, &iCount, sizeof(int)); for (int i = 0 ; i < iCount; ++i) { sffinfo.format = i; ::sf_command(NULL, SFC_GET_FORMAT_MAJOR, &sffinfo, sizeof(sffinfo)); pFormat = new FileFormat; pFormat->type = SndFile; pFormat->name = QString(sffinfo.name) .replace('/', '-') // Replace some illegal characters. .replace('(', QString::null) .replace(')', QString::null); pFormat->ext = sffinfo.extension; pFormat->data = sffinfo.format; m_formats.append(pFormat); // Add for the extension map (should be unique)... QString sExt = pFormat->ext; QString sExts(sExtMask.arg(sExt)); if (m_types.find(sExt) == m_types.end()) { m_types[sExt] = pFormat; // Take care of some old 8.3 convention, // specially regarding filename extensions... if (sExt.length() > 3) { sExt = sExt.left(3); if (m_types.find(sExt) == m_types.end()) { sExts = sExtMask.arg(sExt) + ' ' + sExts; m_types[sExt] = pFormat; } } // Make a stance on the default format... if (sExt == "wav") m_pDefaultFormat = pFormat; } // What we see on dialog is some excerpt... m_filters.append( sFilterMask.arg(pFormat->name).arg(sExts)); } #ifdef CONFIG_LIBVORBIS // Add for libvorbis... pFormat = new FileFormat; pFormat->type = VorbisFile; pFormat->name = "OGG Vorbis"; pFormat->ext = "ogg"; pFormat->data = 0; m_formats.append(pFormat); m_types[pFormat->ext] = pFormat; m_filters.append( sFilterMask.arg(pFormat->name).arg(sExtMask.arg(pFormat->ext))); // Oh yeah, this will be the official default format... m_pDefaultFormat = pFormat; #endif #ifdef CONFIG_LIBMAD // Add for libmad (mp3 read-only)... pFormat = new FileFormat; pFormat->type = MadFile; pFormat->name = "MP3 MPEG-1 Audio Layer 3"; pFormat->ext = "mp3"; pFormat->data = 0; m_formats.append(pFormat); m_types[pFormat->ext] = pFormat; m_filters.append( sFilterMask.arg(pFormat->name).arg(sExtMask.arg(pFormat->ext))); #endif // Finally, simply build the all (most commonly) supported files entry. QRegExp rx("^(aif(|f)|fla(|c)|mp3|ogg|w(av|64))", Qt::CaseInsensitive); QStringList exts; FileTypes::ConstIterator iter = m_types.constBegin(); const FileTypes::ConstIterator& iter_end = m_types.constEnd(); for ( ; iter != iter_end; ++iter) { const QString& sExt = iter.key(); if (rx.exactMatch(sExt)) exts.append(sExtMask.arg(sExt)); } m_filters.prepend(QObject::tr("Audio files (%1)").arg(exts.join(" "))); m_filters.append(QObject::tr("All files (*.*)")); } // Factory methods. qtractorAudioFile *qtractorAudioFileFactory::createAudioFile ( const QString& sFilename, unsigned short iChannels, unsigned int iSampleRate, unsigned int iBufferSize ) { return getInstance().newAudioFile( sFilename, iChannels, iSampleRate, iBufferSize); } qtractorAudioFile *qtractorAudioFileFactory::createAudioFile ( FileType type, unsigned short iChannels, unsigned int iSampleRate, unsigned int iBufferSize ) { return getInstance().newAudioFile(type, iChannels, iSampleRate, iBufferSize); } // Internal factory methods. qtractorAudioFile *qtractorAudioFileFactory::newAudioFile ( const QString& sFilename, unsigned short iChannels, unsigned int iSampleRate, unsigned int iBufferSize ) { const QString sExt = QFileInfo(sFilename).suffix().toLower(); FileTypes::ConstIterator iter = m_types.constFind(sExt); if (iter == m_types.constEnd()) return NULL; return newAudioFile(iter.value()->type, iChannels, iSampleRate, iBufferSize); } qtractorAudioFile *qtractorAudioFileFactory::newAudioFile ( FileType type, unsigned short iChannels, unsigned int iSampleRate, unsigned int iBufferSize ) { switch (type) { case SndFile: return new qtractorAudioSndFile(iChannels, iSampleRate, iBufferSize); case VorbisFile: return new qtractorAudioVorbisFile(iChannels, iSampleRate, iBufferSize); case MadFile: return new qtractorAudioMadFile(iBufferSize); default: return NULL; } } const qtractorAudioFileFactory::FileFormats& qtractorAudioFileFactory::formats (void) { return getInstance().m_formats; } // Retrieve supported filters (suitable for QFileDialog usage). QString qtractorAudioFileFactory::filters (void) { return getInstance().m_filters.join(";;"); } // Default audio file format accessors // (specific to capture/recording) void qtractorAudioFileFactory::setDefaultType(const QString& sExt, int iType, int iFormat, int iQuality ) { // Search for type-format first... int iDefaultFormat = 0; QListIterator iter(getInstance().m_formats); while (iter.hasNext()) { FileFormat *pFormat = iter.next(); if (sExt == pFormat->ext && iType == pFormat->data) { getInstance().m_pDefaultFormat = pFormat; iDefaultFormat = format(pFormat, iFormat); break; } } // Rest is not so obviously trivial... getInstance().m_iDefaultFormat = iDefaultFormat; getInstance().m_iDefaultQuality = iQuality; } QString qtractorAudioFileFactory::defaultExt (void) { FileFormat *pFormat = getInstance().m_pDefaultFormat; if (pFormat) return pFormat->ext; #ifdef CONFIG_LIBVORBIS return "ogg"; #else return "wav"; #endif } int qtractorAudioFileFactory::defaultFormat (void) { int iDefaultFormat = getInstance().m_iDefaultFormat; FileFormat *pFormat = getInstance().m_pDefaultFormat; if (pFormat) iDefaultFormat |= pFormat->data; #ifndef CONFIG_LIBVORBIS else iDefaultFormat |= SF_FORMAT_WAV; #endif return iDefaultFormat; } int qtractorAudioFileFactory::defaultQuality (void) { return getInstance().m_iDefaultQuality; } // Check whether given file type/format is valid. bool qtractorAudioFileFactory::isValidFormat ( const qtractorAudioFileFactory::FileFormat *pFormat, int iFormat ) { if (pFormat == NULL) return false; bool bValid = true; // Translate this to some libsndfile slang... if (pFormat->type == SndFile) { SF_INFO sfinfo; ::memset(&sfinfo, 0, sizeof(sfinfo)); sfinfo.samplerate = 44100; // Dummy samplerate. sfinfo.channels = 2; // Dummy stereo. sfinfo.format = pFormat->data | format(pFormat, iFormat); bValid = ::sf_format_check(&sfinfo); } return bValid; } // Translate format index into libsndfile specific... int qtractorAudioFileFactory::format ( const qtractorAudioFileFactory::FileFormat *pFormat, int iFormat ) { // Translate this to some libsndfile slang... if (pFormat && pFormat->type == SndFile) { switch (iFormat) { case 4: return SF_FORMAT_DOUBLE; case 3: return SF_FORMAT_FLOAT; case 2: return SF_FORMAT_PCM_32; case 1: return SF_FORMAT_PCM_24; case 0: default: return SF_FORMAT_PCM_16; } } return 0; } // end of qtractorAudioFile.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiTimer.h0000644000175000001440000000012311331527151021056 xustar000000000000000027 mtime=1265020521.610577 26 atime=1381134667.16208 30 ctime=1381134667.162080051 qtractor-0.5.11/src/qtractorMidiTimer.h0000644000175000001440000000504311331527151020347 0ustar00rncbcusers00000000000000// qtractorMidiTimer.h // /**************************************************************************** Copyright (C) 2005-2010, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiTimer_h #define __qtractorMidiTimer_h #include //---------------------------------------------------------------------- // class qtractorMidiTimer -- ALSA sequencer timer stuff (singleton). // class qtractorMidiTimer { public: // Constructor. qtractorMidiTimer(); // Destructor. ~qtractorMidiTimer(); // Returns the number of available timers. int count() const; // Index of the a timer key. int indexOf(int iKey) const; // Key from index. int key(int iIndex) const; // Name from index. const QString& name(int iIndex) const; // ALSA sequencer timer key stuff. class Key { public: // Constructors. Key(int iAlsaTimer = 0) { setAlsaTimer(iAlsaTimer); } Key(int iClass, int iCard, int iDevice, int iSubDev) { setAlsaTimer(iClass, iCard, iDevice, iSubDev); } Key(const Key& key) { setAlsaTimer(key.alsaTimer()); } // Getters. int alsaTimer() const { return m_iAlsaTimer; } int alsaTimerClass() const { return int((m_iAlsaTimer & 0x7f000000) >> 24); } int alsaTimerCard() const { return int((m_iAlsaTimer & 0x007f0000) >> 16); } int alsaTimerDevice() const { return int((m_iAlsaTimer & 0x00007f00) >> 8); } int alsaTimerSubDev() const { return int(m_iAlsaTimer & 0x0000007f); } protected: // Setters. void setAlsaTimer(int iAlsaTimer); void setAlsaTimer(int iClass, int iCard, int iDevice, int iSubDev); private: // Queue timer int m_iAlsaTimer; }; private: // Instance variables; QStringList m_names; QList m_keys; }; #endif // __qtractorMidiTimer_h // end of qtractorMidiTimer.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorOptions.cpp0000644000175000001440000000012112203713015021152 xustar000000000000000025 mtime=1376753165.6215 26 atime=1381134670.67008 30 ctime=1381134670.670080107 qtractor-0.5.11/src/qtractorOptions.cpp0000644000175000001440000007530612203713015020456 0ustar00rncbcusers00000000000000// qtractorOptions.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorOptions.h" #include #include #include #include #include #include // Supposed to be determinant as default audio file type // (effective only for capture/record) #ifdef CONFIG_LIBVORBIS #define AUDIO_DEFAULT_EXT "ogg" #else #define AUDIO_DEFAULT_EXT "wav" #endif //------------------------------------------------------------------------- // qtractorOptions - Prototype settings structure (pseudo-singleton). // // Singleton instance pointer. qtractorOptions *qtractorOptions::g_pOptions = NULL; // Singleton instance accessor (static). qtractorOptions *qtractorOptions::getInstance (void) { return g_pOptions; } // Constructor. qtractorOptions::qtractorOptions (void) : m_settings(QTRACTOR_DOMAIN, QTRACTOR_TITLE) { // Pseudo-singleton reference setup. g_pOptions = this; loadOptions(); } // Default Destructor. qtractorOptions::~qtractorOptions (void) { saveOptions(); // Pseudo-singleton reference shut-down. g_pOptions = NULL; } // Explicit load method. void qtractorOptions::loadOptions (void) { // And go into general options group. m_settings.beginGroup("/Options"); // Load display options... m_settings.beginGroup("/Display"); sMessagesFont = m_settings.value("/MessagesFont").toString(); bMessagesLimit = m_settings.value("/MessagesLimit", true).toBool(); iMessagesLimitLines = m_settings.value("/MessagesLimitLines", 1000).toInt(); bConfirmRemove = m_settings.value("/ConfirmRemove", true).toBool(); bStdoutCapture = m_settings.value("/StdoutCapture", true).toBool(); bCompletePath = m_settings.value("/CompletePath", true).toBool(); bPeakAutoRemove = m_settings.value("/PeakAutoRemove", true).toBool(); bKeepToolsOnTop = m_settings.value("/KeepToolsOnTop", true).toBool(); iDisplayFormat = m_settings.value("/DisplayFormat", 1).toInt(); iMaxRecentFiles = m_settings.value("/MaxRecentFiles", 5).toInt(); iBaseFontSize = m_settings.value("/BaseFontSize", 0).toInt(); m_settings.endGroup(); // Load logging options... m_settings.beginGroup("/Logging"); bMessagesLog = m_settings.value("/MessagesLog", false).toBool(); sMessagesLogPath = m_settings.value("/MessagesLogPath", "qtractor.log").toString(); m_settings.endGroup(); // And go into view options group. m_settings.beginGroup("/View"); bMenubar = m_settings.value("/Menubar", true).toBool(); bStatusbar = m_settings.value("/Statusbar", true).toBool(); bFileToolbar = m_settings.value("/FileToolbar", true).toBool(); bEditToolbar = m_settings.value("/EditToolbar", true).toBool(); bTrackToolbar = m_settings.value("/TrackToolbar", true).toBool(); bViewToolbar = m_settings.value("/ViewToolbar", true).toBool(); bOptionsToolbar = m_settings.value("/OptionsToolbar", true).toBool(); bTransportToolbar = m_settings.value("/TransportToolbar", true).toBool(); bTimeToolbar = m_settings.value("/TimeToolbar", true).toBool(); bThumbToolbar = m_settings.value("/ThumbToolbar", true).toBool(); iZoomMode = m_settings.value("/ZoomMode", 1).toInt(); m_settings.endGroup(); // Transport options group. m_settings.beginGroup("/Transport"); bMetronome = m_settings.value("/Metronome", false).toBool(); bFollowPlayhead = m_settings.value("/FollowPlayhead", true).toBool(); bAutoBackward = m_settings.value("/AutoBackward", false).toBool(); bContinuePastEnd = m_settings.value("/ContinuePastEnd", true).toBool(); iTransportMode = m_settings.value("/TransportMode", 3).toInt(); m_settings.endGroup(); // Audio rendering options group. m_settings.beginGroup("/Audio"); sAudioCaptureExt = m_settings.value("/CaptureExt", AUDIO_DEFAULT_EXT).toString(); iAudioCaptureType = m_settings.value("/CaptureType", 0).toInt(); iAudioCaptureFormat = m_settings.value("/CaptureFormat", 0).toInt(); iAudioCaptureQuality = m_settings.value("/CaptureQuality", 4).toInt(); iAudioResampleType = m_settings.value("/ResampleType", 2).toInt(); bAudioAutoTimeStretch = m_settings.value("/AutoTimeStretch", false).toBool(); bAudioWsolaTimeStretch = m_settings.value("/WsolaTimeStretch", true).toBool(); bAudioWsolaQuickSeek = m_settings.value("/WsolaQuickSeek", false).toBool(); bAudioPlayerBus = m_settings.value("/PlayerBus", false).toBool(); bAudioMetroBus = m_settings.value("/MetroBus", false).toBool(); bAudioMetronome = m_settings.value("/Metronome", false).toBool(); bAudioMasterAutoConnect = m_settings.value("/MasterAutoConnect", true).toBool(); bAudioPlayerAutoConnect = m_settings.value("/PlayerAutoConnect", true).toBool(); bAudioMetroAutoConnect = m_settings.value("/MetroAutoConnect", true).toBool(); m_settings.endGroup(); // MIDI rendering options group. m_settings.beginGroup("/Midi"); iMidiCaptureFormat = m_settings.value("/CaptureFormat", 1).toInt(); iMidiCaptureQuantize = m_settings.value("/CaptureQuantize", 0).toInt(); iMidiQueueTimer = m_settings.value("/QueueTimer", 0).toInt(); bMidiPlayerBus = m_settings.value("/PlayerBus", false).toBool(); bMidiControlBus = m_settings.value("/ControlBus", false).toBool(); bMidiMetroBus = m_settings.value("/MetroBus", false).toBool(); bMidiMetronome = m_settings.value("/Metronome", true).toBool(); iMidiMmcDevice = m_settings.value("/MmcDevice", 0x7f).toInt(); iMidiMmcMode = m_settings.value("/MmcMode", 3).toInt(); iMidiSppMode = m_settings.value("/SppMode", 3).toInt(); iMidiClockMode = m_settings.value("/ClockMode", 0).toInt(); m_settings.endGroup(); // Metronome options group. m_settings.beginGroup("/Metronome"); // Audio metronome... sMetroBarFilename = m_settings.value("/BarFilename").toString(); fMetroBarGain = float(m_settings.value("/BarGain", 1.0).toDouble()); sMetroBeatFilename = m_settings.value("/BeatFilename").toString(); fMetroBeatGain = float(m_settings.value("/BeatGain", 1.0).toDouble()); // MIDI metronome... iMetroChannel = m_settings.value("/Channel", 9).toInt(); iMetroBarNote = m_settings.value("/BarNote", 76).toInt(); iMetroBarVelocity = m_settings.value("/BarVelocity", 96).toInt(); iMetroBarDuration = m_settings.value("/BarDuration", 48).toInt(); iMetroBeatNote = m_settings.value("/BeatNote", 77).toInt(); iMetroBeatVelocity = m_settings.value("/BeatVelocity", 64).toInt(); iMetroBeatDuration = m_settings.value("/BeatDuration", 24).toInt(); m_settings.endGroup(); m_settings.endGroup(); // Options group. // Last but not least, get the defaults. m_settings.beginGroup("/Default"); sSessionExt = m_settings.value("/SessionExt", "qtr").toString(); bSessionTemplate = m_settings.value("/SessionTemplate", false).toBool(); sSessionTemplatePath = m_settings.value("/SessionTemplatePath").toString(); bSessionBackup = m_settings.value("/SessionBackup", false).toBool(); iSessionBackupMode = m_settings.value("/SessionBackupMode", 0).toInt(); sSessionDir = m_settings.value("/SessionDir").toString(); sAudioDir = m_settings.value("/AudioDir").toString(); sMidiDir = m_settings.value("/MidiDir").toString(); sPresetDir = m_settings.value("/PresetDir").toString(); sInstrumentDir = m_settings.value("/InstrumentDir").toString(); sMidiControlDir = m_settings.value("/MidiControlDir").toString(); sMidiSysexDir = m_settings.value("/MidiSysexDir").toString(); bAutoMonitor = m_settings.value("/AutoMonitor", true).toBool(); iSnapPerBeat = m_settings.value("/SnapPerBeat", 4).toInt(); fTempo = float(m_settings.value("/Tempo", 120.0).toDouble()); iBeatsPerBar = m_settings.value("/BeatsPerBar", 4).toInt(); iBeatDivisor = m_settings.value("/BeatDivisor", 2).toInt(); iLoopRecordingMode = m_settings.value("/LoopRecordingMode", 0).toInt(); iPasteRepeatCount = m_settings.value("/PasteRepeatCount", 2).toInt(); bPasteRepeatPeriod = m_settings.value("/PasteRepeatPeriod", false).toInt(); sPluginSearch = m_settings.value("/PluginSearch").toString(); iPluginType = m_settings.value("/PluginType", 1).toInt(); bPluginActivate = m_settings.value("/PluginActivate", false).toBool(); iCurveMode = m_settings.value("/CurveMode", 0).toInt(); iEditRangeOptions = m_settings.value("/EditRangeOptions", 3).toInt(); bMidButtonModifier = m_settings.value("/MidButtonModifier", false).toBool(); m_settings.endGroup(); // Plug-in paths. m_settings.beginGroup("/Plugins"); ladspaPaths = m_settings.value("/LadspaPaths").toStringList(); dssiPaths = m_settings.value("/DssiPaths").toStringList(); vstPaths = m_settings.value("/VstPaths").toStringList(); lv2Paths = m_settings.value("/Lv2Paths").toStringList(); sLv2PresetDir = m_settings.value("/Lv2PresetDir").toString(); bAudioOutputBus = m_settings.value("/AudioOutputBus", false).toBool(); bAudioOutputAutoConnect = m_settings.value("/AudioOutputAutoConnect", true).toBool(); bOpenEditor = m_settings.value("/OpenEditor", true).toBool(); bDummyVstScan = m_settings.value("/DummyVstScan", true).toBool(); m_settings.endGroup(); // Instrument file list. const QString sFilePrefix = "/File%1"; int iFile = 0; instrumentFiles.clear(); m_settings.beginGroup("/InstrumentFiles"); for (;;) { QString sFilename = m_settings.value( sFilePrefix.arg(++iFile)).toString(); if (sFilename.isEmpty()) break; instrumentFiles.append(sFilename); } m_settings.endGroup(); // MIDI controller file list. iFile = 0; midiControlFiles.clear(); m_settings.beginGroup("/MidiControlFiles"); for (;;) { QString sFilename = m_settings.value( sFilePrefix.arg(++iFile)).toString(); if (sFilename.isEmpty()) break; midiControlFiles.append(sFilename); } m_settings.endGroup(); // Recent file list. iFile = 0; recentFiles.clear(); m_settings.beginGroup("/RecentFiles"); while (iFile < iMaxRecentFiles) { QString sFilename = m_settings.value( sFilePrefix.arg(++iFile)).toString(); if (sFilename.isEmpty()) break; recentFiles.append(sFilename); } m_settings.endGroup(); // Tracks widget settings. m_settings.beginGroup("/Tracks"); iTrackViewSelectMode = m_settings.value("/TrackViewSelectMode", 0).toInt(); bTrackViewDropSpan = m_settings.value("/TrackViewDropSpan", false).toBool(); bTrackViewSnapZebra = m_settings.value("/TrackViewSnapZebra", true).toBool(); bTrackViewSnapGrid = m_settings.value("/TrackViewSnapGrid", true).toBool(); bTrackViewToolTips = m_settings.value("/TrackViewToolTips", true).toBool(); bTrackViewCurveEdit = m_settings.value("/TrackViewCurveEdit", false).toBool(); m_settings.endGroup(); // MIDI options group. m_settings.beginGroup("/MidiEditor"); m_settings.beginGroup("/View"); bMidiMenubar = m_settings.value("/Menubar", true).toBool(); bMidiStatusbar = m_settings.value("/Statusbar", true).toBool(); bMidiFileToolbar = m_settings.value("/FileToolbar", true).toBool(); bMidiEditToolbar = m_settings.value("/EditToolbar", true).toBool(); bMidiViewToolbar = m_settings.value("/ViewToolbar", true).toBool(); bMidiTransportToolbar = m_settings.value("/TransportToolbar", false).toBool(); bMidiScaleToolbar = m_settings.value("/ScaleToolbar", false).toBool(); bMidiNoteDuration = m_settings.value("/NoteDuration", true).toBool(); bMidiNoteColor = m_settings.value("/NoteColor", false).toBool(); bMidiValueColor = m_settings.value("/ValueColor", false).toBool(); bMidiPreview = m_settings.value("/Preview", true).toBool(); bMidiFollow = m_settings.value("/Follow", false).toBool(); bMidiEditMode = m_settings.value("/EditMode", false).toBool(); bMidiEditModeDraw = m_settings.value("/EditModeDraw", false).toBool(); iMidiZoomMode = m_settings.value("/ZoomMode", 3).toInt(); iMidiHorizontalZoom = m_settings.value("/HorizontalZoom", 100).toInt(); iMidiVerticalZoom = m_settings.value("/VerticalZoom", 100).toInt(); iMidiSnapPerBeat = m_settings.value("/SnapPerBeat", 4).toInt(); bMidiSnapZebra = m_settings.value("/SnapZebra", false).toBool(); bMidiSnapGrid = m_settings.value("/SnapGrid", false).toBool(); bMidiToolTips = m_settings.value("/ToolTips", true).toBool(); iMidiSnapToScaleKey = m_settings.value("/SnapToScaleKey", 0).toInt(); iMidiSnapToScaleType = m_settings.value("/SnapToScaleType", 0).toInt(); m_settings.endGroup(); // Meter colors. m_settings.beginGroup("/Colors"); audioMeterColors = m_settings.value("/AudioMeter").toStringList(); midiMeterColors = m_settings.value("/MidiMeter").toStringList(); m_settings.endGroup(); m_settings.endGroup(); } // Explicit save method. void qtractorOptions::saveOptions (void) { // Make program version available in the future. m_settings.beginGroup("/Program"); m_settings.setValue("/Version", QTRACTOR_VERSION); m_settings.endGroup(); // And go into general options group. m_settings.beginGroup("/Options"); // Save display options. m_settings.beginGroup("/Display"); m_settings.setValue("/MessagesFont", sMessagesFont); m_settings.setValue("/MessagesLimit", bMessagesLimit); m_settings.setValue("/MessagesLimitLines", iMessagesLimitLines); m_settings.setValue("/ConfirmRemove", bConfirmRemove); m_settings.setValue("/StdoutCapture", bStdoutCapture); m_settings.setValue("/CompletePath", bCompletePath); m_settings.setValue("/PeakAutoRemove", bPeakAutoRemove); m_settings.setValue("/KeepToolsOnTop", bKeepToolsOnTop); m_settings.setValue("/DisplayFormat", iDisplayFormat); m_settings.setValue("/MaxRecentFiles", iMaxRecentFiles); m_settings.setValue("/BaseFontSize", iBaseFontSize); m_settings.endGroup(); // Save logging options... m_settings.beginGroup("/Logging"); m_settings.setValue("/MessagesLog", bMessagesLog); m_settings.setValue("/MessagesLogPath", sMessagesLogPath); m_settings.endGroup(); // View options group. m_settings.beginGroup("/View"); m_settings.setValue("/Menubar", bMenubar); m_settings.setValue("/Statusbar", bStatusbar); m_settings.setValue("/FileToolbar", bFileToolbar); m_settings.setValue("/EditToolbar", bEditToolbar); m_settings.setValue("/TrackToolbar", bTrackToolbar); m_settings.setValue("/ViewToolbar", bViewToolbar); m_settings.setValue("/OptionsToolbar", bOptionsToolbar); m_settings.setValue("/TransportToolbar", bTransportToolbar); m_settings.setValue("/TimeToolbar", bTimeToolbar); m_settings.setValue("/ThumbToolbar", bThumbToolbar); m_settings.setValue("/ZoomMode", iZoomMode); m_settings.endGroup(); // Transport options group. m_settings.beginGroup("/Transport"); m_settings.setValue("/Metronome", bMetronome); m_settings.setValue("/FollowPlayhead", bFollowPlayhead); m_settings.setValue("/AutoBackward", bAutoBackward); m_settings.setValue("/ContinuePastEnd", bContinuePastEnd); m_settings.setValue("/TransportMode", iTransportMode); m_settings.endGroup(); // Audio redndering options group. m_settings.beginGroup("/Audio"); m_settings.setValue("/CaptureExt", sAudioCaptureExt); m_settings.setValue("/CaptureType", iAudioCaptureType); m_settings.setValue("/CaptureFormat", iAudioCaptureFormat); m_settings.setValue("/CaptureQuality", iAudioCaptureQuality); m_settings.setValue("/ResampleType", iAudioResampleType); m_settings.setValue("/AutoTimeStretch", bAudioAutoTimeStretch); m_settings.setValue("/WsolaTimeStretch", bAudioWsolaTimeStretch); m_settings.setValue("/WsolaQuickSeek", bAudioWsolaQuickSeek); m_settings.setValue("/PlayerBus", bAudioPlayerBus); m_settings.setValue("/MetroBus", bAudioMetroBus); m_settings.setValue("/Metronome", bAudioMetronome); m_settings.setValue("/MasterAutoConnect", bAudioMasterAutoConnect); m_settings.setValue("/PlayerAutoConnect", bAudioPlayerAutoConnect); m_settings.setValue("/MetroAutoConnect", bAudioMetroAutoConnect); m_settings.endGroup(); // MIDI rendering options group. m_settings.beginGroup("/Midi"); m_settings.setValue("/CaptureFormat", iMidiCaptureFormat); m_settings.setValue("/CaptureQuantize", iMidiCaptureQuantize); m_settings.setValue("/QueueTimer", iMidiQueueTimer); m_settings.setValue("/PlayerBus", bMidiPlayerBus); m_settings.setValue("/ControlBus", bMidiControlBus); m_settings.setValue("/MetroBus", bMidiMetroBus); m_settings.setValue("/Metronome", bMidiMetronome); m_settings.setValue("/MmcDevice", iMidiMmcDevice); m_settings.setValue("/MmcMode", iMidiMmcMode); m_settings.setValue("/SppMode", iMidiSppMode); m_settings.setValue("/ClockMode", iMidiClockMode); m_settings.endGroup(); // Metronome options group. m_settings.beginGroup("/Metronome"); // Audio metronome... m_settings.setValue("/BarFilename", sMetroBarFilename); m_settings.setValue("/BarGain", fMetroBarGain); m_settings.setValue("/BeatFilename", sMetroBeatFilename); m_settings.setValue("/BeatGain", fMetroBeatGain); // MIDI metronome... m_settings.setValue("/Channel", iMetroChannel); m_settings.setValue("/BarNote", iMetroBarNote); m_settings.setValue("/BarVelocity", iMetroBarVelocity); m_settings.setValue("/BarDuration", iMetroBarDuration); m_settings.setValue("/BeatNote", iMetroBeatNote); m_settings.setValue("/BeatVelocity", iMetroBeatVelocity); m_settings.setValue("/BeatDuration", iMetroBeatDuration); m_settings.endGroup(); m_settings.endGroup(); // Options group. // Default directories. m_settings.beginGroup("/Default"); m_settings.setValue("/SessionExt", sSessionExt); m_settings.setValue("/SessionTemplate", bSessionTemplate); m_settings.setValue("/SessionTemplatePath", sSessionTemplatePath); m_settings.setValue("/SessionBackup", bSessionBackup); m_settings.setValue("/SessionBackupMode", iSessionBackupMode); m_settings.setValue("/SessionDir", sSessionDir); m_settings.setValue("/AudioDir", sAudioDir); m_settings.setValue("/MidiDir", sMidiDir); m_settings.setValue("/PresetDir", sPresetDir); m_settings.setValue("/InstrumentDir", sInstrumentDir); m_settings.setValue("/MidiControlDir", sMidiControlDir); m_settings.setValue("/MidiSysexDir", sMidiSysexDir); m_settings.setValue("/AutoMonitor", bAutoMonitor); m_settings.setValue("/SnapPerBeat", iSnapPerBeat); m_settings.setValue("/Tempo", double(fTempo)); m_settings.setValue("/BeatsPerBar", iBeatsPerBar); m_settings.setValue("/BeatDivisor", iBeatDivisor); m_settings.setValue("/LoopRecordingMode", iLoopRecordingMode); m_settings.setValue("/PasteRepeatCount", iPasteRepeatCount); m_settings.setValue("/PasteRepeatPeriod", bPasteRepeatPeriod); m_settings.setValue("/PluginSearch", sPluginSearch); m_settings.setValue("/PluginType", iPluginType); m_settings.setValue("/PluginActivate", bPluginActivate); m_settings.setValue("/CurveMode", iCurveMode); m_settings.setValue("/EditRangeOptions", iEditRangeOptions); m_settings.setValue("/MidButtonModifier", bMidButtonModifier); m_settings.endGroup(); // Plug-in paths. m_settings.beginGroup("/Plugins"); m_settings.setValue("/LadspaPaths", ladspaPaths); m_settings.setValue("/DssiPaths", dssiPaths); m_settings.setValue("/VstPaths", vstPaths); m_settings.setValue("/Lv2Paths", lv2Paths); m_settings.setValue("/Lv2PresetDir", sLv2PresetDir); m_settings.setValue("/AudioOutputBus", bAudioOutputBus); m_settings.setValue("/AudioOutputAutoConnect", bAudioOutputAutoConnect); m_settings.setValue("/OpenEditor", bOpenEditor); m_settings.setValue("/DummyVstScan", bDummyVstScan); m_settings.endGroup(); // Instrument file list. const QString sFilePrefix = "/File%1"; int iFile = 0; m_settings.beginGroup("/InstrumentFiles"); QStringListIterator iter1(instrumentFiles); while (iter1.hasNext()) m_settings.setValue(sFilePrefix.arg(++iFile), iter1.next()); // Cleanup old entries, if any... while (!m_settings.value(sFilePrefix.arg(++iFile)).isNull()) m_settings.remove(sFilePrefix.arg(iFile)); m_settings.endGroup(); // MIDI controller file list. iFile = 0; m_settings.beginGroup("/MidiControlFiles"); QStringListIterator iter2(midiControlFiles); while (iter2.hasNext()) m_settings.setValue(sFilePrefix.arg(++iFile), iter2.next()); // Cleanup old entries, if any... while (!m_settings.value(sFilePrefix.arg(++iFile)).isNull()) m_settings.remove(sFilePrefix.arg(iFile)); m_settings.endGroup(); // Recent file list. iFile = 0; m_settings.beginGroup("/RecentFiles"); QStringListIterator iter3(recentFiles); while (iter3.hasNext()) m_settings.setValue(sFilePrefix.arg(++iFile), iter3.next()); m_settings.endGroup(); // Tracks widget settings. m_settings.beginGroup("/Tracks"); m_settings.setValue("/TrackViewSelectMode", iTrackViewSelectMode); m_settings.setValue("/TrackViewDropSpan", bTrackViewDropSpan); m_settings.setValue("/TrackViewSnapZebra", bTrackViewSnapZebra); m_settings.setValue("/TrackViewSnapGrid", bTrackViewSnapGrid); m_settings.setValue("/TrackViewToolTips", bTrackViewToolTips); m_settings.setValue("/TrackViewCurveEdit", bTrackViewCurveEdit); m_settings.endGroup(); // MIDI Editor options group. m_settings.beginGroup("/MidiEditor"); m_settings.beginGroup("/View"); m_settings.setValue("/Menubar", bMidiMenubar); m_settings.setValue("/Statusbar", bMidiStatusbar); m_settings.setValue("/FileToolbar", bMidiFileToolbar); m_settings.setValue("/EditToolbar", bMidiEditToolbar); m_settings.setValue("/ViewToolbar", bMidiViewToolbar); m_settings.setValue("/TransportToolbar", bMidiTransportToolbar); m_settings.setValue("/ScaleToolbar", bMidiScaleToolbar); m_settings.setValue("/NoteDuration", bMidiNoteDuration); m_settings.setValue("/NoteColor", bMidiNoteColor); m_settings.setValue("/ValueColor", bMidiValueColor); m_settings.setValue("/Preview", bMidiPreview); m_settings.setValue("/Follow", bMidiFollow); m_settings.setValue("/EditMode", bMidiEditMode); m_settings.setValue("/EditModeDraw", bMidiEditModeDraw); m_settings.setValue("/ZoomMode", iMidiZoomMode); m_settings.setValue("/HorizontalZoom", iMidiHorizontalZoom); m_settings.setValue("/VerticalZoom", iMidiVerticalZoom); m_settings.setValue("/SnapPerBeat", iMidiSnapPerBeat); m_settings.setValue("/SnapZebra", bMidiSnapZebra); m_settings.setValue("/SnapGrid", bMidiSnapGrid); m_settings.setValue("/ToolTips", bMidiToolTips); m_settings.setValue("/SnapToScaleKey", iMidiSnapToScaleKey); m_settings.setValue("/SnapToScaleType", iMidiSnapToScaleType); m_settings.endGroup(); // Meter colors. m_settings.beginGroup("/Colors"); m_settings.setValue("/AudioMeter", audioMeterColors); m_settings.setValue("/MidiMeter", midiMeterColors); m_settings.endGroup(); m_settings.endGroup(); // Save/commit to disk. m_settings.sync(); } //------------------------------------------------------------------------- // Settings accessor. // QSettings& qtractorOptions::settings (void) { return m_settings; } //------------------------------------------------------------------------- // Command-line argument stuff. // // Help about command line options. void qtractorOptions::print_usage ( const QString& arg0 ) { QTextStream out(stderr); const QString sEot = "\n\t"; const QString sEol = "\n\n"; out << QObject::tr("Usage: %1" " [options] [session-file]").arg(arg0) + sEol; out << QTRACTOR_TITLE " - " + QObject::tr(QTRACTOR_SUBTITLE) + sEol; out << QObject::tr("Options:") + sEol; #ifdef CONFIG_JACK_SESSION out << " -s, --session-id=[uuid]" + sEot + QObject::tr("Set session identification (uuid)") + sEol; #endif out << " -h, --help" + sEot + QObject::tr("Show help about command line options") + sEol; out << " -v, --version" + sEot + QObject::tr("Show version information") + sEol; } // Parse command line arguments into m_settings. bool qtractorOptions::parse_args ( const QStringList& args ) { QTextStream out(stderr); const QString sEol = "\n\n"; int iCmdArgs = 0; int argc = args.count(); for (int i = 1; i < argc; ++i) { if (iCmdArgs > 0) { sSessionFile += ' '; sSessionFile += args.at(i); ++iCmdArgs; continue; } QString sArg = args.at(i); #ifdef CONFIG_JACK_SESSION QString sVal = QString::null; int iEqual = sArg.indexOf('='); if (iEqual >= 0) { sVal = sArg.right(sArg.length() - iEqual - 1); sArg = sArg.left(iEqual); } else if (i < argc - 1) sVal = args.at(i + 1); if (sArg == "-s" || sArg == "--session-id") { if (sVal.isNull()) { out << QObject::tr("Option -s requires an argument (session-id).") + sEol; return false; } sSessionId = sVal; if (iEqual < 0) ++i; } else #endif if (sArg == "-h" || sArg == "--help") { print_usage(args.at(0)); return false; } else if (sArg == "-v" || sArg == "--version") { out << QObject::tr("Qt: %1\n").arg(qVersion()); out << QObject::tr(QTRACTOR_TITLE ": %1\n").arg(QTRACTOR_VERSION); return false; } else { // If we don't have one by now, // this will be the startup session file... sSessionFile += sArg; ++iCmdArgs; } } // Alright with argument parsing. return true; } //--------------------------------------------------------------------------- // Widget geometry persistence helper methods. void qtractorOptions::loadWidgetGeometry ( QWidget *pWidget, bool bVisible ) { // Try to restore old form window positioning. if (pWidget) { QPoint wpos; QSize wsize; m_settings.beginGroup("/Geometry/" + pWidget->objectName()); wpos.setX(m_settings.value("/x", -1).toInt()); wpos.setY(m_settings.value("/y", -1).toInt()); wsize.setWidth(m_settings.value("/width", -1).toInt()); wsize.setHeight(m_settings.value("/height", -1).toInt()); if (!bVisible) bVisible = m_settings.value("/visible", false).toBool(); m_settings.endGroup(); if (wpos.x() > 0 && wpos.y() > 0) pWidget->move(wpos); if (wsize.width() > 0 && wsize.height() > 0) pWidget->resize(wsize); // else // pWidget->adjustSize(); if (bVisible) pWidget->show(); // else // pWidget->hide(); } } void qtractorOptions::saveWidgetGeometry ( QWidget *pWidget, bool bVisible ) { // Try to save form window position... // (due to X11 window managers ideossincrasies, we better // only save the form geometry while its up and visible) if (pWidget) { m_settings.beginGroup("/Geometry/" + pWidget->objectName()); const QPoint& wpos = pWidget->pos(); const QSize& wsize = pWidget->size(); if (!bVisible) bVisible = pWidget->isVisible(); m_settings.setValue("/x", wpos.x()); m_settings.setValue("/y", wpos.y()); m_settings.setValue("/width", wsize.width()); m_settings.setValue("/height", wsize.height()); m_settings.setValue("/visible", bVisible); m_settings.endGroup(); } } //--------------------------------------------------------------------------- // Combo box history persistence helper implementation. void qtractorOptions::loadComboBoxHistory ( QComboBox *pComboBox, int iLimit ) { // Load combobox list from configuration settings file... m_settings.beginGroup("/History/" + pComboBox->objectName()); if (m_settings.childKeys().count() > 0) { pComboBox->setUpdatesEnabled(false); pComboBox->setDuplicatesEnabled(false); pComboBox->clear(); for (int i = 0; i < iLimit; ++i) { const QString& sText = m_settings.value( "/Item" + QString::number(i + 1)).toString(); if (sText.isEmpty()) break; pComboBox->addItem(sText); } pComboBox->setUpdatesEnabled(true); } m_settings.endGroup(); } void qtractorOptions::saveComboBoxHistory ( QComboBox *pComboBox, int iLimit ) { int iCount = pComboBox->count(); // Add current text as latest item... const QString& sCurrentText = pComboBox->currentText(); if (!sCurrentText.isEmpty()) { int i = pComboBox->findText(sCurrentText); if (i >= 0) { pComboBox->removeItem(i); --iCount; } pComboBox->insertItem(0, sCurrentText); ++iCount; } // Take care of item limit... while (iCount > iLimit) pComboBox->removeItem(--iCount); // Save combobox list to configuration settings file... m_settings.beginGroup("/History/" + pComboBox->objectName()); for (int i = 0; i < iCount; ++i) { const QString& sText = pComboBox->itemText(i); if (sText.isEmpty()) continue; m_settings.setValue("/Item" + QString::number(i + 1), sText); } m_settings.endGroup(); } //--------------------------------------------------------------------------- // Splitter widget sizes persistence helper methods. void qtractorOptions::loadSplitterSizes ( QSplitter *pSplitter, QList& sizes ) { // Try to restore old splitter sizes... if (pSplitter) { m_settings.beginGroup("/Splitter/" + pSplitter->objectName()); QStringList list = m_settings.value("/sizes").toStringList(); if (!list.isEmpty()) { sizes.clear(); QStringListIterator iter(list); while (iter.hasNext()) sizes.append(iter.next().toInt()); } pSplitter->setSizes(sizes); m_settings.endGroup(); } } void qtractorOptions::saveSplitterSizes ( QSplitter *pSplitter ) { // Try to save current splitter sizes... if (pSplitter) { m_settings.beginGroup("/Splitter/" + pSplitter->objectName()); QStringList list; QList sizes = pSplitter->sizes(); QListIterator iter(sizes); while (iter.hasNext()) list.append(QString::number(iter.next())); if (!list.isEmpty()) m_settings.setValue("/sizes", list); m_settings.endGroup(); } } //--------------------------------------------------------------------------- // Action shortcut persistence helper methos. void qtractorOptions::loadActionShortcuts ( QObject *pObject ) { m_settings.beginGroup("/Shortcuts/" + pObject->objectName()); QList actions = pObject->findChildren (); QListIterator iter(actions); while (iter.hasNext()) { QAction *pAction = iter.next(); if (pAction->objectName().isEmpty()) continue; const QString& sKey = '/' + pAction->objectName(); const QString& sValue = m_settings.value('/' + sKey).toString(); if (sValue.isEmpty()) continue; pAction->setShortcut(QKeySequence(sValue)); } m_settings.endGroup(); } void qtractorOptions::saveActionShortcuts ( QObject *pObject ) { m_settings.beginGroup("/Shortcuts/" + pObject->objectName()); QList actions = pObject->findChildren (); QListIterator iter(actions); while (iter.hasNext()) { QAction *pAction = iter.next(); if (pAction->objectName().isEmpty()) continue; const QString& sKey = '/' + pAction->objectName(); const QString& sValue = pAction->shortcut().toString(); if (!sValue.isEmpty()) m_settings.setValue(sKey, sValue); else if (m_settings.contains(sKey)) m_settings.remove(sKey); } m_settings.endGroup(); } // end of qtractorOptions.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMonitor.h0000644000175000001440000000012311575731706020637 xustar000000000000000027 mtime=1308079046.654199 26 atime=1381134667.26308 30 ctime=1381134667.263080053 qtractor-0.5.11/src/qtractorMonitor.h0000644000175000001440000000424311575731706020131 0ustar00rncbcusers00000000000000// qtractorMonitor.h // /**************************************************************************** Copyright (C) 2006-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMonitor_h #define __qtractorMonitor_h #include "qtractorObserver.h" //---------------------------------------------------------------------------- // qtractorMonitor -- Monitor bridge value processor. class qtractorMonitor { public: // Constructor. qtractorMonitor(float fGain = 1.0f, float fPanning = 0.0f) : m_gain(fGain, 1.0f), m_panning(fPanning, 0.0f) { m_panning.setMinValue(-1.0f); } // Virtual destructor. virtual ~qtractorMonitor() {} // Gain accessors. qtractorSubject *gainSubject() { return &m_gain; } void setGain(float fGain) { m_gain.setValue(fGain); update(); } float gain() const { return m_gain.value(); } float prevGain() const { return m_gain.prevValue(); } // Stereo panning accessors. qtractorSubject *panningSubject() { return &m_panning; } void setPanning(float fPanning) { m_panning.setValue(fPanning); update(); } float panning() const { return m_panning.value(); } float prevPanning() const { return m_panning.prevValue(); } // Rebuild the whole panning-gain array... virtual void update() = 0; private: // Instance variables. qtractorSubject m_gain; qtractorSubject m_panning; }; #endif // __qtractorMonitor_h // end of qtractorMonitor.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorSession.h0000644000175000001440000000012312110216324020607 xustar000000000000000027 mtime=1361124564.419273 26 atime=1381134669.66908 30 ctime=1381134669.669080091 qtractor-0.5.11/src/qtractorSession.h0000644000175000001440000003325312110216324020104 0ustar00rncbcusers00000000000000// qtractorSession.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorSession_h #define __qtractorSession_h #include "qtractorAtomic.h" #include "qtractorTrack.h" #include "qtractorTimeScale.h" // Forward declarations. class qtractorClip; // Special forward declarations. class qtractorMidiEngine; class qtractorAudioEngine; class qtractorAudioPeakFactory; class qtractorSessionCursor; class qtractorSessionDocument; class qtractorMidiManager; class qtractorInstrumentList; class qtractorCommandList; class qtractorCommand; class qtractorFileList; class QDomElement; //------------------------------------------------------------------------- // qtractorSession -- Session container (singleton). class qtractorSession { public: // Default destructor. ~qtractorSession(); // Open/close session engine(s). bool init(); bool open(); void close(); // Reset session. void clear(); // Session directory path accessors. void setSessionDir(const QString& sSessionDir); const QString& sessionDir() const; // Session filename accessors. void setSessionName(const QString& sSessionName); const QString& sessionName() const; // Session description accessors. void setDescription(const QString& sDescription); const QString& description() const; // Session startlength mod-accessors. void updateSession( unsigned long iSessionStart = 0, unsigned long iSessionEnd = 0); unsigned long sessionStart() const; unsigned long sessionEnd() const; // Time-scale helper accessors. qtractorTimeScale *timeScale(); // Device engine common client name accessors. void setClientName(const QString& sClientName); const QString& clientName() const; // Sample rate accessors. void setSampleRate(unsigned int iSampleRate); unsigned int sampleRate() const; // Session tempo accessors. void setTempo(float fTempo); float tempo() const; // Tempo beat type accessors. void setBeatType(unsigned short iBeatType); unsigned short beatType() const; // Resolution accessors. void setTicksPerBeat(unsigned short iTicksPerBeat); unsigned short ticksPerBeat() const; // Beats/Bar(measure) accessors. void setBeatsPerBar(unsigned short iBeatsPerBar); unsigned short beatsPerBar() const; // Time signature (denominator) accessors. void setBeatDivisor(unsigned short iBeatDivisor); unsigned short beatDivisor() const; // Horizontal zoom factor. void setHorizontalZoom(unsigned short iHorizontalZoom); unsigned short horizontalZoom() const; // Vertical zoom factor. void setVerticalZoom(unsigned short iVerticalZoom); unsigned short verticalZoom() const; // Pixels per beat (width). void setPixelsPerBeat(unsigned short iPixelsPerBeat); unsigned short pixelsPerBeat() const; // Beat divisor (snap) accessors. void setSnapPerBeat(unsigned short iSnapPerBeat); unsigned short snapPerBeat(void) const; // Pixel/Tick number conversion. unsigned long tickFromPixel(unsigned int x); unsigned int pixelFromTick(unsigned long iTick); // Pixel/Frame number conversion. unsigned long frameFromPixel(unsigned int x) const; unsigned int pixelFromFrame(unsigned long iFrame) const; // Beat/frame conversion. unsigned long frameFromBeat(unsigned int iBeat); unsigned int beatFromFrame(unsigned long iFrame); // Tick/Frame number conversion. unsigned long frameFromTick(unsigned long iTick); unsigned long tickFromFrame(unsigned long iFrame); // Tick/Frame range conversion (delta conversion). unsigned long frameFromTickRange( unsigned long iTickStart, unsigned long iTickEnd); unsigned long tickFromFrameRange( unsigned long iFrameStart, unsigned long iFrameEnd); // Beat/frame snap filters. unsigned long tickSnap(unsigned long iTick); unsigned long frameSnap(unsigned long iFrame); unsigned int pixelSnap(unsigned int x); // Frame/locate (SMPTE) conversion. unsigned long frameFromLocate(unsigned long iLocate) const; unsigned long locateFromFrame(unsigned long iFrame) const; // Song position pointer (SPP=MIDI beats) to frame converters. unsigned long frameFromSongPos(unsigned short iSongPos); unsigned short songPosFromFrame(unsigned long iFrame); // Update time scale divisor factors. void updateTimeScale(); // Update time resolution divisor factors. void updateTimeResolution(); // Update from disparate sample-rate. void updateSampleRate(unsigned int iSampleRate); // Track list management methods. const qtractorList& tracks() const; void addTrack(qtractorTrack *pTrack); void insertTrack(qtractorTrack *pTrack, qtractorTrack *pPrevTrack = NULL); void moveTrack(qtractorTrack *pTrack, qtractorTrack *pNextTrack); void updateTrack(qtractorTrack *pTrack); void unlinkTrack(qtractorTrack *pTrack); qtractorTrack *trackAt(int iTrack) const; // Current number of record-armed tracks. void setRecordTracks(bool bRecord); unsigned int recordTracks() const; // Current number of mued tracks. void setMuteTracks(bool bMute); unsigned int muteTracks() const; // Current number of solo tracks. void setSoloTracks(bool bSolo); unsigned int soloTracks() const; // Temporary current track accessors. void setCurrentTrack(qtractorTrack *pTrack); qtractorTrack *currentTrack() const; // Temporary current track predicates. bool isTrackMonitor(qtractorTrack *pTrack) const; bool isTrackMidiChannel(qtractorTrack *pTrack, unsigned short iChannel) const; // Session cursor factory methods. qtractorSessionCursor *createSessionCursor(unsigned long iFrame = 0, qtractorTrack::TrackType syncType = qtractorTrack::None); void unlinkSessionCursor(qtractorSessionCursor *pSessionCursor); // Reset (reactivate) all plugin chains... void resetAllPlugins(); // Device engine accessors. qtractorMidiEngine *midiEngine() const; qtractorAudioEngine *audioEngine() const; // Wait for application stabilization. static void stabilize(int msecs = 20); // Consolidated session engine activation status. bool isActivated() const; // Session RT-safe pseudo-locking primitives. bool acquire(); void release(); void lock(); void unlock(); // Re-entrancy check. bool isBusy() const; // Consolidated session engine start status. void setPlaying(bool bPlaying); bool isPlaying() const; // Shutdown procedure. void shutdown(); // (Hazardous) bi-directional locate method. void seek(unsigned long iFrame, bool bSync = false); // Playhead positioning. void setPlayHead(unsigned long iFrame); unsigned long playHead() const; // Edit-head positioning. void setEditHead(unsigned long iEditHead); unsigned long editHead() const; // Edit-tail positioning. void setEditTail(unsigned long iEditTail); unsigned long editTail() const; // Session loop points accessors. void setLoop(unsigned long iLoopStart, unsigned long iLoopEnd); unsigned long loopStart() const; unsigned long loopEnd() const; bool isLooping() const; // Session punch points accessors. void setPunch(unsigned long iPunchIn, unsigned long iPunchOut); unsigned long punchIn() const; unsigned long punchOut() const; bool isPunching() const; unsigned long punchInTime() const; unsigned long punchOutTime() const; // Absolute frame time and offset. unsigned long frameTime() const; unsigned long frameTimeEx() const; // Sanitize a given name. static QString sanitize(const QString& s); // Create a brand new filename (absolute file path). QString createFilePath( const QString& sTrackName, const QString& sExt, int iClipNo = 0); // Consolidated session record state. void setRecording(bool bRecording); bool isRecording() const; // Loop-recording/take mode. void setLoopRecordingMode(int iLoopRecordingMode); int loopRecordingMode() const; // Loop-recording/take state. bool isLoopRecording() const; // Track recording specifics. unsigned short audioRecord() const; unsigned short midiRecord() const; // Special track-immediate methods. void trackRecord(qtractorTrack *pTrack, bool bRecord, unsigned long iClipStart, unsigned long iFrameTime); void trackMute(qtractorTrack *pTrack, bool bMute); void trackSolo(qtractorTrack *pTrack, bool bSolo); // Audio peak factory accessor. qtractorAudioPeakFactory *audioPeakFactory() const; // MIDI track tagging specifics. unsigned short midiTag() const; void acquireMidiTag(qtractorTrack *pTrack); void releaseMidiTag(qtractorTrack *pTrack); // MIDI session/tracks instrument/controller patching (conditional). void setMidiPatch(bool bForceImmediate); // MIDI manager list accessors. void addMidiManager(qtractorMidiManager *pMidiManager); void removeMidiManager(qtractorMidiManager *pMidiManager); const qtractorList& midiManagers() const; // Auto time-stretching global flag (when tempo changes) void setAutoTimeStretch(bool bAutoTimeStretch); bool isAutoTimeStretch() const; // Session special process cycle executive. void process(qtractorSessionCursor *pSessionCursor, unsigned long iFrameStart, unsigned long iFrameEnd); // Session special process record executive (audio recording only). void process_record( unsigned long iFrameStart, unsigned long iFrameEnd); // Session special process automation executive. void process_curve(unsigned long iFrame); // Document element methods. bool loadElement(qtractorSessionDocument *pDocument, QDomElement *pElement); bool saveElement(qtractorSessionDocument *pDocument, QDomElement *pElement); // Session property structure. struct Properties { // Default constructor. Properties() { clear(); } // Copy constructor. Properties(const Properties& props) { copy(props); } // Assignment operator, Properties& operator=(const Properties& props) { return copy(props); } // Helper copy method. Properties& copy(const Properties& props); // Helper clear/reset method. void clear(); // Members. QString sessionDir; QString sessionName; QString description; // Intrinsic time scale. qtractorTimeScale timeScale; }; // Alternate properties accessor. Properties& properties(); // Session command executive (undo/redo) bool execute(qtractorCommand *pCommand); // Session command list reference (undo/redo) qtractorCommandList *commands() const; // Instrument names mapping. qtractorInstrumentList *instruments() const; // Find track of specific curve-list. qtractorTrack *findTrack(qtractorCurveList *pCurveList) const; // Session files registry accessor. qtractorFileList *files() const; // Singleton instance accessor. static qtractorSession *getInstance(); // Singleton destroyer. static void Destroy(); protected: // Constructor. qtractorSession(); private: Properties m_props; // Session properties. unsigned long m_iSessionStart; // Session start in frames. unsigned long m_iSessionEnd; // Session end in frames. unsigned int m_iRecordTracks; // Current number of record-armed tracks. unsigned int m_iMuteTracks; // Current number of muted tracks. unsigned int m_iSoloTracks; // Current number of solo tracks. qtractorTrack *m_pCurrentTrack; // Temporary current track. // The track list. qtractorList m_tracks; // Managed session cursors. qtractorList m_cursors; // Device engine common client name. QString m_sClientName; // Device engine instances. qtractorMidiEngine *m_pMidiEngine; qtractorAudioEngine *m_pAudioEngine; // Audio peak factory (singleton) instance. qtractorAudioPeakFactory *m_pAudioPeakFactory; // Track recording counts. unsigned short m_iAudioRecord; unsigned short m_iMidiRecord; // MIDI track tagging specifics. unsigned short m_iMidiTag; QList m_midiTags; // Base edit members. unsigned long m_iEditHead; unsigned long m_iEditTail; // Session time-normalized edit points. unsigned long m_iEditHeadTime; unsigned long m_iEditTailTime; // Session loop points. unsigned long m_iLoopStart; unsigned long m_iLoopEnd; // Session time-normalized loop points. unsigned long m_iLoopStartTime; unsigned long m_iLoopEndTime; // Session punch points. unsigned long m_iPunchIn; unsigned long m_iPunchOut; // Session time-normalized punch points. unsigned long m_iPunchInTime; unsigned long m_iPunchOutTime; // Consolidated record state. bool m_bRecording; // Loop-recording/take mode. int m_iLoopRecordingMode; // Auto time-stretching global flag (when tempo changes) bool m_bAutoTimeStretch; // MIDI plugin manager list. qtractorList m_midiManagers; // RT-safeness hackish lock-mutex. qtractorAtomic m_locks; qtractorAtomic m_mutex; // Re-entrancy mutex. qtractorAtomic m_busy; // Instrument names mapping. qtractorInstrumentList *m_pInstruments; // Session command executive (undo/redo) qtractorCommandList *m_pCommands; // Curve-to-track mapping. QHash m_curves; // File registry. qtractorFileList *m_pFiles; // The singleton instance. static qtractorSession *g_pSession; }; #endif // __qtractorSession_h // end of qtractorSession.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorClipCommand.cpp0000644000175000001440000000012112165061700021711 xustar000000000000000025 mtime=1372873664.1859 26 atime=1381134670.48008 30 ctime=1381134670.480080104 qtractor-0.5.11/src/qtractorClipCommand.cpp0000644000175000001440000006213112165061700021205 0ustar00rncbcusers00000000000000// qtractorClipCommand.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorClipCommand.h" #include "qtractorTrackCommand.h" #include "qtractorMainForm.h" #include "qtractorSession.h" #include "qtractorAudioClip.h" #include "qtractorAudioEngine.h" #include "qtractorMidiEngine.h" #include "qtractorMidiClip.h" #include "qtractorFiles.h" #include "qtractorMidiEditCommand.h" #include "qtractorTimeScaleCommand.h" #include "qtractorSessionCommand.h" #include "qtractorCurveCommand.h" //---------------------------------------------------------------------- // class qtractorClipCommand - declaration. // // Constructor. qtractorClipCommand::qtractorClipCommand ( const QString& sName ) : qtractorCommand(sName) { } // Destructor. qtractorClipCommand::~qtractorClipCommand (void) { QListIterator iter(m_items); while (iter.hasNext()) { Item *pItem = iter.next(); if (pItem->takeInfo) pItem->takeInfo->releaseRef(); if (pItem->editCommand) delete pItem->editCommand; if (pItem->autoDelete) delete pItem->clip; } qDeleteAll(m_items); m_items.clear(); qDeleteAll(m_trackCommands); m_trackCommands.clear(); m_clips.clear(); } // Primitive command methods. void qtractorClipCommand::addClip ( qtractorClip *pClip, qtractorTrack *pTrack ) { m_items.append(new Item(AddClip, pClip, pTrack)); setClearSelect(true); } void qtractorClipCommand::removeClip ( qtractorClip *pClip ) { m_items.append(new Item(RemoveClip, pClip, pClip->track())); setClearSelect(true); } // Edit command methods. void qtractorClipCommand::fileClip ( qtractorClip *pClip, const QString& sFilename, unsigned short iTrackChannel ) { Item *pItem = new Item(FileClip, pClip, pClip->track()); pItem->filename = sFilename; pItem->trackChannel = iTrackChannel; m_items.append(pItem); reopenClip(pClip, true); } void qtractorClipCommand::renameClip ( qtractorClip *pClip, const QString& sClipName ) { Item *pItem = new Item(RenameClip, pClip, pClip->track()); pItem->clipName = sClipName; m_items.append(pItem); } void qtractorClipCommand::moveClip ( qtractorClip *pClip, qtractorTrack *pTrack, unsigned long iClipStart, unsigned long iClipOffset, unsigned long iClipLength ) { Item *pItem = new Item(MoveClip, pClip, pTrack); pItem->clipStart = iClipStart; pItem->clipOffset = iClipOffset; pItem->clipLength = iClipLength; if (iClipOffset == pClip->clipOffset()) pItem->fadeInLength = pClip->fadeInLength(); if (iClipOffset + iClipLength == pClip->clipOffset() + pClip->clipLength()) pItem->fadeOutLength = pClip->fadeOutLength(); m_items.append(pItem); // ATTN: when moving across tracks: // reset all take(record) descriptors... if (pTrack != pClip->track()) { qtractorClip::TakeInfo *pTakeInfo = pClip->takeInfo(); if (pTakeInfo) { pClip = pTakeInfo->clipPart(qtractorClip::TakeInfo::ClipHead); if (pClip) takeInfoClip(pClip, NULL); pClip = pTakeInfo->clipPart(qtractorClip::TakeInfo::ClipTake); if (pClip) takeInfoClip(pClip, NULL); } } setClearSelect(true); } void qtractorClipCommand::resizeClip ( qtractorClip *pClip, unsigned long iClipStart, unsigned long iClipOffset, unsigned long iClipLength, float fTimeStretch, float fPitchShift ) { Item *pItem = new Item(ResizeClip, pClip, pClip->track()); pItem->clipStart = iClipStart; pItem->clipOffset = iClipOffset; pItem->clipLength = iClipLength; long iFadeInLength = long(pClip->fadeInLength()); if (iFadeInLength > 0) { iFadeInLength += long(pClip->clipOffset()) - long(iClipOffset); if (iFadeInLength > 0) pItem->fadeInLength = iFadeInLength; } long iFadeOutLength = long(pClip->fadeOutLength()); if (iFadeOutLength > 0) { iFadeOutLength += long(iClipOffset + iClipLength) - long(pClip->clipOffset() + pClip->clipLength()); if (iFadeOutLength > 0) pItem->fadeOutLength = iFadeOutLength; } if (fTimeStretch > 0.0f) { pItem->timeStretch = fTimeStretch; switch ((pClip->track())->trackType()) { case qtractorTrack::Audio: { qtractorAudioClip *pAudioClip = static_cast (pClip); float fRatio = fTimeStretch / pAudioClip->timeStretch(); pItem->clipOffset = (unsigned long) (fRatio * float(iClipOffset)); break; } case qtractorTrack::Midi: { qtractorMidiClip *pMidiClip = static_cast (pClip); pItem->editCommand = createMidiEditCommand(pMidiClip, fTimeStretch); break; } default: break; } } if (fPitchShift > 0.0f) pItem->pitchShift = fPitchShift; m_items.append(pItem); if (pItem->editCommand == NULL) reopenClip(pClip, fTimeStretch > 0.0f); else setClearSelect(true); } void qtractorClipCommand::gainClip ( qtractorClip *pClip, float fGain ) { Item *pItem = new Item(GainClip, pClip, pClip->track()); pItem->clipGain = fGain; m_items.append(pItem); } void qtractorClipCommand::fadeInClip ( qtractorClip *pClip, unsigned long iFadeInLength, qtractorClip::FadeType fadeInType ) { Item *pItem = new Item(FadeInClip, pClip, pClip->track()); pItem->fadeInLength = iFadeInLength; pItem->fadeInType = fadeInType; m_items.append(pItem); } void qtractorClipCommand::fadeOutClip ( qtractorClip *pClip, unsigned long iFadeOutLength, qtractorClip::FadeType fadeOutType ) { Item *pItem = new Item(FadeOutClip, pClip, pClip->track()); pItem->fadeOutLength = iFadeOutLength; pItem->fadeOutType = fadeOutType; m_items.append(pItem); } void qtractorClipCommand::timeStretchClip ( qtractorClip *pClip, float fTimeStretch ) { Item *pItem = new Item(TimeStretchClip, pClip, pClip->track()); pItem->timeStretch = fTimeStretch; m_items.append(pItem); reopenClip(pClip, true); } void qtractorClipCommand::pitchShiftClip ( qtractorClip *pClip, float fPitchShift ) { Item *pItem = new Item(PitchShiftClip, pClip, pClip->track()); pItem->pitchShift = fPitchShift; m_items.append(pItem); reopenClip(pClip); } void qtractorClipCommand::takeInfoClip ( qtractorClip *pClip, qtractorClip::TakeInfo *pTakeInfo ) { Item *pItem = new Item(TakeInfoClip, pClip, pClip->track()); pItem->takeInfo = pTakeInfo; m_items.append(pItem); if (pTakeInfo) pTakeInfo->addRef(); } void qtractorClipCommand::resetClip ( qtractorClip *pClip ) { Item *pItem = new Item(ResetClip, pClip, pClip->track()); pItem->clipOffset = pClip->clipOffset(); pItem->clipLength = pClip->clipLength(); m_items.append(pItem); setClearSelect(true); } void qtractorClipCommand::reopenClip ( qtractorClip *pClip, bool bClose ) { QHash::ConstIterator iter = m_clips.constFind(pClip); if (iter == m_clips.constEnd()) m_clips.insert(pClip, bClose); setClearSelect(true); } // Special clip record nethods. bool qtractorClipCommand::addClipRecord ( qtractorTrack *pTrack, unsigned long iFrameTime ) { qtractorClip *pClip = pTrack->clipRecord(); if (pClip == NULL) return false; unsigned long iClipEnd = pTrack->clipRecordEnd(iFrameTime); unsigned long iClipStart = pClip->clipStart(); if (iClipStart >= iClipEnd) return false; // Time to close the clip... pClip->close(); // Actual clip length might have changed on close. if (pClip->clipLength() < 1) return false; // Recorded clip length and offset... unsigned long iClipLength = iClipEnd - iClipStart; unsigned long iClipOffset = 0; // Attend to audio clip record latency compensation... if (pTrack->trackType() == qtractorTrack::Audio) { qtractorAudioBus *pAudioBus = static_cast (pTrack->inputBus()); if (pAudioBus) iClipOffset += pAudioBus->latency_in(); } // Check whether in loop-recording/takes mode.... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession && pSession->isLoopRecording() && iClipEnd > pSession->loopEnd()) { qtractorClip::TakeInfo *pTakeInfo = new qtractorClip::TakeInfo( iClipStart, iClipOffset, iClipLength, pSession->loopStart(), pSession->loopEnd()); int iTake = (pSession->loopRecordingMode() == 1 ? 0 : -1); iTake = pTakeInfo->select(this, pTrack, iTake); pTakeInfo->setCurrentTake(iTake); } else addClipRecordTake(pTrack, pClip, iClipStart, iClipOffset, iClipLength); // Can get rid of the recorded clip. pTrack->setClipRecord(NULL); // Done. return true; } bool qtractorClipCommand::addClipRecordTake ( qtractorTrack *pTrack, qtractorClip *pClip, unsigned long iClipStart, unsigned long iClipOffset, unsigned long iClipLength, qtractorClip::TakePart *pTakePart ) { #ifdef CONFIG_DEBUG qDebug("qtractorClipCommand[%p]::addClipRecordTake(%p, %p, %lu, %lu, %lu, %p)", this, pTrack, pClip, iClipStart, iClipOffset, iClipLength, pTakePart); #endif // Now, its imperative to make a proper copy of those clips... // -- formerly a cloning clip factory method. // Reference for immediate file addition... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); switch (pTrack->trackType()) { case qtractorTrack::Audio: { qtractorAudioClip *pAudioClip = static_cast (pClip); if (pAudioClip) { pAudioClip = new qtractorAudioClip(*pAudioClip); pAudioClip->setClipStart(iClipStart); pAudioClip->setClipOffset(iClipOffset); pAudioClip->setClipLength(iClipLength); addClip(pAudioClip, pTrack); if (pTakePart) { takeInfoClip(pAudioClip, pTakePart->takeInfo()); pTakePart->setClip(pAudioClip); } if (pMainForm) pMainForm->addAudioFile(pAudioClip->filename()); } break; } case qtractorTrack::Midi: { qtractorMidiClip *pMidiClip = static_cast (pClip); if (pMidiClip) { pMidiClip = new qtractorMidiClip(*pMidiClip); pMidiClip->setClipStart(iClipStart); pMidiClip->setClipOffset(iClipOffset); pMidiClip->setClipLength(iClipLength); addClip(pMidiClip, pTrack); if (pTakePart) { takeInfoClip(pMidiClip, pTakePart->takeInfo()); pTakePart->setClip(pMidiClip); } if (pMainForm) pMainForm->addMidiFile(pMidiClip->filename()); } break; } default: return false; } return true; } // When new tracks are needed. void qtractorClipCommand::addTrack ( qtractorTrack *pTrack ) { m_trackCommands.append( new qtractorAddTrackCommand(pTrack)); } // When MIDI clips are stretched. qtractorMidiEditCommand *qtractorClipCommand::createMidiEditCommand ( qtractorMidiClip *pMidiClip, float fTimeStretch ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return NULL; // Make it like an undoable command... qtractorMidiEditCommand *pEditCommand = new qtractorMidiEditCommand(pMidiClip, name()); qtractorMidiSequence *pSeq = pMidiClip->sequence(); unsigned long iTimeOffset = pSeq->timeOffset(); qtractorTimeScale::Cursor cursor(pSession->timeScale()); qtractorTimeScale::Node *pNode = cursor.seekFrame(pMidiClip->clipStart()); unsigned long t0 = pNode->tickFromFrame(pMidiClip->clipStart()); unsigned long f1 = pMidiClip->clipStart() + pMidiClip->clipOffset(); pNode = cursor.seekFrame(f1); unsigned long t1 = pNode->tickFromFrame(f1); unsigned long iTimeStart = t1 - t0; iTimeStart = (iTimeStart > iTimeOffset ? iTimeStart - iTimeOffset : 0); pNode = cursor.seekFrame(f1 += pMidiClip->clipLength()); unsigned long iTimeEnd = iTimeStart + pNode->tickFromFrame(f1) - t1; for (qtractorMidiEvent *pEvent = pSeq->events().first(); pEvent; pEvent = pEvent->next()) { unsigned long iTime = pEvent->time(); if (iTime >= iTimeStart && iTime < iTimeEnd) { iTime = qtractorTimeScale::uroundf( fTimeStretch * float(iTime)); unsigned long iDuration = pEvent->duration(); if (pEvent->type() == qtractorMidiEvent::NOTEON) { iDuration = qtractorTimeScale::uroundf( fTimeStretch * float(iDuration)); } pEditCommand->resizeEventTime(pEvent, iTime, iDuration); } } // Must have brand new revision... pMidiClip->setRevision(0); // That's it... return pEditCommand; } // Composite predicate. bool qtractorClipCommand::isEmpty (void) const { return m_trackCommands.isEmpty() && m_items.isEmpty(); } // Common executive method. bool qtractorClipCommand::execute ( bool bRedo ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; pSession->lock(); QListIterator track(m_trackCommands); while (track.hasNext()) { qtractorTrackCommand *pTrackCommand = track.next(); if (bRedo) pTrackCommand->redo(); else pTrackCommand->undo(); } // Pre-close needed clips once... QHash::ConstIterator clip = m_clips.constBegin(); const QHash::ConstIterator& clip_end = m_clips.constEnd(); for ( ; clip != clip_end; ++clip) { if (clip.value()) // Scrap peak file (audio). clip.key()->close(); } QListIterator iter(m_items); while (iter.hasNext()) { Item *pItem = iter.next(); qtractorClip *pClip = pItem->clip; qtractorTrack *pTrack = pItem->track; // Execute the command item... switch (pItem->command) { case AddClip: { if (bRedo) pTrack->addClip(pClip); else pTrack->removeClip(pClip); pItem->autoDelete = !bRedo; pSession->updateTrack(pTrack); break; } case RemoveClip: { if (bRedo) pTrack->removeClip(pClip); else pTrack->addClip(pClip); pItem->autoDelete = bRedo; pSession->updateTrack(pTrack); break; } case FileClip: { QString sOldFilename = pClip->filename(); unsigned short iOldTrackChannel = 0; pClip->setFilename(pItem->filename); qtractorMidiClip *pMidiClip = NULL; if (pTrack->trackType() == qtractorTrack::Midi) pMidiClip = static_cast (pClip); if (pMidiClip) { iOldTrackChannel = pMidiClip->trackChannel(); pMidiClip->setTrackChannel(pItem->trackChannel); } //--pClip->close(); // Scrap peak file (audio). //--pClip->open(); pItem->filename = sOldFilename; if (pMidiClip) pItem->trackChannel = iOldTrackChannel; pSession->updateTrack(pTrack); break; } case RenameClip: { QString sOldName = pClip->clipName(); pClip->setClipName(pItem->clipName); pItem->clipName = sOldName; break; } case MoveClip: { qtractorTrack *pOldTrack = pClip->track(); unsigned long iOldStart = pClip->clipStart(); unsigned long iOldOffset = pClip->clipOffset(); unsigned long iOldLength = pClip->clipLength(); unsigned long iOldFadeIn = pClip->fadeInLength(); unsigned long iOldFadeOut = pClip->fadeOutLength(); pOldTrack->removeClip(pClip); pClip->setClipStart(pItem->clipStart); pClip->setClipOffset(pItem->clipOffset); pClip->setClipLength(pItem->clipLength); pClip->setFadeInLength(pItem->fadeInLength); pClip->setFadeOutLength(pItem->fadeOutLength); pTrack->addClip(pClip); pItem->track = pOldTrack; pItem->clipStart = iOldStart; pItem->clipOffset = iOldOffset; pItem->clipLength = iOldLength; pItem->fadeInLength = iOldFadeIn; pItem->fadeOutLength = iOldFadeOut; if (pOldTrack != pTrack) pSession->updateTrack(pOldTrack); pSession->updateTrack(pTrack); break; } case ResizeClip: { unsigned long iOldStart = pClip->clipStart(); unsigned long iOldOffset = pClip->clipOffset(); unsigned long iOldLength = pClip->clipLength(); unsigned long iOldFadeIn = pClip->fadeInLength(); unsigned long iOldFadeOut = pClip->fadeOutLength(); float fOldTimeStretch = 0.0f; float fOldPitchShift = 0.0f; qtractorAudioClip *pAudioClip = NULL; if (pTrack->trackType() == qtractorTrack::Audio) { pAudioClip = static_cast (pClip); if (pAudioClip) { if (pItem->timeStretch > 0.0f) { fOldTimeStretch = pAudioClip->timeStretch(); //--pAudioClip->close(); // Scrap peak file. } if (pItem->pitchShift > 0.0f) fOldPitchShift = pAudioClip->pitchShift(); } } //--else //--if (pItem->editCommand == NULL) //-- pClip->close(); if (iOldStart != pItem->clipStart) pTrack->unlinkClip(pClip); pClip->setClipStart(pItem->clipStart); pClip->setClipOffset(pItem->clipOffset); pClip->setClipLength(pItem->clipLength); pClip->setFadeInLength(pItem->fadeInLength); pClip->setFadeOutLength(pItem->fadeOutLength); if (pAudioClip) { if (pItem->timeStretch > 0.0f) { pAudioClip->setTimeStretch(pItem->timeStretch); pItem->timeStretch = fOldTimeStretch; } if (pItem->pitchShift > 0.0f) { pAudioClip->setPitchShift(pItem->pitchShift); pItem->pitchShift = fOldPitchShift; } } if (pItem->editCommand) { if (bRedo) (pItem->editCommand)->redo(); else (pItem->editCommand)->undo(); } //--else pClip->open(); if (iOldStart != pItem->clipStart) pTrack->insertClip(pClip); pItem->clipStart = iOldStart; pItem->clipOffset = iOldOffset; pItem->clipLength = iOldLength; pItem->fadeInLength = iOldFadeIn; pItem->fadeOutLength = iOldFadeOut; pSession->updateTrack(pTrack); break; } case GainClip: { float fOldGain = pClip->clipGain(); pClip->setClipGain(pItem->clipGain); pItem->clipGain = fOldGain; break; } case FadeInClip: { unsigned long iOldFadeIn = pClip->fadeInLength(); qtractorClip::FadeType oldFadeInType = pClip->fadeInType(); pClip->setFadeInType(pItem->fadeInType); pClip->setFadeInLength(pItem->fadeInLength); pItem->fadeInLength = iOldFadeIn; pItem->fadeInType = oldFadeInType; break; } case FadeOutClip: { unsigned long iOldFadeOut = pClip->fadeOutLength(); qtractorClip::FadeType oldFadeOutType = pClip->fadeOutType(); pClip->setFadeOutType(pItem->fadeOutType); pClip->setFadeOutLength(pItem->fadeOutLength); pItem->fadeOutLength = iOldFadeOut; pItem->fadeOutType = oldFadeOutType; break; } case TimeStretchClip: { qtractorAudioClip *pAudioClip = NULL; if (pTrack->trackType() == qtractorTrack::Audio) pAudioClip = static_cast (pClip); if (pAudioClip) { float fOldTimeStretch = pAudioClip->timeStretch(); pAudioClip->setTimeStretch(pItem->timeStretch); //--pAudioClip->close(); // Scrap peak file. pAudioClip->updateClipTime(); // Care of tempo change. //--pAudioClip->open(); pItem->timeStretch = fOldTimeStretch; } break; } case PitchShiftClip: { qtractorAudioClip *pAudioClip = NULL; if (pTrack->trackType() == qtractorTrack::Audio) pAudioClip = static_cast (pClip); if (pAudioClip) { float fOldPitchShift = pAudioClip->pitchShift(); pAudioClip->setPitchShift(pItem->pitchShift); //--pAudioClip->open(); pItem->pitchShift = fOldPitchShift; } break; } case TakeInfoClip: { qtractorClip::TakeInfo *pTakeInfo = pClip->takeInfo(); if (pTakeInfo) pTakeInfo->addRef(); pClip->setTakeInfo(pItem->takeInfo); if (pItem->takeInfo) pItem->takeInfo->releaseRef(); pItem->takeInfo = pTakeInfo; break; } case ResetClip: { unsigned long iClipStartTime = pClip->clipStartTime(); unsigned long iClipOffsetTime = pClip->clipOffsetTime(); unsigned long iClipLengthTime = pClip->clipLengthTime(); pClip->setClipOffset(pItem->clipOffset); pClip->setClipLength(pItem->clipLength); pItem->clipOffset = pSession->frameFromTickRange( iClipStartTime, iClipStartTime + iClipOffsetTime); pItem->clipLength = pSession->frameFromTickRange( iClipStartTime, iClipStartTime + iClipLengthTime); break; } default: break; } } // Re-open needed clips, just once... for (clip = m_clips.constBegin(); clip != m_clips.constEnd(); ++clip) clip.key()->open(); pSession->unlock(); return true; } // Virtual command methods. bool qtractorClipCommand::redo (void) { return execute(true); } bool qtractorClipCommand::undo (void) { return execute(false); } //---------------------------------------------------------------------- // class qtractorClipTakeCommand - declaration. // // Constructor. qtractorClipTakeCommand::qtractorClipTakeCommand ( qtractorClip::TakeInfo *pTakeInfo, qtractorTrack *pTrack, int iCurrentTake ) : qtractorClipCommand(QString()), m_pTakeInfo(pTakeInfo), m_iCurrentTake(iCurrentTake) { if (pTrack) qtractorCommand::setName(QObject::tr("take %1").arg(iCurrentTake + 1)); else qtractorCommand::setName(QObject::tr("reset takes")); if (pTrack && iCurrentTake >= 0) m_pTakeInfo->select(this, pTrack, iCurrentTake); else m_pTakeInfo->reset(this, pTrack == NULL); } // Executive override. bool qtractorClipTakeCommand::execute ( bool bRedo ) { int iCurrentTake = m_pTakeInfo->currentTake(); m_pTakeInfo->setCurrentTake(m_iCurrentTake); m_iCurrentTake = iCurrentTake;; return qtractorClipCommand::execute(bRedo); } //---------------------------------------------------------------------- // class qtractorClipRangeCommand - declaration. // // Constructor. qtractorClipRangeCommand::qtractorClipRangeCommand ( const QString& sName ) : qtractorClipCommand(sName) { } // Destructor. qtractorClipRangeCommand::~qtractorClipRangeCommand (void) { qDeleteAll(m_sessionCommands); m_sessionCommands.clear(); qDeleteAll(m_curveEditCommands); m_curveEditCommands.clear(); qDeleteAll(m_timeScaleMarkerCommands); m_timeScaleMarkerCommands.clear(); qDeleteAll(m_timeScaleNodeCommands); m_timeScaleNodeCommands.clear(); } // When Loop/Punch changes are needed. void qtractorClipRangeCommand::addSessionCommand ( qtractorSessionCommand *pSessionCommand ) { m_sessionCommands.append(pSessionCommand); } // When automation curves are needed. void qtractorClipRangeCommand::addCurveEditCommand ( qtractorCurveEditCommand *pCurveEditCommand ) { m_curveEditCommands.append(pCurveEditCommand); } // When location markers are needed. void qtractorClipRangeCommand::addTimeScaleMarkerCommand ( qtractorTimeScaleMarkerCommand *pTimeScaleMarkerCommand ) { m_timeScaleMarkerCommands.append(pTimeScaleMarkerCommand); } // When tempo-map/time-sig nodes are needed. void qtractorClipRangeCommand::addTimeScaleNodeCommand ( qtractorTimeScaleNodeCommand *pTimeScaleNodeCommand ) { m_timeScaleNodeCommands.append(pTimeScaleNodeCommand); } // Executive override. bool qtractorClipRangeCommand::execute ( bool bRedo ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // Loop/Punch... if (!m_sessionCommands.isEmpty()) { QListIterator iter(m_sessionCommands); while (iter.hasNext()) { qtractorSessionCommand *pSessionCommand = iter.next(); if (bRedo) pSessionCommand->redo(); else pSessionCommand->undo(); } } // Automation... if (!m_curveEditCommands.isEmpty()) { QListIterator curve_iter(m_curveEditCommands); if (bRedo) { while (curve_iter.hasNext()) { qtractorCurveEditCommand *pCurveEditCommand = curve_iter.next(); pCurveEditCommand->redo(); pCurveEditCommand->curve()->update(); } } else { curve_iter.toBack(); while (curve_iter.hasPrevious()) { qtractorCurveEditCommand *pCurveEditCommand = curve_iter.previous(); pCurveEditCommand->undo(); pCurveEditCommand->curve()->update(); } } } // Markers... if (!m_timeScaleMarkerCommands.isEmpty()) { QListIterator marker_iter(m_timeScaleMarkerCommands); if (bRedo) { while (marker_iter.hasNext()) { qtractorTimeScaleMarkerCommand *pTimeScaleMarkerCommand = marker_iter.next(); pTimeScaleMarkerCommand->redo(); } } else { marker_iter.toBack(); while (marker_iter.hasPrevious()) { qtractorTimeScaleMarkerCommand *pTimeScaleMarkerCommand = marker_iter.previous(); pTimeScaleMarkerCommand->undo(); } } } // Time-map... if (!m_timeScaleNodeCommands.isEmpty()) { // If currently playing, we need to do a stop and go... bool bPlaying = pSession->isPlaying(); if (bPlaying) pSession->lock(); QListIterator node_iter(m_timeScaleNodeCommands); if (bRedo) { while (node_iter.hasNext()) { qtractorTimeScaleNodeCommand *pTimeScaleNodeCommand = node_iter.next(); pTimeScaleNodeCommand->redo(); } } else { node_iter.toBack(); while (node_iter.hasPrevious()) { qtractorTimeScaleNodeCommand *pTimeScaleNodeCommand = node_iter.previous(); pTimeScaleNodeCommand->undo(); } } // Restore playback state, if needed... if (bPlaying) { // The Audio engine too... if (pSession->audioEngine()) pSession->audioEngine()->resetMetro(); // The MIDI engine queue needs a reset... if (pSession->midiEngine()) pSession->midiEngine()->resetTempo(); pSession->unlock(); } } // Clips... return qtractorClipCommand::execute(bRedo); } // end of qtractorClipCommand.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorClipSelect.cpp0000644000175000001440000000012312214366354021564 xustar000000000000000027 mtime=1379003628.863677 26 atime=1381134666.49308 30 ctime=1381134666.494080041 qtractor-0.5.11/src/qtractorClipSelect.cpp0000644000175000001440000001054412214366354021057 0ustar00rncbcusers00000000000000// qtractorClipSelect.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorClipSelect.h" #include "qtractorSession.h" #include "qtractorTrack.h" #include "qtractorClip.h" //------------------------------------------------------------------------- // qtractorClipSelect -- Track clip selection capsule. // Constructor. qtractorClipSelect::qtractorClipSelect (void) { m_bTrackSingle = false; m_pTrackSingle = NULL; } // Default constructor. qtractorClipSelect::~qtractorClipSelect (void) { clear(); } // Clip selection method. void qtractorClipSelect::selectItem ( qtractorClip *pClip, const QRect& rect, bool bSelect ) { // Add/remove clip selection... Item *pClipItem = NULL; ItemList::Iterator iter = m_items.find(pClip); if (iter != m_items.end()) pClipItem = iter.value(); if (pClipItem && !bSelect) { iter = m_items.erase(iter); delete pClipItem; pClip->setClipSelected(false); m_bTrackSingle = false; // Reset united selection rectangle... m_rect.setRect(0, 0, 0, 0); const ItemList::Iterator& iter_end = m_items.end(); for (iter = m_items.begin(); iter != iter_end; ++iter) m_rect = m_rect.united(iter.value()->rectClip); // Done with clip deselection. } else if (bSelect) { pClip->setClipSelected(true); if (pClipItem) pClipItem->rectClip = rect; else m_items.insert(pClip, new Item(rect)); // Special optimization: no need to recache // our single track reference if we add some outsider clip... if (m_bTrackSingle) { if (m_pTrackSingle && m_pTrackSingle != pClip->track()) m_pTrackSingle = NULL; } else if (m_pTrackSingle == NULL) { m_pTrackSingle = pClip->track(); m_bTrackSingle = true; } // Unite whole selection reactangular area... m_rect = m_rect.united(rect); } } // Clip addition (no actual selection). void qtractorClipSelect::addItem ( qtractorClip *pClip, const QRect& rect ) { m_items.insert(pClip, new Item(rect)); m_rect = m_rect.united(rect); } // The united selection rectangle. const QRect& qtractorClipSelect::rect (void) const { return m_rect; } // Dynamic helper: // Do all selected clips belong to the same track? qtractorTrack *qtractorClipSelect::singleTrack (void) { // Check if predicate is already cached... if (!m_bTrackSingle) { m_pTrackSingle = NULL; ItemList::ConstIterator iter = m_items.constBegin(); const ItemList::ConstIterator& iter_end = m_items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorClip *pClip = iter.key(); if (m_pTrackSingle == NULL) m_pTrackSingle = pClip->track(); else if (m_pTrackSingle != pClip->track()) { m_pTrackSingle = NULL; break; } } m_bTrackSingle = true; } // Return current selected single track (if any)... return m_pTrackSingle; } // Selection list accessor. const qtractorClipSelect::ItemList& qtractorClipSelect::items (void) const { return m_items; } // Clip selection item lookup. qtractorClipSelect::Item *qtractorClipSelect::findItem ( qtractorClip *pClip ) const { return m_items.value(pClip, NULL); } // Reset clip selection. void qtractorClipSelect::reset (void) { m_bTrackSingle = false; m_pTrackSingle = NULL; m_rect.setRect(0, 0, 0, 0); qDeleteAll(m_items); m_items.clear(); } // Clear clip selection. void qtractorClipSelect::clear (void) { ItemList::ConstIterator iter = m_items.constBegin(); const ItemList::ConstIterator& iter_end = m_items.constEnd(); for ( ; iter != iter_end; ++iter) iter.key()->setClipSelected(false); reset(); } // end of qtractorClipSelect.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorFileList.cpp0000644000175000001440000000012312141747305021246 xustar000000000000000027 mtime=1367854789.991712 26 atime=1381134667.31508 30 ctime=1381134667.315080054 qtractor-0.5.11/src/qtractorFileList.cpp0000644000175000001440000001225012141747305020535 0ustar00rncbcusers00000000000000// qtractorFileList.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorFileList.h" #include "qtractorFileListView.h" #include "qtractorClip.h" #include //--------------------------------------------------------------------- // class qtractorFileList::Key -- file hash key. // uint qHash ( const qtractorFileList::Key& key ) { return qHash(key.type()) ^ qHash(key.path()); } //---------------------------------------------------------------------- // class qtractorFileList -- file path registry. // // File path registry management. qtractorFileListItem *qtractorFileList::findFileItem ( qtractorFileList::Type iType, const QString& sPath ) const { Item *pItem = findItem(iType, sPath); return (pItem ? pItem->fileItem() : NULL); } void qtractorFileList::addFileItem ( qtractorFileList::Type iType, qtractorFileListItem *pFileItem, bool bAutoRemove ) { Item *pItem = addItem(iType, pFileItem->path(), bAutoRemove); if (pItem) { pItem->setFileItem(pFileItem); #ifdef CONFIG_DEBUG_0 qDebug("qtractorFileList::addFileItem(%d, \"%s\") refCount=%d clips=%d (%d)", int(pItem->type()), pItem->path().toUtf8().constData(), pItem->refCount(), pItem->clipRefCount(), int(pItem->isAutoRemove())); #endif } } void qtractorFileList::removeFileItem ( qtractorFileList::Type iType, qtractorFileListItem *pFileItem ) { Item *pItem = findItem(iType, pFileItem->path()); if (pItem) { pItem->setFileItem(NULL); #ifdef CONFIG_DEBUG_0 qDebug("qtractorFileList::removeFileItem(%d, \"%s\") refCount=%d clips=%d (%d)", int(pItem->type()), pItem->path().toUtf8().constData(), pItem->refCount() - 1, pItem->clipRefCount(), int(pItem->isAutoRemove())); #endif removeItem(pItem); } } // Clip/path registry management. void qtractorFileList::addClipItem ( qtractorFileList::Type iType, qtractorClip *pClip, bool bAutoRemove ) { Item *pItem = addItem(iType, pClip->filename(), bAutoRemove); if (pItem) { pItem->addClipRef(); #ifdef CONFIG_DEBUG_0 qDebug("qtractorFileList::addClipItem(%d, \"%s\") refCount=%d clips=%d (%d)", int(pItem->type()), pItem->path().toUtf8().constData(), pItem->refCount(), pItem->clipRefCount(), int(pItem->isAutoRemove())); #endif } } void qtractorFileList::removeClipItem ( qtractorFileList::Type iType, qtractorClip *pClip ) { Item *pItem = findItem(iType, pClip->filename()); if (pItem) { pItem->removeClipRef(); #ifdef CONFIG_DEBUG_0 qDebug("qtractorFileList::removeClipItem(%d, \"%s\") refCount=%d clips=%d (%d)", int(pItem->type()), pItem->path().toUtf8().constData(), pItem->refCount() - 1, pItem->clipRefCount(), int(pItem->isAutoRemove())); #endif removeItem(pItem); } } // File hash table management. qtractorFileList::Item *qtractorFileList::findItem ( qtractorFileList::Type iType, const QString& sPath ) const { return m_items.value(Key(iType, sPath), NULL); } qtractorFileList::Item *qtractorFileList::addItem ( qtractorFileList::Type iType, const QString& sPath, bool bAutoRemove ) { Item *pItem = NULL; Key key(iType, sPath); Hash::ConstIterator iter = m_items.constFind(key); if (iter == m_items.constEnd()) { pItem = new Item(key, bAutoRemove); m_items.insert(key, pItem); if (bAutoRemove) // HACK! pItem->addRef(); } else pItem = iter.value(); pItem->addRef(); return pItem; } void qtractorFileList::removeItem ( qtractorFileList::Item *pItem ) { pItem->removeRef(); if (pItem->refCount() < 1) { m_items.remove(Key(pItem->type(), pItem->path())); delete pItem; } } void qtractorFileList::cleanup ( bool bForce ) { Hash::ConstIterator iter = m_items.constBegin(); const Hash::ConstIterator& iter_end = m_items.constEnd(); for ( ; iter != iter_end; ++iter) { Item *pItem = iter.value(); if (pItem->isAutoRemove()) { const QString& sPath = pItem->path(); #ifdef CONFIG_DEBUG_0 qDebug("qtractorFileList::cleanup(%d, \"%s\") refCount=%d clips=%d", int(pItem->type()), pItem->path().toUtf8().constData(), pItem->refCount(), pItem->clipRefCount()); #endif if (!bForce && pItem->clipRefCount() > 0) { pItem->setAutoRemove(false); pItem->removeRef(); } // Time for the kill...? if (bForce) QFile::remove(sPath); } } } void qtractorFileList::clear (void) { qDeleteAll(m_items); m_items.clear(); } // end of qtractorFileList.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorCurveFile.cpp0000644000175000001440000000012211660274744021425 xustar000000000000000027 mtime=1321302500.982775 26 atime=1381134670.83808 29 ctime=1381134670.83808011 qtractor-0.5.11/src/qtractorCurveFile.cpp0000644000175000001440000002017511660274744020722 0ustar00rncbcusers00000000000000// qtractorCurveFile.cpp // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorCurveFile.h" #include "qtractorDocument.h" #include "qtractorTimeScale.h" #include "qtractorMidiFile.h" #include "qtractorMidiControl.h" #include #include //---------------------------------------------------------------------- // class qtractorCurveFile -- Automation curve file interface impl. // // Curve item list serialization methods. void qtractorCurveFile::load ( QDomElement *pElement ) { clear(); for (QDomNode nChild = pElement->firstChild(); !nChild.isNull(); nChild = nChild.nextSibling()) { // Convert node to element, if any. QDomElement eChild = nChild.toElement(); if (eChild.isNull()) continue; // Check for child item... if (eChild.tagName() == "filename") m_sFilename = eChild.text(); else if (eChild.tagName() == "current") m_iCurrentCurve = eChild.text().toInt(); else if (eChild.tagName() == "curve-items") { for (QDomNode nItem = eChild.firstChild(); !nItem.isNull(); nItem = nItem.nextSibling()) { // Convert node to element, if any. QDomElement eItem = nItem.toElement(); if (eItem.isNull()) continue; // Check for controller item... if (eItem.tagName() == "curve-item") { Item *pItem = new Item; pItem->name = eItem.attribute("name"); pItem->index = eItem.attribute("index").toULong(); pItem->mode = modeFromText(eItem.attribute("mode")); pItem->process = false; // Defaults. pItem->capture = false; pItem->locked = false; pItem->logarithmic = false; for (QDomNode nProp = eItem.firstChild(); !nProp.isNull(); nProp = nProp.nextSibling()) { // Convert node to element, if any. QDomElement eProp = nProp.toElement(); if (eProp.isNull()) continue; // Check for property item... if (eProp.tagName() == "type") pItem->ctype = qtractorMidiControl::typeFromText(eProp.text()); if (eProp.tagName() == "channel") pItem->channel = eProp.text().toUShort(); else if (eProp.tagName() == "param") pItem->param = eProp.text().toUShort(); else if (eProp.tagName() == "process") pItem->process = qtractorDocument::boolFromText(eProp.text()); else if (eProp.tagName() == "capture") pItem->capture = qtractorDocument::boolFromText(eProp.text()); else if (eProp.tagName() == "locked") pItem->locked = qtractorDocument::boolFromText(eProp.text()); else if (eProp.tagName() == "logarithmic") pItem->logarithmic = qtractorDocument::boolFromText(eProp.text()); else if (eProp.tagName() == "color") pItem->color.setNamedColor(eProp.text()); } pItem->subject = NULL; addItem(pItem); } } } } } void qtractorCurveFile::save ( qtractorDocument *pDocument, QDomElement *pElement, qtractorTimeScale *pTimeScale ) const { if (m_pCurveList == NULL) return; unsigned short iSeq; unsigned short iSeqs = m_items.count(); if (iSeqs < 1) return; qtractorMidiFile file; if (!file.open(m_sFilename, qtractorMidiFile::Write)) return; unsigned short iTicksPerBeat = pTimeScale->ticksPerBeat(); qtractorMidiSequence **ppSeqs = new qtractorMidiSequence * [iSeqs]; for (iSeq = 0; iSeq < iSeqs; ++iSeq) ppSeqs[iSeq] = new qtractorMidiSequence(QString(), 0, iTicksPerBeat); iSeq = 0; int iCurrent = -1; QDomElement eItems = pDocument->document()->createElement("curve-items"); QListIterator iter(m_items); while (iter.hasNext()) { Item *pItem = iter.next(); qtractorCurve *pCurve = (pItem->subject)->curve(); if (pCurve && !pCurve->isEmpty()) { qtractorMidiSequence *pSeq = ppSeqs[iSeq]; pCurve->writeMidiSequence(pSeq, pItem->ctype, pItem->channel, pItem->param, pTimeScale); QDomElement eItem = pDocument->document()->createElement("curve-item"); eItem.setAttribute("name", pItem->name); eItem.setAttribute("index", QString::number(pItem->index)); eItem.setAttribute("mode", textFromMode(pItem->mode)); pDocument->saveTextElement("type", qtractorMidiControl::textFromType(pItem->ctype), &eItem); pDocument->saveTextElement("channel", QString::number(pItem->channel), &eItem); pDocument->saveTextElement("param", QString::number(pItem->param), &eItem); pDocument->saveTextElement("mode", textFromMode(pItem->mode), &eItem); pDocument->saveTextElement("process", pDocument->textFromBool(pItem->process), &eItem); pDocument->saveTextElement("capture", pDocument->textFromBool(pItem->capture), &eItem); pDocument->saveTextElement("locked", pDocument->textFromBool(pItem->locked), &eItem); pDocument->saveTextElement("logarithmic", pDocument->textFromBool(pItem->logarithmic), &eItem); pDocument->saveTextElement("color", pItem->color.name(), &eItem); if (m_pCurveList->currentCurve() == pCurve) iCurrent = pItem->index; eItems.appendChild(eItem); } ++iSeq; } pElement->appendChild(eItems); file.writeHeader(1, iSeqs, iTicksPerBeat); file.writeTracks(ppSeqs, iSeqs); file.close(); for (iSeq = 0; iSeq < iSeqs; ++iSeq) delete ppSeqs[iSeq]; delete [] ppSeqs; const QString& sFilename = QDir(m_sBaseDir).relativeFilePath(m_sFilename); pDocument->saveTextElement("filename", pDocument->addFile(sFilename), pElement); if (iCurrent >= 0) { pDocument->saveTextElement("current", QString::number(iCurrent), pElement); } } void qtractorCurveFile::apply ( qtractorTimeScale *pTimeScale ) { if (m_pCurveList == NULL) return; const QString& sFilename = QDir(m_sBaseDir).absoluteFilePath(m_sFilename); qtractorMidiFile file; if (!file.open(sFilename, qtractorMidiFile::Read)) return; unsigned short iSeq = 0; unsigned short iTicksPerBeat = pTimeScale->ticksPerBeat(); qtractorCurve *pCurrentCurve = NULL; QListIterator iter(m_items); while (iter.hasNext()) { Item *pItem = iter.next(); qtractorCurve *pCurve = (pItem->subject)->curve(); if (pCurve == NULL) pCurve = new qtractorCurve(m_pCurveList, pItem->subject, pItem->mode); if (m_iCurrentCurve == int(pItem->index)) pCurrentCurve = pCurve; qtractorMidiSequence seq(QString(), pItem->channel, iTicksPerBeat); if (file.readTrack(&seq, iSeq)) { pCurve->readMidiSequence(&seq, pItem->ctype, pItem->channel, pItem->param, pTimeScale); } pCurve->setProcess(pItem->process); pCurve->setCapture(pItem->capture); pCurve->setLocked(pItem->locked); pCurve->setLogarithmic(pItem->logarithmic); pCurve->setColor(pItem->color); ++iSeq; } file.close(); if (pCurrentCurve) m_pCurveList->setCurrentCurve(pCurrentCurve); clear(); } // Text/curve-mode converters... qtractorCurve::Mode qtractorCurveFile::modeFromText ( const QString& sText ) { qtractorCurve::Mode mode = qtractorCurve::Hold; if (sText == "Spline") mode = qtractorCurve::Spline; else if (sText == "Linear") mode = qtractorCurve::Linear; return mode; } QString qtractorCurveFile::textFromMode ( qtractorCurve::Mode mode ) { QString sText; switch (mode) { case qtractorCurve::Spline: sText = "Spline"; break; case qtractorCurve::Linear: sText = "Linear"; break; case qtractorCurve::Hold: default: sText = "Hold"; break; } return sText; } // end of qtractorCurveFile.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorFileList.h0000644000175000001440000000012312141747305020713 xustar000000000000000027 mtime=1367854789.991712 26 atime=1381134667.10808 30 ctime=1381134667.108080051 qtractor-0.5.11/src/qtractorFileList.h0000644000175000001440000000777612141747305020223 0ustar00rncbcusers00000000000000// qtractorFileList.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorFileList_h #define __qtractorFileList_h #include #include // Forward declarations. class qtractorFileListItem; class qtractorClip; //---------------------------------------------------------------------- // class qtractorFileList -- file path registry. // class qtractorFileList { public: // Constructor. qtractorFileList() {} // Destructor. ~qtractorFileList() { clear(); } // File types. enum Type { Audio = 0, Midi = 1 }; // File hash key. // class Key { public: // Constructors. Key(Type iType, const QString& sPath) : m_iType(iType), m_sPath(sPath) {} Key(const Key& key) : m_iType(key.type()), m_sPath(key.path()) {} // Key accessors. Type type() const { return m_iType; } const QString& path() const { return m_sPath; } // Match descriminator. bool operator== (const Key& other) const { return m_iType == other.type() && m_sPath == other.path(); } private: // Interesting variables. Type m_iType; QString m_sPath; }; // File hash item. // class Item { public: // Constructor. Item(const Key& key, bool bAutoRemove = false) : m_key(key), m_bAutoRemove(bAutoRemove), m_pFileItem(0), m_iClipRefCount(0), m_iRefCount(0) {} // Key accessors. Type type() const { return m_key.type(); } const QString& path() const { return m_key.path(); } // Auto-destruction flag accessor. void setAutoRemove(bool bAutoRemove) { m_bAutoRemove = bAutoRemove; } bool isAutoRemove() const { return m_bAutoRemove; } // Payload accessors. void setFileItem(qtractorFileListItem *pFileItem) { m_pFileItem = pFileItem; } qtractorFileListItem *fileItem() const { return m_pFileItem; } // Clip ref-counting methods. void addClipRef() { ++m_iClipRefCount; } void removeClipRef() { --m_iClipRefCount; } unsigned int clipRefCount() const { return m_iClipRefCount; } // Ref-counting methods. unsigned int refCount() const { return m_iRefCount; } void addRef() { ++m_iRefCount; } void removeRef() { --m_iRefCount; } private: // Most interesting variables. Key m_key; bool m_bAutoRemove; qtractorFileListItem *m_pFileItem; unsigned int m_iClipRefCount; unsigned int m_iRefCount; }; typedef QHash Hash; // File/path registry management. qtractorFileListItem *findFileItem(Type iType, const QString& sPath) const; void addFileItem(Type iType, qtractorFileListItem *pFileItem, bool bAutoRemove); void removeFileItem(Type iType, qtractorFileListItem *pFileItem); // Clip/path registry management. void addClipItem(Type iType, qtractorClip *pClip, bool bAutoRemove = false); void removeClipItem(Type iType, qtractorClip *pClip); Item *findItem(Type iType, const QString& sPath) const; // Cleanup (dtors). void cleanup(bool bForce); void clear(); protected: // File hash table management. Item *addItem(Type iType, const QString& sPath, bool bAutoRemove); void removeItem(Item *pItem); private: // File hash table. Hash m_items; }; #endif // __qtractorFileList_h // end of qtractorFileList.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorInsertPlugin.cpp0000644000175000001440000000012312215372276022161 xustar000000000000000027 mtime=1379267774.934138 26 atime=1381134667.96808 30 ctime=1381134667.968080064 qtractor-0.5.11/src/qtractorInsertPlugin.cpp0000644000175000001440000004437412215372276021464 0ustar00rncbcusers00000000000000// qtractorInsertPlugin.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. Copyright (C) 2011, Holger Dehnhardt. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorInsertPlugin.h" #include "qtractorSession.h" #include "qtractorAudioEngine.h" #include "qtractorPluginListView.h" #if defined(__SSE__) #include // SSE detection. static inline bool sse_enabled (void) { #if defined(__GNUC__) unsigned int eax, ebx, ecx, edx; #if defined(__x86_64__) || (!defined(PIC) && !defined(__PIC__)) __asm__ __volatile__ ( "cpuid\n\t" \ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ : "a" (1) : "cc"); #else __asm__ __volatile__ ( "push %%ebx\n\t" \ "cpuid\n\t" \ "movl %%ebx,%1\n\t" \ "pop %%ebx\n\t" \ : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) \ : "a" (1) : "cc"); #endif return (edx & (1 << 25)); #else return false; #endif } // SSE enabled processor versions. static inline void sse_process_send_gain ( float **ppFrames, unsigned int iFrames, unsigned short iChannels, float fGain ) { __m128 v0 = _mm_load_ps1(&fGain); for (unsigned short i = 0; i < iChannels; ++i) { float *pFrames = ppFrames[i]; unsigned int nframes = iFrames; for (; (long(pFrames) & 15) && (nframes > 0); --nframes) *pFrames++ *= fGain; for (; nframes >= 4; nframes -= 4) { _mm_store_ps(pFrames, _mm_mul_ps( _mm_loadu_ps(pFrames), v0 ) ); pFrames += 4; } for (; nframes > 0; --nframes) *pFrames++ *= fGain; } } static inline void sse_process_dry_wet ( float **ppBuffer, float **ppFrames, unsigned int iFrames, unsigned short iChannels, float fGain ) { __m128 v0 = _mm_load_ps1(&fGain); for (unsigned short i = 0; i < iChannels; ++i) { float *pBuffer = ppBuffer[i]; float *pFrames = ppFrames[i]; unsigned int nframes = iFrames; for (; (long(pBuffer) & 15) && (nframes > 0); --nframes) *pBuffer++ += fGain * *pFrames++; for (; nframes >= 4; nframes -= 4) { _mm_store_ps(pBuffer, _mm_add_ps( _mm_loadu_ps(pBuffer), _mm_mul_ps( _mm_loadu_ps(pFrames), v0) ) ); pFrames += 4; pBuffer += 4; } for (; nframes > 0; --nframes) *pBuffer++ += fGain * *pFrames++; } } #endif // Standard processor versions. static inline void std_process_send_gain ( float **ppFrames, unsigned int iFrames, unsigned short iChannels, float fGain ) { for (unsigned short i = 0; i < iChannels; ++i) { float *pFrames = ppFrames[i]; for (unsigned int n = 0; n < iFrames; ++n) *pFrames++ *= fGain; } } static inline void std_process_dry_wet ( float **ppBuffer, float **ppFrames, unsigned int iFrames, unsigned short iChannels, float fGain ) { for (unsigned short i = 0; i < iChannels; ++i) { float *pBuffer = ppBuffer[i]; float *pFrames = ppFrames[i]; for (unsigned int n = 0; n < iFrames; ++n) *pBuffer++ += fGain * *pFrames++; } } //---------------------------------------------------------------------------- // qtractorInsertPluginType -- Insert pseudo-plugin type instance. // // Derived methods. bool qtractorInsertPluginType::open (void) { // Sanity check... unsigned short iChannels = index(); if (iChannels < 1) return false; #ifdef CONFIG_DEBUG qDebug("qtractorInsertPluginType[%p]::open() channels=%u", this, iChannels); #endif // Pseudo-plugin type names. m_sName = "Insert"; m_sLabel = m_sName; // Pseudo-plugin unique identifier. m_iUniqueID = iChannels; // Pseudo-plugin port counts... m_iControlIns = 2; m_iControlOuts = 0; m_iAudioIns = iChannels; m_iAudioOuts = iChannels; m_iMidiIns = 0; m_iMidiOuts = 0; // Cache flags. m_bRealtime = true; m_bConfigure = true; // Done. return true; } void qtractorInsertPluginType::close (void) { } // Factory method (static) qtractorInsertPluginType *qtractorInsertPluginType::createType ( unsigned short iChannels ) { // Sanity check... if (iChannels < 1) return NULL; // Yep, most probably its a valid pseu-plugin... return new qtractorInsertPluginType(iChannels); } //---------------------------------------------------------------------------- // qtractorInsertPlugin -- Insert pseudo-plugin instance. // // Constructors. qtractorInsertPlugin::qtractorInsertPlugin ( qtractorPluginList *pList, qtractorInsertPluginType *pInsertType ) : qtractorPlugin(pList, pInsertType), m_pAudioBus(NULL) { #ifdef CONFIG_DEBUG qDebug("qtractorInsertPlugin[%p] channels=%u", this, pInsertType->channels()); #endif // Custom optimized processors. #if defined(__SSE__) if (sse_enabled()) { m_pfnProcessSendGain = sse_process_send_gain; m_pfnProcessDryWet = sse_process_dry_wet; } else { #endif m_pfnProcessSendGain = std_process_send_gain; m_pfnProcessDryWet = std_process_dry_wet; #if defined(__SSE__) } #endif // Create and attach the custom parameters... m_pSendGainParam = new qtractorInsertPluginParam(this, 0); m_pSendGainParam->setName(QObject::tr("Send Gain")); m_pSendGainParam->setMinValue(0.0f); m_pSendGainParam->setMaxValue(2.0f); m_pSendGainParam->setDefaultValue(1.0f); m_pSendGainParam->setValue(1.0f, false); addParam(m_pSendGainParam); m_pDryWetParam = new qtractorInsertPluginParam(this, 1); m_pDryWetParam->setName(QObject::tr("Dry / Wet")); m_pDryWetParam->setMinValue(0.0f); m_pDryWetParam->setMaxValue(2.0f); m_pDryWetParam->setDefaultValue(0.0f); m_pDryWetParam->setValue(0.0f, false); addParam(m_pDryWetParam); // Setup plugin instance... setChannels(channels()); } // Destructor. qtractorInsertPlugin::~qtractorInsertPlugin (void) { // Cleanup plugin instance... setChannels(0); } // Channel/instance number accessors. void qtractorInsertPlugin::setChannels ( unsigned short iChannels ) { // Check our type... qtractorPluginType *pType = type(); if (pType == NULL) return; // We'll need this globals... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine == NULL) return; // Estimate the (new) number of instances... unsigned short iInstances = pType->instances(iChannels, list()->isMidi()); // Now see if instance count changed anyhow... if (iInstances == instances()) return; // Gotta go for a while... bool bActivated = isActivated(); setActivated(false); // TODO: Cleanup bus... if (m_pAudioBus) { pAudioEngine->removeBusEx(m_pAudioBus); m_pAudioBus->close(); delete m_pAudioBus; m_pAudioBus = NULL; } // Set new instance number... setInstances(iInstances); if (iInstances < 1) { setActivated(bActivated); return; } #ifdef CONFIG_DEBUG qDebug("qtractorInsertPlugin[%p]::setChannels(%u) instances=%u", this, iChannels, iInstances); #endif // Audio bus name -- it must be unique... const QString& sBusNamePrefix = qtractorSession::sanitize(list()->name() + '/' + pType->name()); int iBusName = 1; QString sBusName = sBusNamePrefix; while (pAudioEngine->findBus(sBusName) || pAudioEngine->findBusEx(sBusName)) sBusName = sBusNamePrefix + '_' + QString::number(++iBusName); // Create the private audio bus... m_pAudioBus = new qtractorAudioBus(pAudioEngine, sBusName, qtractorBus::BusMode(qtractorBus::Duplex | qtractorBus::Ex), false, iChannels); // Add this one to the engine's exo-bus list, // for conection persistence purposes... pAudioEngine->addBusEx(m_pAudioBus); // (Re)issue all configuration as needed... realizeConfigs(); realizeValues(); // But won't need it anymore. releaseConfigs(); releaseValues(); // Open-up private bus... m_pAudioBus->open(); // (Re)activate instance if necessary... setActivated(bActivated); } // Do the actual activation. void qtractorInsertPlugin::activate (void) { } // Do the actual deactivation. void qtractorInsertPlugin::deactivate (void) { } // The main plugin processing procedure. void qtractorInsertPlugin::process ( float **ppIBuffer, float **ppOBuffer, unsigned int nframes ) { if (m_pAudioBus == NULL) return; // m_pAudioBus->process_prepare(nframes); float **ppOut = m_pAudioBus->out(); // Sends. float **ppIn = m_pAudioBus->in(); // Returns. const unsigned short iChannels = channels(); for (unsigned short i = 0; i < iChannels; ++i) { ::memcpy(ppOut[i], ppIBuffer[i], nframes * sizeof(float)); ::memcpy(ppOBuffer[i], ppIn[i], nframes * sizeof(float)); } const float fSendGain = m_pSendGainParam->value(); (*m_pfnProcessSendGain)(ppOut, nframes, iChannels, fSendGain); const float fDryWet = m_pDryWetParam->value(); if (fDryWet > 0.001f) (*m_pfnProcessDryWet)(ppOBuffer, ppIBuffer, nframes, iChannels, fDryWet); // m_pAudioBus->process_commit(nframes); } // Pseudo-plugin configuration handlers. void qtractorInsertPlugin::configure ( const QString& sKey, const QString& sValue ) { if (m_pAudioBus == NULL) return; qtractorBus::ConnectItem *pItem = new qtractorBus::ConnectItem; pItem->index = sValue.section('|', 0, 0).toUShort(); const QString& sClient = sValue.section('|', 1, 1); const QString& sClientName = sClient.section(':', 1); if (sClientName.isEmpty()) { pItem->clientName = sClient; } else { // pItem->client = sClient.section(':', 0, 0).toInt(); pItem->clientName = sClientName; } const QString& sPort = sValue.section('|', 2, 2); const QString& sPortName = sPort.section(':', 1); if (sPortName.isEmpty()) { pItem->portName = sPort; } else { // pItem->port = sPort.section(':', 0, 0).toInt(); pItem->portName = sPortName; } const QString& sKeyPrefix = sKey.section('_', 0, 0); if (sKeyPrefix == "in") m_pAudioBus->inputs().append(pItem); else if (sKeyPrefix == "out") m_pAudioBus->outputs().append(pItem); else delete pItem; } // Pseudo-plugin configuration/state snapshot. void qtractorInsertPlugin::freezeConfigs (void) { #ifdef CONFIG_DEBUG qDebug("qtractorInsertPlugin[%p]::freezeConfigs()", this); #endif clearConfigs(); freezeConfigs(qtractorBus::Input); freezeConfigs(qtractorBus::Output); } void qtractorInsertPlugin::releaseConfigs (void) { #ifdef CONFIG_DEBUG qDebug("qtractorInsertPlugin[%p]::releaseConfigs()", this); #endif clearConfigs(); } void qtractorInsertPlugin::freezeConfigs ( int iBusMode ) { if (m_pAudioBus == NULL) return; // Save connect items... qtractorBus::BusMode busMode = qtractorBus::BusMode(iBusMode); const QString sKeyPrefix(busMode & qtractorBus::Input ? "in" : "out"); int iKey = 0; qtractorBus::ConnectList connects; m_pAudioBus->updateConnects(busMode, connects); QListIterator iter(connects); while (iter.hasNext()) { qtractorBus::ConnectItem *pItem = iter.next(); QString sIndex = QString::number(pItem->index); QString sClient; if (pItem->client >= 0) sClient += QString::number(pItem->client) + ':'; sClient += pItem->clientName; QString sPort; if (pItem->port >= 0) sPort += QString::number(pItem->port) + ':'; sPort += pItem->portName; QString sKey = sKeyPrefix + '_' + QString::number(iKey++); setConfig(sKey, sIndex + '|' + sClient + '|' + sPort); } } // Audio specific accessor. qtractorAudioBus *qtractorInsertPlugin::audioBus (void) const { return m_pAudioBus; } //---------------------------------------------------------------------------- // qtractorAuxSendPluginType -- Aux-send pseudo-plugin type instance. // // Derived methods. bool qtractorAuxSendPluginType::open (void) { // Sanity check... unsigned short iChannels = index(); if (iChannels < 1) return false; #ifdef CONFIG_DEBUG qDebug("qtractorAuxSendPluginType[%p]::open() channels=%u", this, iChannels); #endif // Pseudo-plugin type names. m_sName = "Aux Send"; m_sLabel = m_sName; m_sLabel.remove(' '); // Pseudo-plugin unique identifier. m_iUniqueID = iChannels; // Pseudo-plugin port counts... m_iControlIns = 1; m_iControlOuts = 0; m_iAudioIns = iChannels; m_iAudioOuts = iChannels; m_iMidiIns = 0; m_iMidiOuts = 0; // Cache flags. m_bRealtime = true; m_bConfigure = true; // Done. return true; } void qtractorAuxSendPluginType::close (void) { } // Factory method (static) qtractorAuxSendPluginType *qtractorAuxSendPluginType::createType ( unsigned short iChannels ) { // Sanity check... if (iChannels < 1) return NULL; // Yep, most probably its a valid pseu-plugin... return new qtractorAuxSendPluginType(iChannels); } //---------------------------------------------------------------------------- // qtractorAuxSendPlugin -- Aux-send pseudo-plugin instance. // // Constructors. qtractorAuxSendPlugin::qtractorAuxSendPlugin ( qtractorPluginList *pList, qtractorAuxSendPluginType *pAuxSendType ) : qtractorPlugin(pList, pAuxSendType), m_pAudioBus(NULL) { #ifdef CONFIG_DEBUG qDebug("qtractorAuxSendPlugin[%p] channels=%u", this, pAuxSendType->channels()); #endif // Custom optimized processors. #if defined(__SSE__) if (sse_enabled()) { m_pfnProcessDryWet = sse_process_dry_wet; } else { #endif m_pfnProcessDryWet = std_process_dry_wet; #if defined(__SSE__) } #endif // Create and attach the custom parameters... m_pSendGainParam = new qtractorInsertPluginParam(this, 0); m_pSendGainParam->setName(QObject::tr("Send Gain")); m_pSendGainParam->setMinValue(0.0f); m_pSendGainParam->setMaxValue(2.0f); m_pSendGainParam->setDefaultValue(0.0f); m_pSendGainParam->setValue(0.0f, false); addParam(m_pSendGainParam); } // Destructor. qtractorAuxSendPlugin::~qtractorAuxSendPlugin (void) { // Cleanup plugin instance... setChannels(0); } // Channel/instance number accessors. void qtractorAuxSendPlugin::setChannels ( unsigned short iChannels ) { // Check our type... qtractorPluginType *pType = type(); if (pType == NULL) return; // We'll need this globals... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine == NULL) return; // Estimate the (new) number of instances... unsigned short iInstances = pType->instances(iChannels, list()->isMidi()); // Now see if instance count changed anyhow... if (iInstances == instances()) return; // Gotta go for a while... bool bActivated = isActivated(); setActivated(false); // TODO: Cleanup bus... if (m_pAudioBus) m_pAudioBus = NULL; // Set new instance number... setInstances(iInstances); if (iInstances < 1) { setActivated(bActivated); return; } #ifdef CONFIG_DEBUG qDebug("qtractorAuxSendPlugin[%p]::setChannels(%u) instances=%u", this, iChannels, iInstances); #endif realizeConfigs(); realizeValues(); // But won't need it anymore. releaseConfigs(); releaseValues(); // Try to find a nice default... if (m_sAudioBusName.isEmpty()) { for (qtractorBus *pBus = pAudioEngine->buses().first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Output) { qtractorAudioBus *pAudioBus = static_cast (pBus); if (pAudioBus && pAudioBus->channels() == iChannels) { m_sAudioBusName = pAudioBus->busName(); break; } } } } // Setup aux-send bus... setAudioBusName(m_sAudioBusName); // (Re)activate instance if necessary... setActivated(bActivated); } // Audio bus specific accessors. void qtractorAuxSendPlugin::setAudioBusName ( const QString& sAudioBusName ) { if (sAudioBusName.isEmpty()) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine == NULL) return; qtractorAudioBus *pAudioBus = static_cast ( pAudioEngine->findOutputBus(sAudioBusName)); if (pAudioBus && pAudioBus->channels() == channels()) { m_pAudioBus = pAudioBus; m_sAudioBusName = sAudioBusName; // setConfig("audioBusName", m_sAudioBusName); } else { m_pAudioBus = NULL; m_sAudioBusName.clear(); // clearConfigs(); } updateAudioBusName(); } const QString& qtractorAuxSendPlugin::audioBusName (void) const { return m_sAudioBusName; } // Audio bus to appear on plugin lists. void qtractorAuxSendPlugin::updateAudioBusName (void) const { const QString& sText = (m_pAudioBus ? m_sAudioBusName : type()->name()); QListIterator iter(items()); while (iter.hasNext()) iter.next()->setText(sText); } // The main plugin processing procedure. void qtractorAuxSendPlugin::process ( float **ppIBuffer, float **ppOBuffer, unsigned int nframes ) { if (m_pAudioBus == NULL) return; // m_pAudioBus->process_prepare(nframes); float **ppOut = m_pAudioBus->out(); const unsigned short iChannels = channels(); for (unsigned short i = 0; i < iChannels; ++i) ::memcpy(ppOBuffer[i], ppIBuffer[i], nframes * sizeof(float)); const float fSendGain = m_pSendGainParam->value(); (*m_pfnProcessDryWet)(ppOut, ppOBuffer, nframes, iChannels, fSendGain); // m_pAudioBus->process_commit(nframes); } // Do the actual activation. void qtractorAuxSendPlugin::activate (void) { } // Do the actual deactivation. void qtractorAuxSendPlugin::deactivate (void) { } // Pseudo-plugin configuration handlers. void qtractorAuxSendPlugin::configure ( const QString& sKey, const QString& sValue ) { #ifdef CONFIG_DEBUG qDebug("qtractorAuxSendPlugin[%p]::configure()", this); #endif if (sKey == "audioBusName") setAudioBusName(sValue); } // Pseudo-plugin configuration/state snapshot. void qtractorAuxSendPlugin::freezeConfigs (void) { #ifdef CONFIG_DEBUG qDebug("qtractorAuxSendPlugin[%p]::freezeConfigs()", this); #endif clearConfigs(); setConfig("audioBusName", m_sAudioBusName); } void qtractorAuxSendPlugin::releaseConfigs (void) { #ifdef CONFIG_DEBUG qDebug("qtractorAuxSendPlugin[%p]::releaseConfigs()", this); #endif clearConfigs(); } // end of qtractorInsertPlugin.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEngine.cpp0000644000175000001440000000012212147363653021550 xustar000000000000000026 mtime=1369302955.45825 26 atime=1381134670.31808 30 ctime=1381134670.319080101 qtractor-0.5.11/src/qtractorMidiEngine.cpp0000644000175000001440000036765412147363653021065 0ustar00rncbcusers00000000000000// qtractorMidiEngine.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiEngine.h" #include "qtractorMidiMonitor.h" #include "qtractorMidiEvent.h" #include "qtractorSession.h" #include "qtractorSessionCursor.h" #include "qtractorDocument.h" #include "qtractorAudioEngine.h" #include "qtractorMidiSequence.h" #include "qtractorMidiClip.h" #include "qtractorMidiBuffer.h" #include "qtractorMidiControl.h" #include "qtractorMidiTimer.h" #include "qtractorMidiSysex.h" #include "qtractorPlugin.h" #include "qtractorCurveFile.h" #include #include #include #include #include #include #include #include #include // Specific controller definitions #define BANK_SELECT_MSB 0x00 #define BANK_SELECT_LSB 0x20 #define ALL_SOUND_OFF 0x78 #define ALL_CONTROLLERS_OFF 0x79 #define ALL_NOTES_OFF 0x7b #define CHANNEL_VOLUME 0x07 #define CHANNEL_PANNING 0x0a // Audio vs. MIDI time drift cycle #define DRIFT_CHECK 8 //---------------------------------------------------------------------- // class qtractorMidiInputThread -- MIDI input thread (singleton). // class qtractorMidiInputThread : public QThread { public: // Constructor. qtractorMidiInputThread(qtractorMidiEngine *pMidiEngine); // Destructor. ~qtractorMidiInputThread(); // Thread run state accessors. void setRunState(bool bRunState); bool runState() const; protected: // The main thread executive. void run(); private: // The thread launcher engine. qtractorMidiEngine *m_pMidiEngine; // Whether the thread is logically running. bool m_bRunState; }; //---------------------------------------------------------------------- // class qtractorMidiOutputThread -- MIDI output thread (singleton). // class qtractorMidiOutputThread : public QThread { public: // Constructor. qtractorMidiOutputThread( qtractorMidiEngine *pMidiEngine, unsigned int iReadAhead); // Destructor. ~qtractorMidiOutputThread(); // Thread run state accessors. void setRunState(bool bRunState); bool runState() const; // Read ahead frames configuration. void setReadAhead(unsigned int iReadAhead); unsigned int readAhead() const; // MIDI/Audio sync-check predicate. qtractorSessionCursor *midiCursorSync(bool bStart = false); // MIDI track output process resync. void trackSync(qtractorTrack *pTrack, unsigned long iFrameStart); // MIDI metronome output process resync. void metroSync(unsigned long iFrameStart); // MIDI output process cycle iteration (locked). void processSync(); // Wake from executive wait condition. void sync(); protected: // The main thread executive. void run(); // MIDI output process cycle iteration. void process(); private: // The thread launcher engine. qtractorMidiEngine *m_pMidiEngine; // The number of frames to read-ahead. unsigned int m_iReadAhead; // Whether the thread is logically running. bool m_bRunState; // Thread synchronization objects. QMutex m_mutex; QWaitCondition m_cond; }; //---------------------------------------------------------------------- // class qtractorMidiPlayerThread -- MIDI player thread. // class qtractorMidiPlayer; class qtractorMidiPlayerThread : public QThread { public: // Constructor. qtractorMidiPlayerThread(qtractorMidiPlayer *pMidiPlayer); // Destructor. ~qtractorMidiPlayerThread(); protected: // The main thread executive. void run(); private: // Instance variables. qtractorMidiPlayer *m_pMidiPlayer; bool m_bRunState; }; //---------------------------------------------------------------------- // class qtractorMidiPlayer -- Simple MIDI player. // class qtractorMidiPlayer { public: // Constructor. qtractorMidiPlayer(qtractorMidiBus *pMidiBus); // Destructor. ~qtractorMidiPlayer(); // Open and start playing. bool open(const QString& sFilename, int iTrackChannel = -1); // Close and stop playing. void close(); // Process playing executive. bool process(unsigned long iFrameStart, unsigned long iFrameEnd); // Open status predicate. bool isOpen() const; // Sample-rate accessor. unsigned int sampleRate() const; // Queue time (ticks) accessor. unsigned long queueTime() const; // Queue time (frames) accessor. unsigned long queueFrame() const; protected: // Enqueue process event. void enqueue(unsigned short iMidiChannel, qtractorMidiEvent *pEvent, unsigned long iTime, float fGain); private: // Instance variables. qtractorMidiBus *m_pMidiBus; qtractorMidiEngine *m_pMidiEngine; unsigned short m_iSeqs; qtractorMidiSequence **m_ppSeqs; qtractorMidiCursor **m_ppSeqCursors; qtractorTimeScale *m_pTimeScale; qtractorTimeScale::Cursor *m_pCursor; float m_fTempo; qtractorMidiPlayerThread *m_pPlayerThread; }; //---------------------------------------------------------------------- // class qtractorMidiInputThread -- MIDI input thread (singleton). // // Constructor. qtractorMidiInputThread::qtractorMidiInputThread ( qtractorMidiEngine *pMidiEngine ) : QThread() { m_pMidiEngine = pMidiEngine; m_bRunState = false; } // Destructor. qtractorMidiInputThread::~qtractorMidiInputThread (void) { // Try to terminate executive thread, // but give it a bit of time to cleanup... if (isRunning()) do { setRunState(false); // terminate(); } while (wait(100)); } // Thread run state accessors. void qtractorMidiInputThread::setRunState ( bool bRunState ) { m_bRunState = bRunState; } bool qtractorMidiInputThread::runState (void) const { return m_bRunState; } // The main thread executive. void qtractorMidiInputThread::run (void) { snd_seq_t *pAlsaSeq = m_pMidiEngine->alsaSeq(); if (pAlsaSeq == NULL) return; #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiInputThread[%p]::run(%p): started...", this); #endif int nfds; struct pollfd *pfds; nfds = snd_seq_poll_descriptors_count(pAlsaSeq, POLLIN); pfds = (struct pollfd *) alloca(nfds * sizeof(struct pollfd)); snd_seq_poll_descriptors(pAlsaSeq, pfds, nfds, POLLIN); m_bRunState = true; int iPoll = 0; while (m_bRunState && iPoll >= 0) { // Wait for events... iPoll = poll(pfds, nfds, 200); while (iPoll > 0) { snd_seq_event_t *pEv = NULL; snd_seq_event_input(pAlsaSeq, &pEv); // Process input event - ... // - enqueue to input track mapping; m_pMidiEngine->capture(pEv); // snd_seq_free_event(pEv); iPoll = snd_seq_event_input_pending(pAlsaSeq, 0); } } #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiInputThread[%p]::run(): stopped.", this); #endif } //---------------------------------------------------------------------- // class qtractorMidiOutputThread -- MIDI output thread (singleton). // // Constructor. qtractorMidiOutputThread::qtractorMidiOutputThread ( qtractorMidiEngine *pMidiEngine, unsigned int iReadAhead ) : QThread() { m_pMidiEngine = pMidiEngine; m_bRunState = false; m_iReadAhead = iReadAhead; } // Destructor. qtractorMidiOutputThread::~qtractorMidiOutputThread (void) { // Try to wake and terminate executive thread, // but give it a bit of time to cleanup... if (isRunning()) do { setRunState(false); // terminate(); sync(); } while (!wait(100)); } // Thread run state accessors. void qtractorMidiOutputThread::setRunState ( bool bRunState ) { QMutexLocker locker(&m_mutex); m_bRunState = bRunState; } bool qtractorMidiOutputThread::runState (void) const { return m_bRunState; } // Read ahead frames configuration. void qtractorMidiOutputThread::setReadAhead ( unsigned int iReadAhead ) { QMutexLocker locker(&m_mutex); m_iReadAhead = iReadAhead; } unsigned int qtractorMidiOutputThread::readAhead (void) const { return m_iReadAhead; } // Audio/MIDI sync-check and cursor predicate. qtractorSessionCursor *qtractorMidiOutputThread::midiCursorSync ( bool bStart ) { // We'll need access to master audio engine... qtractorSessionCursor *pAudioCursor = (m_pMidiEngine->session())->audioEngine()->sessionCursor(); if (pAudioCursor == NULL) return NULL; // And to our slave MIDI engine too... qtractorSessionCursor *pMidiCursor = m_pMidiEngine->sessionCursor(); if (pMidiCursor == NULL) return NULL; // Can MIDI be ever behind audio? if (bStart) { pMidiCursor->seek(pAudioCursor->frame()); // pMidiCursor->setFrameTime(pAudioCursor->frameTime()); } else // No, it cannot be behind more than the read-ahead period... if (pMidiCursor->frameTime() > pAudioCursor->frameTime() + m_iReadAhead) return NULL; // Nope. OK. return pMidiCursor; } // The main thread executive. void qtractorMidiOutputThread::run (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiOutputThread[%p]::run(): started...", this); #endif m_bRunState = true; m_mutex.lock(); while (m_bRunState) { // Wait for sync... m_cond.wait(&m_mutex); #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiOutputThread[%p]::run(): waked.", this); #endif // Only if playing, the output process cycle. if (m_pMidiEngine->isPlaying()) process(); } m_mutex.unlock(); #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiOutputThread[%p]::run(): stopped.", this); #endif } // MIDI output process cycle iteration. void qtractorMidiOutputThread::process (void) { // Must have a valid session... qtractorSession *pSession = m_pMidiEngine->session(); if (pSession == NULL) return; // Get a handle on our slave MIDI engine... qtractorSessionCursor *pMidiCursor = midiCursorSync(); // Isn't MIDI slightly behind audio? if (pMidiCursor == NULL) return; // Free overriden SysEx queued events. m_pMidiEngine->clearSysexCache(); // Now for the next readahead bunch... unsigned long iFrameStart = pMidiCursor->frame(); unsigned long iFrameEnd = iFrameStart + m_iReadAhead; #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiOutputThread[%p]::process(%lu, %lu)", this, iFrameStart, iFrameEnd); #endif // Split processing, in case we're looping... bool bLooping = pSession->isLooping(); unsigned long le = pSession->loopEnd(); if (bLooping && iFrameStart < le) { // Loop-length might be shorter than the read-ahead... while (iFrameEnd >= le) { // Process metronome clicks... m_pMidiEngine->processMetro(iFrameStart, le); // Process the remaining until end-of-loop... pSession->process(pMidiCursor, iFrameStart, le); // Reset to start-of-loop... iFrameStart = pSession->loopStart(); iFrameEnd = iFrameStart + (iFrameEnd - le); pMidiCursor->seek(iFrameStart); // This is really a must... m_pMidiEngine->restartLoop(); } } // Process metronome clicks... m_pMidiEngine->processMetro(iFrameStart, iFrameEnd); // Regular range... pSession->process(pMidiCursor, iFrameStart, iFrameEnd); // Sync with loop boundaries (unlikely?)... if (bLooping && iFrameStart < le && iFrameEnd >= le) iFrameEnd = pSession->loopStart() + (iFrameEnd - le); // Sync to the next bunch, also critical for Audio-MIDI sync... pMidiCursor->seek(iFrameEnd); pMidiCursor->process(m_iReadAhead); // Flush the MIDI engine output queue... m_pMidiEngine->flush(); // Always do the queue drift stats // at the bottom of the pack... m_pMidiEngine->drift(); } // MIDI output process cycle iteration (locked). void qtractorMidiOutputThread::processSync (void) { QMutexLocker locker(&m_mutex); #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiOutputThread[%p]::processSync()", this); #endif process(); } // MIDI track output process resync. void qtractorMidiOutputThread::trackSync ( qtractorTrack *pTrack, unsigned long iFrameStart ) { QMutexLocker locker(&m_mutex); // Must have a valid session... qtractorSession *pSession = m_pMidiEngine->session(); if (pSession == NULL) return; // Pick our actual MIDI sequencer cursor... qtractorSessionCursor *pMidiCursor = m_pMidiEngine->sessionCursor(); if (pMidiCursor == NULL) return; // This is the last framestamp to be trown out... unsigned long iFrameEnd = pMidiCursor->frame(); #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiOutputThread[%p]::trackSync(%p, %lu, %lu)", this, pTrack, iFrameStart, iFrameEnd); #endif // Split processing, in case we've been caught looping... if (pSession->isLooping() && iFrameStart > iFrameEnd && iFrameStart < pSession->loopEnd()) iFrameStart = pSession->loopStart(); // Locate the immediate nearest clip in track // and render them all thereafter, immediately... qtractorClip *pClip = pTrack->clips().first(); while (pClip && pClip->clipStart() < iFrameEnd) { if (iFrameStart < pClip->clipStart() + pClip->clipLength()) pClip->process(iFrameStart, iFrameEnd); pClip = pClip->next(); } // Surely must realize the output queue... m_pMidiEngine->flush(); } // MIDI metronome output process resync. void qtractorMidiOutputThread::metroSync ( unsigned long iFrameStart ) { QMutexLocker locker(&m_mutex); // Pick our actual MIDI sequencer cursor... qtractorSessionCursor *pMidiCursor = m_pMidiEngine->sessionCursor(); if (pMidiCursor == NULL) return; // This is the last framestamp to be trown out... unsigned long iFrameEnd = pMidiCursor->frame(); #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiOutputThread[%p]::metroSync(%lu, %lu)", this, iFrameStart, iFrameEnd); #endif // (Re)process the metronome stuff... m_pMidiEngine->processMetro(iFrameStart, iFrameEnd); // Surely must realize the output queue... m_pMidiEngine->flush(); } // Wake from executive wait condition. void qtractorMidiOutputThread::sync (void) { if (m_mutex.tryLock()) { m_cond.wakeAll(); m_mutex.unlock(); } #ifdef CONFIG_DEBUG_0 else qDebug("qtractorMidiOutputThread[%p]::sync(): tryLock() failed.", this); #endif } //---------------------------------------------------------------------- // class qtractorMidiPlayerThread -- MIDI player thread. // // Constructor. qtractorMidiPlayerThread::qtractorMidiPlayerThread ( qtractorMidiPlayer *pMidiPlayer ) : QThread(), m_pMidiPlayer(pMidiPlayer), m_bRunState(false) { } // Destructor. qtractorMidiPlayerThread::~qtractorMidiPlayerThread (void) { if (isRunning()) do { m_bRunState = false; // terminate(); } while (!wait(200)); } // The main thread executive. void qtractorMidiPlayerThread::run (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiPlayerThread[%p]::run(): started...", this); #endif const unsigned int iSampleRate = m_pMidiPlayer->sampleRate(); const unsigned long iReadAhead = (iSampleRate >> 2); unsigned long iFrameStart = 0; unsigned long iFrameEnd = 0; m_bRunState = true; while (m_bRunState) { iFrameEnd += iReadAhead; if (m_pMidiPlayer->process(iFrameStart, iFrameEnd)) { const unsigned long iQueueFrame = m_pMidiPlayer->queueFrame(); const long iDelta = long(iFrameStart) - long(iQueueFrame); #ifdef CONFIG_DEBUG qDebug("qtractorMidiPlayer::process(%lu, %lu) iQueueFrame=%lu (%ld)", iFrameStart, iFrameEnd, iQueueFrame, iDelta); #endif unsigned long iSleep = iReadAhead; if (iSleep + iDelta > 0) iSleep += iDelta; msleep((1000 * iSleep) / iSampleRate); iFrameStart = iFrameEnd; } else m_bRunState = false; } #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiPlayerThread[%p]::run(): stopped.", this); #endif } //---------------------------------------------------------------------- // class qtractorMidiPlayer -- Simple MIDI player. // // Constructor. qtractorMidiPlayer::qtractorMidiPlayer (qtractorMidiBus *pMidiBus ) : m_pMidiBus(pMidiBus), m_pMidiEngine(static_cast (pMidiBus->engine())), m_iSeqs(0), m_ppSeqs(NULL), m_ppSeqCursors(NULL), m_pTimeScale(NULL), m_pCursor(NULL), m_fTempo(0.0f), m_pPlayerThread(NULL) { } // Destructor. qtractorMidiPlayer::~qtractorMidiPlayer (void) { close(); } // Open and start playing. bool qtractorMidiPlayer::open ( const QString& sFilename, int iTrackChannel ) { close(); if (m_pMidiBus == NULL) return false; qtractorSession *pSession = m_pMidiEngine->session(); if (pSession == NULL) return false; qtractorSessionCursor *pAudioCursor = pSession->audioEngine()->sessionCursor(); if (pAudioCursor == NULL) return false; qtractorTimeScale *pTimeScale = pSession->timeScale(); if (pTimeScale == NULL) return false; snd_seq_t *pAlsaSeq = m_pMidiEngine->alsaSeq(); if (pAlsaSeq == NULL) return false; qtractorMidiFile file; if (!file.open(sFilename)) return false; m_pTimeScale = new qtractorTimeScale(*pTimeScale); m_pTimeScale->setTicksPerBeat(file.ticksPerBeat()); if (iTrackChannel < 0) { m_iSeqs = (file.format() == 1 ? file.tracks() : 16); iTrackChannel = 0; } else m_iSeqs = 1; m_ppSeqs = new qtractorMidiSequence * [m_iSeqs]; m_ppSeqCursors = new qtractorMidiCursor * [m_iSeqs]; for (unsigned short iSeq = 0; iSeq < m_iSeqs; ++iSeq) { m_ppSeqs[iSeq] = new qtractorMidiSequence( QString(), iSeq, m_pTimeScale->ticksPerBeat()); m_ppSeqCursors[iSeq] = new qtractorMidiCursor(); } if (file.readTracks(m_ppSeqs, m_iSeqs, iTrackChannel) && file.tempoMap()) file.tempoMap()->intoTimeScale(m_pTimeScale); file.close(); m_pCursor = new qtractorTimeScale::Cursor(m_pTimeScale); m_fTempo = m_pTimeScale->tempo(); int iAlsaQueue = m_pMidiEngine->alsaQueue(); snd_seq_queue_tempo_t *tempo; snd_seq_queue_tempo_alloca(&tempo); snd_seq_get_queue_tempo(pAlsaSeq, iAlsaQueue, tempo); snd_seq_queue_tempo_set_ppq(tempo, (int) m_pTimeScale->ticksPerBeat()); snd_seq_queue_tempo_set_tempo(tempo, (unsigned int) (60000000.0f / m_fTempo)); snd_seq_set_queue_tempo(pAlsaSeq, iAlsaQueue, tempo); snd_seq_start_queue(pAlsaSeq, iAlsaQueue, NULL); snd_seq_drain_output(pAlsaSeq); pAudioCursor->setFrameTime(0); qtractorMidiMonitor::resetTime(m_pTimeScale, 0); if (m_pMidiBus->midiMonitor_out()) m_pMidiBus->midiMonitor_out()->reset(); m_pPlayerThread = new qtractorMidiPlayerThread(this); m_pPlayerThread->start(QThread::HighPriority); return true; } // Close and stop playing. void qtractorMidiPlayer::close (void) { if (m_pPlayerThread) { delete m_pPlayerThread; m_pPlayerThread = NULL; } if (m_ppSeqs && m_pMidiBus) { snd_seq_t *pAlsaSeq = m_pMidiEngine->alsaSeq(); if (pAlsaSeq) { snd_seq_drop_output(pAlsaSeq); int iAlsaQueue = m_pMidiEngine->alsaQueue(); if (iAlsaQueue >= 0) snd_seq_stop_queue(pAlsaSeq, iAlsaQueue, NULL); for (unsigned short iSeq = 0; iSeq < m_iSeqs; ++iSeq) { unsigned short iChannel = m_ppSeqs[iSeq]->channel(); m_pMidiBus->setController(iChannel, ALL_SOUND_OFF); m_pMidiBus->setController(iChannel, ALL_NOTES_OFF); m_pMidiBus->setController(iChannel, ALL_CONTROLLERS_OFF); } snd_seq_drain_output(pAlsaSeq); } if (m_pMidiBus->pluginList_out() && (m_pMidiBus->pluginList_out())->midiManager()) (m_pMidiBus->pluginList_out())->midiManager()->reset(); } if (m_pCursor) { delete m_pCursor; m_pCursor = NULL; } m_fTempo = 0.0f; for (unsigned short iSeq = 0; iSeq < m_iSeqs; ++iSeq) { if (m_ppSeqCursors && m_ppSeqCursors[iSeq]) delete m_ppSeqCursors[iSeq]; if (m_ppSeqs && m_ppSeqs[iSeq]) delete m_ppSeqs[iSeq]; } if (m_ppSeqCursors) { delete [] m_ppSeqCursors; m_ppSeqCursors = NULL; } if (m_ppSeqs) { delete [] m_ppSeqs; m_ppSeqs = NULL; } m_iSeqs = 0; if (m_pTimeScale) { delete m_pTimeScale; m_pTimeScale = NULL; } } // Process playing executive. bool qtractorMidiPlayer::process ( unsigned long iFrameStart, unsigned long iFrameEnd ) { if (m_pMidiBus == NULL) return false; if (m_pCursor == NULL) return false; snd_seq_t *pAlsaSeq = m_pMidiEngine->alsaSeq(); if (pAlsaSeq == NULL) return false; int iAlsaQueue = m_pMidiEngine->alsaQueue(); if (iAlsaQueue < 0) return false; qtractorTimeScale::Node *pNode = m_pCursor->seekFrame(iFrameEnd); if (pNode->tempo != m_fTempo) { unsigned long iTime = (pNode->frame < iFrameStart ? pNode->tickFromFrame(iFrameStart) : pNode->tick); snd_seq_event_t ev; snd_seq_ev_clear(&ev); snd_seq_ev_schedule_tick(&ev, iAlsaQueue, 0, iTime); ev.type = SND_SEQ_EVENT_TEMPO; ev.data.queue.queue = iAlsaQueue; ev.data.queue.param.value = (unsigned int) (60000000.0f / pNode->tempo); ev.dest.client = SND_SEQ_CLIENT_SYSTEM; ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; snd_seq_event_output(pAlsaSeq, &ev); m_fTempo = pNode->tempo; qtractorMidiMonitor::splitTime( m_pCursor->timeScale(), pNode->frame, iTime); } unsigned long iTimeStart = m_pTimeScale->tickFromFrame(iFrameStart); unsigned long iTimeEnd = m_pTimeScale->tickFromFrame(iFrameEnd); unsigned int iProcess = 0; for (unsigned short iSeq = 0; iSeq < m_iSeqs; ++iSeq) { qtractorMidiSequence *pSeq = m_ppSeqs[iSeq]; qtractorMidiCursor *pSeqCursor = m_ppSeqCursors[iSeq]; qtractorMidiEvent *pEvent = pSeqCursor->seek(pSeq, iTimeStart); while (pEvent) { unsigned long iTime = pEvent->time(); // + iTimeOffset? if (iTime >= iTimeEnd) break; if (iTime >= iTimeStart) enqueue(pSeq->channel(), pEvent, iTime, 1.0f); pEvent = pEvent->next(); } if (iTimeEnd < pSeq->duration()) ++iProcess; } snd_seq_drain_output(pAlsaSeq); return (iProcess > 0); } // Enqueue process event. void qtractorMidiPlayer::enqueue ( unsigned short iMidiChannel, qtractorMidiEvent *pEvent, unsigned long iTime, float fGain ) { snd_seq_event_t ev; snd_seq_ev_clear(&ev); snd_seq_ev_set_source(&ev, m_pMidiBus->alsaPort()); snd_seq_ev_set_subs(&ev); snd_seq_ev_schedule_tick(&ev, m_pMidiEngine->alsaQueue(), 0, iTime); switch (pEvent->type()) { case qtractorMidiEvent::NOTEON: ev.type = SND_SEQ_EVENT_NOTE; ev.data.note.channel = iMidiChannel; ev.data.note.note = pEvent->note(); ev.data.note.velocity = int(fGain * float(pEvent->value())) & 0x7f; ev.data.note.duration = pEvent->duration(); break; case qtractorMidiEvent::KEYPRESS: ev.type = SND_SEQ_EVENT_KEYPRESS; ev.data.note.channel = iMidiChannel; ev.data.note.note = pEvent->note(); ev.data.note.velocity = pEvent->velocity(); ev.data.note.duration = 0; break; case qtractorMidiEvent::CONTROLLER: ev.type = SND_SEQ_EVENT_CONTROLLER; ev.data.control.channel = iMidiChannel; ev.data.control.param = pEvent->controller(); ev.data.control.value = pEvent->value(); break; case qtractorMidiEvent::PGMCHANGE: ev.type = SND_SEQ_EVENT_PGMCHANGE; ev.data.control.channel = iMidiChannel; ev.data.control.value = pEvent->value(); break; case qtractorMidiEvent::CHANPRESS: ev.type = SND_SEQ_EVENT_CHANPRESS; ev.data.control.channel = iMidiChannel; ev.data.control.value = pEvent->value(); break; case qtractorMidiEvent::PITCHBEND: ev.type = SND_SEQ_EVENT_PITCHBEND; ev.data.control.channel = iMidiChannel; ev.data.control.value = pEvent->pitchBend(); break; case qtractorMidiEvent::SYSEX: ev.type = SND_SEQ_EVENT_SYSEX; snd_seq_ev_set_sysex(&ev, pEvent->sysex_len(), pEvent->sysex()); break; default: break; } snd_seq_event_output(m_pMidiEngine->alsaSeq(), &ev); if (m_pMidiBus->midiMonitor_out()) m_pMidiBus->midiMonitor_out()->enqueue( pEvent->type(), pEvent->value(), iTime); if (m_pMidiBus->pluginList_out() && (m_pMidiBus->pluginList_out())->midiManager()) ((m_pMidiBus->pluginList_out())->midiManager())->queued( m_pTimeScale, &ev, iTime, 0); } // Open status predicate. bool qtractorMidiPlayer::isOpen (void) const { return (m_pPlayerThread && m_pPlayerThread->isRunning()); } // Sample-rate accessor. unsigned int qtractorMidiPlayer::sampleRate (void) const { return (m_pTimeScale ? m_pTimeScale->sampleRate() : 44100); } // Queue time (ticks) accessor. unsigned long qtractorMidiPlayer::queueTime (void) const { snd_seq_t *pAlsaSeq = m_pMidiEngine->alsaSeq(); if (pAlsaSeq == NULL) return 0; int iAlsaQueue = m_pMidiEngine->alsaQueue(); if (iAlsaQueue < 0) return 0; unsigned long iQueueTime = 0; snd_seq_queue_status_t *pQueueStatus; snd_seq_queue_status_alloca(&pQueueStatus); if (snd_seq_get_queue_status( pAlsaSeq, iAlsaQueue, pQueueStatus) >= 0) { iQueueTime = snd_seq_queue_status_get_tick_time(pQueueStatus); } return iQueueTime; } // Queue time (frames) accessor. unsigned long qtractorMidiPlayer::queueFrame (void) const { return (m_pTimeScale ? m_pTimeScale->frameFromTick(queueTime()) : 0); } //---------------------------------------------------------------------- // class qtractorMidiEngine -- ALSA sequencer client instance (singleton). // // Constructor. qtractorMidiEngine::qtractorMidiEngine ( qtractorSession *pSession ) : qtractorEngine(pSession, qtractorTrack::Midi) { m_pAlsaSeq = NULL; m_iAlsaClient = -1; m_iAlsaQueue = -1; m_iAlsaTimer = 0; m_pAlsaSubsSeq = NULL; m_iAlsaSubsPort = -1; m_pAlsaNotifier = NULL; m_pInputThread = NULL; m_pOutputThread = NULL; m_iDriftCheck = 0; m_iTimeStart = 0; m_iTimeDrift = 0; m_iFrameStart = 0; m_iFrameTime = 0; m_bControlBus = false; m_pIControlBus = NULL; m_pOControlBus = NULL; m_bMetronome = false; m_bMetroBus = false; m_pMetroBus = NULL; m_iMetroChannel = 9; // GM Drums channel (10) m_iMetroBarNote = 76; // GM High-wood stick m_iMetroBarVelocity = 96; m_iMetroBarDuration = 48; m_iMetroBeatNote = 77; // GM Low-wood stick m_iMetroBeatVelocity = 64; m_iMetroBeatDuration = 24; m_bMetroEnabled = false; // Time-scale cursor (tempo/time-signature map) m_pMetroCursor = NULL; // Track down tempo changes. m_fMetroTempo = 0.0f; // SMF player stuff. m_bPlayerBus = false; m_pPlayerBus = NULL; m_pPlayer = NULL; // No input/capture quantization (default). m_iCaptureQuantize = 0; // MIDI controller mapping flagger. m_iResetAllControllers = 0; // MIDI MMC/SPP modes. m_mmcDevice = 0x7f; // All-caller-id. m_mmcMode = qtractorBus::Duplex; m_sppMode = qtractorBus::Duplex; // MIDI Clock mode. m_clockMode = qtractorBus::None; // MIDI Clock tempo tracking. m_iClockCount = 0; m_fClockTempo = 120.0f; } // Special event notifier proxy object. const qtractorMidiEngineProxy *qtractorMidiEngine::proxy (void) const { return &m_proxy; } // ALSA sequencer client descriptor accessor. snd_seq_t *qtractorMidiEngine::alsaSeq (void) const { return m_pAlsaSeq; } int qtractorMidiEngine::alsaClient (void) const { return m_iAlsaClient; } int qtractorMidiEngine::alsaQueue (void) const { return m_iAlsaQueue; } // ALSA subscription port notifier. QSocketNotifier *qtractorMidiEngine::alsaNotifier (void) const { return m_pAlsaNotifier; } // ALSA subscription notifier acknowledgment. void qtractorMidiEngine::alsaNotifyAck (void) { if (m_pAlsaSubsSeq == NULL) return; do { snd_seq_event_t *pAlsaEvent; snd_seq_event_input(m_pAlsaSubsSeq, &pAlsaEvent); snd_seq_free_event(pAlsaEvent); } while (snd_seq_event_input_pending(m_pAlsaSubsSeq, 0) > 0); } // Special slave sync method. void qtractorMidiEngine::sync (void) { // Pure conditional thread slave syncronization... if (m_pOutputThread && m_pOutputThread->midiCursorSync()) m_pOutputThread->sync(); } // Read ahead frames configuration. void qtractorMidiEngine::setReadAhead ( unsigned int iReadAhead ) { if (m_pOutputThread) m_pOutputThread->setReadAhead(iReadAhead); } unsigned int qtractorMidiEngine::readAhead (void) const { return (m_pOutputThread ? m_pOutputThread->readAhead() : 0); } // Reset queue tempo. void qtractorMidiEngine::resetTempo (void) { // It must be surely activated... if (!isActivated()) return; // Needs a valid cursor... if (m_pMetroCursor == NULL) return; // Reset tempo cursor. m_pMetroCursor->reset(); // There must a session reference... qtractorSession *pSession = session(); if (pSession == NULL) return; // Recache tempo node... qtractorTimeScale::Node *pNode = m_pMetroCursor->seekFrame(pSession->playHead()); // Set queue tempo... snd_seq_queue_tempo_t *tempo; snd_seq_queue_tempo_alloca(&tempo); // Fill tempo struct with current tempo info. snd_seq_get_queue_tempo(m_pAlsaSeq, m_iAlsaQueue, tempo); // Set the new intended ones... snd_seq_queue_tempo_set_ppq(tempo, (int) pSession->ticksPerBeat()); snd_seq_queue_tempo_set_tempo(tempo, (unsigned int) (60000000.0f / pNode->tempo)); // Give tempo struct to the queue. snd_seq_set_queue_tempo(m_pAlsaSeq, m_iAlsaQueue, tempo); // Recache tempo value... m_fMetroTempo = pNode->tempo; // MIDI Clock tempo tracking. m_iClockCount = 0; m_fClockTempo = pNode->tempo; } // Reset all MIDI monitoring... void qtractorMidiEngine::resetAllMonitors (void) { // There must a session reference... qtractorSession *pSession = session(); if (pSession == NULL) return; // Reset common MIDI monitor stuff... qtractorMidiMonitor::resetTime( pSession->timeScale(), pSession->playHead()); // Reset all MIDI bus monitors... for (qtractorBus *pBus = buses().first(); pBus; pBus = pBus->next()) { qtractorMidiBus *pMidiBus = static_cast (pBus); if (pMidiBus) { if (pMidiBus->midiMonitor_in()) pMidiBus->midiMonitor_in()->reset(); if (pMidiBus->midiMonitor_out()) pMidiBus->midiMonitor_out()->reset(); } } // Reset all MIDI track channel monitors... for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { if (pTrack->trackType() == qtractorTrack::Midi) { qtractorMidiMonitor *pMidiMonitor = static_cast (pTrack->monitor()); if (pMidiMonitor) pMidiMonitor->reset(); } } } // Reset all MIDI instrument/controllers... void qtractorMidiEngine::resetAllControllers ( bool bForceImmediate ) { // Deferred processsing? if (!bForceImmediate) { ++m_iResetAllControllers; return; } // There must a session reference... qtractorSession *pSession = session(); if (pSession == NULL) return; // Reset all MIDI bus controllers... for (qtractorBus *pBus = buses().first(); pBus; pBus = pBus->next()) { qtractorMidiBus *pMidiBus = static_cast (pBus); if (pMidiBus) { qtractorMidiMonitor *pOutputMonitor = pMidiBus->midiMonitor_out(); if (pOutputMonitor) { pMidiBus->sendSysexList(); // SysEx setup! pMidiBus->setMasterVolume(pOutputMonitor->gain()); pMidiBus->setMasterPanning(pOutputMonitor->panning()); } else { qtractorMidiMonitor *pInputMonitor = pMidiBus->midiMonitor_in(); if (pInputMonitor) { pMidiBus->setMasterVolume(pInputMonitor->gain()); pMidiBus->setMasterPanning(pInputMonitor->panning()); } } } } // Reset all MIDI tracks channel bank/program and controllers... for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { if (pTrack->trackType() == qtractorTrack::Midi) { // MIDI track instrument patching (channel bank/program)... pTrack->setMidiPatch(pSession->instruments()); // MIDI track channel controllers... qtractorMidiBus *pMidiBus = static_cast (pTrack->outputBus()); qtractorMidiMonitor *pMidiMonitor = static_cast (pTrack->monitor()); if (pMidiBus && pMidiMonitor) { pMidiBus->setVolume(pTrack, pMidiMonitor->gain()); pMidiBus->setPanning(pTrack, pMidiMonitor->panning()); } } } // Re-send all mapped feedback MIDI controllers... qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl) pMidiControl->sendAllControllers(); // Done. m_iResetAllControllers = 0; } // Whether is actually pending a reset of // all the MIDI instrument/controllers... bool qtractorMidiEngine::isResetAllControllers (void) const { return (m_iResetAllControllers > 0); } // Shut-off all MIDI tracks (panic)... void qtractorMidiEngine::shutOffAllTracks (void) const { qtractorSession *pSession = session(); if (pSession == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMidiEngine::shutOffAllTracks()"); #endif QHash channels; for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { if (pTrack->trackType() == qtractorTrack::Midi) { qtractorMidiBus *pMidiBus = static_cast (pTrack->outputBus()); if (pMidiBus) { unsigned short iChannel = pTrack->midiChannel(); unsigned short iChannelMask = (1 << iChannel); unsigned short iChannelFlags = channels.value(pMidiBus, 0); if ((iChannelFlags & iChannelMask) == 0) { pMidiBus->setController(pTrack, ALL_SOUND_OFF); pMidiBus->setController(pTrack, ALL_NOTES_OFF); pMidiBus->setController(pTrack, ALL_CONTROLLERS_OFF); channels.insert(pMidiBus, iChannelFlags | iChannelMask); } } } } } // MIDI event capture method. void qtractorMidiEngine::capture ( snd_seq_event_t *pEv ) { qtractorMidiEvent::EventType type; unsigned short iChannel = 0; unsigned char data1 = 0; unsigned char data2 = 0; unsigned long duration = 0; unsigned char *pSysex = NULL; unsigned short iSysex = 0; int iAlsaPort = pEv->dest.port; qtractorSession *pSession = session(); if (pSession == NULL) return; // - capture quantization... if (m_iCaptureQuantize > 0) { unsigned long q = pSession->ticksPerBeat() / m_iCaptureQuantize; pEv->time.tick = q * ((pEv->time.tick + (q >> 1)) / q); } #ifdef CONFIG_DEBUG_0 // - show event for debug purposes... fprintf(stderr, "MIDI In %06lu 0x%02x", pEv->time.tick, pEv->type); if (pEv->type == SND_SEQ_EVENT_SYSEX) { fprintf(stderr, " sysex {"); unsigned char *data = (unsigned char *) pEv->data.ext.ptr; for (unsigned int i = 0; i < pEv->data.ext.len; ++i) fprintf(stderr, " %02x", data[i]); fprintf(stderr, " }\n"); } else { for (unsigned int i = 0; i < sizeof(pEv->data.raw8.d); ++i) fprintf(stderr, " %3d", pEv->data.raw8.d[i]); fprintf(stderr, "\n"); } #endif switch (pEv->type) { case SND_SEQ_EVENT_NOTE: case SND_SEQ_EVENT_NOTEON: type = qtractorMidiEvent::NOTEON; iChannel = pEv->data.note.channel; data1 = pEv->data.note.note; data2 = pEv->data.note.velocity; duration = pEv->data.note.duration; if (data2 == 0) { pEv->type = SND_SEQ_EVENT_NOTEOFF; type = qtractorMidiEvent::NOTEOFF; } break; case SND_SEQ_EVENT_NOTEOFF: type = qtractorMidiEvent::NOTEOFF; iChannel = pEv->data.note.channel; data1 = pEv->data.note.note; data2 = pEv->data.note.velocity; duration = pEv->data.note.duration; break; case SND_SEQ_EVENT_KEYPRESS: type = qtractorMidiEvent::KEYPRESS; iChannel = pEv->data.note.channel; data1 = pEv->data.note.note; data2 = pEv->data.note.velocity; break; case SND_SEQ_EVENT_CONTROLLER: type = qtractorMidiEvent::CONTROLLER; iChannel = pEv->data.control.channel; data1 = pEv->data.control.param; data2 = pEv->data.control.value; break; case SND_SEQ_EVENT_PGMCHANGE: type = qtractorMidiEvent::PGMCHANGE; iChannel = pEv->data.control.channel; data1 = 0; data2 = pEv->data.control.value; break; case SND_SEQ_EVENT_CHANPRESS: type = qtractorMidiEvent::CHANPRESS; iChannel = pEv->data.control.channel; data1 = 0; data2 = pEv->data.control.value; break; case SND_SEQ_EVENT_PITCHBEND: type = qtractorMidiEvent::PITCHBEND; iChannel = pEv->data.control.channel; iSysex = (unsigned short) (0x2000 + pEv->data.control.value); // aux. data1 = (iSysex & 0x007f); data2 = (iSysex & 0x3f80) >> 7; break; case SND_SEQ_EVENT_START: case SND_SEQ_EVENT_STOP: case SND_SEQ_EVENT_CONTINUE: case SND_SEQ_EVENT_SONGPOS: // Trap SPP commands... if ((m_sppMode & qtractorBus::Input) && m_pIControlBus && m_pIControlBus->alsaPort() == iAlsaPort) { // Post the stuffed event... m_proxy.notifySppEvent(int(pEv->type), pEv->data.control.value); } // Not handled any longer. return; case SND_SEQ_EVENT_CLOCK: // Trap MIDI Clocks... if ((m_clockMode & qtractorBus::Input) && m_pIControlBus && m_pIControlBus->alsaPort() == iAlsaPort) { static QTime s_clockTime; if (++m_iClockCount == 1) s_clockTime.start(); else if (m_iClockCount > 72) { // 3 beat averaging... m_iClockCount = 0; float fTempo = int(180000.0f / float(s_clockTime.elapsed())); if (::fabs(fTempo - m_fClockTempo) / m_fClockTempo > 0.01f) { m_fClockTempo = fTempo; // Post the stuffed event... m_proxy.notifyClkEvent(m_fClockTempo); } } } // Not handled any longer. return; case SND_SEQ_EVENT_SYSEX: type = qtractorMidiEvent::SYSEX; pSysex = (unsigned char *) pEv->data.ext.ptr; iSysex = (unsigned short) pEv->data.ext.len; // Trap MMC commands... if ((m_mmcMode & qtractorBus::Input) && pSysex[1] == 0x7f && pSysex[3] == 0x06 // MMC command mode. && m_pIControlBus && m_pIControlBus->alsaPort() == iAlsaPort) { // Post the stuffed event... m_proxy.notifyMmcEvent(qtractorMmcEvent(pSysex)); // Bail out, right now! return; } break; default: // Not handled here... return; } // Now check which bus and track we're into... bool bRecording = (pSession->isRecording() && isPlaying()); unsigned long iTime = m_iTimeStart + pEv->time.tick; for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { // Must be a MIDI track in capture/passthru // mode and for the intended channel... if (pTrack->trackType() == qtractorTrack::Midi && (pTrack->isRecord() || pSession->isTrackMonitor(pTrack)) // && !pTrack->isMute() && (!pSession->soloTracks() || pTrack->isSolo()) && pSession->isTrackMidiChannel(pTrack, iChannel)) { qtractorMidiBus *pMidiBus = static_cast (pTrack->inputBus()); if (pMidiBus && pMidiBus->alsaPort() == iAlsaPort) { // Is it actually recording?... if (pTrack->isRecord() && bRecording) { qtractorMidiClip *pMidiClip = static_cast (pTrack->clipRecord()); if (pMidiClip // && tick >= pMidiClip->clipStartTime() && (!pSession->isPunching() || ((iTime >= pSession->punchInTime()) && (iTime < pSession->punchOutTime())))) { // Yep, we got a new MIDI event... qtractorMidiEvent *pEvent = new qtractorMidiEvent( pEv->time.tick, type, data1, data2, duration); if (pSysex) pEvent->setSysex(pSysex, iSysex); (pMidiClip->sequence())->addEvent(pEvent); } } // Track input monitoring... qtractorMidiMonitor *pMidiMonitor = static_cast (pTrack->monitor()); if (pMidiMonitor) pMidiMonitor->enqueue(type, data2); // Output monitoring on record... if (pSession->isTrackMonitor(pTrack)) { pMidiBus = static_cast (pTrack->outputBus()); if (pMidiBus && pMidiBus->midiMonitor_out()) { // FIXME: MIDI-thru channel filtering prolog... unsigned short iOldChannel = pEv->data.note.channel; pEv->data.note.channel = pTrack->midiChannel(); // MIDI-thru: same event redirected... snd_seq_ev_set_source(pEv, pMidiBus->alsaPort()); snd_seq_ev_set_subs(pEv); snd_seq_ev_set_direct(pEv); snd_seq_event_output_direct(m_pAlsaSeq, pEv); // Done with MIDI-thru. pMidiBus->midiMonitor_out()->enqueue(type, data2); // Do it for the MIDI plugins too... if (!pMidiBus->isMonitor() && pMidiBus->pluginList_out() && (pMidiBus->pluginList_out())->midiManager()) ((pMidiBus->pluginList_out())->midiManager())->queued( pSession->timeScale(), pEv, iTime, m_iFrameStart); // Do it for the MIDI plugins too... if ((pTrack->pluginList())->midiManager()) (pTrack->pluginList())->midiManager()->queued( pSession->timeScale(), pEv, iTime, m_iFrameStart); // FIXME: MIDI-thru channel filtering epilog... pEv->data.note.channel = iOldChannel; } } } } } // Bus monitoring... for (qtractorBus *pBus = buses().first(); pBus; pBus = pBus->next()) { qtractorMidiBus *pMidiBus = static_cast (pBus); if (pMidiBus && pMidiBus->alsaPort() == iAlsaPort) { // Input monitoring... if (pMidiBus->midiMonitor_in()) pMidiBus->midiMonitor_in()->enqueue(type, data2); // Do it for the MIDI input plugins too... if (pMidiBus->pluginList_in() && (pMidiBus->pluginList_in())->midiManager()) ((pMidiBus->pluginList_in())->midiManager())->queued( pSession->timeScale(), pEv, iTime, m_iFrameStart); // Output monitoring on passthru... if (pMidiBus->isMonitor()) { // Do it for the MIDI output plugins too... if (pMidiBus->pluginList_out() && (pMidiBus->pluginList_out())->midiManager()) ((pMidiBus->pluginList_out())->midiManager())->queued( pSession->timeScale(), pEv, iTime, m_iFrameStart); if (pMidiBus->midiMonitor_out()) { // MIDI-thru: same event redirected... snd_seq_ev_set_source(pEv, pMidiBus->alsaPort()); snd_seq_ev_set_subs(pEv); snd_seq_ev_set_direct(pEv); snd_seq_event_output_direct(m_pAlsaSeq, pEv); // Done with MIDI-thru. pMidiBus->midiMonitor_out()->enqueue(type, data2); } } } } // Trap controller commands... if (type == qtractorMidiEvent::SYSEX) return; if (m_pIControlBus && m_pIControlBus->alsaPort() == iAlsaPort) { // Post the stuffed event... if (type == qtractorMidiEvent::PITCHBEND) { m_proxy.notifyCtlEvent( qtractorCtlEvent(type, iChannel, 0, iSysex)); } else { m_proxy.notifyCtlEvent( qtractorCtlEvent(type, iChannel, data1, data2)); } } } // MIDI event enqueue method. void qtractorMidiEngine::enqueue ( qtractorTrack *pTrack, qtractorMidiEvent *pEvent, unsigned long iTime, float fGain ) { qtractorSession *pSession = session(); if (pSession == NULL) return; // Target MIDI bus... qtractorMidiBus *pMidiBus = static_cast (pTrack->outputBus()); if (pMidiBus == NULL) return; #if 0 // HACK: Ignore our own mixer-monitor supplied controllers... if (pEvent->type() == qtractorMidiEvent::CONTROLLER) { if (pEvent->controller() == CHANNEL_VOLUME || pEvent->controller() == CHANNEL_PANNING) return; } #endif // Scheduled delivery: take into account // the time playback/queue started... unsigned long tick = (long(iTime) > m_iTimeStart ? iTime - m_iTimeStart : 0); #ifdef CONFIG_DEBUG_0 // - show event for debug purposes... fprintf(stderr, "MIDI Out %06lu 0x%02x", tick, (int) pEvent->type() | pTrack->midiChannel()); if (pEvent->type() == qtractorMidiEvent::SYSEX) { fprintf(stderr, " sysex {"); unsigned char *data = (unsigned char *) pEvent->sysex(); for (unsigned int i = 0; i < pEvent->sysex_len(); ++i) fprintf(stderr, " %02x", data[i]); fprintf(stderr, " }\n"); } else { fprintf(stderr, " %3d %3d (duration=%lu)\n", pEvent->note(), pEvent->velocity(), pEvent->duration()); } #endif // Intialize outbound event... snd_seq_event_t ev; snd_seq_ev_clear(&ev); // Set Event tag... ev.tag = (unsigned char) (pTrack->midiTag() & 0xff); // Addressing... snd_seq_ev_set_source(&ev, pMidiBus->alsaPort()); snd_seq_ev_set_subs(&ev); // Scheduled delivery... snd_seq_ev_schedule_tick(&ev, m_iAlsaQueue, 0, tick); // Set proper event data... switch (pEvent->type()) { case qtractorMidiEvent::NOTEON: ev.type = SND_SEQ_EVENT_NOTE; ev.data.note.channel = pTrack->midiChannel(); ev.data.note.note = pEvent->note(); ev.data.note.velocity = int(fGain * float(pEvent->value())) & 0x7f; ev.data.note.duration = pEvent->duration(); if (pSession->isLooping()) { unsigned long le = pSession->tickFromFrame(pSession->loopEnd()); if (le < iTime + ev.data.note.duration) ev.data.note.duration = le - iTime; } break; case qtractorMidiEvent::KEYPRESS: ev.type = SND_SEQ_EVENT_KEYPRESS; ev.data.note.channel = pTrack->midiChannel(); ev.data.note.note = pEvent->note(); ev.data.note.velocity = pEvent->velocity(); ev.data.note.duration = 0; break; case qtractorMidiEvent::CONTROLLER: ev.type = SND_SEQ_EVENT_CONTROLLER; ev.data.control.channel = pTrack->midiChannel(); ev.data.control.param = pEvent->controller(); // Track properties override... switch (pEvent->controller()) { case BANK_SELECT_MSB: if (pTrack->midiBank() >= 0) ev.data.control.value = (pTrack->midiBank() & 0x3f80) >> 7; break; case BANK_SELECT_LSB: if (pTrack->midiBank() >= 0) ev.data.control.value = (pTrack->midiBank() & 0x7f); break; case CHANNEL_VOLUME: ev.data.control.value = int(pTrack->gain() * float(pEvent->value())) & 0x7f; break; default: ev.data.control.value = pEvent->value(); } break; case qtractorMidiEvent::PGMCHANGE: ev.type = SND_SEQ_EVENT_PGMCHANGE; ev.data.control.channel = pTrack->midiChannel(); ev.data.control.value = pEvent->value(); // HACK: Track properties override... if (pTrack->midiProg() >= 0) ev.data.control.value = pTrack->midiProg(); break; case qtractorMidiEvent::CHANPRESS: ev.type = SND_SEQ_EVENT_CHANPRESS; ev.data.control.channel = pTrack->midiChannel(); ev.data.control.value = pEvent->value(); break; case qtractorMidiEvent::PITCHBEND: ev.type = SND_SEQ_EVENT_PITCHBEND; ev.data.control.channel = pTrack->midiChannel(); ev.data.control.value = pEvent->pitchBend(); break; case qtractorMidiEvent::SYSEX: { ev.type = SND_SEQ_EVENT_SYSEX; if (pMidiBus->midiMonitor_out()) { // HACK: Master volume hack... unsigned char *data = pEvent->sysex(); if (data[1] == 0x7f && data[2] == 0x7f && data[3] == 0x04 && data[4] == 0x01) { // Make a copy, update and cache it while queued... pEvent = new qtractorMidiEvent(*pEvent); data = pEvent->sysex(); data[5] = 0; data[6] = int(pMidiBus->midiMonitor_out()->gain() * float(data[6])) & 0x7f; m_sysexCache.append(pEvent); } } snd_seq_ev_set_sysex(&ev, pEvent->sysex_len(), pEvent->sysex()); break; } default: break; } // Pump it into the queue. snd_seq_event_output(m_pAlsaSeq, &ev); // MIDI track monitoring... qtractorMidiMonitor *pMidiMonitor = static_cast (pTrack->monitor()); if (pMidiMonitor) pMidiMonitor->enqueue(pEvent->type(), pEvent->value(), tick); // MIDI bus monitoring... if (pMidiBus->midiMonitor_out()) pMidiBus->midiMonitor_out()->enqueue( pEvent->type(), pEvent->value(), tick); // Do it for the MIDI track plugins too... qtractorTimeScale *pTimeScale = pSession->timeScale(); if ((pTrack->pluginList())->midiManager()) (pTrack->pluginList())->midiManager()->queued( pTimeScale, &ev, iTime, m_iFrameStart); // And for the MIDI output plugins as well... if (pMidiBus->pluginList_out() && (pMidiBus->pluginList_out())->midiManager()) { ((pMidiBus->pluginList_out())->midiManager())->queued( pTimeScale, &ev, iTime, m_iFrameStart); } } // Reset ouput queue drift stats (audio vs. MIDI)... void qtractorMidiEngine::resetDrift (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiEngine::resetDrift()"); #endif m_iDriftCheck = 0; //--DRIFT-SKEW-BEGIN-- snd_seq_queue_tempo_t *pAlsaTempo; snd_seq_queue_tempo_alloca(&pAlsaTempo); snd_seq_get_queue_tempo(m_pAlsaSeq, m_iAlsaQueue, pAlsaTempo); unsigned int iSkewBase = snd_seq_queue_tempo_get_skew_base(pAlsaTempo); snd_seq_queue_tempo_set_skew(pAlsaTempo, iSkewBase); snd_seq_set_queue_tempo(m_pAlsaSeq, m_iAlsaQueue, pAlsaTempo); //--DRIFT-SKEW-END-- m_iTimeDrift = 0; } // Do ouput queue status (audio vs. MIDI)... void qtractorMidiEngine::drift (void) { if (++m_iDriftCheck < DRIFT_CHECK) return; qtractorSession *pSession = session(); if (pSession == NULL) return; // if (pSession->isRecording()) // return; if (m_pMetroCursor == NULL) return; // Time to have some corrective approach...? snd_seq_queue_status_t *pQueueStatus; snd_seq_queue_status_alloca(&pQueueStatus); if (snd_seq_get_queue_status( m_pAlsaSeq, m_iAlsaQueue, pQueueStatus) >= 0) { // unsigned long iAudioFrame = pSession->playHead(); unsigned long iAudioFrame = pSession->audioEngine()->jackFrame() - m_iFrameTime; qtractorTimeScale::Node *pNode = m_pMetroCursor->seekFrame(iAudioFrame); long iAudioTime = long(pNode->tickFromFrame(iAudioFrame)); long iMidiTime = m_iTimeStart + long(snd_seq_queue_status_get_tick_time(pQueueStatus)); long iDeltaTime = (iAudioTime - iMidiTime); if (iDeltaTime && iAudioTime > 0 && iMidiTime > m_iTimeDrift) { //--DRIFT-SKEW-BEGIN-- snd_seq_queue_tempo_t *pAlsaTempo; snd_seq_queue_tempo_alloca(&pAlsaTempo); snd_seq_get_queue_tempo(m_pAlsaSeq, m_iAlsaQueue, pAlsaTempo); unsigned int iSkewBase = snd_seq_queue_tempo_get_skew_base(pAlsaTempo); unsigned int iSkewPrev = snd_seq_queue_tempo_get_skew(pAlsaTempo); unsigned int iSkewNext = (unsigned int) (float(iSkewBase) * float(iAudioTime) / float(iMidiTime - m_iTimeDrift)); if (iSkewNext != iSkewPrev) { snd_seq_queue_tempo_set_skew(pAlsaTempo, iSkewNext); snd_seq_set_queue_tempo(m_pAlsaSeq, m_iAlsaQueue, pAlsaTempo); } //--DRIFT-SKEW-END-- m_iTimeDrift += iDeltaTime; // m_iTimeDrift >>= 1; // Damp fast-average drift? #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiEngine::drift(): " "iAudioTime=%ld iMidiTime=%ld (%ld) iTimeDrift=%ld (%.2g%%)", iAudioTime, iMidiTime, iDeltaTime, m_iTimeDrift, ((100.0f * float(iSkewNext)) / float(iSkewBase)) - 100.0f); #endif } } // Restart counting... m_iDriftCheck = 0; } // Flush ouput queue (if necessary)... void qtractorMidiEngine::flush (void) { // Really flush MIDI output... snd_seq_drain_output(m_pAlsaSeq); } // Device engine initialization method. bool qtractorMidiEngine::init (void) { // There must a session reference... qtractorSession *pSession = session(); if (pSession == NULL) return false; // Try open a new client... if (snd_seq_open(&m_pAlsaSeq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK) < 0) return false; if (m_pAlsaSeq == NULL) return false; // Fix client name. const QByteArray aClientName = pSession->clientName().toUtf8(); snd_seq_set_client_name(m_pAlsaSeq, aClientName.constData()); m_iAlsaClient = snd_seq_client_id(m_pAlsaSeq); m_iAlsaQueue = snd_seq_alloc_queue(m_pAlsaSeq); // Set sequencer queue timer. if (qtractorMidiTimer().indexOf(m_iAlsaTimer) > 0) { qtractorMidiTimer::Key key(m_iAlsaTimer); snd_timer_id_t *pAlsaTimerId; snd_timer_id_alloca(&pAlsaTimerId); snd_timer_id_set_class(pAlsaTimerId, key.alsaTimerClass()); snd_timer_id_set_card(pAlsaTimerId, key.alsaTimerCard()); snd_timer_id_set_device(pAlsaTimerId, key.alsaTimerDevice()); snd_timer_id_set_subdevice(pAlsaTimerId, key.alsaTimerSubDev()); snd_seq_queue_timer_t *pAlsaTimer; snd_seq_queue_timer_alloca(&pAlsaTimer); snd_seq_queue_timer_set_type(pAlsaTimer, SND_SEQ_TIMER_ALSA); snd_seq_queue_timer_set_id(pAlsaTimer, pAlsaTimerId); snd_seq_set_queue_timer(m_pAlsaSeq, m_iAlsaQueue, pAlsaTimer); } // Setup subscriptions stuff... if (snd_seq_open(&m_pAlsaSubsSeq, "hw", SND_SEQ_OPEN_DUPLEX, 0) >= 0) { m_iAlsaSubsPort = snd_seq_create_simple_port( m_pAlsaSubsSeq, clientName().toUtf8().constData(), SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE | SND_SEQ_PORT_CAP_NO_EXPORT, SND_SEQ_PORT_TYPE_APPLICATION); if (m_iAlsaSubsPort >= 0) { struct pollfd pfd[1]; snd_seq_addr_t seq_addr; snd_seq_port_subscribe_t *pAlsaSubs; snd_seq_port_subscribe_alloca(&pAlsaSubs); seq_addr.client = SND_SEQ_CLIENT_SYSTEM; seq_addr.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE; snd_seq_port_subscribe_set_sender(pAlsaSubs, &seq_addr); seq_addr.client = snd_seq_client_id(m_pAlsaSubsSeq); seq_addr.port = m_iAlsaSubsPort; snd_seq_port_subscribe_set_dest(pAlsaSubs, &seq_addr); snd_seq_subscribe_port(m_pAlsaSubsSeq, pAlsaSubs); snd_seq_poll_descriptors(m_pAlsaSubsSeq, pfd, 1, POLLIN); m_pAlsaNotifier = new QSocketNotifier( pfd[0].fd, QSocketNotifier::Read); } } // Time-scale cursor (tempo/time-signature map) m_pMetroCursor = new qtractorTimeScale::Cursor(pSession->timeScale()); return true; } // Device engine activation method. bool qtractorMidiEngine::activate (void) { // Open SMF player to last... openPlayerBus(); // Open control/metronome buses, at least try... openControlBus(); openMetroBus(); // Create and start our own MIDI input queue thread... m_pInputThread = new qtractorMidiInputThread(this); m_pInputThread->start(QThread::TimeCriticalPriority); // Create and start our own MIDI output queue thread... unsigned int iReadAhead = (session()->sampleRate() >> 1); m_pOutputThread = new qtractorMidiOutputThread(this, iReadAhead); m_pOutputThread->start(QThread::HighPriority); // Reset/zero tickers... m_iTimeStart = 0; // Reset output queue drift compensator... resetDrift(); // Reset all dependable monitoring... resetAllMonitors(); return true; } // Device engine start method. bool qtractorMidiEngine::start (void) { // It must be surely activated... if (!isActivated()) return false; // There must a session reference... qtractorSession *pSession = session(); if (pSession == NULL) return false; // Output thread must be around too... if (m_pOutputThread == NULL) return false; // Close any SMF player out there... closePlayer(); // Initial output thread bumping... qtractorSessionCursor *pMidiCursor = m_pOutputThread->midiCursorSync(true); if (pMidiCursor == NULL) return false; // Reset all dependables... resetTempo(); resetAllMonitors(); // Reset output queue drift compensator... resetDrift(); // Start queue timer... m_iFrameStart = long(pMidiCursor->frame()); m_iTimeStart = long(pSession->tickFromFrame(m_iFrameStart)); m_iFrameTime = long(pSession->audioEngine()->jackFrame()) - m_iFrameStart; // Effectively start sequencer queue timer... snd_seq_start_queue(m_pAlsaSeq, m_iAlsaQueue, NULL); snd_seq_drain_output(m_pAlsaSeq); // Carry on... m_pOutputThread->processSync(); return true; } // Device engine stop method. void qtractorMidiEngine::stop (void) { if (!isActivated()) return; // Cleanup queues... snd_seq_drop_input(m_pAlsaSeq); snd_seq_drop_output(m_pAlsaSeq); // Stop queue timer... snd_seq_stop_queue(m_pAlsaSeq, m_iAlsaQueue, NULL); snd_seq_drain_output(m_pAlsaSeq); // Shut-off all MIDI buses... for (qtractorBus *pBus = qtractorEngine::buses().first(); pBus; pBus = pBus->next()) { qtractorMidiBus *pMidiBus = static_cast (pBus); if (pMidiBus) pMidiBus->shutOff(); } } // Device engine deactivation method. void qtractorMidiEngine::deactivate (void) { // We're stopping now... setPlaying(false); // Stop our queue threads... m_pInputThread->setRunState(false); m_pOutputThread->setRunState(false); m_pOutputThread->sync(); } // Device engine cleanup method. void qtractorMidiEngine::clean (void) { // Clean control/metronome buses... deleteControlBus(); deleteMetroBus(); // Close SMF player last... deletePlayerBus(); // Delete output thread... if (m_pOutputThread) { // Make it nicely... if (m_pOutputThread->isRunning()) { // m_pOutputThread->terminate(); m_pOutputThread->wait(); } delete m_pOutputThread; m_pOutputThread = NULL; m_iTimeStart = 0; m_iTimeDrift = 0; } // Last but not least, delete input thread... if (m_pInputThread) { // Make it nicely... if (m_pInputThread->isRunning()) { // m_pInputThread->terminate(); m_pInputThread->wait(); } delete m_pInputThread; m_pInputThread = NULL; } // Time-scale cursor (tempo/time-signature map) if (m_pMetroCursor) { delete m_pMetroCursor; m_pMetroCursor = NULL; } // Drop subscription stuff. if (m_pAlsaSubsSeq) { if (m_pAlsaNotifier) { delete m_pAlsaNotifier; m_pAlsaNotifier = NULL; } if (m_iAlsaSubsPort >= 0) { snd_seq_delete_simple_port(m_pAlsaSubsSeq, m_iAlsaSubsPort); m_iAlsaSubsPort = -1; } snd_seq_close(m_pAlsaSubsSeq); m_pAlsaSubsSeq = NULL; } // Drop everything else, finally. if (m_pAlsaSeq) { // And now, the sequencer queue and handle... snd_seq_free_queue(m_pAlsaSeq, m_iAlsaQueue); snd_seq_close(m_pAlsaSeq); m_iAlsaQueue = -1; m_iAlsaClient = -1; m_pAlsaSeq = NULL; } // Clean any other left-overs... clearSysexCache(); } // Special rewind method, for queue loop. void qtractorMidiEngine::restartLoop (void) { qtractorSession *pSession = session(); if (pSession && pSession->isLooping()) { unsigned long iLoopStart = pSession->loopStart(); unsigned long iLoopEnd = pSession->loopEnd(); long iLoopLength = long(iLoopEnd - iLoopStart); m_iFrameTime += iLoopLength; m_iFrameStart -= iLoopLength; m_iTimeStart -= long(pSession->tickFromFrame(iLoopEnd) - pSession->tickFromFrame(iLoopStart)); // m_iTimeStart += m_iTimeDrift; -- Drift correction? resetDrift(); } } // The delta-time/frame accessors. long qtractorMidiEngine::timeStart (void) const { return m_iTimeStart; } long qtractorMidiEngine::frameStart (void) const { return m_iFrameStart; } // Immediate track mute. void qtractorMidiEngine::trackMute ( qtractorTrack *pTrack, bool bMute ) { #ifdef CONFIG_DEBUG qDebug("qtractorMidiEngine::trackMute(%p, %d)", pTrack, bMute); #endif qtractorSession *pSession = session(); if (pSession == NULL) return; unsigned long iFrame = pSession->playHead(); if (bMute) { // Remove all already enqueued events // for the given track and channel... snd_seq_remove_events_t *pre; snd_seq_remove_events_alloca(&pre); snd_seq_timestamp_t ts; unsigned long iTime = pSession->tickFromFrame(iFrame); ts.tick = ((long) iTime > m_iTimeStart ? iTime - m_iTimeStart : 0); snd_seq_remove_events_set_time(pre, &ts); snd_seq_remove_events_set_tag(pre, pTrack->midiTag()); snd_seq_remove_events_set_channel(pre, pTrack->midiChannel()); snd_seq_remove_events_set_queue(pre, m_iAlsaQueue); snd_seq_remove_events_set_condition(pre, SND_SEQ_REMOVE_OUTPUT | SND_SEQ_REMOVE_TIME_AFTER | SND_SEQ_REMOVE_TIME_TICK | SND_SEQ_REMOVE_DEST_CHANNEL | SND_SEQ_REMOVE_IGNORE_OFF | SND_SEQ_REMOVE_TAG_MATCH); snd_seq_remove_events(m_pAlsaSeq, pre); // Immediate all current notes off. qtractorMidiBus *pMidiBus = static_cast (pTrack->outputBus()); if (pMidiBus) pMidiBus->setController(pTrack, ALL_NOTES_OFF); // Clear/reset track monitor... qtractorMidiMonitor *pMidiMonitor = static_cast (pTrack->monitor()); if (pMidiMonitor) pMidiMonitor->clear(); // Reset track plugin buffers... if ((pTrack->pluginList())->midiManager()) (pTrack->pluginList())->midiManager()->reset(); // Done track mute. } else { // Must redirect to MIDI ouput thread: // the immediate re-enqueueing of MIDI events. m_pOutputThread->trackSync(pTrack, iFrame); // Done track unmute. } } // Immediate metronome mute. void qtractorMidiEngine::metroMute ( bool bMute ) { if (!m_bMetroEnabled) return; if (!m_bMetronome) return; #ifdef CONFIG_DEBUG qDebug("qtractorMidiEngine::metroMute(%d)\n", int(bMute)); #endif qtractorSession *pSession = session(); if (pSession == NULL) return; unsigned long iFrame = pSession->playHead(); if (bMute) { // Remove all already enqueued events // for the given track and channel... snd_seq_remove_events_t *pre; snd_seq_remove_events_alloca(&pre); snd_seq_timestamp_t ts; unsigned long iTime = pSession->tickFromFrame(iFrame); ts.tick = ((long) iTime > m_iTimeStart ? iTime - m_iTimeStart : 0); snd_seq_remove_events_set_time(pre, &ts); snd_seq_remove_events_set_tag(pre, 0xff); snd_seq_remove_events_set_channel(pre, m_iMetroChannel); snd_seq_remove_events_set_queue(pre, m_iAlsaQueue); snd_seq_remove_events_set_condition(pre, SND_SEQ_REMOVE_OUTPUT | SND_SEQ_REMOVE_TIME_AFTER | SND_SEQ_REMOVE_TIME_TICK | SND_SEQ_REMOVE_DEST_CHANNEL | SND_SEQ_REMOVE_IGNORE_OFF | SND_SEQ_REMOVE_TAG_MATCH); snd_seq_remove_events(m_pAlsaSeq, pre); // Done metronome mute. } else { // Must redirect to MIDI ouput thread: // the immediate re-enqueueing of MIDI events. m_pOutputThread->metroSync(iFrame); // Done metronome unmute. } } // Control bus accessors. void qtractorMidiEngine::setControlBus ( bool bControlBus ) { deleteControlBus(); m_bControlBus = bControlBus; createControlBus(); if (isActivated()) openControlBus(); } bool qtractorMidiEngine::isControlBus (void) const { return m_bControlBus; } void qtractorMidiEngine::resetControlBus (void) { if (m_bControlBus && m_pOControlBus) return; createControlBus(); } // Control bus simple management. void qtractorMidiEngine::createControlBus (void) { deleteControlBus(); // Whether control bus is here owned, or... if (m_bControlBus) { m_pOControlBus = new qtractorMidiBus(this, "Control", qtractorBus::BusMode(qtractorBus::Duplex | qtractorBus::Ex)); m_pIControlBus = m_pOControlBus; } else { // Find available control buses... for (qtractorBus *pBus = qtractorEngine::buses().first(); pBus; pBus = pBus->next()) { if (m_pIControlBus == NULL && (pBus->busMode() & qtractorBus::Input)) m_pIControlBus = static_cast (pBus); if (m_pOControlBus == NULL && (pBus->busMode() & qtractorBus::Output)) m_pOControlBus = static_cast (pBus); } } } // Open MIDI control stuff... bool qtractorMidiEngine::openControlBus (void) { closeControlBus(); // Is there any? if (m_pOControlBus == NULL) createControlBus(); if (m_pOControlBus == NULL) return false; // This is it, when dedicated... if (m_bControlBus) { addBusEx(m_pOControlBus); m_pOControlBus->open(); } return true; } // Close MIDI control stuff. void qtractorMidiEngine::closeControlBus (void) { if (m_pOControlBus && m_bControlBus) { m_pOControlBus->close(); removeBusEx(m_pOControlBus); } } // Destroy MIDI control stuff. void qtractorMidiEngine::deleteControlBus (void) { closeControlBus(); // When owned, both input and output // bus are the one and the same... if (m_pOControlBus && m_bControlBus) delete m_pOControlBus; // Reset both control buses... m_pIControlBus = NULL; m_pOControlBus = NULL; } // Control buses accessors. qtractorMidiBus *qtractorMidiEngine::controlBus_in() const { return m_pIControlBus; } qtractorMidiBus *qtractorMidiEngine::controlBus_out() const { return m_pOControlBus; } // Player bus accessors. void qtractorMidiEngine::setPlayerBus ( bool bPlayerBus ) { deletePlayerBus(); m_bPlayerBus = bPlayerBus; createPlayerBus(); if (isActivated()) openPlayerBus(); } bool qtractorMidiEngine::isPlayerBus (void) const { return m_bPlayerBus; } // Player bus simple management. void qtractorMidiEngine::createPlayerBus (void) { deletePlayerBus(); // Whether metronome bus is here owned, or... if (m_bPlayerBus) { m_pPlayerBus = new qtractorMidiBus(this, "Player", qtractorBus::BusMode(qtractorBus::Output | qtractorBus::Ex)); } else { // Find first available output buses... for (qtractorBus *pBus = qtractorEngine::buses().first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Output) { m_pPlayerBus = static_cast (pBus); break; } } } } // Open MIDI player stuff... bool qtractorMidiEngine::openPlayerBus (void) { closePlayerBus(); // Is there any? if (m_pPlayerBus == NULL) createPlayerBus(); if (m_pPlayerBus == NULL) return false; // This is it, when dedicated... if (m_bPlayerBus) { addBusEx(m_pPlayerBus); m_pPlayerBus->open(); } // Time to create our player... m_pPlayer = new qtractorMidiPlayer(m_pPlayerBus); return true; } // Close MIDI player stuff. void qtractorMidiEngine::closePlayerBus (void) { if (m_pPlayer) m_pPlayer->close(); if (m_pPlayerBus && m_bPlayerBus) { m_pPlayerBus->close(); removeBusEx(m_pPlayerBus); } } // Destroy MIDI player stuff. void qtractorMidiEngine::deletePlayerBus (void) { closePlayerBus(); if (m_pPlayer) { delete m_pPlayer; m_pPlayer = NULL; } if (m_pPlayerBus && m_bPlayerBus) delete m_pPlayerBus; m_pPlayerBus = NULL; } // Tell whether audition/pre-listening is active... bool qtractorMidiEngine::isPlayerOpen (void) const { return (m_pPlayer ? m_pPlayer->isOpen() : false); } // Open and start audition/pre-listening... bool qtractorMidiEngine::openPlayer ( const QString& sFilename, int iTrackChannel ) { if (isPlaying()) return false; m_iFrameStart = 0; m_iTimeStart = 0; return (m_pPlayer ? m_pPlayer->open(sFilename, iTrackChannel) : false); } // Stop and close audition/pre-listening... void qtractorMidiEngine::closePlayer (void) { if (m_pPlayer) m_pPlayer->close(); } // MMC dispatch special commands. void qtractorMidiEngine::sendMmcLocate ( unsigned long iLocate ) const { unsigned char data[6]; data[0] = 0x01; data[1] = iLocate / (3600 * 30); iLocate -= (3600 * 30) * (int) data[1]; data[2] = iLocate / ( 60 * 30); iLocate -= ( 60 * 30) * (int) data[2]; data[3] = iLocate / ( 30); iLocate -= ( 30) * (int) data[3]; data[4] = iLocate; data[5] = 0; sendMmcCommand(qtractorMmcEvent::LOCATE, data, sizeof(data)); } void qtractorMidiEngine::sendMmcMaskedWrite ( qtractorMmcEvent::SubCommand scmd, int iTrack, bool bOn ) const { unsigned char data[4]; int iMask = (1 << (iTrack < 2 ? iTrack + 5 : (iTrack - 2) % 7)); data[0] = scmd; data[1] = (unsigned char) (iTrack < 2 ? 0 : 1 + (iTrack - 2) / 7); data[2] = (unsigned char) iMask; data[3] = (unsigned char) (bOn ? iMask : 0); sendMmcCommand(qtractorMmcEvent::MASKED_WRITE, data, sizeof(data)); } void qtractorMidiEngine::sendMmcCommand ( qtractorMmcEvent::Command cmd, unsigned char *pMmcData, unsigned short iMmcData ) const { // Do we have MMC output enabled? if ((m_mmcMode & qtractorBus::Output) == 0) return; // We surely need a output control bus... if (m_pOControlBus == NULL) return; // Build up the MMC sysex message... unsigned char *pSysex; unsigned short iSysex; iSysex = 6; if (pMmcData && iMmcData > 0) iSysex += 1 + iMmcData; pSysex = new unsigned char [iSysex]; iSysex = 0; pSysex[iSysex++] = 0xf0; // Sysex header. pSysex[iSysex++] = 0x7f; // Realtime sysex. pSysex[iSysex++] = m_mmcDevice; // MMC device id. pSysex[iSysex++] = 0x06; // MMC command mode. pSysex[iSysex++] = (unsigned char) cmd; // MMC command code. if (pMmcData && iMmcData > 0) { pSysex[iSysex++] = iMmcData; ::memcpy(&pSysex[iSysex], pMmcData, iMmcData); iSysex += iMmcData; } pSysex[iSysex++] = 0xf7; // Sysex trailer. // Send it out, now. m_pOControlBus->sendSysex(pSysex, iSysex); // Done. delete [] pSysex; } // SPP dispatch special command. void qtractorMidiEngine::sendSppCommand ( int iCmdType, unsigned short iSongPos ) const { // Do we have SPP output enabled? if ((m_sppMode & qtractorBus::Output) == 0) return; // We surely need a output control bus... if (m_pOControlBus == NULL) return; // Initialize sequencer event... snd_seq_event_t ev; snd_seq_ev_clear(&ev); // Addressing... snd_seq_ev_set_source(&ev, m_pOControlBus->alsaPort()); snd_seq_ev_set_subs(&ev); // The event will be direct... snd_seq_ev_set_direct(&ev); // Set command parameters... // - SND_SEQ_EVENT_START // - SND_SEQ_EVENT_STOP // - SND_SEQ_EVENT_CONTINUE // - SND_SEQ_EVENT_SONGPOS ev.type = snd_seq_event_type(iCmdType); ev.data.control.value = iSongPos; // Bail out... snd_seq_event_output_direct(m_pAlsaSeq, &ev); } // Metronome switching. void qtractorMidiEngine::setMetronome ( bool bMetronome ) { m_bMetronome = bMetronome; if (isPlaying()) metroMute(!m_bMetronome); } bool qtractorMidiEngine::isMetronome (void) const { return m_bMetronome; } // Metronome enabled accessors. void qtractorMidiEngine::setMetroEnabled ( bool bMetroEnabled ) { m_bMetroEnabled = bMetroEnabled; } bool qtractorMidiEngine::isMetroEnabled (void) const { return m_bMetroEnabled; } // Metronome bus accessors. void qtractorMidiEngine::setMetroBus ( bool bMetroBus ) { deleteMetroBus(); m_bMetroBus = bMetroBus; createMetroBus(); if (isActivated()) openMetroBus(); } bool qtractorMidiEngine::isMetroBus (void) const { return m_bMetroBus; } void qtractorMidiEngine::resetMetroBus (void) { if (m_bMetroBus && m_pMetroBus) return; createMetroBus(); } // Metronome bus simple management. void qtractorMidiEngine::createMetroBus (void) { deleteMetroBus(); if (!m_bMetroEnabled) return; // Whether metronome bus is here owned, or... if (m_bMetroBus) { m_pMetroBus = new qtractorMidiBus(this, "Metronome", qtractorBus::BusMode(qtractorBus::Output | qtractorBus::Ex)); } else { // Find first available output buses... for (qtractorBus *pBus = qtractorEngine::buses().first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Output) { m_pMetroBus = static_cast (pBus); break; } } } } // Open MIDI metronome stuff... bool qtractorMidiEngine::openMetroBus (void) { closeMetroBus(); if (!m_bMetroEnabled) return false; // Is there any? if (m_pMetroBus == NULL) createMetroBus(); if (m_pMetroBus == NULL) return false; // This is it, when dedicated... if (m_bMetroBus) { addBusEx(m_pMetroBus); m_pMetroBus->open(); } return true; } // Close MIDI metronome stuff. void qtractorMidiEngine::closeMetroBus (void) { if (m_pMetroBus && m_bMetroBus) { m_pMetroBus->close(); removeBusEx(m_pMetroBus); } } // Destroy MIDI metronome stuff. void qtractorMidiEngine::deleteMetroBus (void) { closeMetroBus(); if (m_pMetroBus && m_bMetroBus) delete m_pMetroBus; m_pMetroBus = NULL; } // Metronome channel accessors. void qtractorMidiEngine::setMetroChannel ( unsigned short iChannel ) { m_iMetroChannel = iChannel; } unsigned short qtractorMidiEngine::metroChannel (void) const { return m_iMetroChannel; } // Metronome bar parameters. void qtractorMidiEngine::setMetroBar ( int iNote, int iVelocity, unsigned long iDuration ) { m_iMetroBarNote = iNote; m_iMetroBarVelocity = iVelocity; m_iMetroBarDuration = iDuration; } int qtractorMidiEngine::metroBarNote (void) const { return m_iMetroBarNote; } int qtractorMidiEngine::metroBarVelocity (void) const { return m_iMetroBarVelocity; } unsigned long qtractorMidiEngine::metroBarDuration (void) const { return m_iMetroBarDuration; } // Metronome bar parameters. void qtractorMidiEngine::setMetroBeat ( int iNote, int iVelocity, unsigned long iDuration ) { m_iMetroBeatNote = iNote; m_iMetroBeatVelocity = iVelocity; m_iMetroBeatDuration = iDuration; } int qtractorMidiEngine::metroBeatNote (void) const { return m_iMetroBarNote; } int qtractorMidiEngine::metroBeatVelocity (void) const { return m_iMetroBarVelocity; } unsigned long qtractorMidiEngine::metroBeatDuration (void) const { return m_iMetroBeatDuration; } // Process metronome clicks. void qtractorMidiEngine::processMetro ( unsigned long iFrameStart, unsigned long iFrameEnd ) { if (m_pMetroCursor == NULL) return; qtractorTimeScale::Node *pNode = m_pMetroCursor->seekFrame(iFrameEnd); // Take this moment to check for tempo changes... if (pNode->tempo != m_fMetroTempo) { // New tempo node... unsigned long iTime = (pNode->frame < iFrameStart ? pNode->tickFromFrame(iFrameStart) : pNode->tick); // Enqueue tempo event... snd_seq_event_t ev; snd_seq_ev_clear(&ev); // Scheduled delivery: take into account // the time playback/queue started... unsigned long tick = ((long) iTime > m_iTimeStart ? iTime - m_iTimeStart : 0); snd_seq_ev_schedule_tick(&ev, m_iAlsaQueue, 0, tick); ev.type = SND_SEQ_EVENT_TEMPO; ev.data.queue.queue = m_iAlsaQueue; ev.data.queue.param.value = (unsigned int) (60000000.0f / pNode->tempo); ev.dest.client = SND_SEQ_CLIENT_SYSTEM; ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; // Pump it into the queue. snd_seq_event_output(m_pAlsaSeq, &ev); // Save for next change. m_fMetroTempo = pNode->tempo; // Update MIDI monitor slot stuff... qtractorMidiMonitor::splitTime( m_pMetroCursor->timeScale(), pNode->frame, tick); } // Get on with the actual metronome/clock stuff... if (!m_bMetronome && (m_clockMode & qtractorBus::Output) == 0) return; // Register the next metronome/clock beat slot. unsigned long iTimeEnd = pNode->tickFromFrame(iFrameEnd); pNode = m_pMetroCursor->seekFrame(iFrameStart); unsigned long iTimeStart = pNode->tickFromFrame(iFrameStart); unsigned int iBeat = pNode->beatFromTick(iTimeStart); unsigned long iTime = pNode->tickFromBeat(iBeat); // Intialize outbound metronome event... snd_seq_event_t ev; snd_seq_ev_clear(&ev); // Addressing... if (m_pMetroBus) { snd_seq_ev_set_source(&ev, m_pMetroBus->alsaPort()); snd_seq_ev_set_subs(&ev); } // Set common event data... ev.tag = (unsigned char) 0xff; ev.type = SND_SEQ_EVENT_NOTE; ev.data.note.channel = m_iMetroChannel; // Intialize outbound clock event... snd_seq_event_t ev_clock; snd_seq_ev_clear(&ev_clock); // Addressing... if (m_pOControlBus) { snd_seq_ev_set_source(&ev_clock, m_pOControlBus->alsaPort()); snd_seq_ev_set_subs(&ev_clock); } // Set common event data... ev_clock.tag = (unsigned char) 0xff; ev_clock.type = SND_SEQ_EVENT_CLOCK; while (iTime < iTimeEnd) { // Scheduled delivery: take into account // the time playback/queue started... if (m_clockMode & qtractorBus::Output) { unsigned long iTimeClock = iTime; unsigned int iTicksPerClock = pNode->ticksPerBeat / 24; for (unsigned int iClock = 0; iClock < 24; ++iClock) { if (iTimeClock >= iTimeEnd) break; if (iTimeClock >= iTimeStart) { unsigned long tick = (long(iTimeClock) > m_iTimeStart ? iTimeClock - m_iTimeStart : 0); snd_seq_ev_schedule_tick(&ev_clock, m_iAlsaQueue, 0, tick); snd_seq_event_output(m_pAlsaSeq, &ev_clock); } iTimeClock += iTicksPerClock; } } if (m_bMetronome && iTime >= iTimeStart) { unsigned long tick = (long(iTime) > m_iTimeStart ? iTime - m_iTimeStart : 0); snd_seq_ev_schedule_tick(&ev, m_iAlsaQueue, 0, tick); // Set proper event data... if (pNode->beatIsBar(iBeat)) { ev.data.note.note = m_iMetroBarNote; ev.data.note.velocity = m_iMetroBarVelocity; ev.data.note.duration = m_iMetroBarDuration; } else { ev.data.note.note = m_iMetroBeatNote; ev.data.note.velocity = m_iMetroBeatVelocity; ev.data.note.duration = m_iMetroBeatDuration; } // Pump it into the queue. snd_seq_event_output(m_pAlsaSeq, &ev); // MIDI track monitoring... if (m_pMetroBus->midiMonitor_out()) { m_pMetroBus->midiMonitor_out()->enqueue( qtractorMidiEvent::NOTEON, ev.data.note.velocity, tick); } } // Go for next beat... iTime += pNode->ticksPerBeat; pNode = m_pMetroCursor->seekBeat(++iBeat); } } // Access to current tempo/time-signature cursor. qtractorTimeScale::Cursor *qtractorMidiEngine::metroCursor (void) const { return m_pMetroCursor; } // Document element methods. bool qtractorMidiEngine::loadElement ( qtractorDocument *pDocument, QDomElement *pElement ) { qtractorEngine::clear(); createControlBus(); createMetroBus(); // Load session children... for (QDomNode nChild = pElement->firstChild(); !nChild.isNull(); nChild = nChild.nextSibling()) { // Convert node to element... QDomElement eChild = nChild.toElement(); if (eChild.isNull()) continue; if (eChild.tagName() == "midi-control") { for (QDomNode nProp = eChild.firstChild(); !nProp.isNull(); nProp = nProp.nextSibling()) { QDomElement eProp = nProp.toElement(); if (eProp.isNull()) continue; if (eProp.tagName() == "mmc-mode") { qtractorMidiEngine::setMmcMode( qtractorBus::busModeFromText(eProp.text())); } else if (eProp.tagName() == "mmc-device") { qtractorMidiEngine::setMmcDevice( eProp.text().toInt() & 0x7f); } else if (eProp.tagName() == "spp-mode") { qtractorMidiEngine::setSppMode( qtractorBus::busModeFromText(eProp.text())); } else if (eProp.tagName() == "clock-mode") { qtractorMidiEngine::setClockMode( qtractorBus::busModeFromText(eProp.text())); } } } else if (eChild.tagName() == "midi-bus") { QString sBusName = eChild.attribute("name"); qtractorMidiBus::BusMode busMode = qtractorBus::busModeFromText(eChild.attribute("mode")); qtractorMidiBus *pMidiBus = new qtractorMidiBus(this, sBusName, busMode); if (!pMidiBus->loadElement(pDocument, &eChild)) return false; qtractorMidiEngine::addBus(pMidiBus); } else if (eChild.tagName() == "control-inputs") { if (m_bControlBus && m_pIControlBus) { m_pIControlBus->loadConnects( m_pIControlBus->inputs(), pDocument, &eChild); } } else if (eChild.tagName() == "control-outputs") { if (m_bControlBus && m_pOControlBus) { m_pOControlBus->loadConnects( m_pOControlBus->outputs(), pDocument, &eChild); } } else if (eChild.tagName() == "metronome-outputs") { if (m_bMetroBus && m_pMetroBus) { m_pMetroBus->loadConnects( m_pMetroBus->outputs(), pDocument, &eChild); } } } return true; } bool qtractorMidiEngine::saveElement ( qtractorDocument *pDocument, QDomElement *pElement ) const { // Save transport/control modes... QDomElement eControl = pDocument->document()->createElement("midi-control"); pDocument->saveTextElement("mmc-mode", qtractorBus::textFromBusMode( qtractorMidiEngine::mmcMode()), &eControl); pDocument->saveTextElement("mmc-device", QString::number(int(qtractorMidiEngine::mmcDevice())), &eControl); pDocument->saveTextElement("spp-mode", qtractorBus::textFromBusMode( qtractorMidiEngine::sppMode()), &eControl); pDocument->saveTextElement("clock-mode", qtractorBus::textFromBusMode( qtractorMidiEngine::clockMode()), &eControl); pElement->appendChild(eControl); // Save MIDI buses... for (qtractorBus *pBus = qtractorEngine::buses().first(); pBus; pBus = pBus->next()) { qtractorMidiBus *pMidiBus = static_cast (pBus); if (pMidiBus) { // Create the new MIDI bus element... QDomElement eMidiBus = pDocument->document()->createElement("midi-bus"); pMidiBus->saveElement(pDocument, &eMidiBus); pElement->appendChild(eMidiBus); } } // Control bus (input) connects... if (m_bControlBus && m_pIControlBus) { QDomElement eInputs = pDocument->document()->createElement("control-inputs"); qtractorBus::ConnectList inputs; m_pIControlBus->updateConnects(qtractorBus::Input, inputs); m_pIControlBus->saveConnects(inputs, pDocument, &eInputs); pElement->appendChild(eInputs); } // Control bus (output) connects... if (m_bControlBus && m_pOControlBus) { QDomElement eOutputs = pDocument->document()->createElement("control-outputs"); qtractorBus::ConnectList outputs; m_pOControlBus->updateConnects(qtractorBus::Output, outputs); m_pOControlBus->saveConnects(outputs, pDocument, &eOutputs); pElement->appendChild(eOutputs); } // Metronome bus connects... if (m_bMetroBus && m_pMetroBus) { QDomElement eOutputs = pDocument->document()->createElement("metronome-outputs"); qtractorBus::ConnectList outputs; m_pMetroBus->updateConnects(qtractorBus::Output, outputs); m_pMetroBus->saveConnects(outputs, pDocument, &eOutputs); pElement->appendChild(eOutputs); } return true; } // MIDI-export method. bool qtractorMidiEngine::fileExport ( const QString& sExportPath, unsigned long iExportStart, unsigned long iExportEnd, qtractorMidiBus *pExportBus ) { // No simultaneous or foul exports... if (isPlaying()) return false; // Make sure we have an actual session cursor... qtractorSession *pSession = session(); if (pSession == NULL) return false; // Cannot have exports longer than current session. if (iExportStart >= iExportEnd) iExportEnd = pSession->sessionEnd(); if (iExportStart >= iExportEnd) return false; // We'll grab the first bus around, if none is given... if (pExportBus == NULL) pExportBus = static_cast (buses().first()); if (pExportBus == NULL) return false; unsigned short iTicksPerBeat = pSession->ticksPerBeat(); unsigned long iTimeStart = pSession->tickFromFrame(iExportStart); unsigned long iTimeEnd = pSession->tickFromFrame(iExportEnd); unsigned short iFormat = qtractorMidiClip::defaultFormat(); unsigned short iSeq; unsigned short iSeqs = 0; QList seqs; qtractorMidiSequence **ppSeqs = NULL; if (iFormat == 0) { iSeqs = 16; ppSeqs = new qtractorMidiSequence * [iSeqs]; for (iSeq = 0; iSeq < iSeqs; ++iSeq) { ppSeqs[iSeq] = new qtractorMidiSequence( QString(), iSeq, iTicksPerBeat); } } // Do the real grunt work, get eaach elligigle track // and copy the events in range to be written out... unsigned short iTracks = 0; for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { if (pTrack->trackType() != qtractorTrack::Midi) continue; if (pTrack->isMute() || (pSession->soloTracks() && !pTrack->isSolo())) continue; qtractorMidiBus *pMidiBus = static_cast (pTrack->outputBus()); if (pMidiBus == NULL) continue; if (pMidiBus->alsaPort() != pExportBus->alsaPort()) continue; // We have a target sequence, maybe reused... qtractorMidiSequence *pSeq; if (ppSeqs) { // SMF Format 0 pSeq = ppSeqs[pTrack->midiChannel() & 0x0f]; QString sName = pSeq->name(); if (!sName.isEmpty()) sName += "; "; pSeq->setName(sName + pTrack->trackName()); } else { // SMF Format 1 ++iTracks; pSeq = new qtractorMidiSequence( pTrack->trackName(), iTracks, iTicksPerBeat); pSeq->setChannel(pTrack->midiChannel()); seqs.append(pSeq); } // Make this track setup... if (pSeq->bank() < 0) pSeq->setBank(pTrack->midiBank()); if (pSeq->prog() < 0) pSeq->setProg(pTrack->midiProg()); // Now, for every clip... qtractorClip *pClip = pTrack->clips().first(); while (pClip && pClip->clipStart() + pClip->clipLength() < iExportStart) pClip = pClip->next(); while (pClip && pClip->clipStart() < iExportEnd) { qtractorMidiClip *pMidiClip = static_cast (pClip); if (pMidiClip) { unsigned long iTimeClip = pSession->tickFromFrame(pClip->clipStart()); unsigned long iTimeOffset = iTimeClip - iTimeStart; // For each event... qtractorMidiEvent *pEvent = pMidiClip->sequence()->events().first(); while (pEvent && iTimeClip + pEvent->time() < iTimeStart) pEvent = pEvent->next(); while (pEvent && iTimeClip + pEvent->time() < iTimeEnd) { qtractorMidiEvent *pNewEvent = new qtractorMidiEvent(*pEvent); pNewEvent->setTime(iTimeOffset + pEvent->time()); if (pNewEvent->type() == qtractorMidiEvent::NOTEON) { unsigned long iTimeEvent = iTimeClip + pEvent->time(); float fGain = pMidiClip->gain( pSession->frameFromTick(iTimeEvent) - pClip->clipStart()); pNewEvent->setVelocity((unsigned char) (fGain * float(pEvent->velocity())) & 0x7f); if (iTimeEvent + pEvent->duration() > iTimeEnd) pNewEvent->setDuration(iTimeEnd - iTimeEvent); } pSeq->insertEvent(pNewEvent); pEvent = pEvent->next(); } } pClip = pClip->next(); } // Have a break... qtractorSession::stabilize(); } // Account for the only or META info track... ++iTracks; // Special on SMF Format 1... if (ppSeqs == NULL) { // Sanity check... if (iTracks < 1) return false; // Number of actual track sequences... iSeqs = iTracks; ppSeqs = new qtractorMidiSequence * [iSeqs]; QListIterator iter(seqs); ppSeqs[0] = NULL; // META info track... for (iSeq = 1; iSeq < iSeqs && iter.hasNext(); ++iSeq) ppSeqs[iSeq] = iter.next(); // May clear it now. seqs.clear(); } // Prepare file for writing... qtractorMidiFile file; // File ready for export? bool bResult = file.open(sExportPath, qtractorMidiFile::Write); if (bResult) { if (file.writeHeader(iFormat, iTracks, iTicksPerBeat)) { // Export SysEx setup... qtractorMidiSysexList *pSysexList = pExportBus->sysexList(); if (pSysexList && pSysexList->count() > 0) { if (ppSeqs[0] == NULL) { ppSeqs[0] = new qtractorMidiSequence( QFileInfo(sExportPath).baseName(), 0, iTicksPerBeat); } pExportBus->exportSysexList(ppSeqs[0]); } // Export tempo map as well... if (file.tempoMap()) { file.tempoMap()->fromTimeScale( pSession->timeScale(), iTimeStart); } file.writeTracks(ppSeqs, iSeqs); } file.close(); } // Free locally allocated track/sequence array. for (iSeq = 0; iSeq < iSeqs; ++iSeq) { if (ppSeqs[iSeq]) delete ppSeqs[iSeq]; } delete [] ppSeqs; // Done successfully. return bResult; } // Retrieve/restore all connections, on all MIDI buses. // return the total number of effective (re)connection attempts... int qtractorMidiEngine::updateConnects (void) { // Do it as usual, on all standard owned dependable buses... int iUpdate = qtractorEngine::updateConnects(); // Reset all pending controllers, if any... if (m_iResetAllControllers > 0) resetAllControllers(true); // Force immediate! // Done. return iUpdate; } // Capture/input (record) quantization accessors. // (value in snap-per-beat units) void qtractorMidiEngine::setCaptureQuantize ( unsigned short iCaptureQuantize ) { m_iCaptureQuantize = iCaptureQuantize; } unsigned short qtractorMidiEngine::captureQuantize (void) const { return m_iCaptureQuantize; } // ALSA device queue timer. void qtractorMidiEngine::setAlsaTimer ( int iAlsaTimer ) { m_iAlsaTimer = iAlsaTimer; } int qtractorMidiEngine::alsaTimer (void) const { return m_iAlsaTimer; } // MMC device-id accessors. void qtractorMidiEngine::setMmcDevice ( unsigned char mmcDevice ) { m_mmcDevice = mmcDevice; } unsigned char qtractorMidiEngine::mmcDevice (void) const { return m_mmcDevice; } // MMC mode accessors. void qtractorMidiEngine::setMmcMode ( qtractorBus::BusMode mmcMode ) { m_mmcMode = mmcMode; } qtractorBus::BusMode qtractorMidiEngine::mmcMode (void) const { return m_mmcMode; } // SPP mode accessors. void qtractorMidiEngine::setSppMode ( qtractorBus::BusMode sppMode ) { m_sppMode = sppMode; } qtractorBus::BusMode qtractorMidiEngine::sppMode (void) const { return m_sppMode; } // MIDI Clock mode accessors. void qtractorMidiEngine::setClockMode ( qtractorBus::BusMode clockMode ) { m_clockMode = clockMode; } qtractorBus::BusMode qtractorMidiEngine::clockMode (void) const { return m_clockMode; } // Free overriden SysEx queued events. void qtractorMidiEngine::clearSysexCache (void) { qDeleteAll(m_sysexCache); m_sysexCache.clear(); } //---------------------------------------------------------------------- // class qtractorMidiBus -- Managed ALSA sequencer port set // // Constructor. qtractorMidiBus::qtractorMidiBus ( qtractorMidiEngine *pMidiEngine, const QString& sBusName, BusMode busMode, bool bMonitor ) : qtractorBus(pMidiEngine, sBusName, busMode, bMonitor) { m_iAlsaPort = -1; if ((busMode & qtractorBus::Input) && !(busMode & qtractorBus::Ex)) { m_pIMidiMonitor = new qtractorMidiMonitor(); m_pIPluginList = createPluginList(qtractorPluginList::MidiInBus); m_pICurveFile = new qtractorCurveFile(m_pIPluginList->curveList()); } else { m_pIMidiMonitor = NULL; m_pIPluginList = NULL; m_pICurveFile = NULL; } if ((busMode & qtractorBus::Output) && !(busMode & qtractorBus::Ex)) { m_pOMidiMonitor = new qtractorMidiMonitor(); m_pOPluginList = createPluginList(qtractorPluginList::MidiOutBus); m_pOCurveFile = new qtractorCurveFile(m_pOPluginList->curveList()); m_pSysexList = new qtractorMidiSysexList(); } else { m_pOMidiMonitor = NULL; m_pOPluginList = NULL; m_pOCurveFile = NULL; m_pSysexList = NULL; } } // Destructor. qtractorMidiBus::~qtractorMidiBus (void) { close(); if (m_pIMidiMonitor) delete m_pIMidiMonitor; if (m_pOMidiMonitor) delete m_pOMidiMonitor; if (m_pICurveFile) delete m_pICurveFile; if (m_pOCurveFile) delete m_pOCurveFile; if (m_pIPluginList) delete m_pIPluginList; if (m_pOPluginList) delete m_pOPluginList; if (m_pSysexList) delete m_pSysexList; } // ALSA sequencer port accessor. int qtractorMidiBus::alsaPort (void) const { return m_iAlsaPort; } // Register and pre-allocate bus port buffers. bool qtractorMidiBus::open (void) { // close(); qtractorMidiEngine *pMidiEngine = static_cast (engine()); if (pMidiEngine == NULL) return false; if (pMidiEngine->alsaSeq() == NULL) return false; // The verry same port might be used for input and output... unsigned int flags = 0; if (busMode() & qtractorBus::Input) flags |= SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; if (busMode() & qtractorBus::Output) flags |= SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; m_iAlsaPort = snd_seq_create_simple_port( pMidiEngine->alsaSeq(), busName().toUtf8().constData(), flags, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); if (m_iAlsaPort < 0) return false; // We want to know when the events get delivered to us... snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca(&pinfo); if (snd_seq_get_port_info(pMidiEngine->alsaSeq(), m_iAlsaPort, pinfo) < 0) return false; snd_seq_port_info_set_timestamping(pinfo, 1); snd_seq_port_info_set_timestamp_queue(pinfo, pMidiEngine->alsaQueue()); snd_seq_port_info_set_timestamp_real(pinfo, 0); // MIDI ticks. if (snd_seq_set_port_info(pMidiEngine->alsaSeq(), m_iAlsaPort, pinfo) < 0) return false; // Plugin lists need some buffer (re)allocation too... if (m_pIPluginList) updatePluginList(m_pIPluginList, qtractorPluginList::MidiInBus); if (m_pOPluginList) updatePluginList(m_pOPluginList, qtractorPluginList::MidiOutBus); // Done. return true; } // Unregister and post-free bus port buffers. void qtractorMidiBus::close (void) { qtractorMidiEngine *pMidiEngine = static_cast (engine()); if (pMidiEngine == NULL) return; if (pMidiEngine->alsaSeq() == NULL) return; shutOff(true); snd_seq_delete_simple_port(pMidiEngine->alsaSeq(), m_iAlsaPort); m_iAlsaPort = -1; } // Bus mode change event. void qtractorMidiBus::updateBusMode (void) { const qtractorBus::BusMode mode = busMode(); // Have a new/old input monitor? if ((mode & qtractorBus::Input) && !(mode & qtractorBus::Ex)) { if (m_pIMidiMonitor == NULL) m_pIMidiMonitor = new qtractorMidiMonitor(); if (m_pIPluginList == NULL) m_pIPluginList = createPluginList(qtractorPluginList::MidiInBus); if (m_pICurveFile == NULL) m_pICurveFile = new qtractorCurveFile(m_pIPluginList->curveList()); } else { if (m_pIMidiMonitor) { delete m_pIMidiMonitor; m_pIMidiMonitor = NULL; } if (m_pICurveFile) { delete m_pICurveFile; m_pICurveFile = NULL; } if (m_pIPluginList) { delete m_pIPluginList; m_pIPluginList = NULL; } } // Have a new/old output monitor? if ((mode & qtractorBus::Output) && !(mode & qtractorBus::Ex)) { if (m_pOMidiMonitor == NULL) m_pOMidiMonitor = new qtractorMidiMonitor(); if (m_pOPluginList == NULL) m_pOPluginList = createPluginList(qtractorPluginList::MidiOutBus); if (m_pOCurveFile == NULL) m_pOCurveFile = new qtractorCurveFile(m_pOPluginList->curveList()); if (m_pSysexList == NULL) m_pSysexList = new qtractorMidiSysexList(); } else { if (m_pOMidiMonitor) { delete m_pOMidiMonitor; m_pOMidiMonitor = NULL; } if (m_pOCurveFile) { delete m_pOCurveFile; m_pOCurveFile = NULL; } if (m_pOPluginList) { delete m_pOPluginList; m_pOPluginList = NULL; } if (m_pSysexList) { delete m_pSysexList; m_pSysexList = NULL; } } } // Shut-off everything out there. void qtractorMidiBus::shutOff ( bool bClose ) const { qtractorMidiEngine *pMidiEngine = static_cast (engine()); if (pMidiEngine == NULL) return; if (pMidiEngine->alsaSeq() == NULL) return; #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiBus[%p]::shutOff(%d)", this, int(bClose)); #endif QHash::ConstIterator iter = m_patches.constBegin(); const QHash::ConstIterator& iter_end = m_patches.constEnd(); for ( ; iter != iter_end; ++iter) { unsigned short iChannel = iter.key(); setControllerEx(iChannel, ALL_SOUND_OFF); setControllerEx(iChannel, ALL_NOTES_OFF); if (bClose) setControllerEx(iChannel, ALL_CONTROLLERS_OFF); } } // Default instrument name accessors. void qtractorMidiBus::setInstrumentName ( const QString& sInstrumentName ) { m_sInstrumentName = sInstrumentName; } const QString& qtractorMidiBus::instrumentName (void) const { return m_sInstrumentName; } // SysEx setup list accessors. qtractorMidiSysexList *qtractorMidiBus::sysexList (void) const { return m_pSysexList; } // Direct MIDI bank/program selection helper. void qtractorMidiBus::setPatch ( unsigned short iChannel, const QString& sInstrumentName, int iBankSelMethod, int iBank, int iProg, qtractorTrack *pTrack ) { // We always need our MIDI engine reference... qtractorMidiEngine *pMidiEngine = static_cast (engine()); if (pMidiEngine == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMidiBus[%p]::setPatch(%d, \"%s\", %d, %d, %d)", this, iChannel, sInstrumentName.toUtf8().constData(), iBankSelMethod, iBank, iProg); #endif // Sanity check. if (sInstrumentName.isEmpty()) m_patches.remove(iChannel & 0x0f); if (iProg < 0) return; // Update patch mapping... Patch& patch = m_patches[iChannel & 0x0f]; patch.instrumentName = sInstrumentName; patch.bankSelMethod = iBankSelMethod; patch.bank = iBank; patch.prog = iProg; // Don't do anything else if engine // has not been activated... if (pMidiEngine->alsaSeq() == NULL) return; // Do it for the MIDI plugins if applicable... qtractorMidiManager *pTrackMidiManager = NULL; if (pTrack) pTrackMidiManager = (pTrack->pluginList())->midiManager(); qtractorMidiManager *pBusMidiManager = NULL; if (pluginList_out()) pBusMidiManager = pluginList_out()->midiManager(); // Initialize sequencer event... snd_seq_event_t ev; snd_seq_ev_clear(&ev); // Addressing... snd_seq_ev_set_source(&ev, m_iAlsaPort); snd_seq_ev_set_subs(&ev); // The event will be direct... snd_seq_ev_set_direct(&ev); // Select Bank MSB. if (iBank >= 0 && (iBankSelMethod == 0 || iBankSelMethod == 1)) { ev.type = SND_SEQ_EVENT_CONTROLLER; ev.data.control.channel = iChannel; ev.data.control.param = BANK_SELECT_MSB; if (iBankSelMethod == 0) ev.data.control.value = (iBank & 0x3f80) >> 7; else ev.data.control.value = (iBank & 0x007f); snd_seq_event_output_direct(pMidiEngine->alsaSeq(), &ev); if (pTrackMidiManager) pTrackMidiManager->direct(&ev); if (pBusMidiManager) pBusMidiManager->direct(&ev); } // Select Bank LSB. if (iBank >= 0 && (iBankSelMethod == 0 || iBankSelMethod == 2)) { ev.type = SND_SEQ_EVENT_CONTROLLER; ev.data.control.channel = iChannel; ev.data.control.param = BANK_SELECT_LSB; ev.data.control.value = (iBank & 0x007f); snd_seq_event_output_direct(pMidiEngine->alsaSeq(), &ev); if (pTrackMidiManager) pTrackMidiManager->direct(&ev); if (pBusMidiManager) pBusMidiManager->direct(&ev); } // Program change... ev.type = SND_SEQ_EVENT_PGMCHANGE; ev.data.control.channel = iChannel; ev.data.control.value = iProg; snd_seq_event_output_direct(pMidiEngine->alsaSeq(), &ev); if (pTrackMidiManager) pTrackMidiManager->direct(&ev); if (pBusMidiManager) pBusMidiManager->direct(&ev); // pMidiEngine->flush(); } // Direct MIDI controller helper. void qtractorMidiBus::setController ( qtractorTrack *pTrack, int iController, int iValue ) const { setControllerEx(pTrack->midiChannel(), iController, iValue, pTrack); } void qtractorMidiBus::setController ( unsigned short iChannel, int iController, int iValue ) const { setControllerEx(iChannel, iController, iValue, NULL); } // Direct MIDI controller common helper. void qtractorMidiBus::setControllerEx ( unsigned short iChannel, int iController, int iValue, qtractorTrack *pTrack ) const { // We always need our MIDI engine reference... qtractorMidiEngine *pMidiEngine = static_cast (engine()); if (pMidiEngine == NULL) return; // Don't do anything else if engine // has not been activated... if (pMidiEngine->alsaSeq() == NULL) return; #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiBus[%p]::setController(%d, %d, %d)", this, iChannel, iController, iValue); #endif // Initialize sequencer event... snd_seq_event_t ev; snd_seq_ev_clear(&ev); // Addressing... snd_seq_ev_set_source(&ev, m_iAlsaPort); snd_seq_ev_set_subs(&ev); // The event will be direct... snd_seq_ev_set_direct(&ev); // Set controller parameters... ev.type = SND_SEQ_EVENT_CONTROLLER; ev.data.control.channel = iChannel; ev.data.control.param = iController; ev.data.control.value = iValue; snd_seq_event_output_direct(pMidiEngine->alsaSeq(), &ev); // Do it for the MIDI plugins too... if (pTrack && (pTrack->pluginList())->midiManager()) (pTrack->pluginList())->midiManager()->direct(&ev); if (pluginList_out() && pluginList_out()->midiManager()) (pluginList_out()->midiManager())->direct(&ev); // pMidiEngine->flush(); } // Direct MIDI channel event helper. void qtractorMidiBus::sendEvent ( qtractorMidiEvent::EventType etype, unsigned short iChannel, unsigned short iParam, unsigned short iValue ) const { // We always need our MIDI engine reference... qtractorMidiEngine *pMidiEngine = static_cast (engine()); if (pMidiEngine == NULL) return; // Don't do anything else if engine // has not been activated... if (pMidiEngine->alsaSeq() == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMidiBus[%p]::sendEvent(0x%02x, %u, %u, %u)", this, int(etype), iChannel, iParam, iValue); #endif // Initialize sequencer event... snd_seq_event_t ev; snd_seq_ev_clear(&ev); // Addressing... snd_seq_ev_set_source(&ev, m_iAlsaPort); snd_seq_ev_set_subs(&ev); // The event will be direct... snd_seq_ev_set_direct(&ev); // Set controller parameters... switch (etype) { case qtractorMidiEvent::NOTEON: ev.type = SND_SEQ_EVENT_NOTEON; ev.data.note.channel = iChannel; ev.data.note.note = iParam; ev.data.note.velocity = iValue; break; case qtractorMidiEvent::NOTEOFF: ev.type = SND_SEQ_EVENT_NOTEOFF; ev.data.note.channel = iChannel; ev.data.note.note = iParam; ev.data.note.velocity = iValue; break; case qtractorMidiEvent::KEYPRESS: ev.type = SND_SEQ_EVENT_KEYPRESS; ev.data.note.channel = iChannel; ev.data.note.note = iParam; ev.data.note.velocity = iValue; break; case qtractorMidiEvent::CONTROLLER: default: ev.type = SND_SEQ_EVENT_CONTROLLER; ev.data.control.channel = iChannel; ev.data.control.param = iParam; ev.data.control.value = iValue; break; case qtractorMidiEvent::PGMCHANGE: ev.type = SND_SEQ_EVENT_PGMCHANGE; ev.data.control.channel = iChannel; ev.data.control.param = 0; ev.data.control.value = iValue; break; case qtractorMidiEvent::CHANPRESS: ev.type = SND_SEQ_EVENT_CHANPRESS; ev.data.control.channel = iChannel; ev.data.control.param = 0; ev.data.control.value = iValue; break; case qtractorMidiEvent::PITCHBEND: ev.type = SND_SEQ_EVENT_PITCHBEND; ev.data.control.channel = iChannel; ev.data.control.param = 0; ev.data.control.value = int(iValue) - 0x2000; break; } snd_seq_event_output_direct(pMidiEngine->alsaSeq(), &ev); } // Direct MIDI note on/off helper. void qtractorMidiBus::sendNote ( qtractorTrack *pTrack, int iNote, int iVelocity ) const { // We always need our MIDI engine reference... qtractorMidiEngine *pMidiEngine = static_cast (engine()); if (pMidiEngine == NULL) return; // Don't do anything else if engine // has not been activated... if (pMidiEngine->alsaSeq() == NULL) return; unsigned short iChannel = pTrack->midiChannel(); #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiBus[%p]::sendNote(%d, %d, %d)", this, iChannel, iNote, iVelocity); #endif // Initialize sequencer event... snd_seq_event_t ev; snd_seq_ev_clear(&ev); // Addressing... snd_seq_ev_set_source(&ev, m_iAlsaPort); snd_seq_ev_set_subs(&ev); // The event will be direct... snd_seq_ev_set_direct(&ev); // Set controller parameters... ev.type = (iVelocity > 0 ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF); ev.data.note.channel = iChannel; ev.data.note.note = iNote; ev.data.note.velocity = iVelocity; snd_seq_event_output_direct(pMidiEngine->alsaSeq(), &ev); // Do it for the MIDI plugins too... if ((pTrack->pluginList())->midiManager()) (pTrack->pluginList())->midiManager()->direct(&ev); if (pluginList_out() && pluginList_out()->midiManager()) (pluginList_out()->midiManager())->direct(&ev); // pMidiEngine->flush(); // Bus/track output monitoring... if (iVelocity > 0) { // Bus output monitoring... if (m_pOMidiMonitor) m_pOMidiMonitor->enqueue(qtractorMidiEvent::NOTEON, iVelocity); // Track output monitoring... qtractorMidiMonitor *pMidiMonitor = static_cast (pTrack->monitor()); if (pMidiMonitor) pMidiMonitor->enqueue(qtractorMidiEvent::NOTEON, iVelocity); } } // Direct SysEx helpers. void qtractorMidiBus::sendSysex ( unsigned char *pSysex, unsigned int iSysex ) const { // Yet again, we need our MIDI engine reference... qtractorMidiEngine *pMidiEngine = static_cast (engine()); if (pMidiEngine == NULL) return; // Don't do anything else if engine // has not been activated... if (pMidiEngine->alsaSeq() == NULL) return; #ifdef CONFIG_DEBUG_0 fprintf(stderr, "qtractorMidiBus::sendSysex(%p, %u)", pSysex, iSysex); fprintf(stderr, " sysex {"); for (unsigned int i = 0; i < iSysex; ++i) fprintf(stderr, " %02x", pSysex[i]); fprintf(stderr, " }\n"); #endif // Initialize sequencer event... snd_seq_event_t ev; snd_seq_ev_clear(&ev); // Addressing... snd_seq_ev_set_source(&ev, m_iAlsaPort); snd_seq_ev_set_subs(&ev); // The event will be direct... snd_seq_ev_set_direct(&ev); // Just set SYSEX stuff and send it out.. ev.type = SND_SEQ_EVENT_SYSEX; snd_seq_ev_set_sysex(&ev, iSysex, pSysex); snd_seq_event_output_direct(pMidiEngine->alsaSeq(), &ev); // pMidiEngine->flush(); } void qtractorMidiBus::sendSysexList (void) const { // Check that we have some SysEx for setup... if (m_pSysexList == NULL) return; if (m_pSysexList->count() < 1) return; // Yet again, we need our MIDI engine reference... qtractorMidiEngine *pMidiEngine = static_cast (engine()); if (pMidiEngine == NULL) return; // Don't do anything else if engine // has not been activated... if (pMidiEngine->alsaSeq() == NULL) return; QListIterator iter(*m_pSysexList); while (iter.hasNext()) { qtractorMidiSysex *pSysex = iter.next(); #ifdef CONFIG_DEBUG_0 unsigned char *pData = pSysex->data(); unsigned short iSize = pSysex->size(); fprintf(stderr, "qtractorMidiBus::sendSysexList(%p, %u)", pData, iSize); fprintf(stderr, " sysex {"); for (unsigned short i = 0; i < iSize; ++i) fprintf(stderr, " %02x", pData[i]); fprintf(stderr, " }\n"); #endif // Initialize sequencer event... snd_seq_event_t ev; snd_seq_ev_clear(&ev); // Addressing... snd_seq_ev_set_source(&ev, m_iAlsaPort); snd_seq_ev_set_subs(&ev); // The event will be direct... snd_seq_ev_set_direct(&ev); // Just set SYSEX stuff and send it out.. ev.type = SND_SEQ_EVENT_SYSEX; snd_seq_ev_set_sysex(&ev, pSysex->size(), pSysex->data()); snd_seq_event_output(pMidiEngine->alsaSeq(), &ev); // AG: Do it for the MIDI plugins too... if (pluginList_out() && pluginList_out()->midiManager()) (pluginList_out()->midiManager())->direct(&ev); } pMidiEngine->flush(); } // Virtual I/O bus-monitor accessors. qtractorMonitor *qtractorMidiBus::monitor_in (void) const { return midiMonitor_in(); } qtractorMonitor *qtractorMidiBus::monitor_out (void) const { return midiMonitor_out(); } // MIDI I/O bus-monitor accessors. qtractorMidiMonitor *qtractorMidiBus::midiMonitor_in (void) const { return m_pIMidiMonitor; } qtractorMidiMonitor *qtractorMidiBus::midiMonitor_out (void) const { return m_pOMidiMonitor; } // Plugin-chain accessors. qtractorPluginList *qtractorMidiBus::pluginList_in (void) const { return m_pIPluginList; } qtractorPluginList *qtractorMidiBus::pluginList_out (void) const { return m_pOPluginList; } // Create plugin-list properly. qtractorPluginList *qtractorMidiBus::createPluginList ( int iFlags ) const { qtractorSession *pSession = engine()->session(); if (pSession == NULL) return NULL; // Create plugin-list alright... unsigned int iSampleRate = 0; qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine) iSampleRate = pAudioEngine->sampleRate(); qtractorPluginList *pPluginList = new qtractorPluginList(0, 0, iSampleRate, iFlags); // Set plugin-list title name... updatePluginListName(pPluginList, iFlags); return pPluginList; } // Update plugin-list title name... void qtractorMidiBus::updatePluginListName ( qtractorPluginList *pPluginList, int iFlags ) const { pPluginList->setName((iFlags & qtractorPluginList::In ? QObject::tr("%1 In") : QObject::tr("%1 Out")).arg(busName())); } // Update plugin-list buffers properly. void qtractorMidiBus::updatePluginList ( qtractorPluginList *pPluginList, int iFlags ) { // Sanity checks... qtractorSession *pSession = engine()->session(); if (pSession == NULL) return; qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine == NULL) return; // Set plugin-list title name... updatePluginListName(pPluginList, iFlags); // Get audio bus as for the plugin list... qtractorAudioBus *pAudioBus = NULL; if (pPluginList->midiManager()) pAudioBus = (pPluginList->midiManager())->audioOutputBus(); if (pAudioBus == NULL) { // Output bus gets to be the first available output bus... for (qtractorBus *pBus = (pAudioEngine->buses()).first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Output) { pAudioBus = static_cast (pBus); break; } } } // Got it? if (pAudioBus == NULL) return; // Set plugin-list buffer alright... pPluginList->setBuffer(pAudioBus->channels(), pAudioEngine->bufferSize(), pAudioEngine->sampleRate(), iFlags); } // Automation curve list accessors. qtractorCurveList *qtractorMidiBus::curveList_in (void) const { return (m_pIPluginList ? m_pIPluginList->curveList() : NULL); } qtractorCurveList *qtractorMidiBus::curveList_out (void) const { return (m_pOPluginList ? m_pOPluginList->curveList() : NULL); } // Automation curve serializer accessors. qtractorCurveFile *qtractorMidiBus::curveFile_in (void) const { return m_pICurveFile; } qtractorCurveFile *qtractorMidiBus::curveFile_out (void) const { return m_pOCurveFile; } // Retrieve all current ALSA connections for a given bus mode interface; // return the effective number of connection attempts... int qtractorMidiBus::updateConnects ( qtractorBus::BusMode busMode, ConnectList& connects, bool bConnect ) const { qtractorMidiEngine *pMidiEngine = static_cast (engine()); if (pMidiEngine == NULL) return 0; if (pMidiEngine->alsaSeq() == NULL) return 0; // Modes must match, at least... if ((busMode & qtractorMidiBus::busMode()) == 0) return 0; if (bConnect && connects.isEmpty()) return 0; // Which kind of subscription? snd_seq_query_subs_type_t subs_type = (busMode == qtractorBus::Input ? SND_SEQ_QUERY_SUBS_WRITE : SND_SEQ_QUERY_SUBS_READ); snd_seq_query_subscribe_t *pAlsaSubs; snd_seq_addr_t seq_addr; snd_seq_query_subscribe_alloca(&pAlsaSubs); snd_seq_client_info_t *pClientInfo; snd_seq_port_info_t *pPortInfo; snd_seq_client_info_alloca(&pClientInfo); snd_seq_port_info_alloca(&pPortInfo); ConnectItem item, *pItem; // Update current client/ports ids. unsigned int iPortFlags; if (busMode == qtractorBus::Input) iPortFlags = SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; else iPortFlags = SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; while (snd_seq_query_next_client( pMidiEngine->alsaSeq(), pClientInfo) >= 0) { item.client = snd_seq_client_info_get_client(pClientInfo); item.clientName = QString::fromUtf8( snd_seq_client_info_get_name(pClientInfo)); snd_seq_port_info_set_client(pPortInfo, item.client); snd_seq_port_info_set_port(pPortInfo, -1); while (snd_seq_query_next_port( pMidiEngine->alsaSeq(), pPortInfo) >= 0) { unsigned int iPortCapability = snd_seq_port_info_get_capability(pPortInfo); if (((iPortCapability & iPortFlags) == iPortFlags) && ((iPortCapability & SND_SEQ_PORT_CAP_NO_EXPORT) == 0)) { item.port = snd_seq_port_info_get_port(pPortInfo); item.portName = QString::fromUtf8( snd_seq_port_info_get_name(pPortInfo)); pItem = connects.findItem(item); if (pItem) { pItem->port = item.port; pItem->client = item.client; } } } } // Get port connections... snd_seq_query_subscribe_set_type(pAlsaSubs, subs_type); snd_seq_query_subscribe_set_index(pAlsaSubs, 0); seq_addr.client = pMidiEngine->alsaClient(); seq_addr.port = m_iAlsaPort; snd_seq_query_subscribe_set_root(pAlsaSubs, &seq_addr); while (snd_seq_query_port_subscribers( pMidiEngine->alsaSeq(), pAlsaSubs) >= 0) { seq_addr = *snd_seq_query_subscribe_get_addr(pAlsaSubs); snd_seq_get_any_client_info( pMidiEngine->alsaSeq(), seq_addr.client, pClientInfo); item.client = seq_addr.client; item.clientName = QString::fromUtf8( snd_seq_client_info_get_name(pClientInfo)); snd_seq_get_any_port_info( pMidiEngine->alsaSeq(), seq_addr.client, seq_addr.port, pPortInfo); item.port = seq_addr.port; item.portName = QString::fromUtf8( snd_seq_port_info_get_name(pPortInfo)); // Check if already in list/connected... pItem = connects.findItem(item); if (pItem && bConnect) { int iItem = connects.indexOf(pItem); if (iItem >= 0) { connects.removeAt(iItem); delete pItem; } } else if (!bConnect) connects.append(new ConnectItem(item)); // Fetch next connection... snd_seq_query_subscribe_set_index(pAlsaSubs, snd_seq_query_subscribe_get_index(pAlsaSubs) + 1); } // Shall we proceed for actual connections? if (!bConnect) return 0; snd_seq_port_subscribe_t *pPortSubs; snd_seq_port_subscribe_alloca(&pPortSubs); // For each (remaining) connection, try... int iUpdate = 0; QListIterator iter(connects); while (iter.hasNext()) { ConnectItem *pItem = iter.next(); // Don't care of non-valid client/ports... if (pItem->client < 0 || pItem->port < 0) continue; // Mangle which is output and input... if (busMode == qtractorBus::Input) { seq_addr.client = pItem->client; seq_addr.port = pItem->port; snd_seq_port_subscribe_set_sender(pPortSubs, &seq_addr); seq_addr.client = pMidiEngine->alsaClient(); seq_addr.port = m_iAlsaPort; snd_seq_port_subscribe_set_dest(pPortSubs, &seq_addr); } else { seq_addr.client = pMidiEngine->alsaClient(); seq_addr.port = m_iAlsaPort; snd_seq_port_subscribe_set_sender(pPortSubs, &seq_addr); seq_addr.client = pItem->client; seq_addr.port = pItem->port; snd_seq_port_subscribe_set_dest(pPortSubs, &seq_addr); } #ifdef CONFIG_DEBUG const QString sPortName = QString::number(m_iAlsaPort) + ':' + busName(); qDebug("qtractorMidiBus[%p]::updateConnects(%d): " "snd_seq_subscribe_port: [%d:%s] => [%d:%s]\n", this, int(busMode), pMidiEngine->alsaClient(), sPortName.toUtf8().constData(), pItem->client, pItem->portName.toUtf8().constData()); #endif if (snd_seq_subscribe_port(pMidiEngine->alsaSeq(), pPortSubs) == 0) { int iItem = connects.indexOf(pItem); if (iItem >= 0) { connects.removeAt(iItem); delete pItem; ++iUpdate; } } } // Remember to resend all session/tracks control stuff, // iif we've changed any of the intended MIDI connections... if (iUpdate) pMidiEngine->resetAllControllers(false); // Deferred++ // Done. return iUpdate; } // MIDI master volume. void qtractorMidiBus::setMasterVolume ( float fVolume ) { unsigned char vol = (unsigned char) (int(127.0f * fVolume) & 0x7f); // Build Universal SysEx and let it go... unsigned char aMasterVolSysex[] = { 0xf0, 0x7f, 0x7f, 0x04, 0x01, 0x00, 0x00, 0xf7 }; // Set the course value right... if (fVolume >= +1.0f) aMasterVolSysex[5] = 0x7f; aMasterVolSysex[6] = vol; sendSysex(aMasterVolSysex, sizeof(aMasterVolSysex)); } // MIDI master panning. void qtractorMidiBus::setMasterPanning ( float fPanning ) { unsigned char pan = (unsigned char) ((0x40 + int(63.0f * fPanning)) & 0x7f); // Build Universal SysEx and let it go... unsigned char aMasterPanSysex[] = { 0xf0, 0x7f, 0x7f, 0x04, 0x02, 0x00, 0x00, 0xf7 }; // Set the course value right... // And fine special for hard right... if (fPanning >= +1.0f) aMasterPanSysex[5] = 0x7f; if (fPanning > -1.0f) aMasterPanSysex[6] = pan; sendSysex(aMasterPanSysex, sizeof(aMasterPanSysex)); } // MIDI channel volume. void qtractorMidiBus::setVolume ( qtractorTrack *pTrack, float fVolume ) { unsigned char vol = (unsigned char) (int(127.0f * fVolume) & 0x7f); setController(pTrack, CHANNEL_VOLUME, vol); } // MIDI channel stereo panning. void qtractorMidiBus::setPanning ( qtractorTrack *pTrack, float fPanning ) { unsigned char pan = (unsigned char) ((0x40 + int(63.0f * fPanning)) & 0x7f); setController(pTrack, CHANNEL_PANNING, pan); } // Document element methods. bool qtractorMidiBus::loadElement ( qtractorDocument *pDocument, QDomElement *pElement ) { for (QDomNode nProp = pElement->firstChild(); !nProp.isNull(); nProp = nProp.nextSibling()) { // Convert node to element... QDomElement eProp = nProp.toElement(); if (eProp.isNull()) continue; // Load map elements (non-critical)... if (eProp.tagName() == "pass-through" || // Legacy compat. eProp.tagName() == "midi-thru" || eProp.tagName() == "monitor") { qtractorMidiBus::setMonitor( qtractorDocument::boolFromText(eProp.text())); } else if (eProp.tagName() == "midi-sysex-list") { qtractorMidiBus::loadSysexList(pDocument, &eProp); } else if (eProp.tagName() == "midi-map") { qtractorMidiBus::loadMidiMap(pDocument, &eProp); } else if (eProp.tagName() == "midi-instrument-name") { qtractorMidiBus::setInstrumentName(eProp.text()); } else if (eProp.tagName() == "input-gain") { if (qtractorMidiBus::monitor_in()) qtractorMidiBus::monitor_in()->setGain( eProp.text().toFloat()); } else if (eProp.tagName() == "input-panning") { if (qtractorMidiBus::monitor_in()) qtractorMidiBus::monitor_in()->setPanning( eProp.text().toFloat()); } else if (eProp.tagName() == "input-controllers") { qtractorMidiBus::loadControllers(&eProp, qtractorBus::Input); } else if (eProp.tagName() == "input-curve-file") { qtractorMidiBus::loadCurveFile(&eProp, qtractorBus::Input, qtractorMidiBus::curveFile_in()); } else if (eProp.tagName() == "input-plugins") { if (qtractorMidiBus::pluginList_in()) qtractorMidiBus::pluginList_in()->loadElement( pDocument, &eProp); } else if (eProp.tagName() == "input-connects") { qtractorMidiBus::loadConnects( qtractorMidiBus::inputs(), pDocument, &eProp); } else if (eProp.tagName() == "output-gain") { if (qtractorMidiBus::monitor_out()) qtractorMidiBus::monitor_out()->setGain( eProp.text().toFloat()); } else if (eProp.tagName() == "output-panning") { if (qtractorMidiBus::monitor_out()) qtractorMidiBus::monitor_out()->setPanning( eProp.text().toFloat()); } else if (eProp.tagName() == "output-controllers") { qtractorMidiBus::loadControllers(&eProp, qtractorBus::Output); } else if (eProp.tagName() == "output-curve-file") { qtractorMidiBus::loadCurveFile(&eProp, qtractorBus::Output, qtractorMidiBus::curveFile_out()); } else if (eProp.tagName() == "output-plugins") { if (qtractorMidiBus::pluginList_out()) qtractorMidiBus::pluginList_out()->loadElement( pDocument, &eProp); } else if (eProp.tagName() == "output-connects") { qtractorMidiBus::loadConnects( qtractorMidiBus::outputs(), pDocument, &eProp); } } return true; } bool qtractorMidiBus::saveElement ( qtractorDocument *pDocument, QDomElement *pElement ) const { pElement->setAttribute("name", qtractorMidiBus::busName()); pElement->setAttribute("mode", qtractorBus::textFromBusMode(qtractorMidiBus::busMode())); pDocument->saveTextElement("monitor", qtractorDocument::textFromBool( qtractorMidiBus::isMonitor()), pElement); if (qtractorMidiBus::busMode() & qtractorBus::Input) { pDocument->saveTextElement("input-gain", QString::number(qtractorMidiBus::monitor_in()->gain()), pElement); pDocument->saveTextElement("input-panning", QString::number(qtractorMidiBus::monitor_in()->panning()), pElement); // Save input bus controllers... QDomElement eInputControllers = pDocument->document()->createElement("input-controllers"); qtractorMidiBus::saveControllers(pDocument, &eInputControllers, qtractorBus::Input); pElement->appendChild(eInputControllers); // Save input bus automation curves... qtractorCurveList *pInputCurveList = qtractorMidiBus::curveList_in(); if (pInputCurveList && !pInputCurveList->isEmpty()) { qtractorCurveFile cfile(pInputCurveList); QDomElement eInputCurveFile = pDocument->document()->createElement("input-curve-file"); qtractorMidiBus::saveCurveFile(pDocument, &eInputCurveFile, qtractorBus::Input, &cfile); pElement->appendChild(eInputCurveFile); } // Save input bus plugins... if (qtractorMidiBus::pluginList_in()) { QDomElement eInputPlugins = pDocument->document()->createElement("input-plugins"); qtractorMidiBus::pluginList_in()->saveElement( pDocument, &eInputPlugins); pElement->appendChild(eInputPlugins); } // Save input bus connections... QDomElement eMidiInputs = pDocument->document()->createElement("input-connects"); qtractorBus::ConnectList inputs; qtractorMidiBus::updateConnects(qtractorBus::Input, inputs); qtractorMidiBus::saveConnects(inputs, pDocument, &eMidiInputs); pElement->appendChild(eMidiInputs); } if (qtractorMidiBus::busMode() & qtractorBus::Output) { pDocument->saveTextElement("output-gain", QString::number(qtractorMidiBus::monitor_out()->gain()), pElement); pDocument->saveTextElement("output-panning", QString::number(qtractorMidiBus::monitor_out()->panning()), pElement); // Save output bus controllers... QDomElement eOutputControllers = pDocument->document()->createElement("output-controllers"); qtractorMidiBus::saveControllers(pDocument, &eOutputControllers, qtractorBus::Output); pElement->appendChild(eOutputControllers); // Save output bus automation curves... qtractorCurveList *pOutputCurveList = qtractorMidiBus::curveList_out(); if (pOutputCurveList && !pOutputCurveList->isEmpty()) { qtractorCurveFile cfile(pOutputCurveList); QDomElement eOutputCurveFile = pDocument->document()->createElement("output-curve-file"); qtractorMidiBus::saveCurveFile(pDocument, &eOutputCurveFile, qtractorBus::Output, &cfile); pElement->appendChild(eOutputCurveFile); } // Save output bus plugins... if (qtractorMidiBus::pluginList_out()) { QDomElement eOutputPlugins = pDocument->document()->createElement("output-plugins"); qtractorMidiBus::pluginList_out()->saveElement( pDocument, &eOutputPlugins); pElement->appendChild(eOutputPlugins); } // Save output bus connections... QDomElement eMidiOutputs = pDocument->document()->createElement("output-connects"); qtractorBus::ConnectList outputs; qtractorMidiBus::updateConnects(qtractorBus::Output, outputs); qtractorMidiBus::saveConnects(outputs, pDocument, &eMidiOutputs); pElement->appendChild(eMidiOutputs); } // Save default intrument name, if any... if (!qtractorMidiBus::instrumentName().isEmpty()) { pDocument->saveTextElement("midi-instrument-name", qtractorMidiBus::instrumentName(), pElement); } // Create the sysex element... if (m_pSysexList && m_pSysexList->count() > 0) { QDomElement eSysexList = pDocument->document()->createElement("midi-sysex-list"); qtractorMidiBus::saveSysexList(pDocument, &eSysexList); pElement->appendChild(eSysexList); } // Create the map element... if (m_patches.count() > 0) { QDomElement eMidiMap = pDocument->document()->createElement("midi-map"); qtractorMidiBus::saveMidiMap(pDocument, &eMidiMap); pElement->appendChild(eMidiMap); } return true; } // Document instrument map methods. bool qtractorMidiBus::loadMidiMap ( qtractorDocument * /*pDocument*/, QDomElement *pElement ) { m_patches.clear(); // Load map items... for (QDomNode nChild = pElement->firstChild(); !nChild.isNull(); nChild = nChild.nextSibling()) { // Convert node to element... QDomElement eChild = nChild.toElement(); if (eChild.isNull()) continue; // Load map item... if (eChild.tagName() == "midi-patch") { unsigned short iChannel = eChild.attribute("channel").toUShort(); Patch& patch = m_patches[iChannel & 0x0f]; for (QDomNode nPatch = eChild.firstChild(); !nPatch.isNull(); nPatch = nPatch.nextSibling()) { // Convert patch node to element... QDomElement ePatch = nPatch.toElement(); if (ePatch.isNull()) continue; // Add this one to map... if (ePatch.tagName() == "midi-instrument") patch.instrumentName = ePatch.text(); else if (ePatch.tagName() == "midi-bank-sel-method") patch.bankSelMethod = ePatch.text().toInt(); else if (ePatch.tagName() == "midi-bank") patch.bank = ePatch.text().toInt(); else if (ePatch.tagName() == "midi-program") patch.prog = ePatch.text().toInt(); } // Rollback if instrument-patch is invalid... if (patch.instrumentName.isEmpty()) m_patches.remove(iChannel & 0x0f); } } return true; } bool qtractorMidiBus::saveMidiMap ( qtractorDocument *pDocument, QDomElement *pElement ) const { // Save map items... QHash::ConstIterator iter = m_patches.constBegin(); const QHash::ConstIterator& iter_end = m_patches.constEnd(); for ( ; iter != iter_end; ++iter) { const Patch& patch = iter.value(); QDomElement ePatch = pDocument->document()->createElement("midi-patch"); ePatch.setAttribute("channel", QString::number(iter.key())); if (!patch.instrumentName.isEmpty()) { pDocument->saveTextElement("midi-instrument", patch.instrumentName, &ePatch); } if (patch.bankSelMethod >= 0) { pDocument->saveTextElement("midi-bank-sel-method", QString::number(patch.bankSelMethod), &ePatch); } if (patch.bank >= 0) { pDocument->saveTextElement("midi-bank", QString::number(patch.bank), &ePatch); } if (patch.prog >= 0) { pDocument->saveTextElement("midi-program", QString::number(patch.prog), &ePatch); } pElement->appendChild(ePatch); } return true; } // Document SysEx setup list methods. bool qtractorMidiBus::loadSysexList ( qtractorDocument * /*pDocument*/, QDomElement *pElement ) { // Must have one... if (m_pSysexList == NULL) return false; // Crystal clear... m_pSysexList->clear(); // Load map items... for (QDomNode nChild = pElement->firstChild(); !nChild.isNull(); nChild = nChild.nextSibling()) { // Convert node to element... QDomElement eChild = nChild.toElement(); if (eChild.isNull()) continue; // Load map item... if (eChild.tagName() == "midi-sysex") { qtractorMidiSysex *pSysex = new qtractorMidiSysex( eChild.attribute("name"), eChild.text()); if (pSysex->size() > 0) m_pSysexList->append(pSysex); else delete pSysex; } } return true; } bool qtractorMidiBus::saveSysexList ( qtractorDocument *pDocument, QDomElement *pElement ) const { // Must have one... if (m_pSysexList == NULL) return false; // Save map items... QListIterator iter(*m_pSysexList); while (iter.hasNext()) { qtractorMidiSysex *pSysex = iter.next(); QDomElement eSysex = pDocument->document()->createElement("midi-sysex"); eSysex.setAttribute("name", pSysex->name()); eSysex.appendChild( pDocument->document()->createTextNode(pSysex->text())); pElement->appendChild(eSysex); } return true; } // Import SysEx setup from event sequence. bool qtractorMidiBus::importSysexList ( qtractorMidiSequence *pSeq ) { if (m_pSysexList == NULL) return false; m_pSysexList->clear(); int iSysex = 0; qtractorMidiEvent *pEvent = pSeq->events().first(); while (pEvent) { if (pEvent->type() == qtractorMidiEvent::SYSEX) { m_pSysexList->append( new qtractorMidiSysex(pSeq->name() + '-' + QString::number(++iSysex), pEvent->sysex(), pEvent->sysex_len()) ); } pEvent = pEvent->next(); } return true; } // Export SysEx setup to event sequence. bool qtractorMidiBus::exportSysexList ( qtractorMidiSequence *pSeq ) { if (m_pSysexList == NULL) return false; QListIterator iter(*m_pSysexList); while (iter.hasNext()) { qtractorMidiSysex *pSysex = iter.next(); qtractorMidiEvent *pEvent = new qtractorMidiEvent(0, qtractorMidiEvent::SYSEX); pEvent->setSysex(pSysex->data(), pSysex->size()); pSeq->addEvent(pEvent); } return true; } // end of qtractorMidiEngine.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiBuffer.h0000644000175000001440000000012312116353330021205 xustar000000000000000027 mtime=1362745048.655446 26 atime=1381134666.88308 30 ctime=1381134666.883080047 qtractor-0.5.11/src/qtractorMidiBuffer.h0000644000175000001440000002401712116353330020500 0ustar00rncbcusers00000000000000// qtractorMidiBuffer.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiBuffer_h #define __qtractorMidiBuffer_h #include "qtractorAbout.h" #include "qtractorList.h" #ifdef CONFIG_VST #include "qtractorVstPlugin.h" #ifndef CONFIG_MIDI_PARSER #define CONFIG_MIDI_PARSER 1 #endif #endif #if defined(CONFIG_LV2_EVENT) || defined(CONFIG_LV2_ATOM) #include "qtractorLv2Plugin.h" #ifndef CONFIG_MIDI_PARSER #define CONFIG_MIDI_PARSER 1 #endif #endif #include #include #include #include #include #include // Forward declarations. class qtractorTimeScale; class qtractorPluginList; class qtractorPlugin; class qtractorAudioBus; class qtractorMidiManagerThread; //---------------------------------------------------------------------- // class qtractorMidiBuffer -- MIDI event FIFO buffer/cache declaration. // class qtractorMidiBuffer { public: // Minimum buffer size enum { MinBufferSize = 0x400 }; // Constructor. qtractorMidiBuffer(unsigned int iBufferSize = MinBufferSize) : m_pBuffer(NULL), m_iBufferSize(0), m_iBufferMask(0), m_iWriteIndex(0), m_iReadIndex(0) { // Adjust size to nearest power-of-two, if necessary. m_iBufferSize = MinBufferSize; while (m_iBufferSize < iBufferSize) m_iBufferSize <<= 1; m_iBufferMask = (m_iBufferSize - 1); m_pBuffer = new snd_seq_event_t [m_iBufferSize]; } // Destructor. ~qtractorMidiBuffer() { if (m_pBuffer) delete [] m_pBuffer; } // Implementation properties. unsigned int bufferSize() const { return m_iBufferSize; } // Clears the buffer. void clear() { m_iReadIndex = m_iWriteIndex = 0; } // Returns nonzero if there aren't any events available. bool isEmpty() const { return (m_iReadIndex == m_iWriteIndex); } // Returns a pointer to the first of the output events. snd_seq_event_t *peek() const { return (isEmpty() ? NULL : &m_pBuffer[m_iReadIndex]); } // Read next event from buffer. snd_seq_event_t *next() { if (!isEmpty()) ++m_iReadIndex &= m_iBufferMask; return peek(); } // Read event from buffer. snd_seq_event_t *pop() { unsigned int iReadIndex = m_iReadIndex; if (iReadIndex == m_iWriteIndex) return NULL; m_iReadIndex = (iReadIndex + 1) & m_iBufferMask; return &m_pBuffer[iReadIndex]; } // Write event to buffer. bool push(snd_seq_event_t *pEvent, unsigned long iTick = 0) { unsigned int iWriteIndex = (m_iWriteIndex + 1) & m_iBufferMask; if (iWriteIndex == m_iReadIndex) return false; m_pBuffer[m_iWriteIndex] = *pEvent; m_pBuffer[m_iWriteIndex].time.tick = iTick; m_iWriteIndex = iWriteIndex; return true; } // Write event to buffer (ordered). bool insert(snd_seq_event_t *pEvent, unsigned long iTick = 0) { unsigned int iWriteIndex = (m_iWriteIndex + 1) & m_iBufferMask; if (iWriteIndex == m_iReadIndex) return false; unsigned int i = m_iWriteIndex; unsigned int j = i; for (;;) { --i &= m_iBufferMask; if (j == m_iReadIndex || iTick >= m_pBuffer[i].time.tick) { m_pBuffer[j] = *pEvent; m_pBuffer[j].time.tick = iTick; break; } m_pBuffer[j] = m_pBuffer[i]; j = i; } m_iWriteIndex = iWriteIndex; return true; } // Returns number of events currently available. unsigned int count() const { unsigned int iWriteIndex = m_iWriteIndex; unsigned int iReadIndex = m_iReadIndex; if (iWriteIndex > iReadIndex) { return (iWriteIndex - iReadIndex); } else { return (iWriteIndex - iReadIndex + m_iBufferSize) & m_iBufferMask; } } // Reset events in buffer. void reset(unsigned long iTick = 0) { unsigned int i = m_iReadIndex; while (i != m_iWriteIndex) { m_pBuffer[i].time.tick = iTick; ++i &= m_iBufferMask; } } private: // Instance variables. snd_seq_event_t *m_pBuffer; unsigned int m_iBufferSize; unsigned int m_iBufferMask; unsigned int m_iWriteIndex; unsigned int m_iReadIndex; }; //---------------------------------------------------------------------- // class qtractorMidiManager -- MIDI internal plugin list manager. // class qtractorMidiManager : public qtractorList::Link { public: // Constructor. qtractorMidiManager(qtractorPluginList *pPluginList, unsigned int iBufferSize = qtractorMidiBuffer::MinBufferSize); // Destructor. ~qtractorMidiManager(); // Implementation properties. qtractorPluginList *pluginList() const { return m_pPluginList; } unsigned int bufferSize() const { return m_queuedBuffer.bufferSize(); } // Clears buffers for processing. void clear(); // Event buffer accessor. snd_seq_event_t *events() const { return m_pBuffer; } // Returns number of events result of process. unsigned int count() const { return m_iBuffer; } // Direct buffering. bool direct(snd_seq_event_t *pEvent); // Queued buffering. bool queued(qtractorTimeScale *pTimeScale, snd_seq_event_t *pEvent, unsigned long iTime, long iFrameStart); // Process buffers. void process(unsigned long iTimeStart, unsigned long iTimeEnd); // Process buffers (in asynchronous controller thread). void processSync(); // Resets all buffering. void reset(); // Sync thread state flags accessors. void setWaitSync(bool bWaitSync); bool isWaitSync() const; // Factory (proxy) methods. static qtractorMidiManager *createMidiManager( qtractorPluginList *pPluginList); static void deleteMidiManager( qtractorMidiManager *pMidiManager); // Some default factory options. static void setDefaultAudioOutputBus(bool bAudioOutputBus); static bool isDefaultAudioOutputBus(); static void setDefaultAudioOutputAutoConnect(bool bAudioOutputAutoConnect); static bool isDefaultAudioOutputAutoConnect(); #ifdef CONFIG_VST // VST event buffer accessors... VstEvents *vst_events_in() const { return (VstEvents *) m_ppVstBuffers[m_iEventBuffer & 1]; } VstEvents *vst_events_out() const { return (VstEvents *) m_ppVstBuffers[(m_iEventBuffer + 1) & 1]; } // Copy VST event buffer (output)... void vst_events_copy(VstEvents *pVstBuffer); // Swap VST event buffers... void vst_events_swap(); #endif #ifdef CONFIG_LV2_EVENT // LV2 event buffer accessors... LV2_Event_Buffer *lv2_events_in() const { return m_ppLv2EventBuffers[m_iEventBuffer & 1]; } LV2_Event_Buffer *lv2_events_out() const { return m_ppLv2EventBuffers[(m_iEventBuffer + 1) & 1]; } // Swap LV2 event buffers... void lv2_events_swap(); #endif #ifdef CONFIG_LV2_ATOM // LV2 atom buffer accessors... LV2_Atom_Buffer *lv2_atom_buffer_in() const { return m_ppLv2AtomBuffers[m_iEventBuffer & 1]; } LV2_Atom_Buffer *lv2_atom_buffer_out() const { return m_ppLv2AtomBuffers[(m_iEventBuffer + 1) & 1]; } // Swap LV2 atom buffers... void lv2_atom_buffer_swap(); #endif // Audio output bus mode accessors. void setAudioOutputBus(bool bAudioOutputBus); bool isAudioOutputBus() const { return m_bAudioOutputBus; } qtractorAudioBus *audioOutputBus() const { return m_pAudioOutputBus; } void resetAudioOutputBus(); // Audio output bus defaults accessors. void setAudioOutputAutoConnect(bool bAudioOutputAutoConnect) { m_bAudioOutputAutoConnect = bAudioOutputAutoConnect; } bool isAudioOutputAutoConnect() const { return m_bAudioOutputAutoConnect; } // Current bank selection accessors. void setCurrentBank(int iBank) { m_iCurrentBank = iBank; } int currentBank() const { return m_iCurrentBank; } // Current program selection accessors. void setCurrentProg(int iProg) { m_iCurrentProg = iProg; } int currentProg() const { return m_iCurrentProg; } // MIDI Instrument collection map-types. typedef QMap Progs; struct Bank { QString name; Progs progs; }; typedef QMap Banks; typedef QMap Instruments; // Instrument map builder. void updateInstruments(); // Instrument map accessor. const Instruments& instruments() const { return m_instruments; } protected: // Audio output (de)activation methods. void createAudioOutputBus(); void deleteAudioOutputBus(); // Swap event buffers (in for out and vice-versa) void swapEventBuffers(); private: // Instance variables qtractorPluginList *m_pPluginList; qtractorMidiBuffer m_directBuffer; qtractorMidiBuffer m_queuedBuffer; qtractorMidiBuffer m_postedBuffer; qtractorMidiBuffer m_controllerBuffer; snd_seq_event_t *m_pBuffer; unsigned int m_iBuffer; volatile bool m_bWaitSync; #ifdef CONFIG_MIDI_PARSER snd_midi_event_t *m_pMidiParser; #endif unsigned short m_iEventBuffer; #ifdef CONFIG_VST VstMidiEvent *m_ppVstMidiBuffers[2]; unsigned char *m_ppVstBuffers[2]; #endif #ifdef CONFIG_LV2_EVENT LV2_Event_Buffer *m_ppLv2EventBuffers[2]; #endif #ifdef CONFIG_LV2_ATOM LV2_Atom_Buffer *m_ppLv2AtomBuffers[2]; #endif bool m_bAudioOutputBus; bool m_bAudioOutputAutoConnect; qtractorAudioBus *m_pAudioOutputBus; int m_iCurrentBank; int m_iCurrentProg; int m_iPendingBankMSB; int m_iPendingBankLSB; int m_iPendingProg; Instruments m_instruments; // Aync manager thread. static qtractorMidiManagerThread *g_pSyncThread; static unsigned int g_iSyncThreadRefCount; // Global factory options. static bool g_bAudioOutputBus; static bool g_bAudioOutputAutoConnect; }; #endif // __qtractorMidiBuffer_h // end of qtractorMidiBuffer.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiListView.cpp0000644000175000001440000000012312166526620022106 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134667.89608 30 ctime=1381134667.896080063 qtractor-0.5.11/src/qtractorMidiListView.cpp0000644000175000001440000001525512166526620021405 0ustar00rncbcusers00000000000000// qtractorMidiListView.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiListView.h" #include "qtractorMidiFile.h" #include "qtractorOptions.h" #include #include #include //---------------------------------------------------------------------- // class qtractorMidiFileItem -- audio file list view item. // // Constructors. qtractorMidiFileItem::qtractorMidiFileItem ( const QString& sPath, qtractorMidiFile *pFile ) : qtractorFileListItem(sPath) { QTreeWidgetItem::setTextAlignment( qtractorMidiListView::Format, Qt::AlignRight); QTreeWidgetItem::setTextAlignment( qtractorMidiListView::Tracks, Qt::AlignRight); QTreeWidgetItem::setTextAlignment( qtractorMidiListView::Resolution, Qt::AlignRight); QTreeWidgetItem::setIcon(qtractorMidiListView::Name, QIcon(":/images/itemMidiFile.png")); QTreeWidgetItem::setText(qtractorMidiListView::Format, QString::number(pFile->format())); QTreeWidgetItem::setText(qtractorMidiListView::Tracks, QString::number(pFile->tracks())); QTreeWidgetItem::setText(qtractorMidiListView::Resolution, QString::number(pFile->ticksPerBeat())); QTreeWidgetItem::setText(qtractorMidiListView::Path, sPath); if (pFile->format() == 1) { // Add track sub-items... for (int iTrack = 0; iTrack < pFile->tracks(); ++iTrack) { new qtractorMidiChannelItem(this, QObject::tr("Track %1").arg(iTrack), iTrack); } } else { // Add channel sub-items... for (int iChannel = 0; iChannel < 16; ++iChannel) { new qtractorMidiChannelItem(this, QObject::tr("Channel %1").arg(iChannel + 1), iChannel); } } } // Tooltip renderer. QString qtractorMidiFileItem::toolTip (void) const { return QObject::tr("%1 (format %2)\n%3 tracks, %4 tpqn\n%5") .arg(QTreeWidgetItem::text(qtractorMidiListView::Name)) .arg(QTreeWidgetItem::text(qtractorMidiListView::Format)) .arg(QTreeWidgetItem::text(qtractorMidiListView::Tracks)) .arg(QTreeWidgetItem::text(qtractorMidiListView::Resolution)) .arg(QTreeWidgetItem::text(qtractorMidiListView::Path)); } //---------------------------------------------------------------------- // class qtractorMidiChannelItem -- MIDI track/channel view item. // // Constructor. qtractorMidiChannelItem::qtractorMidiChannelItem ( qtractorMidiFileItem *pFileItem, const QString& sName, unsigned short iChannel ) : qtractorFileChannelItem(pFileItem, sName, iChannel) { QTreeWidgetItem::setIcon(qtractorMidiListView::Name, QIcon(":/images/itemChannel.png")); } // Tooltip renderer. QString qtractorMidiChannelItem::toolTip (void) const { qtractorMidiFileItem *pFileItem = static_cast (QTreeWidgetItem::parent()); if (pFileItem == NULL) return qtractorFileChannelItem::toolTip(); return QObject::tr("%1 (format %2)\n%3") .arg(pFileItem->text(qtractorMidiListView::Name)) .arg(pFileItem->text(qtractorMidiListView::Format)) .arg(QTreeWidgetItem::text(qtractorMidiListView::Name)); } //---------------------------------------------------------------------------- // qtractorMidiListView -- Group/File list view, supporting drag-n-drop. // // Constructor. qtractorMidiListView::qtractorMidiListView ( QWidget *pParent ) : qtractorFileListView(qtractorFileList::Midi, pParent) { QTreeWidget::setColumnCount(qtractorMidiListView::LastColumn + 1); QTreeWidgetItem *pHeaderItem = QTreeWidget::headerItem(); pHeaderItem->setText(qtractorMidiListView::Name, tr("Name")); pHeaderItem->setText(qtractorMidiListView::Format, tr("Fmt")); pHeaderItem->setText(qtractorMidiListView::Tracks, tr("Tracks")); pHeaderItem->setText(qtractorMidiListView::Resolution, tr("tpqn")); pHeaderItem->setText(qtractorMidiListView::Path, tr("Path")); pHeaderItem->setText(qtractorMidiListView::LastColumn, QString::null); pHeaderItem->setTextAlignment( qtractorMidiListView::Format, Qt::AlignRight); pHeaderItem->setTextAlignment( qtractorMidiListView::Tracks, Qt::AlignRight); pHeaderItem->setTextAlignment( qtractorMidiListView::Resolution, Qt::AlignRight); QHeaderView *pHeader = QTreeWidget::header(); pHeader->resizeSection(qtractorMidiListView::Name, 160); QTreeWidget::resizeColumnToContents(qtractorMidiListView::Format); QTreeWidget::resizeColumnToContents(qtractorMidiListView::Tracks); QTreeWidget::resizeColumnToContents(qtractorMidiListView::Resolution); pHeader->resizeSection(qtractorMidiListView::Path, 160); } // File item factory method. qtractorFileListItem *qtractorMidiListView::createFileItem ( const QString& sPath ) { qtractorFileListItem *pFileItem = NULL; qtractorMidiFile file; if (file.open(sPath)) { pFileItem = new qtractorMidiFileItem(sPath, &file); file.close(); } return pFileItem; } // Prompt for proper file list open. QStringList qtractorMidiListView::getOpenFileNames (void) { QStringList files; const QString sExt("mid"); const QString& sTitle = tr("Open MIDI Files") + " - " QTRACTOR_TITLE; const QString& sFilter = tr("MIDI files (*.%1 *.smf *.midi)").arg(sExt); #if 0//QT_VERSION < 0x040400 // Ask for the filenames to open... files = QFileDialog::getOpenFileNames(this, sTitle, recentDir(), sFilter); #else // Construct open-files dialog... QFileDialog fileDialog(this, sTitle, recentDir(), sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::ExistingFiles); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(pOptions->sMidiDir)); fileDialog.setSidebarUrls(urls); } // Show dialog... if (fileDialog.exec()) files = fileDialog.selectedFiles(); #endif return files; } // end of qtractorMidiListView.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMeter.h0000644000175000001440000000012212106745154020254 xustar000000000000000026 mtime=1360775788.99151 26 atime=1381134667.10908 30 ctime=1381134667.109080051 qtractor-0.5.11/src/qtractorMeter.h0000644000175000001440000001117312106745154017547 0ustar00rncbcusers00000000000000// qtractorMeter.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMeter_h #define __qtractorMeter_h #include // Forward declarations. class qtractorMeter; class qtractorMonitor; class qtractorSubject; class qtractorObserverSlider; class qtractorObserverSpinBox; class qtractorMidiControlObserver; class qtractorDocument; class QDomElement; class QHBoxLayout; class QVBoxLayout; class QPaintEvent; class QResizeEvent; //---------------------------------------------------------------------------- // qtractorMeterScale -- Meter bridge scale widget. class qtractorMeterScale : public QFrame { Q_OBJECT public: // Constructor. qtractorMeterScale(qtractorMeter *pMeter, QWidget *pParent = 0); // Meter accessor. qtractorMeter *meter() const; protected: // Specific event handlers. void paintEvent(QPaintEvent *); // Draw IEC scale line and label. void drawLineLabel(QPainter *p, int y, const QString& sLabel); // Actual scale drawing method. virtual void paintScale(QPainter *p) = 0; private: // Local instance variables. qtractorMeter *m_pMeter; // Running variables. int m_iLastY; }; //---------------------------------------------------------------------------- // qtractorMeter -- Meter bridge slot widget. class qtractorMeter : public QWidget { Q_OBJECT public: // Constructor. qtractorMeter(QWidget *pParent = 0); // Default destructor. virtual ~qtractorMeter(); // Dynamic layout accessors. QHBoxLayout *topLayout() const; QWidget *topWidget() const; QHBoxLayout *boxLayout() const; QWidget *boxWidget() const; // Common slider/spin-box accessors. qtractorObserverSlider *panSlider() const; qtractorObserverSpinBox *panSpinBox() const; qtractorObserverSlider *gainSlider() const; qtractorObserverSpinBox *gainSpinBox() const; // Panning subject accessors. void setPanningSubject(qtractorSubject *pSubject); qtractorSubject *panningSubject() const; qtractorMidiControlObserver *panningObserver() const; // Panning accessors. void setPanning(float fPanning); float panning() const; float prevPanning() const; // Gain subject accessors. void setGainSubject(qtractorSubject *pSubject); qtractorSubject *gainSubject() const; qtractorMidiControlObserver *gainObserver() const; // Gain accessors. void setGain(float fGain); float gain() const; float prevGain() const; // Monitor accessors. virtual void setMonitor(qtractorMonitor *pMonitor) = 0; virtual qtractorMonitor *monitor() const = 0; // Local slider update methods. virtual void updatePanning() = 0; virtual void updateGain() = 0; // Slot refreshment. virtual void refresh() = 0; // Meter reset. virtual void reset() = 0; // Reset peak holder. virtual void peakReset() = 0; // Peak falloff mode setting. void setPeakFalloff(int bPeakFalloff); int peakFalloff() const; // MIDI controller/observer attachment (context menu) activator. void addMidiControlAction( QWidget *pWidget, qtractorMidiControlObserver *pObserver); protected slots: // MIDI controller/observer attachment (context menu) slot. void midiControlActionSlot(); void midiControlMenuSlot(const QPoint& pos); private: // Local forward declarations. class PanSliderInterface; // Local instance variables. QVBoxLayout *m_pVBoxLayout; QWidget *m_pTopWidget; QHBoxLayout *m_pTopLayout; QWidget *m_pBoxWidget; QHBoxLayout *m_pBoxLayout; qtractorObserverSlider *m_pPanSlider; qtractorObserverSpinBox *m_pPanSpinBox; qtractorObserverSlider *m_pGainSlider; qtractorObserverSpinBox *m_pGainSpinBox; class PanObserver; class GainObserver; PanObserver *m_pPanObserver; GainObserver *m_pGainObserver; // Peak falloff mode setting (0=no peak falloff). int m_iPeakFalloff; }; #endif // __qtractorMeter_h // end of qtractorMeter.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiToolsForm.ui0000644000175000001440000000012211700320606022103 xustar000000000000000027 mtime=1325506950.447119 26 atime=1381134667.69808 29 ctime=1381134667.69808006 qtractor-0.5.11/src/qtractorMidiToolsForm.ui0000644000175000001440000011730111700320606021376 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorMidiToolsForm 0 0 455 276 MIDI Tools :/images/qtractorMidiEditor.png 4 4 2 2 160 0 Preset name true Qt::TabFocus Save preset :/images/formSave.png Qt::TabFocus Delete preset :/images/formRemove.png Qt::Horizontal 180 20 0 &Quantize 75 true Quantize selected events &Quantize Qt::Horizontal QSizePolicy::Fixed 16 20 &Time: Quantize time 60 0 Quantize time percent % 0 100 100 Qt::Horizontal 16 20 &Duration: Quantize duration 60 0 Quantize duration percent % 0 100 100 S&wing: Swing-quantize time 60 0 Swing-quantize percent % -100 100 0 Swing-quantize type Linear Quadratic Cubic Qt::Horizontal 73 20 &Scale: Scale-quantize key Scale-quantize type Qt::Vertical 20 16 &Transpose 75 true Transpose selected events &Transpose Qt::Horizontal QSizePolicy::Fixed 16 20 &Note: 60 0 Transpose note -64 64 Qt::Horizontal 16 20 &Time: 120 0 Transpose time Transpose time format Frames Time BBT Qt::Horizontal 16 20 Qt::Vertical 20 16 &Normalize 75 true Normalize selected events &Normalize Qt::Horizontal QSizePolicy::Fixed 16 20 &Percent: 60 0 Normalize percent % 150 Qt::Horizontal 16 20 &Value: 60 0 Normalize value 127 Qt::Vertical 20 16 &Randomize 75 true Randomize selected events &Randomize Qt::Horizontal QSizePolicy::Fixed 16 20 &Note: 60 0 Randomize note/pitch % 150 Qt::Horizontal 16 20 &Time: 60 0 Randomize time % 150 &Duration: 60 0 Randomize duration % 150 &Value: 60 0 Randomize value % 150 Qt::Vertical 20 16 Resi&ze 75 true Resize selected events Resi&ze Qt::Horizontal QSizePolicy::Fixed 16 20 &Duration: 120 0 Resize duration Resize duration format Frames Time BBT Percentage Qt::Horizontal 16 20 &Value: 60 0 Resize value 127 Resize value mode Flat Ramp 60 0 Resize final value 127 Qt::Horizontal 16 20 Qt::Vertical 20 16 Re&scale 75 true Rescale selected events Re&scale Qt::Horizontal QSizePolicy::Fixed 16 19 &Time: 60 0 Rescale time % 1 1000 100 Qt::Horizontal 224 58 &Duration: 60 0 Rescale duration % 1 1000 100 &Value: 60 0 Rescale value % 1 1000 100 Qt::Vertical 358 38 T&imeshift 75 true Timeshift selected events Timeshift Qt::Horizontal QSizePolicy::Fixed 16 19 P: 60 0 Timeshift parameter true 3 -100.0 100.0 0.001 0.000 Timeshift parameter (log) -10000 10000 10 100 0 Qt::Horizontal 80 80 80 80 Timeshift curve QFrame::Panel QFrame::Sunken P = 0 : no change. P > 0 : accelerating shift. P < 0 : slowing down shift. Edit head/tail (blue) markers define the shift range. Timeshift duration Qt::Vertical 358 38 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qtractorTimeSpinBox QSpinBox
qtractorSpinBox.h
PresetNameComboBox PresetSaveToolButton PresetDeleteToolButton ToolTabWidget QuantizeCheckBox QuantizeTimeCheckBox QuantizeTimeComboBox QuantizeTimeSpinBox QuantizeDurationCheckBox QuantizeDurationComboBox QuantizeDurationSpinBox QuantizeSwingCheckBox QuantizeSwingComboBox QuantizeSwingSpinBox QuantizeSwingTypeComboBox QuantizeScaleCheckBox QuantizeScaleKeyComboBox QuantizeScaleComboBox TransposeCheckBox TransposeNoteCheckBox TransposeNoteSpinBox TransposeTimeCheckBox TransposeTimeSpinBox TransposeFormatComboBox NormalizeCheckBox NormalizePercentCheckBox NormalizePercentSpinBox NormalizeValueCheckBox NormalizeValueSpinBox RandomizeCheckBox RandomizeNoteCheckBox RandomizeNoteSpinBox RandomizeTimeCheckBox RandomizeTimeSpinBox RandomizeDurationCheckBox RandomizeDurationSpinBox RandomizeValueCheckBox RandomizeValueSpinBox ResizeCheckBox ResizeDurationCheckBox ResizeDurationSpinBox ResizeFormatComboBox ResizeValueCheckBox ResizeValueSpinBox ResizeValue2ComboBox ResizeValue2SpinBox RescaleCheckBox RescaleTimeCheckBox RescaleTimeSpinBox RescaleDurationCheckBox RescaleDurationSpinBox RescaleValueCheckBox RescaleValueSpinBox TimeshiftCheckBox TimeshiftSpinBox TimeshiftSlider TimeshiftDurationCheckBox DialogButtonBox
qtractor-0.5.11/src/PaxHeaders.10084/qtractorMixer.cpp0000644000175000001440000000012212217361266020620 xustar000000000000000026 mtime=1379787446.61859 26 atime=1381134670.47808 30 ctime=1381134670.479080104 qtractor-0.5.11/src/qtractorMixer.cpp0000644000175000001440000011356212217361266020120 0ustar00rncbcusers00000000000000// qtractorMixer.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMixer.h" #include "qtractorPluginListView.h" #include "qtractorAudioMeter.h" #include "qtractorMidiMeter.h" #include "qtractorAudioMonitor.h" #include "qtractorMidiMonitor.h" #include "qtractorObserverWidget.h" #include "qtractorOptions.h" #include "qtractorSession.h" #include "qtractorTracks.h" #include "qtractorConnections.h" #include "qtractorTrackCommand.h" #include "qtractorEngineCommand.h" #include "qtractorAudioEngine.h" #include "qtractorMidiEngine.h" #include "qtractorMidiControlObserver.h" #include "qtractorCurve.h" #include "qtractorMainForm.h" #include "qtractorBusForm.h" #include #include #include #include #include #include #include #include #ifdef CONFIG_GRADIENT #include #endif //---------------------------------------------------------------------------- // qtractorMonitorButton -- Monitor observer tool button. // Constructors. qtractorMonitorButton::qtractorMonitorButton ( qtractorTrack *pTrack, QWidget *pParent ) : qtractorMidiControlButton(pParent) { initMonitorButton(); setTrack(pTrack); } qtractorMonitorButton::qtractorMonitorButton ( qtractorBus *pBus, QWidget *pParent ) : qtractorMidiControlButton(pParent) { initMonitorButton(); setBus(pBus); } // Common initializer. void qtractorMonitorButton::initMonitorButton (void) { QIcon icons; icons.addPixmap(QPixmap(":/images/itemLedOff.png"), QIcon::Normal, QIcon::Off); icons.addPixmap(QPixmap(":/images/itemLedOn.png"), QIcon::Normal, QIcon::On); QPushButton::setIcon(icons); QPushButton::setText(tr("monitor")); QObject::connect(this, SIGNAL(toggled(bool)), SLOT(toggledSlot(bool))); } // Specific track accessors. void qtractorMonitorButton::setTrack ( qtractorTrack *pTrack ) { m_pTrack = pTrack; m_pBus = NULL; QPushButton::setToolTip(tr("Monitor (rec)")); updateMonitor(); // Visitor setup. } qtractorTrack *qtractorMonitorButton::track (void) const { return m_pTrack; } // Specific bus accessors. void qtractorMonitorButton::setBus ( qtractorBus *pBus ) { m_pBus = pBus; m_pTrack = NULL; QPushButton::setToolTip(tr("Monitor (thru)")); updateMonitor(); // Visitor setup. } qtractorBus *qtractorMonitorButton::bus (void) const { return m_pBus; } // Visitors overload. void qtractorMonitorButton::updateValue ( float fValue ) { // Avoid self-triggering... bool bBlockSignals = QPushButton::blockSignals(true); QPushButton::setChecked(fValue > 0.0f); QPushButton::blockSignals(bBlockSignals); } // Special toggle slot. void qtractorMonitorButton::toggledSlot ( bool bOn ) { // Just emit proper signal... if (m_pTrack) m_pTrack->monitorChangeNotify(bOn); else if (m_pBus) m_pBus->monitorChangeNotify(bOn); } // Monitor state button setup. void qtractorMonitorButton::updateMonitor (void) { if (m_pTrack) { setSubject(m_pTrack->monitorSubject()); qtractorMidiControlObserver *pMidiObserver = m_pTrack->monitorObserver(); if (pMidiObserver) { pMidiObserver->setCurveList(m_pTrack->curveList()); addMidiControlAction(pMidiObserver); } } else if (m_pBus) { if ((m_pBus->busMode() & qtractorBus::Duplex) == qtractorBus::Duplex) { setSubject(m_pBus->monitorSubject()); addMidiControlAction(m_pBus->monitorObserver()); QPushButton::setEnabled(true); } else { QPushButton::setEnabled(false); } } observer()->update(true); } //---------------------------------------------------------------------------- // qtractorMixerStrip::IconLabel -- Custom mixer strip title widget. class qtractorMixerStrip::IconLabel : public QLabel { public: // Constructor. IconLabel(QWidget *pParent = NULL) : QLabel(pParent) {} // Icon accessors. void setIcon(const QIcon& icon) { m_icon = icon; } const QIcon& icon() const { return m_icon; } protected: // Custom paint event. void paintEvent(QPaintEvent *) { QPainter painter(this); QRect rect(QLabel::rect()); painter.drawPixmap(rect.x(), rect.y(), m_icon.pixmap(rect.height())); rect.setX(rect.x() + rect.height() + 1); painter.drawText(rect, QLabel::alignment(), QLabel::text()); } private: // Instance variables. QIcon m_icon; }; //---------------------------------------------------------------------------- // qtractorMixerStrip -- Mixer strip widget. // Constructors. qtractorMixerStrip::qtractorMixerStrip ( qtractorMixerRack *pRack, qtractorBus *pBus, qtractorBus::BusMode busMode ) : QFrame(pRack->workspace()), m_pRack(pRack), m_pBus(pBus), m_busMode(busMode), m_pTrack(NULL) { initMixerStrip(); } qtractorMixerStrip::qtractorMixerStrip ( qtractorMixerRack *pRack, qtractorTrack *pTrack ) : QFrame(pRack->workspace()), m_pRack(pRack), m_pBus(NULL), m_busMode(qtractorBus::None), m_pTrack(pTrack) { initMixerStrip(); } // Default destructor. qtractorMixerStrip::~qtractorMixerStrip (void) { // No need to delete child widgets, Qt does it all for us #if 0 if (m_pMidiLabel) delete m_pMidiLabel; if (m_pMeter) delete m_pMeter; if (m_pSoloButton) delete m_pSoloButton; if (m_pMuteButton) delete m_pMuteButton; if (m_pRecordButton) delete m_pRecordButton; if (m_pMonitorButton) delete m_pMonitorButton; if (m_pBusButton) delete m_pBusButton; delete m_pButtonLayout; delete m_pPluginListView; delete m_pLabel; delete m_pLayout; #endif } // Common mixer-strip initializer. void qtractorMixerStrip::initMixerStrip (void) { m_iMark = 0; const QFont& font = QFrame::font(); const QFont font2(font.family(), font.pointSize() - 2); const int iFixedHeight = QFontMetrics(font2).lineSpacing() + 4; m_pLayout = new QVBoxLayout(this); m_pLayout->setMargin(4); m_pLayout->setSpacing(4); m_pLabel = new IconLabel(/*this*/); m_pLabel->setFont(font2); m_pLabel->setFixedHeight(iFixedHeight); m_pLabel->setBackgroundRole(QPalette::Button); m_pLabel->setForegroundRole(QPalette::ButtonText); m_pLabel->setAutoFillBackground(true); m_pLayout->addWidget(m_pLabel); m_pPluginListView = new qtractorPluginListView(/*this*/); m_pPluginListView->setFont(font2); m_pPluginListView->setFixedHeight(iFixedHeight << 2); m_pPluginListView->setTinyScrollBar(true); m_pLayout->addWidget(m_pPluginListView); const QSizePolicy buttonPolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_pButtonLayout = new QHBoxLayout(/*this*/); m_pButtonLayout->setMargin(0); m_pButtonLayout->setSpacing(2); qtractorTrack::TrackType meterType = qtractorTrack::None; if (m_pTrack) { meterType = m_pTrack->trackType(); m_pMonitorButton = new qtractorMonitorButton(m_pTrack); m_pMonitorButton->setFixedHeight(iFixedHeight); m_pMonitorButton->setSizePolicy(buttonPolicy); m_pMonitorButton->setFont(font2); const QFont font3(font.family(), font.pointSize() - 3); m_pRecordButton = new qtractorTrackButton(m_pTrack, qtractorTrack::Record); m_pRecordButton->setFixedHeight(iFixedHeight); m_pRecordButton->setSizePolicy(buttonPolicy); m_pRecordButton->setFont(font3); m_pMuteButton = new qtractorTrackButton(m_pTrack, qtractorTrack::Mute); m_pMuteButton->setFixedHeight(iFixedHeight); m_pMuteButton->setSizePolicy(buttonPolicy); m_pMuteButton->setFont(font3); m_pSoloButton = new qtractorTrackButton(m_pTrack, qtractorTrack::Solo); m_pSoloButton->setFixedHeight(iFixedHeight); m_pSoloButton->setSizePolicy(buttonPolicy); m_pSoloButton->setFont(font3); m_pButtonLayout->addWidget(m_pRecordButton); m_pButtonLayout->addWidget(m_pMuteButton); m_pButtonLayout->addWidget(m_pSoloButton); m_pBusButton = NULL; } else if (m_pBus) { meterType = m_pBus->busType(); m_pMonitorButton = new qtractorMonitorButton(m_pBus); m_pMonitorButton->setFixedHeight(iFixedHeight); m_pMonitorButton->setSizePolicy(buttonPolicy); m_pMonitorButton->setFont(font2); m_pBusButton = new QPushButton(/*this*/); m_pBusButton->setFixedHeight(iFixedHeight); m_pBusButton->setFocusPolicy(Qt::NoFocus); m_pBusButton->setSizePolicy(buttonPolicy); // m_pBusButton->setToolButtonStyle(Qt::ToolButtonTextOnly); m_pBusButton->setFont(font2); m_pBusButton->setText( m_busMode & qtractorBus::Input ? tr("inputs") : tr("outputs")); m_pBusButton->setToolTip(tr("Connect %1").arg(m_pBusButton->text())); m_pButtonLayout->addWidget(m_pBusButton); QObject::connect(m_pBusButton, SIGNAL(clicked()), SLOT(busButtonSlot())); m_pRecordButton = NULL; m_pMuteButton = NULL; m_pSoloButton = NULL; } m_pLayout->addWidget(m_pMonitorButton); m_pLayout->addLayout(m_pButtonLayout); // Now, there's whether we are Audio or MIDI related... m_pMeter = NULL; m_pMidiLabel = NULL; int iFixedWidth = 42; switch (meterType) { case qtractorTrack::Audio: { // Type cast for proper audio monitor... qtractorAudioMonitor *pAudioMonitor = NULL; if (m_pTrack) { pAudioMonitor = static_cast (m_pTrack->monitor()); m_pPluginListView->setPluginList(m_pTrack->pluginList()); } else { qtractorAudioBus *pAudioBus = static_cast (m_pBus); if (pAudioBus) { if (m_busMode & qtractorBus::Input) { m_pPluginListView->setPluginList( pAudioBus->pluginList_in()); pAudioMonitor = pAudioBus->audioMonitor_in(); } else { m_pPluginListView->setPluginList( pAudioBus->pluginList_out()); pAudioMonitor = pAudioBus->audioMonitor_out(); } } } // Have we an audio monitor/meter?... if (pAudioMonitor) { iFixedWidth += 16 * (pAudioMonitor->channels() < 2 ? 2 : pAudioMonitor->channels()); m_pMeter = new qtractorAudioMeter(pAudioMonitor, this); } m_pPluginListView->setEnabled(true); break; } case qtractorTrack::Midi: { // Type cast for proper MIDI monitor... qtractorMidiMonitor *pMidiMonitor = NULL; qtractorMidiBus *pMidiBus = NULL; if (m_pTrack) { pMidiMonitor = static_cast (m_pTrack->monitor()); m_pPluginListView->setPluginList(m_pTrack->pluginList()); m_pPluginListView->setEnabled(true); } else { pMidiBus = static_cast (m_pBus); if (pMidiBus) { if (m_busMode & qtractorBus::Input) { m_pPluginListView->setPluginList( pMidiBus->pluginList_in()); pMidiMonitor = pMidiBus->midiMonitor_in(); } else { m_pPluginListView->setPluginList( pMidiBus->pluginList_out()); pMidiMonitor = pMidiBus->midiMonitor_out(); } } m_pPluginListView->setEnabled(true); } // Have we a MIDI monitor/meter?... if (pMidiMonitor) { iFixedWidth += 32; m_pMeter = new qtractorMidiMeter(pMidiMonitor, this); // MIDI Tracks might need to show something, // like proper MIDI channel settings... if (m_pTrack) { m_pMidiLabel = new QLabel(/*m_pMeter->topWidget()*/); m_pMidiLabel->setFont(font2); m_pMidiLabel->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter); m_pMeter->topLayout()->insertWidget(1, m_pMidiLabel); updateMidiLabel(); } // No panning on MIDI bus monitors and on duplex ones // only on the output buses should be enabled... if (pMidiBus) { if ((m_busMode & qtractorBus::Input) && (m_pBus->busMode() & qtractorBus::Output)) { m_pMeter->panSlider()->setEnabled(false); m_pMeter->panSpinBox()->setEnabled(false); m_pMeter->gainSlider()->setEnabled(false); m_pMeter->gainSpinBox()->setEnabled(false); } } } break; } case qtractorTrack::None: default: break; } // Eventually the right one... if (m_pMeter) { // Set MIDI controller & automation hooks... qtractorMidiControlObserver *pMidiObserver; pMidiObserver = m_pMeter->panningObserver(); if (m_pTrack) pMidiObserver->setCurveList(m_pTrack->curveList()); m_pMeter->addMidiControlAction(m_pMeter->panSlider(), pMidiObserver); pMidiObserver = m_pMeter->gainObserver(); if (m_pTrack) pMidiObserver->setCurveList(m_pTrack->curveList()); m_pMeter->addMidiControlAction(m_pMeter->gainSlider(), pMidiObserver); // Finally, add to layout... m_pLayout->addWidget(m_pMeter); QObject::connect(m_pMeter->panSlider(), SIGNAL(valueChanged(float)), SLOT(panningChangedSlot(float))); QObject::connect(m_pMeter->panSpinBox(), SIGNAL(valueChanged(float)), SLOT(panningChangedSlot(float))); QObject::connect(m_pMeter->gainSlider(), SIGNAL(valueChanged(float)), SLOT(gainChangedSlot(float))); QObject::connect(m_pMeter->gainSpinBox(), SIGNAL(valueChanged(float)), SLOT(gainChangedSlot(float))); } QFrame::setFrameShape(QFrame::Panel); QFrame::setFrameShadow(QFrame::Raised); QFrame::setFixedWidth(iFixedWidth); // QFrame::setSizePolicy( // QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding)); QFrame::setBackgroundRole(QPalette::Window); // QFrame::setForegroundRole(QPalette::WindowText); QFrame::setAutoFillBackground(true); updateName(); setSelected(false); } // Child properties accessors. void qtractorMixerStrip::setMonitor ( qtractorMonitor *pMonitor ) { if (m_pMeter) m_pMeter->setMonitor(pMonitor); } qtractorMonitor *qtractorMixerStrip::monitor (void) const { return (m_pMeter ? m_pMeter->monitor() : NULL); } // Common mixer-strip caption title updater. void qtractorMixerStrip::updateName (void) { QString sName; qtractorTrack::TrackType meterType = qtractorTrack::None; if (m_pTrack) { meterType = m_pTrack->trackType(); sName = m_pTrack->trackName(); QPalette pal(m_pLabel->palette()); pal.setColor(QPalette::Button, m_pTrack->foreground().lighter()); pal.setColor(QPalette::ButtonText, m_pTrack->background().lighter()); m_pLabel->setPalette(pal); m_pLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); } else if (m_pBus) { meterType = m_pBus->busType(); if (m_busMode & qtractorBus::Input) { sName = tr("%1 In").arg(m_pBus->busName()); } else { sName = tr("%1 Out").arg(m_pBus->busName()); } m_pLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); } QString sType; switch (meterType) { case qtractorTrack::Audio: m_pLabel->setIcon(QIcon(":/images/trackAudio.png")); sType = tr("(Audio)"); break; case qtractorTrack::Midi: m_pLabel->setIcon(QIcon(":/images/trackMidi.png")); sType = tr("(MIDI)"); break; case qtractorTrack::None: default: sType = tr("(None)"); break; } m_pLabel->setText(sName); QFrame::setToolTip(sName + ' ' + sType); } // MIDI (channel) label updater. void qtractorMixerStrip::updateMidiLabel (void) { if (m_pTrack == NULL) return; if (m_pMidiLabel == NULL) return; QString sOmni; if (m_pTrack->isMidiOmni()) sOmni += '*'; m_pMidiLabel->setText( sOmni + QString::number(m_pTrack->midiChannel() + 1)); } // Child accessors. qtractorPluginListView *qtractorMixerStrip::pluginListView (void) const { return m_pPluginListView; } qtractorMeter *qtractorMixerStrip::meter (void) const { return m_pMeter; } // Mixer strip clear/suspend delegates void qtractorMixerStrip::clear (void) { m_pPluginListView->setEnabled(false); m_pPluginListView->setPluginList(NULL); m_pRack->updateStrip(this, NULL); } // Bus property accessors. void qtractorMixerStrip::setBus ( qtractorBus *pBus ) { // Must be actual bus... if (m_pBus == NULL || pBus == NULL) return; m_pBus = pBus; if (m_busMode & qtractorBus::Input) { m_pRack->updateStrip(this, m_pBus->monitor_in()); } else { m_pRack->updateStrip(this, m_pBus->monitor_out()); } switch (m_pBus->busType()) { case qtractorTrack::Audio: { qtractorAudioBus *pAudioBus = static_cast (m_pBus); if (pAudioBus) { if (m_busMode & qtractorBus::Input) { m_pPluginListView->setPluginList(pAudioBus->pluginList_in()); } else { m_pPluginListView->setPluginList(pAudioBus->pluginList_out()); } } m_pPluginListView->setEnabled(true); break; } case qtractorTrack::Midi: { qtractorMidiBus *pMidiBus = static_cast (m_pBus); if (pMidiBus) { if (m_busMode & qtractorBus::Input) { m_pPluginListView->setPluginList(pMidiBus->pluginList_in()); } else { m_pPluginListView->setPluginList(pMidiBus->pluginList_out()); } } m_pPluginListView->setEnabled(true); break; } case qtractorTrack::None: default: break; } m_pMonitorButton->setBus(m_pBus); updateName(); } qtractorBus *qtractorMixerStrip::bus (void) const { return m_pBus; } // Track property accessors. void qtractorMixerStrip::setTrack ( qtractorTrack *pTrack ) { // Must be actual track... if (m_pTrack == NULL || pTrack == NULL) return; m_pTrack = pTrack; m_pRack->updateStrip(this, m_pTrack->monitor()); m_pPluginListView->setPluginList(m_pTrack->pluginList()); m_pPluginListView->setEnabled(true); m_pMonitorButton->setTrack(m_pTrack); m_pRecordButton->setTrack(m_pTrack); m_pMuteButton->setTrack(m_pTrack); m_pSoloButton->setTrack(m_pTrack); updateMidiLabel(); updateName(); } qtractorTrack *qtractorMixerStrip::track (void) const { return m_pTrack; } // Selection methods. void qtractorMixerStrip::setSelected ( bool bSelected ) { m_bSelected = bSelected; QPalette pal; #ifdef CONFIG_GRADIENT const QSize& hint = QFrame::sizeHint(); QLinearGradient grad(0, 0, hint.width() >> 1, hint.height()); if (m_bSelected) { const QColor& rgbBase = pal.midlight().color(); pal.setColor(QPalette::WindowText, rgbBase.lighter()); pal.setColor(QPalette::Window, rgbBase.darker(150)); grad.setColorAt(0.4, rgbBase.darker(150)); grad.setColorAt(0.6, rgbBase.darker(130)); grad.setColorAt(1.0, rgbBase.darker()); } else { const QColor& rgbBase = pal.button().color(); // pal.setColor(QPalette::WindowText, rgbBase.darker()); pal.setColor(QPalette::Window, rgbBase); grad.setColorAt(0.4, rgbBase); grad.setColorAt(0.6, rgbBase.lighter(105)); grad.setColorAt(1.0, rgbBase.darker(130)); } m_pPluginListView->setPalette(pal); m_pMonitorButton->setPalette(pal); if (m_pBusButton) m_pBusButton->setPalette(pal); if (m_pRecordButton) m_pRecordButton->setPalette(pal); if (m_pMuteButton) m_pMuteButton->setPalette(pal); if (m_pSoloButton) m_pSoloButton->setPalette(pal); m_pMeter->setPalette(pal); pal.setBrush(QPalette::Window, grad); #else if (m_bSelected) { const QColor& rgbBase = pal.midlight().color(); pal.setColor(QPalette::WindowText, rgbBase.lighter()); pal.setColor(QPalette::Window, rgbBase.darker(150)); } else { const QColor& rgbBase = pal.button().color(); // pal.setColor(QPalette::WindowText, rgbBase.darker()); pal.setColor(QPalette::Window, rgbBase); } #endif QFrame::setPalette(pal); #ifdef CONFIG_GRADIENT if (m_pRecordButton) m_pRecordButton->observer()->update(true); if (m_pMuteButton) m_pMuteButton->observer()->update(true); if (m_pSoloButton) m_pSoloButton->observer()->update(true); #endif } bool qtractorMixerStrip::isSelected (void) const { return m_bSelected; } // Strip refreshment. void qtractorMixerStrip::refresh (void) { if (m_pMeter) m_pMeter->refresh(); } // Hacko-list-management marking... void qtractorMixerStrip::setMark ( int iMark ) { m_iMark = iMark; } int qtractorMixerStrip::mark (void) const { return m_iMark; } // Mouse selection event handlers. void qtractorMixerStrip::mousePressEvent ( QMouseEvent *pMouseEvent ) { QFrame::mousePressEvent(pMouseEvent); m_pRack->setSelectedStrip(this); } // Mouse selection event handlers. void qtractorMixerStrip::mouseDoubleClickEvent ( QMouseEvent */*pMouseEvent*/ ) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; if (m_pTrack) { pMainForm->trackProperties(); } else { m_pRack->busPropertiesSlot(); } } // Bus connections dispatcher. void qtractorMixerStrip::busConnections ( qtractorBus::BusMode busMode ) { if (m_pBus == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; // Here we go... pMainForm->connections()->showBus(m_pBus, busMode); } // Bus pass-through dispatcher. void qtractorMixerStrip::busMonitor ( bool bMonitor ) { if (m_pBus == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Here we go... pSession->execute( new qtractorBusMonitorCommand(m_pBus, bMonitor)); } // Track monitor dispatcher. void qtractorMixerStrip::trackMonitor ( bool bMonitor ) { if (m_pTrack == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Here we go... pSession->execute( new qtractorTrackMonitorCommand(m_pTrack, bMonitor)); } // Bus connections button slot void qtractorMixerStrip::busButtonSlot (void) { busConnections(m_busMode); } // Pan-meter slider value change slot. void qtractorMixerStrip::panningChangedSlot ( float fPanning ) { if (m_pMeter == NULL) return; #ifdef CONFIG_DEBUG_0 qDebug("qtractorMixerStrip[%p]::panningChangedSlot(%g)", this, fPanning); #endif qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Put it in the form of an undoable command... if (m_pTrack) { pSession->execute( new qtractorTrackPanningCommand(m_pTrack, fPanning)); } else if (m_pBus) { pSession->execute( new qtractorBusPanningCommand(m_pBus, m_busMode, fPanning)); } } // Gain-meter slider value change slot. void qtractorMixerStrip::gainChangedSlot ( float fGain ) { if (m_pMeter == NULL) return; #ifdef CONFIG_DEBUG_0 qDebug("qtractorMixerStrip[%p]::gainChangedSlot(%g)", this, fGain); #endif qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Put it in the form of an undoable command... if (m_pTrack) { pSession->execute( new qtractorTrackGainCommand(m_pTrack, fGain)); } else if (m_pBus) { pSession->execute( new qtractorBusGainCommand(m_pBus, m_busMode, fGain)); } } //---------------------------------------------------------------------------- // qtractorMixerRack -- Meter bridge rack. // Constructor. qtractorMixerRack::qtractorMixerRack ( qtractorMixer *pMixer, const QString& sName ) : QScrollArea(pMixer->splitter()), m_pMixer(pMixer), m_sName(sName), m_bSelectEnabled(false), m_pSelectedStrip(NULL) { m_pWorkspaceLayout = new QHBoxLayout(); m_pWorkspaceLayout->setMargin(0); m_pWorkspaceLayout->setSpacing(0); m_pWorkspace = new QWidget(this); m_pWorkspace->setSizePolicy( QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); m_pWorkspace->setLayout(m_pWorkspaceLayout); QScrollArea::viewport()->setBackgroundRole(QPalette::Dark); // QScrollArea::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwayOn); QScrollArea::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QScrollArea::setWidget(m_pWorkspace); } // Default destructor. qtractorMixerRack::~qtractorMixerRack (void) { // No need to delete child widgets, Qt does it all for us clear(); } // The main mixer widget accessor. qtractorMixer *qtractorMixerRack::mixer (void) const { return m_pMixer; } // Rack name accessors. void qtractorMixerRack::setName ( const QString& sName ) { m_sName = sName; } const QString& qtractorMixerRack::name (void) const { return m_sName; } // Add a mixer strip to rack list. void qtractorMixerRack::addStrip ( qtractorMixerStrip *pStrip ) { // Add this to the workspace layout... m_pWorkspaceLayout->addWidget(pStrip); m_strips.insert(pStrip->meter()->monitor(), pStrip); pStrip->show(); } // Remove a mixer strip from rack list. void qtractorMixerRack::removeStrip ( qtractorMixerStrip *pStrip ) { // Remove this from the workspace layout... m_pWorkspaceLayout->removeWidget(pStrip); // Don't let current selection hanging... if (m_pSelectedStrip == pStrip) m_pSelectedStrip = NULL; pStrip->hide(); qtractorMonitor *pMonitor = pStrip->meter()->monitor(); if (findStrip(pMonitor) == pStrip) { m_strips.remove(pMonitor); delete pStrip; } m_pWorkspace->adjustSize(); } // Find a mixer strip, given its monitor handle. qtractorMixerStrip *qtractorMixerRack::findStrip ( qtractorMonitor *pMonitor ) { return m_strips.value(pMonitor, NULL); } // Update a mixer strip on rack list. void qtractorMixerRack::updateStrip ( qtractorMixerStrip *pStrip, qtractorMonitor *pMonitor ) { qtractorMonitor *pOldMonitor = pStrip->meter()->monitor(); if (findStrip(pOldMonitor) == pStrip) m_strips.remove(pOldMonitor); pStrip->setMonitor(pMonitor); if (pMonitor) m_strips.insert(pMonitor, pStrip); } // Current strip count. int qtractorMixerRack::stripCount (void) const { return m_strips.count(); } // The strip workspace. QWidget *qtractorMixerRack::workspace (void) const { return m_pWorkspace; } // Complete rack refreshment. void qtractorMixerRack::refresh (void) { Strips::ConstIterator strip = m_strips.constBegin(); const Strips::ConstIterator& strip_end = m_strips.constEnd(); for ( ; strip != strip_end; ++strip) strip.value()->refresh(); } // Complete rack recycle. void qtractorMixerRack::clear (void) { m_pSelectedStrip = NULL; qDeleteAll(m_strips); m_strips.clear(); } // Selection stuff. void qtractorMixerRack::setSelectEnabled ( bool bSelectEnabled ) { m_bSelectEnabled = bSelectEnabled; if (m_pSelectedStrip) { if (!m_bSelectEnabled) m_pSelectedStrip->setSelected(false); m_pSelectedStrip = NULL; } } bool qtractorMixerRack::isSelectEnabled (void) const { return m_bSelectEnabled; } void qtractorMixerRack::setSelectedStrip ( qtractorMixerStrip *pStrip ) { if (m_pSelectedStrip != pStrip) { if (m_bSelectEnabled && m_pSelectedStrip) m_pSelectedStrip->setSelected(false); m_pSelectedStrip = pStrip; if (m_bSelectEnabled && m_pSelectedStrip) m_pSelectedStrip->setSelected(true); emit selectionChanged(); } } qtractorMixerStrip *qtractorMixerRack::selectedStrip (void) const { return m_pSelectedStrip; } // Hacko-list-management marking... void qtractorMixerRack::markStrips ( int iMark ) { m_pWorkspace->setUpdatesEnabled(false); Strips::ConstIterator strip = m_strips.constBegin(); const Strips::ConstIterator& strip_end = m_strips.constEnd(); for ( ; strip != strip_end; ++strip) strip.value()->setMark(iMark); } void qtractorMixerRack::cleanStrips ( int iMark ) { Strips::Iterator strip = m_strips.begin(); const Strips::Iterator& strip_end = m_strips.end(); while (strip != strip_end) { qtractorMixerStrip *pStrip = strip.value(); if (pStrip->mark() == iMark) { // Remove from the workspace layout... m_pWorkspaceLayout->removeWidget(pStrip); // Don't let current selection hanging... if (m_pSelectedStrip == pStrip) m_pSelectedStrip = NULL; // Hide strip... pStrip->hide(); // Remove from list... strip = m_strips.erase(strip); // and finally get rid of it. delete pStrip; } else ++strip; } m_pWorkspace->adjustSize(); m_pWorkspace->setUpdatesEnabled(true); } // Resize event handler. void qtractorMixerRack::resizeEvent ( QResizeEvent *pResizeEvent ) { QScrollArea::resizeEvent(pResizeEvent); // m_pWorkspace->setMinimumWidth(QScrollArea::viewport()->width()); m_pWorkspace->setFixedHeight(QScrollArea::viewport()->height()); m_pWorkspace->adjustSize(); } // Context menu request event handler. void qtractorMixerRack::contextMenuEvent ( QContextMenuEvent *pContextMenuEvent ) { // Maybe it's a track strip qtractorBus *pBus = NULL; if (m_pSelectedStrip) pBus = m_pSelectedStrip->bus(); if (pBus == NULL) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->trackMenu()->exec(pContextMenuEvent->globalPos()); // Bail out... return; } // Build the device context menu... QMenu menu(this); QAction *pAction; pAction = menu.addAction( tr("&Inputs"), this, SLOT(busInputsSlot())); pAction->setEnabled(pBus->busMode() & qtractorBus::Input); pAction = menu.addAction( tr("&Outputs"), this, SLOT(busOutputsSlot())); pAction->setEnabled(pBus->busMode() & qtractorBus::Output); menu.addSeparator(); pAction = menu.addAction( tr("&Monitor"), this, SLOT(busMonitorSlot())); pAction->setEnabled( (pBus->busMode() & qtractorBus::Duplex) == qtractorBus::Duplex); pAction->setCheckable(true); pAction->setChecked(pBus->isMonitor()); menu.addSeparator(); pAction = menu.addAction( tr("&Buses..."), this, SLOT(busPropertiesSlot())); menu.exec(pContextMenuEvent->globalPos()); } // Mouse click event handler. void qtractorMixerRack::mousePressEvent ( QMouseEvent *pMouseEvent ) { if (!m_pWorkspace->rect().contains(pMouseEvent->pos())) setSelectedStrip(NULL); QScrollArea::mousePressEvent(pMouseEvent); } // Show/edit bus input connections. void qtractorMixerRack::busInputsSlot (void) { qtractorMixerStrip *pStrip = m_pSelectedStrip; if (pStrip) pStrip->busConnections(qtractorBus::Input); } // Show/edit bus output connections. void qtractorMixerRack::busOutputsSlot (void) { qtractorMixerStrip *pStrip = m_pSelectedStrip; if (pStrip) pStrip->busConnections(qtractorBus::Output); } // Toggle bus passthru flag. void qtractorMixerRack::busMonitorSlot (void) { qtractorMixerStrip *pStrip = m_pSelectedStrip; if (pStrip && pStrip->bus()) pStrip->busMonitor(!(pStrip->bus())->isMonitor()); } // Show/edit bus properties form. void qtractorMixerRack::busPropertiesSlot (void) { qtractorMixerStrip *pStrip = m_pSelectedStrip; if (pStrip && pStrip->bus()) { qtractorBusForm busForm(this); busForm.setBus(pStrip->bus()); busForm.exec(); } } //---------------------------------------------------------------------------- // qtractorMixer -- Mixer widget. // Constructor. qtractorMixer::qtractorMixer ( QWidget *pParent, Qt::WindowFlags wflags ) : QWidget(pParent, wflags) { // Surely a name is crucial (e.g. for storing geometry settings) QWidget::setObjectName("qtractorMixer"); m_pSplitter = new QSplitter(Qt::Horizontal, this); m_pSplitter->setObjectName("MixerSplitter"); // m_pSplitter->setChildrenCollapsible(false); // m_pSplitter->setOpaqueResize(false); m_pSplitter->setHandleWidth(2); m_pInputRack = new qtractorMixerRack(this, tr("Inputs")); m_pTrackRack = new qtractorMixerRack(this, tr("Tracks")); m_pTrackRack->setSelectEnabled(true); m_pOutputRack = new qtractorMixerRack(this, tr("Outputs")); #if 0 m_pSplitter->setStretchFactor(m_pSplitter->indexOf(m_pInputRack), 0); m_pSplitter->setStretchFactor(m_pSplitter->indexOf(m_pTrackRack), 1); m_pSplitter->setStretchFactor(m_pSplitter->indexOf(m_pOutputRack), 0); #else QSizePolicy policy; policy = m_pTrackRack->sizePolicy(); policy.setHorizontalStretch(1); m_pTrackRack->setSizePolicy(policy); #endif // Prepare the layout stuff. QHBoxLayout *pLayout = new QHBoxLayout(); pLayout->setMargin(0); pLayout->setSpacing(0); pLayout->addWidget(m_pSplitter); QWidget::setLayout(pLayout); // Some specialties to this kind of dock window... QWidget::setMinimumWidth(440); QWidget::setMinimumHeight(240); // Finally set the default caption and tooltip. const QString& sCaption = tr("Mixer") + " - " QTRACTOR_TITLE; QWidget::setWindowTitle(sCaption); QWidget::setWindowIcon(QIcon(":/images/viewMixer.png")); QWidget::setToolTip(sCaption); // Get previously saved splitter sizes... loadSplitterSizes(); } // Default destructor. qtractorMixer::~qtractorMixer (void) { // Save splitter sizes... if (m_pSplitter->isVisible()) saveSplitterSizes(); // No need to delete child widgets, Qt does it all for us } // Notify the main application widget that we're emerging. void qtractorMixer::showEvent ( QShowEvent *pShowEvent ) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeForm(); QWidget::showEvent(pShowEvent); } // Notify the main application widget that we're closing. void qtractorMixer::hideEvent ( QHideEvent *pHideEvent ) { QWidget::hideEvent(pHideEvent); qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeForm(); } // Just about to notify main-window that we're closing. void qtractorMixer::closeEvent ( QCloseEvent * /*pCloseEvent*/ ) { // Save splitter sizes... saveSplitterSizes(); QWidget::hide(); qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeForm(); } // The splitter layout widget accessor. QSplitter *qtractorMixer::splitter (void) const { return m_pSplitter; } // Get previously saved splitter sizes... // (with some fair default...) void qtractorMixer::loadSplitterSizes (void) { qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { QList sizes; sizes.append(140); sizes.append(160); sizes.append(140); pOptions->loadSplitterSizes(m_pSplitter, sizes); } } // Save splitter sizes... void qtractorMixer::saveSplitterSizes (void) { qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) pOptions->saveSplitterSizes(m_pSplitter); } // Initial minimum widget extents. QSize qtractorMixer::sizeHint (void) const { return QSize(480, 320); } // The mixer strips rack accessors. qtractorMixerRack *qtractorMixer::inputRack (void) const { return m_pInputRack; } qtractorMixerRack *qtractorMixer::trackRack (void) const { return m_pTrackRack; } qtractorMixerRack *qtractorMixer::outputRack (void) const { return m_pOutputRack; } // Update mixer rack, checking if given monitor already exists. void qtractorMixer::updateBusStrip ( qtractorMixerRack *pRack, qtractorBus *pBus, qtractorBus::BusMode busMode, bool bReset ) { qtractorMonitor *pMonitor = (busMode == qtractorBus::Input ? pBus->monitor_in() : pBus->monitor_out()); qtractorMixerStrip *pStrip = pRack->findStrip(pMonitor); if (pStrip == NULL) { pRack->addStrip(new qtractorMixerStrip(pRack, pBus, busMode)); } else { pStrip->setMark(0); if (bReset) pStrip->setBus(pBus); } pBus->mapControllers(busMode); #if 0 qtractorAudioBus *pAudioBus; qtractorMidiBus *pMidiBus; switch (pBus->busType()) { case qtractorTrack::Audio: pAudioBus = static_cast (pBus); if (pAudioBus) { pAudioBus->applyCurveFile(busMode, (busMode == qtractorBus::Input ? pAudioBus->curveFile_in() : pAudioBus->curveFile_out())); } break; case qtractorTrack::Midi: pMidiBus = static_cast (pBus); if (pMidiBus) { pMidiBus->applyCurveFile(busMode, (busMode == qtractorBus::Input ? pMidiBus->curveFile_in() : pMidiBus->curveFile_out())); } break; default: break; } #endif } void qtractorMixer::updateTrackStrip ( qtractorTrack *pTrack, bool bReset ) { qtractorMixerStrip *pStrip = m_pTrackRack->findStrip(pTrack->monitor()); if (pStrip == NULL) { m_pTrackRack->addStrip(new qtractorMixerStrip(m_pTrackRack, pTrack)); } else { pStrip->setMark(0); if (bReset) pStrip->setTrack(pTrack); } pTrack->mapControllers(); pTrack->applyCurveFile(pTrack->curveFile()); qtractorCurveList *pCurveList = pTrack->curveList(); qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pCurveList && pMainForm && pMainForm->tracks()) { pMainForm->tracks()->updateTrackList(); QObject::connect( pCurveList->proxy(), SIGNAL(update()), pMainForm->tracks(), SLOT(updateTrackView())); } } // Update buses'racks. void qtractorMixer::updateBuses ( bool bReset ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; if (bReset) { m_pInputRack->clear(); m_pOutputRack->clear(); } m_pInputRack->markStrips(1); m_pOutputRack->markStrips(1); // Audio buses first... for (qtractorBus *pBus = pSession->audioEngine()->buses().first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Input) updateBusStrip(m_pInputRack, pBus, qtractorBus::Input); if (pBus->busMode() & qtractorBus::Output) updateBusStrip(m_pOutputRack, pBus, qtractorBus::Output); } // MIDI buses are next... for (qtractorBus *pBus = pSession->midiEngine()->buses().first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Input) updateBusStrip(m_pInputRack, pBus, qtractorBus::Input); if (pBus->busMode() & qtractorBus::Output) updateBusStrip(m_pOutputRack, pBus, qtractorBus::Output); } m_pOutputRack->cleanStrips(1); m_pInputRack->cleanStrips(1); // Autonomic resizing of bus splitter sizes... int ws, iUpdate = 0; QList sizes = m_pSplitter->sizes(); int& w0 = sizes[0]; int& w1 = sizes[1]; int& w2 = sizes[2]; ws = m_pInputRack->workspace()->width() + 4; if (w0 > ws) { w1 += (w0 - ws); w0 = ws; ++iUpdate; } ws = m_pOutputRack->workspace()->width() + 4; if (w2 > ws) { w1 += (w2 - ws); w2 = ws; ++iUpdate; } if (iUpdate > 0) m_pSplitter->setSizes(sizes); } // Update tracks'rack. void qtractorMixer::updateTracks ( bool bReset ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; if (bReset) m_pTrackRack->clear(); m_pTrackRack->markStrips(1); for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { updateTrackStrip(pTrack); } m_pTrackRack->cleanStrips(1); } // Complete mixer refreshment. void qtractorMixer::refresh (void) { m_pInputRack->refresh(); m_pTrackRack->refresh(); m_pOutputRack->refresh(); } // Complete mixer recycle. void qtractorMixer::clear (void) { m_pInputRack->clear(); m_pTrackRack->clear(); m_pOutputRack->clear(); } // Keyboard event handler. void qtractorMixer::keyPressEvent ( QKeyEvent *pKeyEvent ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMixer::keyPressEvent(%d)", pKeyEvent->key()); #endif int iKey = pKeyEvent->key(); switch (iKey) { case Qt::Key_Escape: close(); break; default: QWidget::keyPressEvent(pKeyEvent); break; } } // end of qtractorMixer.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiControlObserverForm.ui0000644000175000001440000000012311707254676024160 xustar000000000000000027 mtime=1327323582.059191 26 atime=1381134666.76108 30 ctime=1381134666.761080045 qtractor-0.5.11/src/qtractorMidiControlObserverForm.ui0000644000175000001440000001355711707254676023462 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorMidiControlObserverForm 0 0 353 179 MIDI Controller - Qtractor :/images/itemControllers.png &Type: ControlTypeComboBox MIDI event type Cha&nnel: ChannelSpinBox MIDI channel false 1 16 Qt::Vertical QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset &Parameter: ParamComboBox MIDI parameter &Logarithmic &Feedback In&vert &Hook Control input connections &Inputs :/images/itemMidiPortIn.png Control output connections &Outputs :/images/itemMidiPortOut.png Qt::Horizontal 8 8 ControlTypeComboBox ChannelSpinBox ParamComboBox LogarithmicCheckBox FeedbackCheckBox InvertCheckBox InputsPushButton OutputsPushButton DialogButtonBox qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioFile.h0000644000175000001440000000012312073012112021022 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134667.40808 30 ctime=1381134667.408080055 qtractor-0.5.11/src/qtractorAudioFile.h0000644000175000001440000001054312073012112020314 0ustar00rncbcusers00000000000000// qtractorAudioFile.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorAudioFile_h #define __qtractorAudioFile_h #include #include //---------------------------------------------------------------------- // class qtractorAudioFile -- Abstract audio file mockup. // class qtractorAudioFile { public: // Virtual destructor. virtual ~qtractorAudioFile() {} // Basic file open mode. enum { None = 0, Read = 1, Write = 2 }; // Pure virtual method mockups. virtual bool open (const QString& sFilename, int iMode = Read) = 0; virtual int read (float **ppFrames, unsigned int iFrames) = 0; virtual int write (float **ppFrames, unsigned int iFrames) = 0; virtual bool seek (unsigned long iOffset) = 0; virtual void close () = 0; // Pure virtual accessor mockups. virtual int mode() const = 0; // These shall give us a clue on the size // of the ring buffer size (in frames). virtual unsigned short channels() const = 0; virtual unsigned long frames() const = 0; // Other special informational methods. virtual unsigned int sampleRate() const = 0; }; //---------------------------------------------------------------------- // class qtractorAudioFileFactory -- Audio file factory (singleton). // class qtractorAudioFileFactory { public: // Supported file types. enum FileType { SndFile, VorbisFile, MadFile }; // Factory methods. static qtractorAudioFile *createAudioFile ( const QString& sFilename, unsigned short iChannels = 0, unsigned int iSampleRate = 0, unsigned int iBufferSize = 0); static qtractorAudioFile *createAudioFile ( FileType type, unsigned short iChannels = 0, unsigned int iSampleRate = 0, unsigned int iBufferSize = 0); // Audio file format descriptor. struct FileFormat { FileType type; QString name; QString ext; int data; }; typedef QList FileFormats; // File type/format global accessors. static const FileFormats& formats(); // Retrieve supported filters (suitable for QFileDialog usage). static QString filters(); // Default audio file format accessors // (specific to capture/recording) static void setDefaultType(const QString& sExt, int iType, int iFormat = 0, int iQuality = 4); static QString defaultExt(); static int defaultFormat(); static int defaultQuality(); // Check whether given file type/format is valid. static bool isValidFormat(const FileFormat *pFormat, int iFormat); // Singleton destroyer. static void Destroy(); protected: // Constructor. qtractorAudioFileFactory(); // Singleton instance accessor. static qtractorAudioFileFactory& getInstance(); // Instance factory methods. qtractorAudioFile *newAudioFile ( const QString& sFilename, unsigned short iChannels, unsigned int iSampleRate, unsigned int iBufferSize); qtractorAudioFile *newAudioFile ( FileType type, unsigned short iChannels, unsigned int iSampleRate, unsigned int iBufferSize); // Translate format index into libsndfile specific... static int format(const FileFormat *pFormat, int iFormat); private: // The singleton instance. static qtractorAudioFileFactory* g_pInstance; // The supported file types/extension map. typedef QHash FileTypes; FileFormats m_formats; FileTypes m_types; // Supported filter strings. QStringList m_filters; // Default file format/type (for capture/record) FileFormat *m_pDefaultFormat; int m_iDefaultFormat; int m_iDefaultQuality; }; #endif // __qtractorAudioFile_h // end of qtractorAudioFile.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorClipForm.cpp0000644000175000001440000000012312166526620021250 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134667.92608 30 ctime=1381134667.926080064 qtractor-0.5.11/src/qtractorClipForm.cpp0000644000175000001440000005470512166526620020552 0ustar00rncbcusers00000000000000// qtractorClipForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorClipForm.h" #include "qtractorAbout.h" #include "qtractorClip.h" #include "qtractorClipCommand.h" #include "qtractorAudioClip.h" #include "qtractorMidiClip.h" #include "qtractorSession.h" #include "qtractorOptions.h" #include "qtractorMainForm.h" #include #include #include #include #include // Needed for fabs(), logf() and powf() #include static inline float log10f2 ( float x ) { return (x > 0.0f ? 20.0f * ::log10f(x) : -60.0f); } static inline float pow10f2 ( float x ) { return ::powf(10.0f, 0.05f * x); } // Translatable macro contextualizer. #undef _TR #define _TR(x) QT_TR_NOOP(x) //---------------------------------------------------------------------------- // Fade types curves. const char *g_aFadeTypeNames[] = { _TR("Linear"), // Linear (obvious:) _TR("Quadratic 1"), // InQuad _TR("Quadratic 2"), // OutQuad _TR("Quadratic 3"), // InOutQuad _TR("Cubic 1"), // InCubic _TR("Cubic 2"), // OutCubic _TR("Cubic 3"), // InOutCubic NULL }; struct FadeTypeInfo { QString name; QIcon iconFadeIn; QIcon iconFadeOut; }; static QHash g_fadeTypes; static void initFadeTypes (void) { if (g_fadeTypes.isEmpty()) { const QPixmap pmFadeIn(":/images/fadeIn.png"); const QPixmap pmFadeOut(":/images/fadeOut.png"); for (int i = 0; g_aFadeTypeNames[i]; ++i) { FadeTypeInfo& info = g_fadeTypes[i]; info.name = QObject::tr(g_aFadeTypeNames[i], "fadeType"); info.iconFadeIn = pmFadeIn.copy(i << 4, 0, 16, 16); info.iconFadeOut = pmFadeOut.copy(i << 4, 0, 16, 16); } } } //---------------------------------------------------------------------------- // qtractorClipForm -- UI wrapper form. // Constructor. qtractorClipForm::qtractorClipForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::WindowModal); // Initialize dirty control state. m_pClip = NULL; m_bClipNew = false; m_pTimeScale = NULL; m_iDirtyCount = 0; m_iDirtySetup = 0; initFadeTypes(); m_ui.FadeInTypeComboBox->clear(); m_ui.FadeOutTypeComboBox->clear(); for (int i = 0; i < g_fadeTypes.count(); ++i) { const FadeTypeInfo& info = g_fadeTypes.value(i); m_ui.FadeInTypeComboBox->addItem(info.iconFadeIn, info.name); m_ui.FadeOutTypeComboBox->addItem(info.iconFadeOut, info.name); } // Try to set minimal window positioning. m_ui.TrackChannelTextLabel->hide(); m_ui.TrackChannelSpinBox->hide(); m_ui.AudioClipGroupBox->hide(); adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.ClipNameLineEdit, SIGNAL(textChanged(const QString&)), SLOT(changed())); QObject::connect(m_ui.FilenameComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(filenameChanged(const QString&))); QObject::connect(m_ui.FilenameToolButton, SIGNAL(clicked()), SLOT(browseFilename())); QObject::connect(m_ui.ClipGainSpinBox, SIGNAL(valueChanged(double)), SLOT(changed())); QObject::connect(m_ui.TrackChannelSpinBox, SIGNAL(valueChanged(int)), SLOT(trackChannelChanged(int))); QObject::connect(m_ui.FormatComboBox, SIGNAL(activated(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.ClipStartSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(clipStartChanged(unsigned long))); QObject::connect(m_ui.ClipStartSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.ClipOffsetSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(changed())); QObject::connect(m_ui.ClipOffsetSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.ClipLengthSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(changed())); QObject::connect(m_ui.ClipOffsetSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.FadeInLengthSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(changed())); QObject::connect(m_ui.FadeInLengthSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.FadeInTypeComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.FadeOutLengthSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(changed())); QObject::connect(m_ui.FadeOutLengthSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.FadeOutTypeComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.TimeStretchSpinBox, SIGNAL(valueChanged(double)), SLOT(changed())); QObject::connect(m_ui.PitchShiftSpinBox, SIGNAL(valueChanged(double)), SLOT(changed())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); } // Destructor. qtractorClipForm::~qtractorClipForm (void) { // Don't forget to get rid of local time-scale instance... if (m_pTimeScale) delete m_pTimeScale; } // Populate (setup) dialog controls from settings descriptors. void qtractorClipForm::setClip ( qtractorClip *pClip, bool bClipNew ) { // Initialize conveniency options... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Mark that we're changing thing's here... ++m_iDirtySetup; // Clip properties cloning... m_pClip = pClip; m_bClipNew = bClipNew; // Why not change the dialog icon accordingly? if (m_bClipNew) QDialog::setWindowIcon(QIcon(":/images/editClipNew.png")); // Copy from global time-scale instance... if (m_pTimeScale) delete m_pTimeScale; m_pTimeScale = new qtractorTimeScale(*pSession->timeScale()); m_ui.ClipStartSpinBox->setTimeScale(m_pTimeScale); m_ui.ClipOffsetSpinBox->setTimeScale(m_pTimeScale); m_ui.ClipLengthSpinBox->setTimeScale(m_pTimeScale); m_ui.FadeInLengthSpinBox->setTimeScale(m_pTimeScale); m_ui.FadeOutLengthSpinBox->setTimeScale(m_pTimeScale); // These have special delta formats... clipStartChanged(m_pClip->clipStart()); // Initialize dialog widgets... m_ui.ClipNameLineEdit->setText(m_pClip->clipName()); // Parameters... m_ui.ClipStartSpinBox->setValue(m_pClip->clipStart()); m_ui.ClipOffsetSpinBox->setValue(m_pClip->clipOffset()); m_ui.ClipLengthSpinBox->setValue(m_pClip->clipLength()); // Fade In/Out... m_ui.FadeInLengthSpinBox->setValue(m_pClip->fadeInLength()); m_ui.FadeInTypeComboBox->setCurrentIndex( indexFromFadeType(m_pClip->fadeInType())); m_ui.FadeOutLengthSpinBox->setValue(m_pClip->fadeOutLength()); m_ui.FadeOutTypeComboBox->setCurrentIndex( indexFromFadeType(m_pClip->fadeOutType())); // Set proper time scales display format... m_ui.FormatComboBox->setCurrentIndex( int(m_pTimeScale->displayFormat())); // Now those things specific on track type... const QString sSuffix = m_ui.FilenameComboBox->objectName(); switch (trackType()) { case qtractorTrack::Audio: { m_ui.FilenameComboBox->setObjectName("Audio" + sSuffix); m_ui.GainVolumeGroupBox->setTitle(tr("&Gain:")); m_ui.ClipGainSpinBox->setSuffix(tr(" dB")); m_ui.ClipGainSpinBox->setRange(-60.0f, +24.0f); m_ui.ClipGainSpinBox->setValue(log10f2(m_pClip->clipGain())); qtractorAudioClip *pAudioClip = static_cast (m_pClip); if (pAudioClip) { m_ui.TimeStretchSpinBox->setValue( 100.0f * pAudioClip->timeStretch()); m_ui.PitchShiftSpinBox->setValue( 12.0f * ::logf(pAudioClip->pitchShift()) / M_LN2); } m_ui.TrackChannelTextLabel->setVisible(false); m_ui.TrackChannelSpinBox->setVisible(false); m_ui.AudioClipGroupBox->setVisible(true); #ifndef CONFIG_LIBRUBBERBAND m_ui.PitchShiftTextLabel->setEnabled(false); m_ui.PitchShiftSpinBox->setEnabled(false); #endif break; } case qtractorTrack::Midi: { m_ui.FilenameComboBox->setObjectName("Midi" + sSuffix); m_ui.GainVolumeGroupBox->setTitle(tr("&Volume:")); m_ui.ClipGainSpinBox->setSuffix(tr(" %")); m_ui.ClipGainSpinBox->setRange(0.0f, 1200.0f); m_ui.ClipGainSpinBox->setValue(100.0f * m_pClip->clipGain()); qtractorMidiClip *pMidiClip = static_cast (m_pClip); if (pMidiClip) m_ui.TrackChannelSpinBox->setValue(pMidiClip->trackChannel()); m_ui.TrackChannelTextLabel->setVisible(true); m_ui.TrackChannelSpinBox->setVisible(true); m_ui.AudioClipGroupBox->setVisible(false); break; } case qtractorTrack::None: default: m_ui.TrackChannelTextLabel->setVisible(false); m_ui.TrackChannelSpinBox->setVisible(false); m_ui.AudioClipGroupBox->setVisible(false); break; } qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) pOptions->loadComboBoxHistory(m_ui.FilenameComboBox); // Finally set clip filename... m_ui.FilenameComboBox->setEditText(m_pClip->filename()); // Shake it a little bit first, but // make it as tight as possible... // resize(width() - 1, height() - 1); adjustSize(); // Backup clean. --m_iDirtySetup; m_iDirtyCount = 0; // Done. stabilizeForm(); } // Retrieve the accepted clip, if the case arises. qtractorClip *qtractorClipForm::clip (void) const { return m_pClip; } // Accept settings (OK button slot). void qtractorClipForm::accept (void) { // Sanity check... if (m_pClip == NULL) return; if (!m_pClip->queryEditor()) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Save settings... if (m_iDirtyCount > 0) { // Cache the changed settings (if any)... qtractorClipCommand *pClipCommand = NULL; qtractorTrack::TrackType clipType = trackType(); const QString& sFilename = m_ui.FilenameComboBox->currentText(); unsigned short iTrackChannel = m_ui.TrackChannelSpinBox->value(); const QString& sClipName = m_ui.ClipNameLineEdit->text(); float fClipGain = 1.0f; float fTimeStretch = 0.0f; float fPitchShift = 0.0f; switch (clipType) { case qtractorTrack::Audio: fClipGain = pow10f2(m_ui.ClipGainSpinBox->value()); fTimeStretch = 0.01f * m_ui.TimeStretchSpinBox->value(); fPitchShift = ::powf(2.0f, m_ui.PitchShiftSpinBox->value() / 12.0f); break; case qtractorTrack::Midi: fClipGain = 0.01f * m_ui.ClipGainSpinBox->value(); break; default: break; } unsigned long iClipStart = m_ui.ClipStartSpinBox->value(); unsigned long iClipOffset = m_ui.ClipOffsetSpinBox->value(); unsigned long iClipLength = m_ui.ClipLengthSpinBox->value(); unsigned long iFadeInLength = m_ui.FadeInLengthSpinBox->value(); qtractorClip::FadeType fadeInType = fadeTypeFromIndex(m_ui.FadeInTypeComboBox->currentIndex()); unsigned long iFadeOutLength = m_ui.FadeOutLengthSpinBox->value(); qtractorClip::FadeType fadeOutType = fadeTypeFromIndex(m_ui.FadeOutTypeComboBox->currentIndex()); int iFileChange = 0; // It depends whether we're adding a new clip or not... if (m_bClipNew) { // Just set new clip properties... pClipCommand = new qtractorClipCommand(tr("new clip")); m_pClip->setClipName(sClipName); // Filename... m_pClip->setFilename(sFilename); // Track-channel and time-stretching... switch (clipType) { case qtractorTrack::Audio: { qtractorAudioClip *pAudioClip = static_cast (m_pClip); if (pAudioClip) { pAudioClip->setTimeStretch(fTimeStretch); pAudioClip->setPitchShift(fPitchShift); ++iFileChange; } break; } case qtractorTrack::Midi: { qtractorMidiClip *pMidiClip = static_cast (m_pClip); if (pMidiClip) { pMidiClip->setTrackChannel(iTrackChannel); ++iFileChange; } break; } case qtractorTrack::None: default: break; } // Gain/volume... m_pClip->setClipGain(fClipGain); // Parameters... m_pClip->setClipStart(iClipStart); m_pClip->setClipOffset(iClipOffset); m_pClip->setClipLength(iClipLength); // Fade in... m_pClip->setFadeInLength(iFadeInLength); m_pClip->setFadeInType(fadeInType); // Fade out... m_pClip->setFadeOutLength(iFadeOutLength); m_pClip->setFadeOutType(fadeOutType); // Ready it... pClipCommand->addClip(m_pClip, m_pClip->track()); // Ready new. } else { // Make changes (incrementally) undoable... pClipCommand = new qtractorClipCommand(tr("edit clip")); pClipCommand->renameClip(m_pClip, sClipName); // Filename changes... if (sFilename != m_pClip->filename()) ++iFileChange; // Track-channel and time-stretch issues... switch (clipType) { case qtractorTrack::Audio: { qtractorAudioClip *pAudioClip = static_cast (m_pClip); if (pAudioClip) { if (::fabs(fTimeStretch - pAudioClip->timeStretch()) < 0.001f) fTimeStretch = 0.0f; if (::fabs(fPitchShift - pAudioClip->pitchShift()) < 0.001f) fPitchShift = 0.0f; } break; } case qtractorTrack::Midi: { qtractorMidiClip *pMidiClip = static_cast (m_pClip); if (pMidiClip) { if (iTrackChannel != pMidiClip->trackChannel()) ++iFileChange; } break; } case qtractorTrack::None: default: break; } // Filename and/or track-channel changes... if (iFileChange > 0) pClipCommand->fileClip(m_pClip, sFilename, iTrackChannel); // Gain/volume... if (::fabs(fClipGain - m_pClip->clipGain()) > 0.001f) pClipCommand->gainClip(m_pClip, fClipGain); // Parameters and/or time-stretching changes... if (iClipStart != m_pClip->clipStart() || iClipOffset != m_pClip->clipOffset() || iClipLength != m_pClip->clipLength() || fTimeStretch > 0.0f || fPitchShift > 0.0f) { pClipCommand->resizeClip(m_pClip, iClipStart, iClipOffset, iClipLength, fTimeStretch, fPitchShift); } // Fade in changes... if (iFadeInLength != m_pClip->fadeInLength() || fadeInType != m_pClip->fadeInType()) pClipCommand->fadeInClip(m_pClip, iFadeInLength, fadeInType); // Fade out changes... if (iFadeOutLength != m_pClip->fadeOutLength() || fadeOutType != m_pClip->fadeOutType()) pClipCommand->fadeOutClip(m_pClip, iFadeOutLength, fadeOutType); // Ready edit. } // Do it (by making it undoable)... if (pClipCommand) pSession->execute(pClipCommand); // Account for a new file in game... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (iFileChange > 0 && pMainForm) { switch (clipType) { case qtractorTrack::Audio: pMainForm->addAudioFile(sFilename); break; case qtractorTrack::Midi: pMainForm->addMidiFile(sFilename); break; case qtractorTrack::None: default: break; } // Save history conveniency options... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) pOptions->saveComboBoxHistory(m_ui.FilenameComboBox); } // Reset dirty flag. m_iDirtyCount = 0; } // Just go with dialog acceptance. QDialog::accept(); } // Reject settings (Cancel button slot). void qtractorClipForm::reject (void) { bool bReject = true; // Check if there's any pending changes... if (m_iDirtyCount > 0) { QMessageBox::StandardButtons buttons = QMessageBox::Discard | QMessageBox::Cancel; if (m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->isEnabled()) buttons |= QMessageBox::Apply; switch (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Some settings have been changed.\n\n" "Do you want to apply the changes?"), buttons)) { case QMessageBox::Apply: accept(); return; case QMessageBox::Discard: break; default: // Cancel. bReject = false; } } if (bReject) QDialog::reject(); } // Dirty up settings. void qtractorClipForm::changed (void) { ++m_iDirtyCount; stabilizeForm(); } // Display format has changed. void qtractorClipForm::formatChanged ( int iDisplayFormat ) { bool bBlockSignals = m_ui.FormatComboBox->blockSignals(true); m_ui.FormatComboBox->setCurrentIndex(iDisplayFormat); qtractorTimeScale::DisplayFormat displayFormat = qtractorTimeScale::DisplayFormat(iDisplayFormat); m_ui.ClipStartSpinBox->setDisplayFormat(displayFormat); m_ui.ClipOffsetSpinBox->setDisplayFormat(displayFormat); m_ui.ClipLengthSpinBox->setDisplayFormat(displayFormat); m_ui.FadeInLengthSpinBox->setDisplayFormat(displayFormat); m_ui.FadeOutLengthSpinBox->setDisplayFormat(displayFormat); if (m_pTimeScale) m_pTimeScale->setDisplayFormat(displayFormat); m_ui.FormatComboBox->blockSignals(bBlockSignals); stabilizeForm(); } // Stabilize current form state. void qtractorClipForm::stabilizeForm (void) { const QString& sFilename = m_ui.FilenameComboBox->currentText(); unsigned long iClipLength = m_ui.ClipLengthSpinBox->value(); m_ui.FadeInTypeComboBox->setEnabled( m_ui.FadeInLengthSpinBox->value() > 0); m_ui.FadeInLengthSpinBox->setMaximum(iClipLength); m_ui.FadeOutTypeComboBox->setEnabled( m_ui.FadeOutLengthSpinBox->value() > 0); m_ui.FadeOutLengthSpinBox->setMaximum(iClipLength); bool bValid = (m_iDirtyCount > 0); bValid = bValid && !m_ui.ClipNameLineEdit->text().isEmpty(); bValid = bValid && !sFilename.isEmpty() && QFileInfo(sFilename).exists(); bValid = bValid && (iClipLength > 0); m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(bValid); } // Fade type index converters. qtractorClip::FadeType qtractorClipForm::fadeTypeFromIndex ( int iIndex ) const { return qtractorClip::FadeType(iIndex); } int qtractorClipForm::indexFromFadeType ( qtractorClip::FadeType fadeType ) const { return int(fadeType); } // Retrieve current clip/track type. qtractorTrack::TrackType qtractorClipForm::trackType (void) const { qtractorTrack *pTrack = NULL; if (m_pClip) pTrack = m_pClip->track(); return (pTrack ? pTrack->trackType() : qtractorTrack::None); } // Browse for audio clip filename. void qtractorClipForm::browseFilename (void) { QString sType; QString sExt; QString sFilter; qtractorTrack::TrackType clipType = trackType(); switch (clipType) { case qtractorTrack::Audio: sType = tr("Audio"); sExt = qtractorAudioFileFactory::defaultExt(); sFilter = qtractorAudioFileFactory::filters(); break; case qtractorTrack::Midi: sType = tr("MIDI"); sExt = "mid"; sFilter = tr("MIDI files (*.%1 *.smf *.midi)").arg(sExt); break; case qtractorTrack::None: default: return; } // Browse for file... QString sFilename; const QString& sTitle = tr("%1 Clip File").arg(sType) + " - " QTRACTOR_TITLE; #if 0//QT_VERSION < 0x040400 sFilename = QFileDialog::getOpenFileName(this, sTitle, m_ui.FilenameComboBox->currentText(), sFilter); #else QFileDialog fileDialog(this, sTitle, m_ui.FilenameComboBox->currentText(), sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::ExistingFile); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); switch (clipType) { case qtractorTrack::Audio: urls.append(QUrl::fromLocalFile(pOptions->sAudioDir)); break; case qtractorTrack::Midi: urls.append(QUrl::fromLocalFile(pOptions->sMidiDir)); break; case qtractorTrack::None: default: break; } fileDialog.setSidebarUrls(urls); } // Show dialog... if (fileDialog.exec()) sFilename = fileDialog.selectedFiles().first(); #endif if (!sFilename.isEmpty()) { m_ui.FilenameComboBox->setEditText(sFilename); m_ui.FilenameComboBox->setFocus(); // changed(); } } // Adjust clip length to (new) selected file. void qtractorClipForm::fileChanged ( const QString& sFilename, unsigned short iTrackChannel ) { if (m_iDirtySetup > 0) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Do nothing else if file is invalid... QFileInfo fi(sFilename); if (!fi.exists()) { changed(); return; } // Give as clip name hint if blank or new... if (m_ui.ClipNameLineEdit->text().isEmpty() || m_bClipNew) m_ui.ClipNameLineEdit->setText(fi.baseName()); // Depending on the clip/track type, // set clip length to the file length (in frames)... unsigned long iClipLength = 0; switch (trackType()) { case qtractorTrack::Midi: { qtractorMidiFile file; if (file.open(sFilename)) { qtractorMidiSequence seq; seq.setTicksPerBeat(pSession->ticksPerBeat()); if (file.readTrack(&seq, iTrackChannel) && seq.duration() > 0) iClipLength = pSession->frameFromTick(seq.duration()); file.close(); } break; } case qtractorTrack::Audio: { qtractorAudioFile *pFile = qtractorAudioFileFactory::createAudioFile(sFilename); if (pFile) { if (pFile->open(sFilename)) { iClipLength = pFile->frames(); if (pFile->sampleRate() > 0 && pFile->sampleRate() != pSession->sampleRate()) { iClipLength = (unsigned long) (iClipLength * float(pSession->sampleRate()) / float(pFile->sampleRate())); } pFile->close(); } delete pFile; } break; } case qtractorTrack::None: default: break; } // Done. m_ui.ClipOffsetSpinBox->setValue(0); m_ui.ClipLengthSpinBox->setValue(iClipLength); changed(); } void qtractorClipForm::filenameChanged ( const QString& sFilename ) { fileChanged(sFilename, m_ui.TrackChannelSpinBox->value()); } void qtractorClipForm::trackChannelChanged ( int iTrackChannel ) { fileChanged(m_ui.FilenameComboBox->currentText(), iTrackChannel); } // Adjust delta-value spin-boxes to new anchor frame. void qtractorClipForm::clipStartChanged ( unsigned long iClipStart ) { m_ui.ClipOffsetSpinBox->setDeltaValue(true, iClipStart); m_ui.ClipLengthSpinBox->setDeltaValue(true, iClipStart); m_ui.FadeInLengthSpinBox->setDeltaValue(true, iClipStart); m_ui.FadeOutLengthSpinBox->setDeltaValue(true, iClipStart); if (m_iDirtySetup == 0) changed(); } // end of qtractorClipForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTrackButton.h0000644000175000001440000000012212207673031021434 xustar000000000000000026 mtime=1377793561.87198 26 atime=1381134668.91708 30 ctime=1381134668.917080079 qtractor-0.5.11/src/qtractorTrackButton.h0000644000175000001440000000531012207673031020723 0ustar00rncbcusers00000000000000// qtractorTrackButton.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorTrackButton_h #define __qtractorTrackButton_h #include "qtractorTrack.h" #include #include "qtractorObserverWidget.h" //---------------------------------------------------------------------------- // qtractorMidiControlButton -- MIDI controller observer tool button. class qtractorMidiControlButton : public qtractorObserverWidget { Q_OBJECT public: // Constructor. qtractorMidiControlButton(QWidget *pParent = 0); protected slots: // MIDI controller/observer attachment (context menu) slot. void midiControlActionSlot(); void midiControlMenuSlot(const QPoint& pos); protected: // MIDI controller/observer attachment (context menu) activator. void addMidiControlAction(qtractorMidiControlObserver *pMidiObserver); private: // MIDI controller/observer leftover. QAction *m_pMidiControlAction; }; //---------------------------------------------------------------------------- // qtractorTrackButton -- Track observer tool button. class qtractorTrackButton : public qtractorMidiControlButton { Q_OBJECT public: // Constructor. qtractorTrackButton(qtractorTrack *pTrack, qtractorTrack::ToolType toolType, QWidget *pParent = 0); // Specific accessors. void setTrack(qtractorTrack *pTrack); qtractorTrack *track() const; qtractorTrack::ToolType toolType() const; protected slots: // Special toggle slot. void toggledSlot(bool bOn); protected: // Visitor setup. void updateTrack(); // Visitors overload. void updateValue(float fValue); private: // Instance variables. qtractorTrack *m_pTrack; qtractorTrack::ToolType m_toolType; // Special background colors. QColor m_rgbText; QColor m_rgbOn; QColor m_rgbOff; }; #endif // __qtractorTrackButton_h // end of qtractorTrackButton.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiControlForm.cpp0000644000175000001440000000012312166526620022604 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134670.27608 30 ctime=1381134670.276080101 qtractor-0.5.11/src/qtractorMidiControlForm.cpp0000644000175000001440000006071212166526620022101 0ustar00rncbcusers00000000000000// qtractorMidiControlForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiControlForm.h" #include "qtractorOptions.h" // Needed for controller names. #include "qtractorMidiEditor.h" #include #include #include #include //---------------------------------------------------------------------- // class qtractorMidiControlForm -- MIDI controller file manager form. // // Constructor. qtractorMidiControlForm::qtractorMidiControlForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::WindowModal); m_iDirtyCount = 0; m_iDirtyMap = 0; m_iUpdating = 0; QHeaderView *pHeader = m_ui.FilesListView->header(); pHeader->setDefaultAlignment(Qt::AlignLeft); #if QT_VERSION >= 0x050000 // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionResizeMode(QHeaderView::ResizeToContents); pHeader->setSectionsMovable(false); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setResizeMode(QHeaderView::ResizeToContents); pHeader->setMovable(false); #endif pHeader = m_ui.ControlMapListView->header(); pHeader->setDefaultAlignment(Qt::AlignLeft); #if QT_VERSION >= 0x050000 // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionResizeMode(QHeaderView::ResizeToContents); pHeader->setSectionsMovable(false); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setResizeMode(QHeaderView::ResizeToContents); pHeader->setMovable(false); #endif const QIcon iconControlType(":/images/itemProperty.png"); // m_ui.ControlTypeComboBox->clear(); m_ui.ControlTypeComboBox->addItem(iconControlType, qtractorMidiControl::nameFromType(qtractorMidiEvent::NOTEON)); m_ui.ControlTypeComboBox->addItem(iconControlType, qtractorMidiControl::nameFromType(qtractorMidiEvent::NOTEOFF)); m_ui.ControlTypeComboBox->addItem(iconControlType, qtractorMidiControl::nameFromType(qtractorMidiEvent::KEYPRESS)); m_ui.ControlTypeComboBox->addItem(iconControlType, qtractorMidiControl::nameFromType(qtractorMidiEvent::CONTROLLER)); m_ui.ControlTypeComboBox->addItem(iconControlType, qtractorMidiControl::nameFromType(qtractorMidiEvent::PGMCHANGE)); m_ui.ControlTypeComboBox->addItem(iconControlType, qtractorMidiControl::nameFromType(qtractorMidiEvent::CHANPRESS)); m_ui.ControlTypeComboBox->addItem(iconControlType, qtractorMidiControl::nameFromType(qtractorMidiEvent::PITCHBEND)); m_ui.ControlTypeComboBox->setCurrentIndex(3); // Controller. // m_ui.ChannelComboBox->clear(); m_ui.ChannelComboBox->addItem("*"); for (unsigned short iChannel = 0; iChannel < 16; ++iChannel) m_ui.ChannelComboBox->addItem(textFromChannel(iChannel)); const QIcon iconCommand(":/images/itemChannel.png"); // m_ui.CommandComboBox->clear(); m_ui.CommandComboBox->addItem(iconCommand, qtractorMidiControl::nameFromCommand(qtractorMidiControl::TRACK_GAIN)); m_ui.CommandComboBox->addItem(iconCommand, qtractorMidiControl::nameFromCommand(qtractorMidiControl::TRACK_PANNING)); m_ui.CommandComboBox->addItem(iconCommand, qtractorMidiControl::nameFromCommand(qtractorMidiControl::TRACK_MONITOR)); m_ui.CommandComboBox->addItem(iconCommand, qtractorMidiControl::nameFromCommand(qtractorMidiControl::TRACK_RECORD)); m_ui.CommandComboBox->addItem(iconCommand, qtractorMidiControl::nameFromCommand(qtractorMidiControl::TRACK_MUTE)); m_ui.CommandComboBox->addItem(iconCommand, qtractorMidiControl::nameFromCommand(qtractorMidiControl::TRACK_SOLO)); stabilizeTypeChange(); refreshFiles(); adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.FilesListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(stabilizeForm())); QObject::connect(m_ui.ControlMapListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(stabilizeForm())); QObject::connect(m_ui.ImportPushButton, SIGNAL(clicked()), SLOT(importSlot())); QObject::connect(m_ui.RemovePushButton, SIGNAL(clicked()), SLOT(removeSlot())); QObject::connect(m_ui.MoveUpPushButton, SIGNAL(clicked()), SLOT(moveUpSlot())); QObject::connect(m_ui.MoveDownPushButton, SIGNAL(clicked()), SLOT(moveDownSlot())); QObject::connect(m_ui.ControlTypeComboBox, SIGNAL(activated(int)), SLOT(typeChangedSlot())); QObject::connect(m_ui.ChannelComboBox, SIGNAL(activated(int)), SLOT(keyChangedSlot())); QObject::connect(m_ui.ParamComboBox, SIGNAL(activated(int)), SLOT(keyChangedSlot())); QObject::connect(m_ui.TrackCheckBox, SIGNAL(toggled(bool)), SLOT(keyChangedSlot())); QObject::connect(m_ui.TrackSpinBox, SIGNAL(valueChanged(int)), SLOT(valueChangedSlot())); QObject::connect(m_ui.CommandComboBox, SIGNAL(activated(int)), SLOT(valueChangedSlot())); QObject::connect(m_ui.FeedbackCheckBox, SIGNAL(toggled(bool)), SLOT(valueChangedSlot())); QObject::connect(m_ui.MapPushButton, SIGNAL(clicked()), SLOT(mapSlot())); QObject::connect(m_ui.UnmapPushButton, SIGNAL(clicked()), SLOT(unmapSlot())); QObject::connect(m_ui.ReloadPushButton, SIGNAL(clicked()), SLOT(reloadSlot())); QObject::connect(m_ui.ExportPushButton, SIGNAL(clicked()), SLOT(exportSlot())); QObject::connect(m_ui.ClosePushButton, SIGNAL(clicked()), SLOT(reject())); } // Destructor. qtractorMidiControlForm::~qtractorMidiControlForm (void) { } // Reject settings (Cancel button slot). void qtractorMidiControlForm::reject (void) { // Check if there's any pending changes... if (m_iDirtyMap > 0) reloadSlot(); if (m_iDirtyMap == 0) QDialog::reject(); } // Import new intrument file(s) into listing. void qtractorMidiControlForm::importSlot (void) { qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; QStringList files; const QString sExt("qtc"); const QString& sTitle = tr("Import Controller Files") + " - " QTRACTOR_TITLE; const QString& sFilter = tr("Controller files (*.%1)").arg(sExt); #if 0//QT_VERSION < 0x040400 // Ask for the filename to open... files = QFileDialog::getOpenFileNames(this, sTitle, pOptions->sMidiControlDir, sFilter); #else // Construct open-files dialog... QFileDialog fileDialog(this, sTitle, pOptions->sMidiControlDir, sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::ExistingFiles); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(pOptions->sMidiControlDir)); fileDialog.setSidebarUrls(urls); // Show dialog... if (fileDialog.exec()) files = fileDialog.selectedFiles(); #endif if (files.isEmpty()) return; // Remember this last directory... // For avery selected controller file to load... QTreeWidgetItem *pItem = NULL; QStringListIterator iter(files); while (iter.hasNext()) { // Merge the file contents into global container... const QString& sPath = iter.next(); // Start inserting in the current selected or last item... if (pItem == NULL) pItem = m_ui.FilesListView->currentItem(); if (pItem == NULL) { int iLastItem = m_ui.FilesListView->topLevelItemCount() - 1; if (iLastItem >= 0) pItem = m_ui.FilesListView->topLevelItem(iLastItem); } // New item on the block :-) pItem = new QTreeWidgetItem(m_ui.FilesListView, pItem); if (pItem) { QFileInfo info(sPath); pItem->setIcon(0, QIcon(":/images/itemFile.png")); pItem->setText(0, info.completeBaseName()); pItem->setText(1, sPath); m_ui.FilesListView->setCurrentItem(pItem); pOptions->sMidiControlDir = info.absolutePath(); } } // Make effect immediately. reloadSlot(); } // Remove a file from controller list. void qtractorMidiControlForm::removeSlot (void) { QTreeWidgetItem *pItem = m_ui.FilesListView->currentItem(); if (pItem == NULL) return; // Prompt user if he/she's sure about this... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions && pOptions->bConfirmRemove) { // Show the warning... if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("About to remove controller file:\n\n" "\"%1\"\n\n" "Are you sure?") .arg(pItem->text(1)), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; } // Just do it! delete pItem; // Effect immediate. reloadSlot(); } // Move a file up on the controller list. void qtractorMidiControlForm::moveUpSlot (void) { QTreeWidgetItem *pItem = m_ui.FilesListView->currentItem(); if (pItem) { int iItem = m_ui.FilesListView->indexOfTopLevelItem(pItem); if (iItem > 0) { pItem = m_ui.FilesListView->takeTopLevelItem(iItem); m_ui.FilesListView->insertTopLevelItem(iItem - 1, pItem); m_ui.FilesListView->setCurrentItem(pItem); } } reloadSlot(); } // Move a file down on the controller list. void qtractorMidiControlForm::moveDownSlot (void) { QTreeWidgetItem *pItem = m_ui.FilesListView->currentItem(); if (pItem) { int iItem = m_ui.FilesListView->indexOfTopLevelItem(pItem); if (iItem < m_ui.FilesListView->topLevelItemCount() - 1) { pItem = m_ui.FilesListView->takeTopLevelItem(iItem); m_ui.FilesListView->insertTopLevelItem(iItem + 1, pItem); m_ui.FilesListView->setCurrentItem(pItem); } } reloadSlot(); } // Map current channel/control command. void qtractorMidiControlForm::mapSlot (void) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return; qtractorMidiControl::ControlType ctype = qtractorMidiControl::typeFromName( m_ui.ControlTypeComboBox->currentText()); unsigned short iChannel = channelFromText( m_ui.ChannelComboBox->currentText()); unsigned short iParam = paramFromText(ctype, m_ui.ParamComboBox->currentText()); if (m_ui.TrackCheckBox->isChecked() && (iChannel & qtractorMidiControl::TrackParam) == 0) iParam |= qtractorMidiControl::TrackParam; qtractorMidiControl::Command command = qtractorMidiControl::commandFromName( m_ui.CommandComboBox->currentText()); int iTrack = m_ui.TrackSpinBox->value(); bool bFeedback = m_ui.FeedbackCheckBox->isChecked(); pMidiControl->mapChannelParam( ctype, iChannel, iParam, command, iTrack, bFeedback); m_iDirtyCount = 0; ++m_iDirtyMap; refreshControlMap(); } // Unmap current channel/control command. void qtractorMidiControlForm::unmapSlot (void) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return; qtractorMidiControl::ControlType ctype = qtractorMidiControl::typeFromName( m_ui.ControlTypeComboBox->currentText()); unsigned short iChannel = channelFromText( m_ui.ChannelComboBox->currentText()); unsigned short iParam = paramFromText(ctype, m_ui.ParamComboBox->currentText()); if (m_ui.TrackCheckBox->isChecked() && (iChannel & qtractorMidiControl::TrackParam) == 0) iParam |= qtractorMidiControl::TrackParam; pMidiControl->unmapChannelParam(ctype, iChannel, iParam); m_iDirtyCount = 0; ++m_iDirtyMap; refreshControlMap(); } // Export the whole state into a single controller file. void qtractorMidiControlForm::exportSlot (void) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return; qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; QString sPath; const QString sExt("qtc"); const QString& sTitle = tr("Export Controller File") + " - " QTRACTOR_TITLE; const QString& sFilter = tr("Controller files (*.%1)").arg(sExt); #if 0//QT_VERSION < 0x040400 // Ask for the filename to open... sPath = QFileDialog::getSaveFileName(this, sTitle, pOptions->sMidiControlDir, sFilter); #else // Construct open-files dialog... QFileDialog fileDialog(this, sTitle, pOptions->sMidiControlDir, sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptSave); fileDialog.setFileMode(QFileDialog::AnyFile); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(pOptions->sMidiControlDir)); fileDialog.setSidebarUrls(urls); // Show dialog... if (fileDialog.exec()) sPath = fileDialog.selectedFiles().first(); #endif if (sPath.isEmpty()) return; // Enforce .qtc extension... if (QFileInfo(sPath).suffix().isEmpty()) { sPath += '.' + sExt; // Check if already exists... if (QFileInfo(sPath).exists()) { if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("The controller file already exists:\n\n" "\"%1\"\n\n" "Do you want to replace it?") .arg(sPath), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; } } // Just save the whole bunch... if (pMidiControl->saveDocument(sPath)) { pOptions->sMidiControlDir = QFileInfo(sPath).absolutePath(); if (m_iDirtyMap > 0 && QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Saved controller mappings may not be effective\n" "the next time you start this program.\n\n" "\"%1\"\n\n" "Do you want to apply to controller files?") .arg(sPath), QMessageBox::Apply | QMessageBox::Ignore) == QMessageBox::Apply) { // Apply by append... pOptions->midiControlFiles.clear(); pOptions->midiControlFiles.append(sPath); // Won't be dirty anymore. m_iDirtyMap = 0; // Make it renew... refreshFiles(); reloadSlot(); } } } // Reload the complete controller configurations, from list. void qtractorMidiControlForm::reloadSlot (void) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return; // Check if there's any pending map changes... if (m_iDirtyMap > 0 && !pMidiControl->controlMap().isEmpty() && QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Controller mappings have been changed.") + "\n\n" + tr("Do you want to save the changes?"), QMessageBox::Save | QMessageBox::Discard) == QMessageBox::Save) { // Export is save... :) exportSlot(); return; } qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; // Ooops... pMidiControl->clear(); pOptions->midiControlFiles.clear(); // Load each file in order... int iItemCount = m_ui.FilesListView->topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = m_ui.FilesListView->topLevelItem(iItem); if (pItem) { const QString& sPath = pItem->text(1); if (pMidiControl->loadDocument(sPath)) pOptions->midiControlFiles.append(sPath); } } // Not dirty anymore... m_iDirtyCount = 0; m_iDirtyMap = 0; refreshControlMap(); } // Mapping type field have changed.. void qtractorMidiControlForm::typeChangedSlot (void) { if (m_iUpdating > 0) return; ++m_iDirtyCount; stabilizeTypeChange(); stabilizeKeyChange(); } void qtractorMidiControlForm::stabilizeTypeChange (void) { m_ui.ParamComboBox->clear(); // m_ui.ParamComboBox->addItem("*"); qtractorMidiControl::ControlType ctype = qtractorMidiControl::typeFromName( m_ui.ControlTypeComboBox->currentText()); const QIcon iconParam(":/images/itemControllers.png"); for (unsigned short iParam = 0; iParam < 128; ++iParam) m_ui.ParamComboBox->addItem(iconParam, textFromParam(ctype, iParam)); } // Mapping key fields have changed.. void qtractorMidiControlForm::keyChangedSlot (void) { if (m_iUpdating > 0) return; ++m_iDirtyCount; stabilizeKeyChange(); } void qtractorMidiControlForm::stabilizeKeyChange (void) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return; const QString& sType = m_ui.ControlTypeComboBox->currentText(); const QString& sChannel = m_ui.ChannelComboBox->currentText(); const QString& sParam = m_ui.ParamComboBox->currentText(); qtractorMidiControl::ControlType ctype = qtractorMidiControl::typeFromName(sType); unsigned short iChannel = channelFromText(sChannel); unsigned short iParam = paramFromText(ctype, sParam); if (m_ui.TrackCheckBox->isChecked() && (iChannel & qtractorMidiControl::TrackParam) == 0) iParam |= qtractorMidiControl::TrackParam; bool bMapped = pMidiControl->isChannelParamMapped(ctype, iChannel, iParam); if (bMapped) { QList items = m_ui.ControlMapListView->findItems(sType, Qt::MatchExactly, 0); QListIterator iter(items); while (iter.hasNext()) { QTreeWidgetItem *pItem = iter.next(); if ((iParam & qtractorMidiControl::TrackParam) == 0 && pItem->text(3)[0] == '+') continue; if (pItem->text(1) == sChannel && pItem->text(2) == sParam) { ++m_iUpdating; m_ui.ControlMapListView->setCurrentItem(pItem); --m_iUpdating; break; } } } m_ui.TrackCheckBox->setEnabled( (iChannel & qtractorMidiControl::TrackParam) == 0); m_ui.MapPushButton->setEnabled(!bMapped && m_iDirtyCount > 0); m_ui.UnmapPushButton->setEnabled(bMapped); } // Mapping value fields have changed.. void qtractorMidiControlForm::valueChangedSlot (void) { if (m_iUpdating > 0) return; ++m_iDirtyCount; stabilizeValueChange(); } void qtractorMidiControlForm::stabilizeValueChange (void) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return; const QString& sType = m_ui.ControlTypeComboBox->currentText(); const QString& sChannel = m_ui.ChannelComboBox->currentText(); const QString& sParam = m_ui.ParamComboBox->currentText(); qtractorMidiControl::ControlType ctype = qtractorMidiControl::typeFromName(sType); unsigned short iChannel = channelFromText(sChannel); unsigned short iParam = paramFromText(ctype, sParam); if (m_ui.TrackCheckBox->isChecked() && (iChannel & qtractorMidiControl::TrackParam) == 0) iParam |= qtractorMidiControl::TrackParam; bool bMapped = pMidiControl->isChannelParamMapped(ctype, iChannel, iParam); if (bMapped) { qtractorMidiControl::Command command = qtractorMidiControl::commandFromName( m_ui.CommandComboBox->currentText()); int iTrack = m_ui.TrackSpinBox->value(); bool bFeedback = m_ui.FeedbackCheckBox->isChecked(); pMidiControl->mapChannelParam( ctype, iChannel, iParam, command, iTrack, bFeedback); m_iDirtyCount = 0; ++m_iDirtyMap; refreshControlMap(); } } // Stabilize form status. void qtractorMidiControlForm::stabilizeForm (void) { if (m_iUpdating > 0) return; QTreeWidgetItem *pItem = m_ui.FilesListView->currentItem(); if (pItem) { int iItem = m_ui.FilesListView->indexOfTopLevelItem(pItem); int iItemCount = m_ui.FilesListView->topLevelItemCount(); m_ui.RemovePushButton->setEnabled(true); m_ui.MoveUpPushButton->setEnabled(iItem > 0); m_ui.MoveDownPushButton->setEnabled(iItem < iItemCount - 1); } else { m_ui.RemovePushButton->setEnabled(false); m_ui.MoveUpPushButton->setEnabled(false); m_ui.MoveDownPushButton->setEnabled(false); } pItem = m_ui.ControlMapListView->currentItem(); if (pItem) { ++m_iUpdating; m_ui.ControlTypeComboBox->setCurrentIndex( m_ui.ControlTypeComboBox->findText(pItem->text(0))); stabilizeTypeChange(); m_ui.ChannelComboBox->setCurrentIndex( m_ui.ChannelComboBox->findText(pItem->text(1))); m_ui.ParamComboBox->setCurrentIndex( m_ui.ParamComboBox->findText(pItem->text(2))); const QString& sText = pItem->text(3); m_ui.TrackCheckBox->setChecked(sText[0] == '+'); m_ui.TrackSpinBox->setValue(sText.toInt()); m_ui.CommandComboBox->setCurrentIndex( m_ui.CommandComboBox->findText(pItem->text(4))); m_ui.FeedbackCheckBox->setChecked(pItem->text(5) == tr("Yes")); --m_iUpdating; } m_ui.ReloadPushButton->setEnabled(m_iDirtyMap > 0); qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl) m_ui.ExportPushButton->setEnabled( !pMidiControl->controlMap().isEmpty()); stabilizeKeyChange(); } // Refresh all controller definition views. void qtractorMidiControlForm::refreshFiles (void) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return; qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; // Freeze... m_ui.FilesListView->setUpdatesEnabled(false); // Files list view... m_ui.FilesListView->clear(); QList files; QStringListIterator iter(pOptions->midiControlFiles); while (iter.hasNext()) { const QString& sPath = iter.next(); QTreeWidgetItem *pFileItem = new QTreeWidgetItem(); pFileItem->setIcon(0, QIcon(":/images/itemFile.png")); pFileItem->setText(0, QFileInfo(sPath).completeBaseName()); pFileItem->setText(1, sPath); files.append(pFileItem); } m_ui.FilesListView->addTopLevelItems(files); // Bail out... m_ui.FilesListView->setUpdatesEnabled(true); refreshControlMap(); } // Refresh controller map view. void qtractorMidiControlForm::refreshControlMap (void) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return; // Freeze... m_ui.ControlMapListView->setUpdatesEnabled(false); // Control map list view... m_ui.ControlMapListView->clear(); QList items; const qtractorMidiControl::ControlMap& controlMap = pMidiControl->controlMap(); qtractorMidiControl::ControlMap::ConstIterator it = controlMap.constBegin(); const qtractorMidiControl::ControlMap::ConstIterator& it_end = controlMap.constEnd(); const QIcon iconControlType(":/images/itemProperty.png"); const QIcon iconParam(":/images/itemControllers.png"); const QIcon iconCommand(":/images/itemChannel.png"); for ( ; it != it_end; ++it) { const qtractorMidiControl::MapKey& key = it.key(); const qtractorMidiControl::MapVal& val = it.value(); QTreeWidgetItem *pItem = new QTreeWidgetItem(); pItem->setIcon(0, iconControlType); pItem->setText(0, qtractorMidiControl::nameFromType(key.type())); pItem->setText(1, textFromChannel(key.channel())); pItem->setIcon(2, iconParam); pItem->setText(2, textFromParam(key.type(), key.param())); QString sText; if (key.isParamTrack()) sText += "+ "; pItem->setText(3, sText + QString::number(val.track())); pItem->setIcon(4, iconCommand); pItem->setText(4, qtractorMidiControl::nameFromCommand(val.command())); pItem->setText(5, val.isFeedback() ? tr("Yes") : tr("No")); items.append(pItem); } m_ui.ControlMapListView->addTopLevelItems(items); // Bail out... m_ui.ControlMapListView->setUpdatesEnabled(true); stabilizeForm(); } // Channel text conversion helpers. unsigned short qtractorMidiControlForm::channelFromText ( const QString& sText ) const { if (sText == "*" || sText.isEmpty()) return qtractorMidiControl::TrackParam; else return sText.toUShort() - 1; } QString qtractorMidiControlForm::textFromChannel ( unsigned short iChannel ) const { if (iChannel & qtractorMidiControl::TrackParam) return "*"; // "TrackParam"; else return QString::number(iChannel + 1); } // Controller parameter text conversion helpers. unsigned short qtractorMidiControlForm::paramFromText ( qtractorMidiControl::ControlType /*ctype*/, const QString& sText ) const { return sText.section(' ', 0, 0).toUShort(); } QString qtractorMidiControlForm::textFromParam ( qtractorMidiControl::ControlType ctype, unsigned short iParam ) const { iParam &= qtractorMidiControl::TrackParamMask; QString sText = QString::number(iParam); switch (ctype) { case qtractorMidiEvent::NOTEON: case qtractorMidiEvent::NOTEOFF: case qtractorMidiEvent::KEYPRESS: sText += " - " + qtractorMidiEditor::defaultNoteName(iParam); break; case qtractorMidiEvent::CONTROLLER: sText += " - " + qtractorMidiEditor::defaultControllerName(iParam); break; default: break; } return sText; } // end of qtractorMidiControlForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/config.h.in0000644000175000001440000000006212224470517017274 xustar000000000000000020 atime=1381134671 30 ctime=1381134671.802080125 qtractor-0.5.11/src/config.h.in0000644000175000001440000001325212224470517016564 0ustar00rncbcusers00000000000000/* src/config.h.in. Generated from configure.ac by autoheader. */ /* Define if debugging is enabled. */ #undef CONFIG_DEBUG /* Define if DSSI header is available. */ #undef CONFIG_DSSI /* Define if IEEE 32bit float optimizations are enabled. */ #undef CONFIG_FLOAT32 /* Define if gradient eye-candy is enabled. */ #undef CONFIG_GRADIENT /* Define if JACK latency support is available. */ #undef CONFIG_JACK_LATENCY /* Define if JACK session support is available. */ #undef CONFIG_JACK_SESSION /* Define if LADSPA header is available. */ #undef CONFIG_LADSPA /* Define if liblilv is available. */ #undef CONFIG_LIBLILV /* Define if liblo is available. */ #undef CONFIG_LIBLO /* Define if libmad is available. */ #undef CONFIG_LIBMAD /* Define if librubberband is available. */ #undef CONFIG_LIBRUBBERBAND /* Define if libsamplerate is available. */ #undef CONFIG_LIBSAMPLERATE /* Define if libsuil is available. */ #undef CONFIG_LIBSUIL /* Define if libvorbis is available. */ #undef CONFIG_LIBVORBIS /* Define if libz is available. */ #undef CONFIG_LIBZ /* Define if LV2 headers are available. */ #undef CONFIG_LV2 /* Define if LV2 Atom/MIDI aupport is available. */ #undef CONFIG_LV2_ATOM /* Define if LV2 Buf-size is supported. */ #undef CONFIG_LV2_BUF_SIZE /* Define if LV2 Event/MIDI support is available. */ #undef CONFIG_LV2_EVENT /* Define if LV2 External UI extension is available. */ #undef CONFIG_LV2_EXTERNAL_UI /* Define if LV2 Options is supported. */ #undef CONFIG_LV2_OPTIONS /* Define if LV2 Presets are supported. */ #undef CONFIG_LV2_PRESETS /* Define if LV2 Programs extension is available. */ #undef CONFIG_LV2_PROGRAMS /* Define if LV2 State extension is available. */ #undef CONFIG_LV2_STATE /* Define if LV2 State Files feature is available. */ #undef CONFIG_LV2_STATE_FILES /* Define if LV2 Time/position is supported. */ #undef CONFIG_LV2_TIME /* Define if LV2 UI support is available. */ #undef CONFIG_LV2_UI /* Define if LV2 Worker/Schedule aupport is available. */ #undef CONFIG_LV2_WORKER /* Define if NSM support is available. */ #undef CONFIG_NSM /* Default installation prefix. */ #undef CONFIG_PREFIX /* Define if round is available. */ #undef CONFIG_ROUND /* Define if debugger stack-trace is enabled. */ #undef CONFIG_STACKTRACE /* Define if suil_instance_get_handle is available. */ #undef CONFIG_SUIL_INSTANCE_GET_HANDLE /* Define if VeSTige header is available. */ #undef CONFIG_VESTIGE /* Define if VST header is available. */ #undef CONFIG_VST /* Define if X11 unique/single instance is enabled. */ #undef CONFIG_XUNIQUE /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM /* Define to 1 if you have the `X11' library (-lX11). */ #undef HAVE_LIBX11 /* Define to 1 if you have the `Xext' library (-lXext). */ #undef HAVE_LIBXEXT /* Define to 1 if you have the header file. */ #undef HAVE_LV2_ATOM_HELPERS_H /* Define to 1 if you have the header file. */ #undef HAVE_LV2_LV2PLUG_IN_NS_EXT_ATOM_ATOM_H /* Define to 1 if you have the header file. */ #undef HAVE_LV2_LV2PLUG_IN_NS_EXT_DATA_ACCESS_DATA_ACCESS_H /* Define to 1 if you have the header file. */ #undef HAVE_LV2_LV2PLUG_IN_NS_EXT_EVENT_EVENT_H /* Define to 1 if you have the header file. */ #undef HAVE_LV2_LV2PLUG_IN_NS_EXT_EVENT_EVENT_HELPERS_H /* Define to 1 if you have the header file. */ #undef HAVE_LV2_LV2PLUG_IN_NS_EXT_INSTANCE_ACCESS_INSTANCE_ACCESS_H /* Define to 1 if you have the header file. */ #undef HAVE_LV2_LV2PLUG_IN_NS_EXT_STATE_STATE_H /* Define to 1 if you have the header file. */ #undef HAVE_LV2_LV2PLUG_IN_NS_EXT_URID_URID_H /* Define to 1 if you have the header file. */ #undef HAVE_LV2_LV2PLUG_IN_NS_EXT_URI_MAP_URI_MAP_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_SIGNAL_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `system' function. */ #undef HAVE_SYSTEM /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEventList.cpp0000644000175000001440000000012212075634407022256 xustar000000000000000027 mtime=1358379271.965668 26 atime=1381134667.66208 29 ctime=1381134667.69608006 qtractor-0.5.11/src/qtractorMidiEventList.cpp0000644000175000001440000006534412075634407021562 0ustar00rncbcusers00000000000000// qtractorMidiEventList.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiEventList.h" #include "qtractorMidiEditor.h" #include "qtractorMidiEditorForm.h" #include "qtractorMidiEditCommand.h" #include "qtractorMidiSequence.h" #include "qtractorSpinBox.h" #include #include #include #include //---------------------------------------------------------------------------- // qtractorMidiEventListModel -- List model. // Constructor. qtractorMidiEventListModel::qtractorMidiEventListModel ( qtractorMidiEditor *pEditor, QObject *pParent ) : QAbstractItemModel(pParent), m_pEditor(pEditor), m_pSeq(NULL), m_iTimeOffset(0), m_pEvent(NULL), m_iEvent(0) { m_headers << tr("Time") << tr("Type") << tr("Name") << tr("Value") << tr("Duration/Data"); reset(); } int qtractorMidiEventListModel::rowCount ( const QModelIndex& /*parent*/ ) const { return (m_pSeq ? m_pSeq->events().count() : 0); } int qtractorMidiEventListModel::columnCount ( const QModelIndex& /*parent*/ ) const { return m_headers.count(); } QVariant qtractorMidiEventListModel::headerData ( int section, Qt::Orientation orient, int role ) const { // qDebug("headerData(%d, %d, %d)", section, int(orient), int(role)); if (orient == Qt::Horizontal) { switch (role) { case Qt::DisplayRole: #if 0 if (section == 0) { switch ((m_pEditor->timeScale())->displayFormat()) { case qtractorTimeScale::Frames: return tr("Frame"); case qtractorTimeScale::Time: return tr("Time"); case qtractorTimeScale::BBT: return tr("BBT"); } } #endif return m_headers.at(section); case Qt::TextAlignmentRole: return columnAlignment(section); default: break; } } return QVariant(); } QVariant qtractorMidiEventListModel::data ( const QModelIndex& index, int role ) const { // qDebug("data(%d, %d, %d)", index.row(), index.column(), int(role)); switch (role) { case Qt::DisplayRole: return itemDisplay(index); case Qt::TextAlignmentRole: return columnAlignment(index.column()); case Qt::ToolTipRole: return itemToolTip(index); default: break; } return QVariant(); } Qt::ItemFlags qtractorMidiEventListModel::flags ( const QModelIndex& index ) const { Qt::ItemFlags ret = Qt::ItemFlags(0); qtractorMidiEvent *pEvent = eventOfIndex(index); if (pEvent) { if (m_pEditor->isEventSelectable(pEvent)) ret = QAbstractItemModel::flags(index); else ret = Qt::ItemIsEnabled; ret |= Qt::ItemIsEditable; } return ret; } QModelIndex qtractorMidiEventListModel::index ( int row, int column, const QModelIndex& /*parent*/) const { // qDebug("index(%d, %d)", row, column); qtractorMidiEvent *pEvent = eventAt(row); if (pEvent) return createIndex(row, column, pEvent); else return QModelIndex(); } QModelIndex qtractorMidiEventListModel::parent ( const QModelIndex& ) const { return QModelIndex(); } void qtractorMidiEventListModel::reset (void) { // qDebug("reset()"); m_pSeq = m_pEditor->sequence(); m_iTimeOffset = m_pEditor->timeOffset(); m_pEvent = NULL; m_iEvent = 0; #if QT_VERSION >= 0x050000 QAbstractItemModel::beginResetModel(); QAbstractItemModel::endResetModel(); #else QAbstractItemModel::reset(); #endif } qtractorMidiEvent *qtractorMidiEventListModel::eventAt ( int i ) const { if (m_pSeq == NULL) return NULL; const int n = m_pSeq->events().count(); const int m = (n >> 1); if (m_pEvent == NULL || i > m_iEvent + m || i < m_iEvent - m) { if (i > m) { m_iEvent = n - 1; m_pEvent = m_pSeq->events().last(); } else { m_iEvent = 0; m_pEvent = m_pSeq->events().first(); } } if (i > m_iEvent) { while (m_pEvent && m_pEvent->next() && i > m_iEvent) { m_pEvent = m_pEvent->next(); ++m_iEvent; } } else if (i < m_iEvent) { while (m_pEvent && m_pEvent->prev() && i < m_iEvent) { m_pEvent = m_pEvent->prev(); --m_iEvent; } } return m_pEvent; } qtractorMidiEvent *qtractorMidiEventListModel::eventOfIndex ( const QModelIndex& index ) const { return static_cast (index.internalPointer()); } QModelIndex qtractorMidiEventListModel::indexOfEvent ( qtractorMidiEvent *pEvent ) const { if (pEvent == NULL) return QModelIndex(); unsigned long iTime = pEvent->time(); if (indexFromTick(m_iTimeOffset + iTime).isValid()) { while (m_pEvent != pEvent && m_pEvent->next() && m_pEvent->time() == iTime) { m_pEvent = m_pEvent->next(); ++m_iEvent; } } return (m_pEvent == pEvent ? createIndex(m_iEvent, 0, m_pEvent) : QModelIndex()); } QModelIndex qtractorMidiEventListModel::indexFromTick ( unsigned long iTick ) const { if (m_pEvent == NULL && m_pSeq) { m_iEvent = 0; m_pEvent = m_pSeq->events().first(); } if (m_pEvent == NULL) return QModelIndex(); unsigned long iTime = (iTick > m_iTimeOffset ? iTick - m_iTimeOffset : 0); if (m_pEvent->time() >= iTime) { while (m_pEvent && m_pEvent->prev() && (m_pEvent->prev())->time() >= iTime) { m_pEvent = m_pEvent->prev(); --m_iEvent; } } else while (m_pEvent && m_pEvent->next() && iTime > m_pEvent->time()) { m_pEvent = m_pEvent->next(); ++m_iEvent; } //qDebug("indexFromTick(%lu) index=%d time=%lu", iTime, m_iEvent, m_pEvent->time()); return createIndex(m_iEvent, 0, m_pEvent); } unsigned long qtractorMidiEventListModel::tickFromIndex ( const QModelIndex& index ) const { qtractorMidiEvent *pEvent = eventOfIndex(index); return m_iTimeOffset + (pEvent ? pEvent->time() : 0); } QModelIndex qtractorMidiEventListModel::indexFromFrame ( unsigned long iFrame ) const { return indexFromTick((m_pEditor->timeScale())->tickFromFrame(iFrame)); } unsigned long qtractorMidiEventListModel::frameFromIndex ( const QModelIndex& index ) const { return (m_pEditor->timeScale())->frameFromTick(tickFromIndex(index)); } qtractorMidiEditor *qtractorMidiEventListModel::editor (void) const { return m_pEditor; } QString qtractorMidiEventListModel::itemDisplay ( const QModelIndex& index ) const { // qDebug("itemDisplay(%d, %d)", index.row(), index.column()); const QString sDashes(2, '-'); qtractorMidiEvent *pEvent = eventOfIndex(index); if (pEvent) { switch (index.column()) { case 0: // Time. return (m_pEditor->timeScale())->textFromTick( m_iTimeOffset + pEvent->time()); case 1: // Type. switch (pEvent->type()) { case qtractorMidiEvent::NOTEON: return tr("Note On (%1)").arg(pEvent->note()); case qtractorMidiEvent::NOTEOFF: return tr("Note Off (%1)").arg(pEvent->note()); case qtractorMidiEvent::KEYPRESS: return tr("Key Press (%1)").arg(pEvent->note()); case qtractorMidiEvent::CONTROLLER: return tr("Controller (%1)").arg(pEvent->controller()); case qtractorMidiEvent::PGMCHANGE: return tr("Pgm Change"); case qtractorMidiEvent::CHANPRESS: return tr("Chan Press"); case qtractorMidiEvent::PITCHBEND: return tr("Pitch Bend"); case qtractorMidiEvent::SYSEX: return tr("SysEx"); case qtractorMidiEvent::META: return tr("Meta (%1)").arg(int(pEvent->type())); default: break; } return tr("Unknown (%1)").arg(int(pEvent->type())); case 2: // Name. switch (pEvent->type()) { case qtractorMidiEvent::NOTEON: case qtractorMidiEvent::NOTEOFF: case qtractorMidiEvent::KEYPRESS: return m_pEditor->noteName(pEvent->note()); case qtractorMidiEvent::CONTROLLER: return m_pEditor->controllerName(pEvent->controller()); default: break; } break; case 3: // Value. switch (pEvent->type()) { case qtractorMidiEvent::NOTEON: case qtractorMidiEvent::NOTEOFF: case qtractorMidiEvent::KEYPRESS: return QString::number(pEvent->velocity()); case qtractorMidiEvent::CONTROLLER: case qtractorMidiEvent::PGMCHANGE: case qtractorMidiEvent::CHANPRESS: return QString::number(pEvent->value()); case qtractorMidiEvent::PITCHBEND: return QString::number(pEvent->pitchBend()); case qtractorMidiEvent::SYSEX: return QString::number(pEvent->sysex_len()); default: break; } break; case 4: // Duration/Data switch (pEvent->type()) { case qtractorMidiEvent::NOTEON: return (m_pEditor->timeScale())->textFromTick( m_iTimeOffset + pEvent->time(), true, pEvent->duration()); case qtractorMidiEvent::SYSEX: { QString sText; unsigned char *data = pEvent->sysex(); unsigned short len = pEvent->sysex_len(); sText += '{'; sText += ' '; for (unsigned short i = 0; i < len; ++i) sText += QString().sprintf("%02x ", data[i]); sText += '}'; return sText; } default: break; } break; } } return sDashes; } QString qtractorMidiEventListModel::itemToolTip ( const QModelIndex& index ) const { qtractorMidiEvent *pEvent = eventOfIndex(index); if (pEvent) return m_pEditor->eventToolTip(pEvent); else return QString(); } int qtractorMidiEventListModel::columnAlignment( int column ) const { if (column == 0 || column == 3) // Time,Value. return int(Qt::AlignRight | Qt::AlignVCenter); else return int(Qt::AlignLeft | Qt::AlignVCenter); } //---------------------------------------------------------------------------- // qtractorMidiEventItemDelegate -- Custom (tree) list item delegate. // Constructor. qtractorMidiEventItemDelegate::qtractorMidiEventItemDelegate ( QObject *pParent ) : QItemDelegate(pParent) { } // Destructor. qtractorMidiEventItemDelegate::~qtractorMidiEventItemDelegate (void) { } // Keyboard event hook. bool qtractorMidiEventItemDelegate::eventFilter ( QObject *pObject, QEvent *pEvent ) { QWidget *pEditor = qobject_cast (pObject); if (pEditor) { switch (pEvent->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: { QKeyEvent *pKeyEvent = static_cast (pEvent); if ((pKeyEvent->modifiers() & Qt::ControlModifier) == 0 && (pKeyEvent->key() == Qt::Key_Up || pKeyEvent->key() == Qt::Key_Down)) { pEvent->ignore(); return true; } if (pKeyEvent->key() == Qt::Key_Enter || pKeyEvent->key() == Qt::Key_Return) { emit commitData(pEditor); if (pEditor) pEditor->close(); return true; } break; } case QEvent::FocusOut: { if (!pEditor->isActiveWindow() || (QApplication::focusWidget() != pEditor)) { QWidget *pWidget = QApplication::focusWidget(); while (pWidget) { if (pWidget == pEditor) return false; pWidget = pWidget->parentWidget(); } emit commitData(pEditor); } return false; } default: break; } } return QItemDelegate::eventFilter(pObject, pEvent); } // QItemDelegate Interface... void qtractorMidiEventItemDelegate::paint ( QPainter *pPainter, const QStyleOptionViewItem& option, const QModelIndex& index) const { QItemDelegate::paint(pPainter, option, index); } QSize qtractorMidiEventItemDelegate::sizeHint ( const QStyleOptionViewItem& option, const QModelIndex& index ) const { return QItemDelegate::sizeHint(option, index) + QSize(4, 4); } QWidget *qtractorMidiEventItemDelegate::createEditor ( QWidget *pParent, const QStyleOptionViewItem& /*option*/, const QModelIndex& index ) const { const qtractorMidiEventListModel *pListModel = static_cast (index.model()); qtractorMidiEvent *pEvent = pListModel->eventOfIndex(index); if (pEvent == NULL) return NULL; qtractorMidiEditor *pMidiEditor = pListModel->editor(); if (pMidiEditor == NULL) return NULL; QWidget *pEditor = NULL; switch (index.column()) { case 0: // Time. { qtractorTimeSpinBox *pTimeSpinBox = new qtractorTimeSpinBox(pParent); pTimeSpinBox->setTimeScale(pMidiEditor->timeScale()); pEditor = pTimeSpinBox; break; } case 2: // Name. { if (pEvent->type() == qtractorMidiEvent::NOTEON || pEvent->type() == qtractorMidiEvent::KEYPRESS) { QComboBox *pComboBox = new QComboBox(pParent); for (unsigned char note = 0; note < 128; ++note) pComboBox->addItem(pMidiEditor->noteName(note)); pEditor = pComboBox; } break; } case 3: // Value. { QSpinBox *pSpinBox = new QSpinBox(pParent); if (pEvent->type() == qtractorMidiEvent::PITCHBEND) { pSpinBox->setMinimum(-8192); pSpinBox->setMaximum(+8192); } else { pSpinBox->setMinimum(0); pSpinBox->setMaximum(127); } pEditor = pSpinBox; break; } case 4: // Duration/Data. { if (pEvent->type() == qtractorMidiEvent::NOTEON) { qtractorTimeSpinBox *pTimeSpinBox = new qtractorTimeSpinBox(pParent); pTimeSpinBox->setTimeScale( (pListModel->editor())->timeScale()); pTimeSpinBox->setDeltaValue(true); pEditor = pTimeSpinBox; } break; } default: break; } if (pEditor) { pEditor->installEventFilter( const_cast (this)); } #ifdef CONFIG_DEBUG qDebug("qtractorMidiEventItemDelegate::createEditor(%p, %d, %d) = %p", pParent, index.row(), index.column(), pEditor); #endif return pEditor; } void qtractorMidiEventItemDelegate::setEditorData ( QWidget *pEditor, const QModelIndex& index ) const { const qtractorMidiEventListModel *pListModel = static_cast (index.model()); qtractorMidiEvent *pEvent = pListModel->eventOfIndex(index); if (pEvent == NULL) return; qtractorMidiEditor *pMidiEditor = pListModel->editor(); if (pMidiEditor == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMidiEventItemDelegate::setEditorData(%p, %p, %d, %d)", pEditor, pListModel, index.row(), index.column()); #endif qtractorTimeScale *pTimeScale = pMidiEditor->timeScale(); switch (index.column()) { case 0: // Time. { qtractorTimeSpinBox *pTimeSpinBox = qobject_cast (pEditor); if (pTimeSpinBox) { pTimeSpinBox->setValue(pTimeScale->frameFromTick( pMidiEditor->timeOffset() + pEvent->time())); } break; } case 2: // Name. { QComboBox *pComboBox = qobject_cast (pEditor); if (pComboBox) pComboBox->setCurrentIndex(int(pEvent->note())); break; } case 3: // Value. { QSpinBox *pSpinBox = qobject_cast (pEditor); if (pSpinBox) { if (pEvent->type() == qtractorMidiEvent::PITCHBEND) pSpinBox->setValue(pEvent->pitchBend()); else pSpinBox->setValue(pEvent->value()); } break; } case 4: // Duration/Data. { qtractorTimeSpinBox *pTimeSpinBox = qobject_cast (pEditor); if (pTimeSpinBox) { pTimeSpinBox->setValue( pTimeScale->frameFromTick(pEvent->duration())); } break; } default: break; } } void qtractorMidiEventItemDelegate::setModelData ( QWidget *pEditor, QAbstractItemModel *pModel, const QModelIndex& index ) const { const qtractorMidiEventListModel *pListModel = static_cast (pModel); qtractorMidiEvent *pEvent = pListModel->eventOfIndex(index); if (pEvent == NULL) return; qtractorMidiEditor *pMidiEditor = pListModel->editor(); if (pMidiEditor == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMidiEventItemDelegate::setModelData(%p, %p, %d, %d)", pEditor, pListModel, index.row(), index.column()); #endif qtractorTimeScale *pTimeScale = pMidiEditor->timeScale(); qtractorMidiEditCommand *pEditCommand = new qtractorMidiEditCommand(pMidiEditor->midiClip(), tr("edit %1").arg(pListModel->headerData( index.column(), Qt::Horizontal, Qt::DisplayRole) .toString().toLower())); switch (index.column()) { case 0: // Time. { qtractorTimeSpinBox *pTimeSpinBox = qobject_cast (pEditor); if (pTimeSpinBox) { unsigned long iTime = pTimeScale->tickFromFrame(pTimeSpinBox->valueFromText()); if (iTime > pMidiEditor->timeOffset()) iTime -= pMidiEditor->timeOffset(); else iTime = 0; unsigned long iDuration = 0; if (pEvent->type() == qtractorMidiEvent::NOTEON) iDuration = pEvent->duration(); pEditCommand->resizeEventTime(pEvent, iTime, iDuration); } break; } case 2: // Name. { QComboBox *pComboBox = qobject_cast (pEditor); if (pComboBox) { int iNote = pComboBox->currentIndex(); unsigned long iTime = pEvent->time(); pEditCommand->moveEvent(pEvent, iNote, iTime); } break; } case 3: // Value. { QSpinBox *pSpinBox = qobject_cast (pEditor); if (pSpinBox) { int iValue = pSpinBox->value(); pEditCommand->resizeEventValue(pEvent, iValue); } break; } case 4: // Duration/Data. { qtractorTimeSpinBox *pTimeSpinBox = qobject_cast (pEditor); if (pTimeSpinBox) { unsigned long iTime = pEvent->time(); unsigned long iDuration = pTimeScale->tickFromFrame(pTimeSpinBox->value()); pEditCommand->resizeEventTime(pEvent, iTime, iDuration); } break; } default: break; } // Do it. pMidiEditor->commands()->exec(pEditCommand); } void qtractorMidiEventItemDelegate::updateEditorGeometry ( QWidget *pEditor, const QStyleOptionViewItem& option, const QModelIndex& index ) const { QItemDelegate::updateEditorGeometry(pEditor, option, index); } //---------------------------------------------------------------------------- // qtractorMidiEventListView -- Custom (tree) list view. // Constructor. qtractorMidiEventListView::qtractorMidiEventListView ( QWidget *pParent ) : QTreeView(pParent), m_pListModel(NULL), m_pItemDelegate(NULL) { } // Destructor. qtractorMidiEventListView::~qtractorMidiEventListView (void) { if (m_pItemDelegate) delete m_pItemDelegate; if (m_pListModel) delete m_pListModel; } // Settlers. void qtractorMidiEventListView::setEditor ( qtractorMidiEditor *pEditor ) { if (m_pItemDelegate) delete m_pItemDelegate; if (m_pListModel) delete m_pListModel; m_pListModel = new qtractorMidiEventListModel(pEditor); m_pItemDelegate = new qtractorMidiEventItemDelegate(); QTreeView::setModel(m_pListModel); QTreeView::setItemDelegate(m_pItemDelegate); QTreeView::setSelectionMode(QAbstractItemView::ExtendedSelection); QTreeView::setRootIsDecorated(false); QTreeView::setUniformRowHeights(true); QTreeView::setItemsExpandable(false); QTreeView::setAllColumnsShowFocus(true); QTreeView::setAlternatingRowColors(true); QHeaderView *pHeader = QTreeView::header(); // pHeader->setDefaultAlignment(Qt::AlignLeft); pHeader->setDefaultSectionSize(80); #if QT_VERSION >= 0x050000 // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionResizeMode(QHeaderView::ResizeToContents); pHeader->setSectionsMovable(false); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setResizeMode(QHeaderView::ResizeToContents); pHeader->setMovable(false); #endif pHeader->resizeSection(2, 60); // Name pHeader->resizeSection(3, 40); // Value pHeader->setStretchLastSection(true); } qtractorMidiEditor *qtractorMidiEventListView::editor (void) const { return (m_pListModel ? m_pListModel->editor() : NULL); } // Refreshner. void qtractorMidiEventListView::refresh (void) { if (m_pListModel == NULL) return; QItemSelectionModel *pSelectionModel = QTreeView::selectionModel(); const QModelIndex& index = pSelectionModel->currentIndex(); m_pListModel->reset(); pSelectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); } // Locators. qtractorMidiEvent *qtractorMidiEventListView::eventOfIndex ( const QModelIndex& index) const { return (m_pListModel ? m_pListModel->eventOfIndex(index) : NULL); } QModelIndex qtractorMidiEventListView::indexOfEvent ( qtractorMidiEvent *pEvent ) const { return (m_pListModel ? m_pListModel->indexOfEvent(pEvent) : QModelIndex()); } QModelIndex qtractorMidiEventListView::indexFromTick ( unsigned long iTick ) const { return (m_pListModel ? m_pListModel->indexFromTick(iTick) : QModelIndex()); } unsigned long qtractorMidiEventListView::tickFromIndex ( const QModelIndex& index ) const { return (m_pListModel ? m_pListModel->tickFromIndex(index) : 0); } QModelIndex qtractorMidiEventListView::indexFromFrame ( unsigned long iFrame ) const { return (m_pListModel ? m_pListModel->indexFromFrame(iFrame) : QModelIndex()); } unsigned long qtractorMidiEventListView::frameFromIndex ( const QModelIndex& index ) const { return (m_pListModel ? m_pListModel->frameFromIndex(index) : 0); } void qtractorMidiEventListView::selectEvent ( qtractorMidiEvent *pEvent, bool bSelect ) { if (m_pListModel == NULL) return; const QModelIndex& index = m_pListModel->indexOfEvent(pEvent); if (index.isValid()) { QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Rows; if (bSelect) flags |= QItemSelectionModel::Select; else flags |= QItemSelectionModel::Deselect; QTreeView::selectionModel()->select(index, flags); } } //---------------------------------------------------------------------------- // qtractorMidiEventList -- MIDI Event List dockable window. // Constructor. qtractorMidiEventList::qtractorMidiEventList ( QWidget *pParent ) : QDockWidget(pParent) { // Surely a name is crucial (e.g.for storing geometry settings) QDockWidget::setObjectName("qtractorMidiEventList"); // Create local list view. m_pListView = new qtractorMidiEventListView(); // Cross-selection fake-mutex. m_iSelectUpdate = 0; const QFont& font = QDockWidget::font(); m_pListView->setFont(QFont(font.family(), font.pointSize() - 1)); // Prepare the dockable window stuff. QDockWidget::setWidget(m_pListView); QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures); QDockWidget::setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); // Some specialties to this kind of dock window... QDockWidget::setMinimumWidth(280); // Finally set the default caption and tooltip. const QString& sCaption = tr("Events"); QDockWidget::setWindowTitle(sCaption); QDockWidget::setWindowIcon(QIcon(":/images/viewEvents.png")); QDockWidget::setToolTip(sCaption); } // Destructor. qtractorMidiEventList::~qtractorMidiEventList (void) { // No need to delete child widgets, Qt does it all for us. } // Full update when show up. void qtractorMidiEventList::showEvent ( QShowEvent *pShowEvent ) { QDockWidget::showEvent(pShowEvent); refresh(); } // Just about to notify main-window that we're closing. void qtractorMidiEventList::closeEvent ( QCloseEvent * /*pCloseEvent*/ ) { QDockWidget::hide(); qtractorMidiEditorForm *pMidiEditorForm = static_cast (QDockWidget::parentWidget()); if (pMidiEditorForm) pMidiEditorForm->stabilizeForm(); } // Settlers. void qtractorMidiEventList::setEditor ( qtractorMidiEditor *pEditor ) { m_pListView->setEditor(pEditor); // Set internal list view change connections. QObject::connect(m_pListView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex&,const QModelIndex&)), SLOT(currentRowChangedSlot(const QModelIndex&,const QModelIndex&))); QObject::connect(m_pListView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)), SLOT(selectionChangedSlot(const QItemSelection&,const QItemSelection&))); // Set MIDI editor change connections. QObject::connect(pEditor, SIGNAL(selectNotifySignal(qtractorMidiEditor*)), SLOT(selectNotifySlot(qtractorMidiEditor*))); QObject::connect(pEditor, SIGNAL(changeNotifySignal(qtractorMidiEditor*)), SLOT(changeNotifySlot(qtractorMidiEditor*))); } qtractorMidiEditor *qtractorMidiEventList::editor (void) const { return m_pListView->editor(); } // Event list view refreshner. void qtractorMidiEventList::refresh (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiEventList[%p]::refresh()", this); #endif m_pListView->refresh(); selectNotifySlot(m_pListView->editor()); } // Context menu request event handler. void qtractorMidiEventList::contextMenuEvent ( QContextMenuEvent *pContextMenuEvent ) { qtractorMidiEditorForm *pMidiEditorForm = static_cast (QDockWidget::parentWidget()); if (pMidiEditorForm) pMidiEditorForm->editMenu()->exec(pContextMenuEvent->globalPos()); } // Current list view row changed slot. void qtractorMidiEventList::currentRowChangedSlot ( const QModelIndex& index, const QModelIndex& /*previous*/ ) { qtractorMidiEditor *pEditor = m_pListView->editor(); if (pEditor == NULL) return; if (m_iSelectUpdate > 0) return; ++m_iSelectUpdate; #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiEventList[%p]::currentRowChangedSlot()", this); #endif pEditor->setEditHead(m_pListView->frameFromIndex(index)); pEditor->selectionChangeNotify(); --m_iSelectUpdate; } // Current list view selection changed slot. void qtractorMidiEventList::selectionChangedSlot ( const QItemSelection& selected, const QItemSelection& deselected ) { qtractorMidiEditor *pEditor = m_pListView->editor(); if (pEditor == NULL) return; if (m_iSelectUpdate > 0) return; #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiEventList[%p]::selectionChangedSlot()", this); #endif ++m_iSelectUpdate; m_pListView->setUpdatesEnabled(false); QListIterator iter1(selected.indexes()); while (iter1.hasNext()) { const QModelIndex& index = iter1.next(); if (index.column() == 0) pEditor->selectEvent(m_pListView->eventOfIndex(index), true); } QListIterator iter2(deselected.indexes()); while (iter2.hasNext()) { const QModelIndex& index = iter2.next(); if (index.column() == 0) pEditor->selectEvent(m_pListView->eventOfIndex(index), false); } m_pListView->setUpdatesEnabled(true); pEditor->selectionChangeNotify(); --m_iSelectUpdate; } // MIDI editor selection changed slot. void qtractorMidiEventList::selectNotifySlot ( qtractorMidiEditor *pEditor ) { if (!isVisible()) return; if (m_iSelectUpdate > 0) return; #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiEventList[%p]::selectNotifySlot()", this); #endif ++m_iSelectUpdate; m_pListView->clearSelection(); const QList& list = pEditor->selectedEvents(); if (list.count() > 0) { m_pListView->setCurrentIndex( m_pListView->indexOfEvent(list.first())); QListIterator iter(list); while (iter.hasNext()) m_pListView->selectEvent(iter.next(), true); } --m_iSelectUpdate; } // MIDI editor selection changed slot. void qtractorMidiEventList::changeNotifySlot ( qtractorMidiEditor * ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMidiEventList[%p]::changeNotifySlot()", this); #endif refresh(); } // end of qtractorMidiEventList.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorSpinBox.h0000644000175000001440000000012312166134117020560 xustar000000000000000027 mtime=1373157455.942698 26 atime=1381134668.17408 30 ctime=1381134668.174080067 qtractor-0.5.11/src/qtractorSpinBox.h0000644000175000001440000001266612166134117020062 0ustar00rncbcusers00000000000000// qtractorSpinBox.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorSpinBox_h #define __qtractorSpinBox_h #include #include // Forward declartions. class QLineEdit; class QShowEvent; //---------------------------------------------------------------------------- // qtractorTimeSpinBox -- A time-scale formatted spin-box widget. class qtractorTimeSpinBox : public QAbstractSpinBox { Q_OBJECT public: // Constructor. qtractorTimeSpinBox(QWidget *pParent = 0); // Destructor. ~qtractorTimeSpinBox(); // Time-scale accessors. void setTimeScale(qtractorTimeScale *pTimeScale); qtractorTimeScale *timeScale() const; // Display-format accessors. void setDisplayFormat(qtractorTimeScale::DisplayFormat displayFormat); qtractorTimeScale::DisplayFormat displayFormat() const; void updateDisplayFormat(); // Nominal value (in frames) accessors. void setValue(unsigned long iValue, bool bNotifyChange = true); unsigned long value() const; // Minimum value (in frames) accessors. void setMinimum(unsigned long iMinimum); unsigned long minimum() const; // Maximum value (in frames) accessors. void setMaximum(unsigned long iMaximum); unsigned long maximum() const; // Differential value mode (BBT format only) accessor. void setDeltaValue(bool bDeltaValue, unsigned long iDeltaValue = 0); bool isDeltaValue() const; unsigned long deltaValue() const; // Editing stabilizer. unsigned long valueFromText() const; signals: // Common value change notification. void valueChanged(unsigned long); void valueChanged(const QString&); // Display format change notification. void displayFormatChanged(int); protected: // Mark that we got actual value. void showEvent(QShowEvent *); // Inherited/override methods. QValidator::State validate(QString& sText,int& iPos) const; void fixup(QString& sText) const; void stepBy(int iSteps); StepEnabled stepEnabled() const; // Value/text format converters. unsigned long valueFromText(const QString& sText) const; QString textFromValue(unsigned long iValue) const; // Local context menu handler. void contextMenuEvent(QContextMenuEvent *pContextMenuEvent); protected slots: // Pseudo-fixup slot. void editingFinishedSlot(); void valueChangedSlot(const QString&); private: // Instance variables. qtractorTimeScale *m_pTimeScale; qtractorTimeScale::DisplayFormat m_displayFormat; unsigned long m_iValue; unsigned long m_iMinimumValue; unsigned long m_iMaximumValue; unsigned long m_iDeltaValue; bool m_bDeltaValue; }; //---------------------------------------------------------------------------- // qtractorTempoSpinBox -- A tempo/time-signature formatted spin-box widget. class qtractorTempoSpinBox : public QAbstractSpinBox { Q_OBJECT public: // Constructor. qtractorTempoSpinBox(QWidget *pParent = 0); // Destructor. ~qtractorTempoSpinBox(); // Nominal tempo value (BPM) accessors. void setTempo(float fTempo, bool bNotifyChange = true); float tempo() const; // Nominal time-signature numerator (beats/bar) accessors. void setBeatsPerBar(unsigned short iBeatsPerBar, bool bNotifyChange = true); unsigned short beatsPerBar() const; // Nominal time-signature denominator (beat-divisor) accessors. void setBeatDivisor(unsigned short iBeatDivisor, bool bNotifyChange = true); unsigned short beatDivisor() const; signals: // Common value change notification. void valueChanged(float, unsigned short, unsigned short); void valueChanged(const QString&); protected: // Mark that we got actual value. void showEvent(QShowEvent *); // Inherited/override methods. QValidator::State validate(QString& sText,int& iPos) const; void fixup(QString& sText) const; void stepBy(int iSteps); StepEnabled stepEnabled() const; // Value/text format converters. float tempoFromText(const QString& sText) const; unsigned short beatsPerBarFromText(const QString& sText) const; unsigned short beatDivisorFromText(const QString& sText) const; QString textFromValue(float fTempo, unsigned short iBeatsPerBar, unsigned short iBeatDivisor) const; // Common value/text setlers. bool updateValue(float fTempo, unsigned short iBeatsPerBar, unsigned short iBeatDivisor, bool bNotifyChange); void updateText(); protected slots: // Pseudo-fixup slot. void valueChangedSlot(const QString&); void editingFinishedSlot(); private: // Instance variables. float m_fTempo; unsigned short m_iBeatsPerBar; unsigned short m_iBeatDivisor; int m_iValueChanged; }; #endif // __qtractorSpinBox_h // end of qtractorSpinBox.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioMadFile.cpp0000644000175000001440000000012211563576072022025 xustar000000000000000027 mtime=1305410618.253123 26 atime=1381134670.83708 29 ctime=1381134670.83708011 qtractor-0.5.11/src/qtractorAudioMadFile.cpp0000644000175000001440000003223211563576072021317 0ustar00rncbcusers00000000000000// qtractorAudioMadFile.cpp // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorAudioMadFile.h" #include //---------------------------------------------------------------------- // class qtractorAudioMadFile -- Buffered audio file implementation. // // Constructor. qtractorAudioMadFile::qtractorAudioMadFile ( unsigned int iBufferSize ) { // Initialize state variables. m_iMode = qtractorAudioMadFile::None; m_pFile = NULL; m_iBitRate = 0; m_iChannels = 0; m_iSampleRate = 0; m_iFramesEst = 0; m_bEndOfStream = false; // Input buffer stuff. m_iInputBufferSize = iBufferSize; m_pInputBuffer = NULL; // Output ring-buffer stuff. m_iRingBufferSize = 0; m_iRingBufferMask = 0; m_iRingBufferRead = 0; m_iRingBufferWrite = 0; m_ppRingBuffer = NULL; // Frame mapping for sample-accurate seeking. m_iSeekOffset = 0; } // Destructor. qtractorAudioMadFile::~qtractorAudioMadFile (void) { close(); } // Open method. bool qtractorAudioMadFile::open ( const QString& sFilename, int iMode ) { #ifdef DEBUG_0 qDebug("qtractorAudioMadFile::open(\"%s\", %d)", sFilename.toUtf8().constData(), iMode); #endif close(); // Whether for Read or Write... sorry only read is allowed. if (iMode != qtractorAudioMadFile::Read) return false; QByteArray aFilename = sFilename.toUtf8(); m_pFile = ::fopen(aFilename.constData(), "rb"); if (m_pFile == NULL) return false; // Create the decoded frame list. m_pFrameList = createFrameList(sFilename); if (m_pFrameList == NULL) { close(); return false; } #ifdef CONFIG_LIBMAD mad_stream_init(&m_madStream); mad_frame_init(&m_madFrame); mad_synth_init(&m_madSynth); #endif // CONFIG_LIBMAD int fdFile = fileno(m_pFile); struct stat st; if (::fstat(fdFile, &st) < 0 || st.st_size == 0) { close(); return false; } // Read the very first bunch of raw-data... if (!input()) { close(); return false; } #ifdef CONFIG_LIBMAD if (mad_header_decode(&m_madFrame.header, &m_madStream) < 0) { if (m_madStream.error == MAD_ERROR_BUFLEN) { close(); return false; } if (!MAD_RECOVERABLE(m_madStream.error)) { close(); return false; } } #endif // CONFIG_LIBMAD // Do the very first frame decoding... m_bEndOfStream = !decode(); // Get a rough estimate of the total decoded length of the file... if (m_iBitRate > 0) { m_iFramesEst = (unsigned long) ((float) m_iSampleRate * st.st_size * 8.0f / (float) m_iBitRate); } #ifdef DEBUG_0 qDebug("qtractorAudioMadFile::open(\"%s\", %d) bit_rate=%u farmes_est=%lu", sFilename.toUtf8().constData(), iMode, m_iBitRate, m_iFramesEst); #endif // Set open mode (deterministically). m_iMode = iMode; return true; } // Local input method. bool qtractorAudioMadFile::input (void) { #ifdef DEBUG_0 qDebug("qtractorAudioMadFile::input()"); #endif #ifdef CONFIG_LIBMAD // Can't go on if EOF. if (feof(m_pFile)) return false; // Allocate input buffer if not already. if (m_pInputBuffer == NULL) { unsigned int iBufferSize = (4096 << 1); while (iBufferSize < m_iInputBufferSize) iBufferSize <<= 1; m_iInputBufferSize = iBufferSize; m_pInputBuffer = new unsigned char [iBufferSize + MAD_BUFFER_GUARD]; m_curr.iInputOffset = 0; } unsigned long iRemaining; unsigned char *pReadStart; unsigned long iReadSize; if (m_madStream.next_frame) { iRemaining = m_madStream.bufend - m_madStream.next_frame; ::memmove(m_pInputBuffer, m_madStream.next_frame, iRemaining); pReadStart = m_pInputBuffer + iRemaining; iReadSize = m_iInputBufferSize - iRemaining; } else { iRemaining = 0; pReadStart = m_pInputBuffer; iReadSize = m_iInputBufferSize; } long iRead = ::fread(pReadStart, 1, iReadSize, m_pFile); if (iRead > 0) { // Update the input offset, as for next time... m_curr.iInputOffset += iRead; // Time to add some frame mapping, on each 3rd iteration... if ((++m_curr.iDecodeCount % 3) == 0 && (m_pFrameList->count() < 1 || m_pFrameList->last().iOutputOffset < m_curr.iOutputOffset)) { unsigned long iInputOffset = m_curr.iInputOffset - iRemaining; m_pFrameList->append(FrameNode(iInputOffset, m_curr.iOutputOffset, m_curr.iDecodeCount)); } // Add some decode buffer guard... if (iRead < (int) iReadSize) { ::memset(pReadStart + iRead, 0, MAD_BUFFER_GUARD); iRead += MAD_BUFFER_GUARD; } mad_stream_buffer(&m_madStream, m_pInputBuffer, iRead + iRemaining); } return (iRead > 0); #else // CONFIG_LIBMAD return false; #endif } // Local decode method. bool qtractorAudioMadFile::decode (void) { #ifdef DEBUG_0 qDebug("qtractorAudioMadFile::decode()"); #endif #ifdef CONFIG_LIBMAD bool bError = (mad_frame_decode(&m_madFrame, &m_madStream) < 0); while (bError && (m_madStream.error == MAD_ERROR_BUFLEN || MAD_RECOVERABLE(m_madStream.error))) { if (!input()) return false; bError = (mad_frame_decode(&m_madFrame, &m_madStream) < 0); } #ifdef DEBUG_0 if (bError) { qDebug("qtractorAudioMadFile::decode()" " ERROR[%lu]: madStream.error=%d (0x%04x)", m_curr.iOutputOffset, m_madStream.error, m_madStream.error); } #endif if (bError) return MAD_RECOVERABLE(m_madStream.error); mad_synth_frame(&m_madSynth, &m_madFrame); unsigned int iFrames = m_madSynth.pcm.length; if (m_ppRingBuffer == NULL) { // Set initial stream parameters. m_iBitRate = m_madFrame.header.bitrate; m_iChannels = m_madSynth.pcm.channels; m_iSampleRate = m_madSynth.pcm.samplerate; // Create/allocate internal output ring-buffer. m_iRingBufferSize = (4096 << 1); while (m_iRingBufferSize < m_iInputBufferSize) m_iRingBufferSize <<= 1; m_iRingBufferMask = (m_iRingBufferSize - 1); // Allocate actual buffer stuff... m_ppRingBuffer = new float* [m_iChannels]; for (unsigned short i = 0; i < m_iChannels; ++i) m_ppRingBuffer[i] = new float [m_iRingBufferSize]; // Reset ring-buffer pointers. m_iRingBufferRead = 0; m_iRingBufferWrite = 0; // Decoder mapping initialization. m_curr.iInputOffset = 0; m_curr.iOutputOffset = 0; m_curr.iDecodeCount = 0; } const float fScale = (float) (1L << MAD_F_FRACBITS); for (unsigned int n = 0; n < iFrames; ++n) { if (m_curr.iOutputOffset >= m_iSeekOffset) { for (unsigned short i = 0; i < m_iChannels; ++i) { int iSample = bError ? 0 : *(m_madSynth.pcm.samples[i] + n); m_ppRingBuffer[i][m_iRingBufferWrite] = (float) iSample / fScale; } ++m_iRingBufferWrite &= m_iRingBufferMask; } #ifdef DEBUG_0 else if (n == 0) { qDebug("qtractorAudioMadFile::decode(%lu) i=%lu o=%lu c=%u", m_iSeekOffset, m_curr.iInputOffset, m_curr.iOutputOffset, m_curr.iDecodeCount); } #endif ++m_curr.iOutputOffset; } return true; #else // CONFIG_LIBMAD return false; #endif } // Read method. int qtractorAudioMadFile::read ( float **ppFrames, unsigned int iFrames ) { #ifdef DEBUG_0 qDebug("qtractorAudioMadFile::read(%p, %d)", ppFrames, iFrames); #endif unsigned int nread = 0; if (m_ppRingBuffer) { if (iFrames > (m_iRingBufferSize >> 1)) iFrames = (m_iRingBufferSize >> 1); while ((nread = readable()) < iFrames && !m_bEndOfStream) m_bEndOfStream = !decode(); if (nread > iFrames) nread = iFrames; // Move the data around... unsigned int r = m_iRingBufferRead; unsigned int n1, n2; if (r + nread > m_iRingBufferSize) { n1 = (m_iRingBufferSize - r); n2 = (r + nread) & m_iRingBufferMask; } else { n1 = nread; n2 = 0; } for (unsigned short i = 0; i < m_iChannels; ++i) { ::memcpy(ppFrames[i], (float *)(m_ppRingBuffer[i] + r), n1 * sizeof(float)); if (n2 > 0) { ::memcpy((float *)(ppFrames[i] + n1), m_ppRingBuffer[i], n2 * sizeof(float)); } } m_iRingBufferRead = (r + nread) & m_iRingBufferMask; m_iSeekOffset += nread; } return nread; } // Write method. int qtractorAudioMadFile::write ( float **/*ppFrames*/, unsigned int /*iFrames*/ ) { return 0; } // Seek method. bool qtractorAudioMadFile::seek ( unsigned long iOffset ) { #ifdef DEBUG_0 qDebug("qtractorAudioMadFile::seek(%lu)", iOffset); #endif // Avoid unprecise seeks... if (iOffset == m_iSeekOffset) return true; // This is the target situation... m_iSeekOffset = iOffset; // Are qe seeking backward or forward // from last known decoded position? if (m_pFrameList->count() > 0 && m_pFrameList->last().iOutputOffset > iOffset) { // Assume the worst case (seek to very beggining...) m_curr.iInputOffset = 0; m_curr.iOutputOffset = 0; m_curr.iDecodeCount = 0; // Find the previous mapped 3rd frame that fits location... QListIterator iter(*m_pFrameList); iter.toBack(); while (iter.hasPrevious()) { if (iter.previous().iOutputOffset < iOffset) { if (iter.hasPrevious()) m_curr = iter.previous(); break; } } #ifdef DEBUG_0 qDebug("qtractorAudioMadFile::seek(%lu) i=%lu o=%lu c=%u", iOffset, m_curr.iInputOffset, m_curr.iOutputOffset, m_curr.iDecodeCount); #endif // Rewind file position... if (::fseek(m_pFile, m_curr.iInputOffset, SEEK_SET)) return false; #ifdef CONFIG_LIBMAD // Release MAD structs... mad_synth_finish(&m_madSynth); mad_frame_finish(&m_madFrame); mad_stream_finish(&m_madStream); // Reset MAD structs... mad_stream_init(&m_madStream); mad_frame_init(&m_madFrame); mad_synth_init(&m_madSynth); #endif // CONFIG_LIBMAD // Reread first seeked input bunch... if (!input()) return false; } // Reset ring-buffer pointers. m_iRingBufferRead = 0; m_iRingBufferWrite = 0; m_bEndOfStream = false; // Now loop until we find the target offset... while (m_curr.iOutputOffset < m_iSeekOffset && !m_bEndOfStream) m_bEndOfStream = !decode(); return !m_bEndOfStream; } // Close method. void qtractorAudioMadFile::close (void) { #ifdef DEBUG_0 qDebug("qtractorAudioMadFile::close()"); #endif // Free allocated buffers, if any. if (m_ppRingBuffer) { for (unsigned short i = 0; i < m_iChannels; ++i) delete [] m_ppRingBuffer[i]; delete [] m_ppRingBuffer; m_ppRingBuffer = NULL; } if (m_pInputBuffer) { delete [] m_pInputBuffer; m_pInputBuffer = NULL; } if (m_pFile) { #ifdef CONFIG_LIBMAD mad_synth_finish(&m_madSynth); mad_frame_finish(&m_madFrame); mad_stream_finish(&m_madStream); #endif // CONFIG_LIBMAD ::fclose(m_pFile); m_pFile = NULL; } // Frame lists are never destroyed here // (they're cached for whole life-time of the program). m_pFrameList = NULL; // Reset all other state relevant variables. m_bEndOfStream = false; m_iFramesEst = 0; m_iSampleRate = 0; m_iChannels = 0; m_iBitRate = 0; m_iMode = qtractorAudioMadFile::None; } // Open mode accessor. int qtractorAudioMadFile::mode (void) const { return m_iMode; } // Open channel(s) accessor. unsigned short qtractorAudioMadFile::channels (void) const { return m_iChannels; } // Estimated number of frames specialty (aprox. 8secs). unsigned long qtractorAudioMadFile::frames (void) const { return m_iFramesEst; } // Sample rate specialty. unsigned int qtractorAudioMadFile::sampleRate (void) const { return m_iSampleRate; } // Internal ring-buffer helper methods. unsigned int qtractorAudioMadFile::readable (void) const { unsigned int w = m_iRingBufferWrite; unsigned int r = m_iRingBufferRead; if (w > r) { return (w - r); } else { return (w - r + m_iRingBufferSize) & m_iRingBufferMask; } } unsigned int qtractorAudioMadFile::writable (void) const { unsigned int w = m_iRingBufferWrite; unsigned int r = m_iRingBufferRead; if (w > r){ return ((r - w + m_iRingBufferSize) & m_iRingBufferMask) - 1; } else if (r > w) { return (r - w) - 1; } else { return m_iRingBufferSize - 1; } } // Frame list factory method. qtractorAudioMadFile::FrameList *qtractorAudioMadFile::createFrameList ( const QString& sFilename ) { // Frame list hash repository // (declared here for proper cleanup). class FrameListFactory : public QHash { public: // Destructor. ~FrameListFactory() { QMutableHashIterator iter(*this); while (iter.hasNext()) { FrameList *pFrameList = iter.next().value(); iter.remove(); delete pFrameList; } } }; // Do the factory thing here... static FrameListFactory s_lists; FrameList *pFrameList = s_lists.value(sFilename, NULL); if (pFrameList == NULL) { pFrameList = new FrameList(); s_lists.insert(sFilename, pFrameList); } return pFrameList; } // end of qtractorAudioMadFile.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiSysex.h0000644000175000001440000000012212067456742021126 xustar000000000000000026 mtime=1356750306.99751 26 atime=1381134666.91608 30 ctime=1381134666.916080047 qtractor-0.5.11/src/qtractorMidiSysex.h0000644000175000001440000000663212067456742020425 0ustar00rncbcusers00000000000000// qtractorMidiSysex.h // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiSysex_h #define __qtractorMidiSysex_h #include #include #include //---------------------------------------------------------------------- // class qtractorMidiSysex -- MIDI SysEx data bank item. // class qtractorMidiSysex { public: // Constructors qtractorMidiSysex(const QString& sName, unsigned char *pSysex, unsigned short iSysex) : m_sName(sName), m_pSysex(NULL), m_iSysex(0) { setData(pSysex, iSysex); } qtractorMidiSysex(const QString& sName, const QString& sText) : m_sName(sName), m_pSysex(NULL), m_iSysex(0) { setText(sText); } // Copy consructor. qtractorMidiSysex(const qtractorMidiSysex& sysex) : m_sName(sysex.name()), m_pSysex(NULL), m_iSysex(0) { setData(sysex.data(), sysex.size()); } // Destructors; ~qtractorMidiSysex() { clear(); } // Name key accessors. void setName(const QString& sName) { m_sName = sName; } const QString& name() const { return m_sName; } // Binary data accessors. void setData(unsigned char *pSysex, unsigned short iSysex) { if (pSysex && iSysex > 0 && pSysex[0] == 0xf0 && pSysex[iSysex - 1] == 0xf7) { if (m_pSysex) delete [] m_pSysex; m_iSysex = iSysex; m_pSysex = new unsigned char [iSysex]; ::memcpy(m_pSysex, pSysex, iSysex); } } unsigned char *data() const { return m_pSysex; } unsigned short size() const { return m_iSysex; } // Text(hex) data accessors. void setText(const QString& sText) { const QByteArray& data = QByteArray::fromHex(sText.toLatin1()); setData((unsigned char *) data.data(), data.size()); } QString text() const { QString sText; char hex[4]; for (unsigned short i = 0; i < m_iSysex; ++i) { ::snprintf(hex, sizeof(hex), "%02x", m_pSysex[i]); sText += hex; if (i < m_iSysex - 1) sText += ' '; } return sText; } // Cleanup. void clear() { m_sName.clear(); if (m_pSysex) { delete [] m_pSysex; m_pSysex = NULL; m_iSysex = 0; } } private: // Instance variables. QString m_sName; unsigned char *m_pSysex; unsigned short m_iSysex; }; //---------------------------------------------------------------------- // class qtractorMidiSysexList -- MIDI SysEx data bank list. // class qtractorMidiSysexList : public QList { public: // Destructor. ~qtractorMidiSysexList() { clear(); } // Destroyer. void clear() { qDeleteAll(*this); QList::clear(); } }; #endif // __qtractorMidiSysex_h // end of qtractorMidiSysex.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiListView.h0000644000175000001440000000012312166526620021553 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134670.36608 30 ctime=1381134670.366080102 qtractor-0.5.11/src/qtractorMidiListView.h0000644000175000001440000000526712166526620021054 0ustar00rncbcusers00000000000000// qtractorMidiListView.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiListView_h #define __qtractorMidiListView_h #include "qtractorFileListView.h" // Forward declarations. class qtractorMidiFile; class qtractorMidiListView; //---------------------------------------------------------------------- // class qtractorMidiFileItem -- MIDI file list view item. // class qtractorMidiFileItem : public qtractorFileListItem { public: // Constructor. qtractorMidiFileItem(const QString& sPath, qtractorMidiFile *pFile); protected: // Virtual tooltip renderer. QString toolTip() const; }; //---------------------------------------------------------------------- // class qtractorMidiChannelItem -- MIDI channel list view item. // class qtractorMidiChannelItem : public qtractorFileChannelItem { public: // Constructors. qtractorMidiChannelItem(qtractorMidiFileItem *pFileItem, const QString& sName, unsigned short iChannel); protected: // Virtual tooltip renderer. QString toolTip() const; }; //---------------------------------------------------------------------------- // qtractorMidiListView -- Group/File list view, supporting drag-n-drop. // class qtractorMidiListView : public qtractorFileListView { Q_OBJECT public: // Constructor. qtractorMidiListView(QWidget *pParent = 0); // QListView::addColumn() ids. enum ItemColumn { Name = 0, Format = 1, Tracks = 2, Resolution = 3, Path = 4, LastColumn = 5 }; protected: // Which column is the complete file path? int pathColumn() const { return Path; } // File item factory method. qtractorFileListItem *createFileItem(const QString& sPath); // Prompt for proper file list open. QStringList getOpenFileNames(); }; #endif // __qtractorMidiListView_h // end of qtractorMidiListView.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorTimeStretcher.h0000644000175000001440000000012311504241462021755 xustar000000000000000027 mtime=1292976946.250514 26 atime=1381134666.91608 30 ctime=1381134666.916080047 qtractor-0.5.11/src/qtractorTimeStretcher.h0000644000175000001440000000531211504241462021245 0ustar00rncbcusers00000000000000// qtractorTimeStretcher.h // /**************************************************************************** Copyright (C) 2005-2010, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorTimeStretcher_h #define __qtractorTimeStretcher_h #include "qtractorAbout.h" #include "qtractorTimeStretch.h" #ifdef CONFIG_LIBRUBBERBAND #include #endif //--------------------------------------------------------------------------- // qtractorTimeStretcher - Time/Pitch-stretcher processor interface. // class qtractorTimeStretcher { public: // Constructor flags. enum Flags { None = 0, WsolaTimeStretch = 1, WsolaQuickSeek = 2 }; // Constructor. qtractorTimeStretcher( unsigned short iChannels = 2, unsigned int iSampleRate = 44100, float fTimeStretch = 1.0f, float fPitchShift = 1.0f, unsigned int iFlags = None, unsigned int iBufferSize = 4096); // Destructor. ~qtractorTimeStretcher(); // Adds frames of samples into the input buffer. void process(float **ppFrames, unsigned int iFrames); // Copies requested frames output buffer and removes them // from the sample buffer. If there are less than available() // samples in the buffer, returns all that available. duh? unsigned int retrieve(float **ppFrames, unsigned int iFrames); // Returns number of frames currently available. unsigned int available() const; // Flush any last samples that are hiding // in the internal processing pipeline. void flush(); // Clears all buffers. void reset(); private: // Instance variables. qtractorTimeStretch *m_pTimeStretch; #ifdef CONFIG_LIBRUBBERBAND RubberBand::RubberBandStretcher *m_pRubberBandStretcher; unsigned short m_iRubberBandChannels; unsigned int m_iRubberBandLatency; unsigned int m_iRubberBandFrames; float **m_ppRubberBandFrames; float **m_ppRubberBandBuffer; bool m_bRubberBandFlush; #endif }; #endif // __qtractorTimeStretcher_h // end of qtractorTimeStretcher.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorTimeScaleForm.h0000644000175000001440000000012312166134117021670 xustar000000000000000027 mtime=1373157455.942698 26 atime=1381134666.35808 30 ctime=1381134666.358080039 qtractor-0.5.11/src/qtractorTimeScaleForm.h0000644000175000001440000000527612166134117021171 0ustar00rncbcusers00000000000000// qtractorTimeScaleForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorTimeScaleForm_h #define __qtractorTimeScaleForm_h #include "ui_qtractorTimeScaleForm.h" // Forward declarations... class qtractorTimeScaleListItem; class QTime; //---------------------------------------------------------------------------- // qtractorTimeScaleForm -- UI wrapper form. class qtractorTimeScaleForm : public QDialog { Q_OBJECT public: // Constructor. qtractorTimeScaleForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); void setTimeScale(qtractorTimeScale *pTimeScale); qtractorTimeScale *timeScale() const; void setFrame(unsigned long iFrame); unsigned long frame() const; unsigned short bar() const; bool isDirty(); protected slots: void reject(); void refresh(); void selectItem(); void addItem(); void updateItem(); void removeItem(); void refreshItems(); void barChanged(int); void timeChanged(unsigned long); void tempoChanged(); void changed(); void tempoTap(); void markerColor(); void contextMenu(const QPoint&); void stabilizeForm(); protected: enum { AddNode = (1 << 0), UpdateNode = (1 << 1), RemoveNode = (1 << 2), AddMarker = (1 << 3), UpdateMarker = (1 << 4), RemoveMarker = (1 << 5) }; unsigned int flags() const; void setCurrentItem(qtractorTimeScale::Node *pNode, unsigned long iFrame); void setCurrentMarker(qtractorTimeScale::Marker *pMarker); void ensureVisibleFrame(unsigned long iFrame); private: // The Qt-designer UI struct... Ui::qtractorTimeScaleForm m_ui; // Instance variables... qtractorTimeScale *m_pTimeScale; QTime *m_pTempoTap; int m_iTempoTap; float m_fTempoTap; int m_iDirtySetup; int m_iDirtyCount; int m_iDirtyTotal; }; #endif // __qtractorTimeScaleForm_h // end of qtractorTimeScaleForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorCurveCommand.h0000644000175000001440000000012312077350414021562 xustar000000000000000027 mtime=1358811404.341432 26 atime=1381134668.01508 30 ctime=1381134668.015080065 qtractor-0.5.11/src/qtractorCurveCommand.h0000644000175000001440000002067212077350414021060 0ustar00rncbcusers00000000000000// qtractorCurveCommand.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorCurveCommand_h #define __qtractorCurveCommand_h #include "qtractorCommand.h" #include "qtractorCurve.h" //---------------------------------------------------------------------- // class qtractorCurveBaseCommand - declaration. // class qtractorCurveBaseCommand : public qtractorCommand { public: // Constructor. qtractorCurveBaseCommand(const QString& sName); // Virtual command methods. bool redo(); bool undo(); protected: // Common executive method. virtual bool execute(bool bRedo); }; //---------------------------------------------------------------------- // class qtractorCurveCommand - declaration. // class qtractorCurveCommand : public qtractorCurveBaseCommand { public: // Constructor. qtractorCurveCommand(const QString& sName, qtractorCurve *pCurve); // Accessor. qtractorCurve *curve() const { return m_pCurve; } protected: // Instance variables. qtractorCurve *m_pCurve; }; //---------------------------------------------------------------------- // class qtractorCurveListCommand - declaration. // class qtractorCurveListCommand : public qtractorCurveBaseCommand { public: // Constructor. qtractorCurveListCommand(const QString& sName, qtractorCurveList *pCurveList); protected: // Instance variables. qtractorCurveList *m_pCurveList; }; //---------------------------------------------------------------------- // class qtractorCurveSelectCommand - declaration. // class qtractorCurveSelectCommand : public qtractorCurveListCommand { public: // Constructor. qtractorCurveSelectCommand( qtractorCurveList *pCurveList, qtractorCurve *pCurrentCurve); protected: // Virtual executive method. bool execute(bool bRedo); private: // Instance variables. qtractorCurve *m_pCurrentCurve; }; //---------------------------------------------------------------------- // class qtractorCurveModeCommand - declaration. // class qtractorCurveModeCommand : public qtractorCurveCommand { public: // Constructor. qtractorCurveModeCommand( qtractorCurve *pCurve, qtractorCurve::Mode mode); protected: // Virtual executive method. bool execute(bool bRedo); private: // Instance variables. qtractorCurve::Mode m_mode; }; //---------------------------------------------------------------------- // class qtractorCurveProcessCommand - declaration. // class qtractorCurveProcessCommand : public qtractorCurveCommand { public: // Constructor. qtractorCurveProcessCommand( qtractorCurve *pCurve, bool bProcess); protected: // Virtual executive method. bool execute(bool bRedo); private: // Instance variables. bool m_bProcess; }; //---------------------------------------------------------------------- // class qtractorCurveCaptureCommand - declaration. // class qtractorCurveCaptureCommand : public qtractorCurveCommand { public: // Constructor. qtractorCurveCaptureCommand( qtractorCurve *pCurve, bool bCapture); protected: // Virtual executive method. bool execute(bool bRedo); private: // Instance variables. bool m_bCapture; }; //---------------------------------------------------------------------- // class qtractorCurveLogarithmicCommand - declaration. // class qtractorCurveLogarithmicCommand : public qtractorCurveCommand { public: // Constructor. qtractorCurveLogarithmicCommand( qtractorCurve *pCurve, bool bLogarithmic); protected: // Virtual executive method. bool execute(bool bRedo); private: // Instance variables. bool m_bLogarithmic; }; //---------------------------------------------------------------------- // class qtractorCurveColorCommand - declaration. // class qtractorCurveColorCommand : public qtractorCurveCommand { public: // Constructor. qtractorCurveColorCommand( qtractorCurve *pCurve, const QColor& color); protected: // Virtual executive method. bool execute(bool bRedo); private: // Instance variables. QColor m_color; }; //---------------------------------------------------------------------- // class qtractorCurveProcessAllCommand - declaration. // class qtractorCurveProcessAllCommand : public qtractorCurveListCommand { public: // Constructor. qtractorCurveProcessAllCommand( qtractorCurveList *pCurveList, bool bProcessAll); protected: // Virtual executive method. bool execute(bool bRedo); private: // Instance variables. bool m_bProcessAll; }; //---------------------------------------------------------------------- // class qtractorCurveCaptureCommand - declaration. // class qtractorCurveCaptureAllCommand : public qtractorCurveListCommand { public: // Constructor. qtractorCurveCaptureAllCommand( qtractorCurveList *pCurveList, bool bCaptureAll); protected: // Virtual executive method. bool execute(bool bRedo); private: // Instance variables. bool m_bCaptureAll; }; //---------------------------------------------------------------------- // class qtractorCurveEditCommand - declaration. // class qtractorCurveEditCommand : public qtractorCurveCommand { public: // Constructor. qtractorCurveEditCommand( const QString& sName, qtractorCurve *pCurve); qtractorCurveEditCommand(qtractorCurve *pCurve); // Destructor. virtual ~qtractorCurveEditCommand(); // Primitive command methods. void addNode(qtractorCurve::Node *pNode); void moveNode(qtractorCurve::Node *pNode, unsigned long iFrame); void removeNode(qtractorCurve::Node *pNode); void addEditList(qtractorCurveEditList *pEditList); // Composite predicate. bool isEmpty() const; protected: // Virtual executive method. bool execute(bool bRedo); private: // Instance variables. qtractorCurveEditList m_edits; }; //---------------------------------------------------------------------- // class qtractorCurveClearCommand - declaration. // class qtractorCurveClearCommand : public qtractorCurveEditCommand { public: // Constructor. qtractorCurveClearCommand(qtractorCurve *pCurve); }; //---------------------------------------------------------------------- // class qtractorCurveClearAllCommand - declaration. // class qtractorCurveClearAllCommand : public qtractorCurveListCommand { public: // Constructor. qtractorCurveClearAllCommand(qtractorCurveList *pCurveList); // Destructor. ~qtractorCurveClearAllCommand(); // Composite predicate. bool isEmpty() const; protected: // Virtual executive method. bool execute(bool bRedo); private: // Instance variables. QList m_commands; }; //---------------------------------------------------------------------- // class qtractorCurveEditListCommand - declaration. // class qtractorCurveEditListCommand : public qtractorCurveListCommand { public: // Constructor. qtractorCurveEditListCommand(qtractorCurveList *pCurveList); // Destructor. ~qtractorCurveEditListCommand(); // Composite predicate. bool isEmpty() const; protected: // Virtual executive method. bool execute(bool bRedo); private: // Instance variables. QList m_curveEditCommands; }; //---------------------------------------------------------------------- // class qtractorCurveCaptureListCommand - declaration. // class qtractorCurveCaptureListCommand : public qtractorCommand { public: // Constructor. qtractorCurveCaptureListCommand(); // Destructor. ~qtractorCurveCaptureListCommand(); // Curve list adder. void addCurveList(qtractorCurveList *pCurveList); // Composite predicate. bool isEmpty() const; // Virtual command methods. bool redo(); bool undo(); private: // Instance variables. QList m_commands; }; #endif // __qtractorCurveCommand_h // end of qtractorCurveCommand.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorPluginCommand.cpp0000644000175000001440000000012311713063454022270 xustar000000000000000027 mtime=1328310060.341966 26 atime=1381134670.67108 30 ctime=1381134670.671080107 qtractor-0.5.11/src/qtractorPluginCommand.cpp0000644000175000001440000003674211713063454021573 0ustar00rncbcusers00000000000000// qtractorPluginCommand.cpp // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorPluginCommand.h" #include "qtractorPluginForm.h" #include "qtractorPluginListView.h" #include "qtractorInsertPlugin.h" #include "qtractorSession.h" #include "qtractorMidiBuffer.h" //---------------------------------------------------------------------- // class qtractorPluginCommand - implementation // // Constructor. qtractorPluginCommand::qtractorPluginCommand ( const QString& sName, qtractorPlugin *pPlugin ) : qtractorCommand(sName) { if (pPlugin) m_plugins.append(pPlugin); setRefresh(false); } // Destructor. qtractorPluginCommand::~qtractorPluginCommand (void) { if (isAutoDelete()) qDeleteAll(m_plugins); m_plugins.clear(); } // Add new plugin(s) command methods. bool qtractorPluginCommand::addPlugins (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // pSession->lock(); // Add all listed plugins, in order... QListIterator iter(m_plugins); while (iter.hasNext()) { qtractorPlugin *pPlugin = iter.next(); qtractorPluginList *pPluginList = pPlugin->list(); if (pPluginList) pPluginList->addPlugin(pPlugin); } // Avoid the disposal of the plugin reference(s). setAutoDelete(false); // pSession->unlock(); return true; } // Remove existing plugin(s) command methods. bool qtractorPluginCommand::removePlugins (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // pSession->lock(); // Unlink all listed plugins, in order... QListIterator iter(m_plugins); iter.toBack(); while (iter.hasPrevious()) { qtractorPlugin *pPlugin = iter.previous(); qtractorPluginList *pPluginList = pPlugin->list(); if (pPluginList) pPluginList->removePlugin(pPlugin); } // Allow the disposal of the plugin reference(s). setAutoDelete(true); // pSession->unlock(); return true; } //---------------------------------------------------------------------- // class qtractorAddPluginCommand - implementation // // Constructor. qtractorAddPluginCommand::qtractorAddPluginCommand ( qtractorPlugin *pPlugin ) : qtractorPluginCommand(QObject::tr("add plugin"), pPlugin) { } // Plugin insertion command methods. bool qtractorAddPluginCommand::redo (void) { return addPlugins(); } bool qtractorAddPluginCommand::undo (void) { return removePlugins(); } //---------------------------------------------------------------------- // class qtractorAddInsertPluginCommand - implementation // // Constructor. qtractorAddInsertPluginCommand::qtractorAddInsertPluginCommand ( qtractorPlugin *pPlugin ) : qtractorPluginCommand( QObject::tr("add insert"), pPlugin) { } // Plugin insertion command methods. bool qtractorAddInsertPluginCommand::redo (void) { return addPlugins(); } bool qtractorAddInsertPluginCommand::undo (void) { return removePlugins(); } //---------------------------------------------------------------------- // class qtractorAddAuxSendPluginCommand - implementation // // Constructor. qtractorAddAuxSendPluginCommand::qtractorAddAuxSendPluginCommand ( qtractorPlugin *pPlugin ) : qtractorPluginCommand( QObject::tr("add aux-send"), pPlugin) { } // Plugin insertion command methods. bool qtractorAddAuxSendPluginCommand::redo (void) { return addPlugins(); } bool qtractorAddAuxSendPluginCommand::undo (void) { return removePlugins(); } //---------------------------------------------------------------------- // class qtractorAuxSendPluginCommand - implementation // // Constructor. qtractorAuxSendPluginCommand::qtractorAuxSendPluginCommand ( qtractorAuxSendPlugin *pAuxSendPlugin, const QString& sAudioBusName ) : qtractorPluginCommand(QObject::tr("aux-send bus"), pAuxSendPlugin), m_sAudioBusName(sAudioBusName) { } // Plugin insertion command methods. bool qtractorAuxSendPluginCommand::redo (void) { qtractorAuxSendPlugin *pAuxSendPlugin = static_cast (plugins().first()); if (pAuxSendPlugin == NULL) return false; QString sAudioBusName = pAuxSendPlugin->audioBusName(); pAuxSendPlugin->setAudioBusName(m_sAudioBusName); m_sAudioBusName = sAudioBusName; (pAuxSendPlugin->form())->updateAudioBusName(); return true; } bool qtractorAuxSendPluginCommand::undo (void) { return redo(); } //---------------------------------------------------------------------- // class qtractorRemovePluginCommand - implementation // // Constructor. qtractorRemovePluginCommand::qtractorRemovePluginCommand ( qtractorPlugin *pPlugin ) : qtractorPluginCommand(QObject::tr("remove plugin"), pPlugin) { } // Plugin-removal command methods. bool qtractorRemovePluginCommand::redo (void) { return removePlugins(); } bool qtractorRemovePluginCommand::undo (void) { return addPlugins(); } //---------------------------------------------------------------------- // class qtractorInsertPluginCommand - implementation // // Constructor. qtractorInsertPluginCommand::qtractorInsertPluginCommand ( const QString& sName, qtractorPlugin *pPlugin, qtractorPlugin *pNextPlugin ) : qtractorPluginCommand(sName, pPlugin) { m_pNextPlugin = pNextPlugin; } // Plugin-insert command methods. bool qtractorInsertPluginCommand::redo (void) { qtractorPlugin *pPlugin = plugins().first(); if (pPlugin == NULL) return false; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // Save the previous track alright... qtractorPluginList *pPluginList = pPlugin->list(); if (pPluginList == NULL) return false; // pSession->lock(); qtractorPlugin *pNextPlugin = pPlugin->next(); // Insert it... pPluginList->insertPlugin(pPlugin, m_pNextPlugin); // Swap it nice, finally. m_pNextPlugin = pNextPlugin; // Whether to allow the disposal of the plugin reference. setAutoDelete(false); // pSession->unlock(); return true; } bool qtractorInsertPluginCommand::undo (void) { qtractorPlugin *pPlugin = plugins().first(); if (pPlugin == NULL) return false; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // Save the previous track alright... qtractorPluginList *pPluginList = pPlugin->list(); if (pPluginList == NULL) return false; // pSession->lock(); qtractorPlugin *pNextPlugin = pPlugin->next(); // Insert it... pPluginList->removePlugin(pPlugin); // Swap it nice, finally. m_pNextPlugin = pNextPlugin; // Whether to allow the disposal of the plugin reference. setAutoDelete(true); // pSession->unlock(); return true; } //---------------------------------------------------------------------- // class qtractorMovePluginCommand - implementation // // Constructor. qtractorMovePluginCommand::qtractorMovePluginCommand ( qtractorPlugin *pPlugin, qtractorPlugin *pNextPlugin, qtractorPluginList *pPluginList ) : qtractorInsertPluginCommand(QObject::tr("move plugin"), pPlugin, pNextPlugin) { m_pPluginList = pPluginList; } // Plugin-move command methods. bool qtractorMovePluginCommand::redo (void) { qtractorPlugin *pPlugin = plugins().first(); if (pPlugin == NULL) return false; if (m_pPluginList == NULL) return false; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // pSession->lock(); // Save the previous track alright... qtractorPlugin *pNextPlugin = pPlugin->next(); qtractorPluginList *pPluginList = pPlugin->list(); // Move it... m_pPluginList->movePlugin(pPlugin, nextPlugin()); // Swap it nice, finally. m_pPluginList = pPluginList; setNextPlugin(pNextPlugin); // pSession->unlock(); return true; } bool qtractorMovePluginCommand::undo (void) { // As we swap the prev/state this is non-idempotent. return redo(); } //---------------------------------------------------------------------- // class qtractorActivatePluginCommand - implementation // // Constructor. qtractorActivatePluginCommand::qtractorActivatePluginCommand ( qtractorPlugin *pPlugin, bool bActivated ) : qtractorPluginCommand(QObject::tr("activate plugin"), pPlugin) { m_bActivated = bActivated; } // Plugin-activate command methods. bool qtractorActivatePluginCommand::redo (void) { // Save the toggled state alright... bool bActivated = !m_bActivated; QListIterator iter(plugins()); while (iter.hasNext()) iter.next()->setActivated(m_bActivated); // Swap it nice, finally. m_bActivated = bActivated; return true; } bool qtractorActivatePluginCommand::undo (void) { // As we toggle the prev/state this is non-idempotent. return redo(); } //---------------------------------------------------------------------- // class qtractorPresetPluginCommand - implementation // // Constructor. qtractorPresetPluginCommand::qtractorPresetPluginCommand ( qtractorPlugin *pPlugin, const QString& sPreset, const QStringList& vlist ) : qtractorPluginCommand(QObject::tr("preset plugin"), pPlugin) { m_sPreset = sPreset; m_vlist = vlist; } // Plugin-preset command methods. bool qtractorPresetPluginCommand::redo (void) { qtractorPlugin *pPlugin = plugins().first(); if (pPlugin == NULL) return false; // Save the current toggled state alright... QString sPreset = pPlugin->preset(); QStringList vlist = pPlugin->valueList(); pPlugin->setPreset(m_sPreset); pPlugin->setValueList(m_vlist); pPlugin->realizeValues(); // Swap it nice, finally. m_sPreset = sPreset; m_vlist = vlist; // Update the form, showing it up as necessary... pPlugin->form()->refresh(); return true; } bool qtractorPresetPluginCommand::undo (void) { // As we swap the prev/state this is non-idempotent. return redo(); } //---------------------------------------------------------------------- // class qtractorResetPluginCommand - implementation // // Constructor. qtractorResetPluginCommand::qtractorResetPluginCommand ( qtractorPlugin *pPlugin ) : qtractorPluginCommand(QObject::tr("reset plugin"), pPlugin) { } // Plugin-reset command methods. bool qtractorResetPluginCommand::redo (void) { qtractorPlugin *pPlugin = plugins().first(); if (pPlugin == NULL) return false; // Toggle/swap it nice... QString sPreset = pPlugin->preset(); QStringList vlist = pPlugin->valueList(); pPlugin->setPreset(m_sPreset); if (m_sPreset.isEmpty() || m_vlist.isEmpty()) { pPlugin->reset(); } else { pPlugin->setValueList(m_vlist); pPlugin->realizeValues(); } // Swap it nice. m_sPreset = sPreset; m_vlist = vlist; // Update the form, showing it up as necessary... pPlugin->form()->refresh(); return true; } bool qtractorResetPluginCommand::undo (void) { // As we swap the prev/state this is non-idempotent. return redo(); } //---------------------------------------------------------------------- // class qtractorPluginParamCommand - implementation // // Constructor. qtractorPluginParamCommand::qtractorPluginParamCommand ( qtractorPluginParam *pParam, float fValue, bool bUpdate ) : qtractorCommand(QString(pParam->name()).toLower()), m_pParam(pParam), m_fValue(fValue), m_bUpdate(bUpdate), m_fPrevValue(pParam->value()) { setRefresh(false); // Try replacing an previously equivalent command... static qtractorPluginParamCommand *s_pPrevParamCommand = NULL; if (s_pPrevParamCommand) { qtractorSession *pSession = qtractorSession::getInstance(); qtractorCommand *pLastCommand = (pSession->commands())->lastCommand(); qtractorCommand *pPrevCommand = static_cast (s_pPrevParamCommand); if (pPrevCommand == pLastCommand && s_pPrevParamCommand->param() == pParam) { qtractorPluginParamCommand *pLastParamCommand = static_cast (pLastCommand); if (pLastParamCommand) { // Equivalence means same (sign) direction too... float fPrevValue = pLastParamCommand->prevValue(); float fLastValue = pLastParamCommand->value(); int iPrevSign = (fPrevValue > fLastValue ? +1 : -1); int iCurrSign = (fPrevValue < m_fValue ? +1 : -1); if (iPrevSign == iCurrSign || m_fValue == m_fPrevValue) { m_fPrevValue = fLastValue; (pSession->commands())->removeLastCommand(); } } } } s_pPrevParamCommand = this; } // Plugin-reset command methods. bool qtractorPluginParamCommand::redo (void) { qtractorPlugin *pPlugin = m_pParam->plugin(); if (pPlugin == NULL) return false; // Set plugin parameter value... float fValue = m_fPrevValue; m_pParam->setValue(m_fValue, m_bUpdate); // Set undo value... m_fPrevValue = m_fValue; m_fValue = fValue; m_bUpdate = true; // Update the form, showing it up as necessary... if (pPlugin->isFormVisible()) (pPlugin->form())->changeParamValue(m_pParam->index()); // Update any GUI editor... // pPlugin->idleEditor(); return true; } bool qtractorPluginParamCommand::undo (void) { // As we swap the prev/value this is non-idempotent. return redo(); } //---------------------------------------------------------------------- // class qtractorAudioOutputBusCommand - declaration. // // Constructor. qtractorAudioOutputBusCommand::qtractorAudioOutputBusCommand ( qtractorMidiManager *pMidiManager, bool bAudioOutputBus, bool bAudioOutputAutoConnect ) : qtractorCommand(QObject::tr("dedicated audio outputs")), m_pMidiManager(pMidiManager), m_bAudioOutputBus(bAudioOutputBus), m_bAudioOutputAutoConnect(bAudioOutputAutoConnect) { } // Plugin audio ouput bus command methods. bool qtractorAudioOutputBusCommand::redo (void) { if (m_pMidiManager == NULL) return false; bool bAudioOutputBus = m_pMidiManager->isAudioOutputBus(); bool bAudioOutputAutoConnect = m_pMidiManager->isAudioOutputAutoConnect(); m_pMidiManager->setAudioOutputAutoConnect(m_bAudioOutputAutoConnect); m_pMidiManager->setAudioOutputBus(m_bAudioOutputBus); m_bAudioOutputAutoConnect = bAudioOutputAutoConnect; m_bAudioOutputBus = bAudioOutputBus; return true; } bool qtractorAudioOutputBusCommand::undo (void) { return redo(); } //---------------------------------------------------------------------- // class qtractorDirectAccessParamCommand - implementation // // Constructor. qtractorDirectAccessParamCommand::qtractorDirectAccessParamCommand ( qtractorPlugin *pPlugin, long iDirectAccessParamIndex ) : qtractorPluginCommand(QObject::tr("direct access param"), pPlugin) { m_iDirectAccessParamIndex = iDirectAccessParamIndex; } // Plugin-change command methods. bool qtractorDirectAccessParamCommand::redo (void) { qtractorPlugin *pPlugin = plugins().first(); if (pPlugin == NULL) return false; long iDirectAccessParamIndex = pPlugin->directAccessParamIndex(); pPlugin->setDirectAccessParamIndex(m_iDirectAccessParamIndex); m_iDirectAccessParamIndex = iDirectAccessParamIndex; return true; } bool qtractorDirectAccessParamCommand::undo (void) { return redo(); } // end of qtractorPluginCommand.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMainForm.cpp0000644000175000001440000000012312223025330021227 xustar000000000000000027 mtime=1380723416.183262 26 atime=1381134667.89408 30 ctime=1381134667.896080063 qtractor-0.5.11/src/qtractorMainForm.cpp0000644000175000001440000063777612223025330020550 0ustar00rncbcusers00000000000000// qtractorMainForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorMainForm.h" #include "qtractorAbout.h" #include "qtractorOptions.h" #include "qtractorInstrument.h" #include "qtractorMessages.h" #include "qtractorFiles.h" #include "qtractorConnections.h" #include "qtractorMixer.h" #include "qtractorTracks.h" #include "qtractorTrackList.h" #include "qtractorTrackTime.h" #include "qtractorTrackView.h" #include "qtractorThumbView.h" #include "qtractorSpinBox.h" #include "qtractorAudioPeak.h" #include "qtractorAudioBuffer.h" #include "qtractorAudioEngine.h" #include "qtractorMidiEngine.h" #include "qtractorSessionDocument.h" #include "qtractorSessionCursor.h" #include "qtractorSessionCommand.h" #include "qtractorTimeScaleCommand.h" #include "qtractorClipCommand.h" #include "qtractorAudioClip.h" #include "qtractorMidiClip.h" #include "qtractorAudioMeter.h" #include "qtractorMidiMeter.h" #include "qtractorMidiMonitor.h" #include "qtractorMidiBuffer.h" #include "qtractorExportForm.h" #include "qtractorSessionForm.h" #include "qtractorOptionsForm.h" #include "qtractorConnectForm.h" #include "qtractorShortcutForm.h" #include "qtractorMidiControlForm.h" #include "qtractorInstrumentForm.h" #include "qtractorTimeScaleForm.h" #include "qtractorBusForm.h" #include "qtractorTakeRangeForm.h" #include "qtractorMidiEditorForm.h" #include "qtractorMidiEditor.h" #include "qtractorTrackCommand.h" #include "qtractorCurveCommand.h" #ifdef CONFIG_DSSI #include "qtractorDssiPlugin.h" #endif #ifdef CONFIG_VST #include "qtractorVstPlugin.h" #endif #ifdef CONFIG_LV2 #include "qtractorLv2Plugin.h" #endif #ifdef CONFIG_JACK_SESSION #include #endif #ifdef CONFIG_NSM #include "qtractorNsmClient.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #endif #if QT_VERSION < 0x050000 #if !defined(QT_NO_STYLE_GTK) #include #endif #endif #if QT_VERSION < 0x040500 namespace Qt { const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000); } #endif #if defined(WIN32) #undef HAVE_SIGNAL_H #endif //------------------------------------------------------------------------- // LADISH Level 1 support stuff. #ifdef HAVE_SIGNAL_H #include #include #include #include // File descriptor for SIGUSR1 notifier. static int g_fdUsr1[2]; // Unix SIGUSR1 signal handler. static void qtractor_sigusr1_handler ( int /* signo */ ) { char c = 1; (::write(g_fdUsr1[0], &c, sizeof(c)) > 0); } // File descriptor for SIGTERM notifier. static int g_fdTerm[2]; // Unix SIGTERM signal handler. static void qtractor_sigterm_handler ( int /* signo */ ) { char c = 1; (::write(g_fdTerm[0], &c, sizeof(c)) > 0); } #endif // HANDLE_SIGNAL_H #include // Timer constant (magic) stuff. #define QTRACTOR_TIMER_MSECS 66 #define QTRACTOR_TIMER_DELAY 233 //------------------------------------------------------------------------- // qtractorTempoCursor -- Custom session tempo helper class class qtractorTempoCursor { public: // Constructor. qtractorTempoCursor() : m_pNode(NULL) {} // Reset method. void clear() { m_pNode = NULL; } // Predicate method. qtractorTimeScale::Node *seek( qtractorSession *pSession, unsigned long iFrame) { qtractorTimeScale::Cursor& cursor = pSession->timeScale()->cursor(); qtractorTimeScale::Node *pNode = cursor.seekFrame(iFrame); return (m_pNode == pNode ? NULL : m_pNode = pNode); } private: // Instance variables. qtractorTimeScale::Node *m_pNode; }; //------------------------------------------------------------------------- // qtractorMainForm -- Main window form implementation. // Kind of singleton reference. qtractorMainForm *qtractorMainForm::g_pMainForm = NULL; // Constructor. qtractorMainForm::qtractorMainForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QMainWindow(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Pseudo-singleton reference setup. g_pMainForm = this; // Initialize some pointer references. m_pOptions = NULL; // FIXME: This gotta go, somwhere in time... m_pSession = qtractorSession::getInstance(); m_pTempoCursor = new qtractorTempoCursor(); // All child forms are to be created later, not earlier than setup. m_pMessages = NULL; m_pFiles = NULL; m_pMixer = NULL; m_pConnections = NULL; m_pTracks = NULL; // To remember last time we've shown the playhead. m_iPlayHead = 0; // We'll start clean. m_iUntitled = 0; m_iDirtyCount = 0; m_iBackupCount = 0; m_iPeakTimer = 0; m_iPlayTimer = 0; m_iIdleTimer = 0; m_iTransportUpdate = 0; m_iTransportRolling = 0; m_bTransportPlaying = false; m_fTransportShuttle = 0.0f; m_iTransportStep = 0; m_iXrunCount = 0; m_iXrunSkip = 0; m_iXrunTimer = 0; m_iAudioRefreshTimer = 0; m_iMidiRefreshTimer = 0; m_iPlayerTimer = 0; m_pNsmClient = NULL; m_bNsmDirty = false; // Configure the audio file peak factory... if (m_pSession->audioPeakFactory()) { QObject::connect(m_pSession->audioPeakFactory(), SIGNAL(peakEvent()), SLOT(peakNotify())); } // Configure the audio engine event handling... qtractorAudioEngine *pAudioEngine = m_pSession->audioEngine(); if (pAudioEngine) { QObject::connect(pAudioEngine->proxy(), SIGNAL(shutEvent()), SLOT(audioShutNotify())); QObject::connect(pAudioEngine->proxy(), SIGNAL(xrunEvent()), SLOT(audioXrunNotify())); QObject::connect(pAudioEngine->proxy(), SIGNAL(portEvent()), SLOT(audioPortNotify())); QObject::connect(pAudioEngine->proxy(), SIGNAL(buffEvent()), SLOT(audioBuffNotify())); QObject::connect(pAudioEngine->proxy(), SIGNAL(sessEvent(void *)), SLOT(audioSessNotify(void *))); QObject::connect(pAudioEngine->proxy(), SIGNAL(syncEvent(unsigned long)), SLOT(audioSyncNotify(unsigned long))); } // Configure the MIDI engine event handling... qtractorMidiEngine *pMidiEngine = m_pSession->midiEngine(); if (pMidiEngine) { qRegisterMetaType ("qtractorMmcEvent"); qRegisterMetaType ("qtractorCtlEvent"); QObject::connect(pMidiEngine->proxy(), SIGNAL(mmcEvent(const qtractorMmcEvent&)), SLOT(midiMmcNotify(const qtractorMmcEvent&))); QObject::connect(pMidiEngine->proxy(), SIGNAL(ctlEvent(const qtractorCtlEvent&)), SLOT(midiCtlNotify(const qtractorCtlEvent&))); QObject::connect(pMidiEngine->proxy(), SIGNAL(sppEvent(int, unsigned short)), SLOT(midiSppNotify(int, unsigned short))); QObject::connect(pMidiEngine->proxy(), SIGNAL(clkEvent(float)), SLOT(midiClkNotify(float))); } // Add the midi controller map... m_pMidiControl = new qtractorMidiControl(); #ifdef HAVE_SIGNAL_H // Set to ignore any fatal "Broken pipe" signals. ::signal(SIGPIPE, SIG_IGN); // LADISH Level 1 suport. // Initialize file descriptors for SIGUSR1 socket notifier. ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdUsr1); m_pUsr1Notifier = new QSocketNotifier(g_fdUsr1[1], QSocketNotifier::Read, this); QObject::connect(m_pUsr1Notifier, SIGNAL(activated(int)), SLOT(handle_sigusr1())); // Install SIGUSR1 signal handler. struct sigaction usr1; usr1.sa_handler = qtractor_sigusr1_handler; ::sigemptyset(&usr1.sa_mask); usr1.sa_flags = 0; usr1.sa_flags |= SA_RESTART; ::sigaction(SIGUSR1, &usr1, NULL); // LADISH termination suport. // Initialize file descriptors for SIGTERM socket notifier. ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdTerm); m_pTermNotifier = new QSocketNotifier(g_fdTerm[1], QSocketNotifier::Read, this); QObject::connect(m_pTermNotifier, SIGNAL(activated(int)), SLOT(handle_sigterm())); // Install SIGTERM signal handler. struct sigaction term; term.sa_handler = qtractor_sigterm_handler; ::sigemptyset(&term.sa_mask); term.sa_flags = 0; term.sa_flags |= SA_RESTART; ::sigaction(SIGTERM, &term, NULL); // Ignore SIGHUP signal. struct sigaction hup; hup.sa_handler = SIG_IGN; ::sigemptyset(&hup.sa_mask); hup.sa_flags = 0; hup.sa_flags |= SA_RESTART; ::sigaction(SIGHUP, &hup, NULL); #else // HAVE_SIGNAL_H m_pUsr1Notifier = NULL; m_pTermNotifier = NULL; #endif // !HAVE_SIGNAL_H // Get edit selection mode action group up... // m_ui.editToolbar->addSeparator(); m_pSelectModeActionGroup = new QActionGroup(this); m_pSelectModeActionGroup->setExclusive(true); // m_pSelectModeActionGroup->setUsesDropDown(true); m_pSelectModeActionGroup->addAction(m_ui.editSelectModeClipAction); m_pSelectModeActionGroup->addAction(m_ui.editSelectModeRangeAction); m_pSelectModeActionGroup->addAction(m_ui.editSelectModeRectAction); m_pSelectModeActionGroup->addAction(m_ui.editSelectModeCurveAction); // m_ui.editToolbar->addActions(m_pSelectModeActionGroup->actions()); // Additional time-toolbar controls... // m_ui.timeToolbar->addSeparator(); // View/Snap-to-beat actions initialization... int iSnap = 0; const QString sSnapObjectName("viewSnapPerBeat%1"); const QString sSnapStatusTip(tr("Set current snap to %1")); const QStringList& snapItems = qtractorTimeScale::snapItems(); QStringListIterator snapIter(snapItems); while (snapIter.hasNext()) { const QString& sSnapText = snapIter.next(); QAction *pAction = new QAction(sSnapText, this); pAction->setObjectName(sSnapObjectName.arg(iSnap)); pAction->setStatusTip(sSnapStatusTip.arg(sSnapText)); pAction->setCheckable(true); pAction->setData(iSnap++); QObject::connect(pAction, SIGNAL(triggered(bool)), SLOT(viewSnap())); m_snapPerBeatActions.append(pAction); addAction(pAction); } // Editable toolbar widgets special palette. QPalette pal; // Outrageous HACK: GTK+ ppl won't see green on black thing... #if QT_VERSION < 0x050000 #if !defined(QT_NO_STYLE_GTK) if (qobject_cast (style()) == NULL) { #endif #endif // pal.setColor(QPalette::Window, Qt::black); pal.setColor(QPalette::Base, Qt::black); pal.setColor(QPalette::Text, Qt::green); // pal.setColor(QPalette::Button, Qt::darkGray); // pal.setColor(QPalette::ButtonText, Qt::green); #if QT_VERSION < 0x050000 #if !defined(QT_NO_STYLE_GTK) } #endif #endif const QSize pad(4, 0); const QFont& font0 = qtractorMainForm::font(); const QFont font(font0.family(), font0.pointSize() + 2); const QFontMetrics fm(font); const int d = fm.height() + fm.leading() + 8; // Transport time. const QString sTime("+99:99:99.999"); m_pTimeSpinBox = new qtractorTimeSpinBox(); m_pTimeSpinBox->setTimeScale(m_pSession->timeScale()); m_pTimeSpinBox->setFont(font); m_pTimeSpinBox->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); m_pTimeSpinBox->setMinimumSize(QSize(fm.width(sTime) + d, d) + pad); m_pTimeSpinBox->setPalette(pal); // m_pTimeSpinBox->setAutoFillBackground(true); m_pTimeSpinBox->setToolTip(tr("Current time (play-head)")); // m_pTimeSpinBox->setContextMenuPolicy(Qt::CustomContextMenu); m_ui.timeToolbar->addWidget(m_pTimeSpinBox); // m_ui.timeToolbar->addSeparator(); // Tempo spin-box. const QString sTempo("999.9 9/9"); m_pTempoSpinBox = new qtractorTempoSpinBox(); // m_pTempoSpinBox->setDecimals(1); // m_pTempoSpinBox->setMinimum(1.0f); // m_pTempoSpinBox->setMaximum(1000.0f); m_pTempoSpinBox->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); m_pTempoSpinBox->setMinimumSize(QSize(fm.width(sTempo) + d, d) + pad); m_pTempoSpinBox->setPalette(pal); // m_pTempoSpinBox->setAutoFillBackground(true); m_pTempoSpinBox->setToolTip(tr("Current tempo (BPM)")); m_pTempoSpinBox->setContextMenuPolicy(Qt::CustomContextMenu); m_ui.timeToolbar->addWidget(m_pTempoSpinBox); m_ui.timeToolbar->addSeparator(); // Snap-per-beat combo-box. m_pSnapPerBeatComboBox = new QComboBox(); m_pSnapPerBeatComboBox->setEditable(false); m_pSnapPerBeatComboBox->insertItems(0, snapItems); m_pSnapPerBeatComboBox->setToolTip(tr("Snap/beat")); m_ui.timeToolbar->addWidget(m_pSnapPerBeatComboBox); // Track-line thumbnail view... m_pThumbView = new qtractorThumbView(); m_ui.thumbToolbar->addWidget(m_pThumbView); m_ui.thumbToolbar->setAllowedAreas( Qt::TopToolBarArea | Qt::BottomToolBarArea); QObject::connect(m_pTimeSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(transportTimeFormatChanged(int))); QObject::connect(m_pTimeSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(transportTimeChanged(unsigned long))); QObject::connect(m_pTimeSpinBox, SIGNAL(editingFinished()), SLOT(transportTimeFinished())); QObject::connect(m_pTempoSpinBox, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(transportTempoContextMenu(const QPoint&))); QObject::connect(m_pTempoSpinBox, SIGNAL(valueChanged(float, unsigned short, unsigned short)), SLOT(transportTempoChanged(float, unsigned short, unsigned short))); QObject::connect(m_pTempoSpinBox, SIGNAL(editingFinished()), SLOT(transportTempoFinished())); QObject::connect(m_pSnapPerBeatComboBox, SIGNAL(activated(int)), SLOT(snapPerBeatChanged(int))); // Create some statusbar labels... QStatusBar *pStatusBar = statusBar(); const QPalette& spal = pStatusBar->palette(); QLabel *pLabel; QPalette *pPalette = new QPalette(spal); m_paletteItems[PaletteNone] = pPalette; pPalette = new QPalette(spal); pPalette->setColor(QPalette::Window, Qt::red); m_paletteItems[PaletteRed] = pPalette; pPalette = new QPalette(spal); pPalette->setColor(QPalette::Window, Qt::yellow); m_paletteItems[PaletteYellow] = pPalette; pPalette = new QPalette(spal); pPalette->setColor(QPalette::Window, Qt::cyan); m_paletteItems[PaletteCyan] = pPalette; pPalette = new QPalette(spal); pPalette->setColor(QPalette::Window, Qt::green); m_paletteItems[PaletteGreen] = pPalette; // Track status. pLabel = new QLabel(tr("Track")); pLabel->setAlignment(Qt::AlignLeft); pLabel->setToolTip(tr("Current track name")); pLabel->setAutoFillBackground(true); m_statusItems[StatusName] = pLabel; pStatusBar->addWidget(pLabel, 2); // Hideous progress bar... m_pProgressBar = new QProgressBar(); m_pProgressBar->setFixedHeight(pLabel->sizeHint().height()); m_pProgressBar->setMinimumWidth(120); pStatusBar->addPermanentWidget(m_pProgressBar); m_pProgressBar->hide(); // Session modification status. pLabel = new QLabel(tr("MOD")); pLabel->setAlignment(Qt::AlignHCenter); pLabel->setMinimumSize(pLabel->sizeHint() + pad); pLabel->setToolTip(tr("Session modification state")); pLabel->setAutoFillBackground(true); m_statusItems[StatusMod] = pLabel; pStatusBar->addPermanentWidget(pLabel); // Session recording status. pLabel = new QLabel(tr("REC")); pLabel->setAlignment(Qt::AlignHCenter); pLabel->setMinimumSize(pLabel->sizeHint() + pad); pLabel->setToolTip(tr("Session record state")); pLabel->setAutoFillBackground(true); m_statusItems[StatusRec] = pLabel; pStatusBar->addPermanentWidget(pLabel); // Session muting status. pLabel = new QLabel(tr("MUTE")); pLabel->setAlignment(Qt::AlignHCenter); pLabel->setMinimumSize(pLabel->sizeHint() + pad); pLabel->setToolTip(tr("Session muting state")); pLabel->setAutoFillBackground(true); m_statusItems[StatusMute] = pLabel; pStatusBar->addPermanentWidget(pLabel); // Session soloing status. pLabel = new QLabel(tr("SOLO")); pLabel->setAlignment(Qt::AlignHCenter); pLabel->setMinimumSize(pLabel->sizeHint() + pad); pLabel->setToolTip(tr("Session soloing state")); pLabel->setAutoFillBackground(true); m_statusItems[StatusSolo] = pLabel; pStatusBar->addPermanentWidget(pLabel); // Session looping status. pLabel = new QLabel(tr("LOOP")); pLabel->setAlignment(Qt::AlignHCenter); pLabel->setMinimumSize(pLabel->sizeHint() + pad); pLabel->setToolTip(tr("Session looping state")); pLabel->setAutoFillBackground(true); m_statusItems[StatusLoop] = pLabel; pStatusBar->addPermanentWidget(pLabel); // Session length time. pLabel = new QLabel(sTime); pLabel->setAlignment(Qt::AlignHCenter); pLabel->setMinimumSize(pLabel->sizeHint() + pad); pLabel->setToolTip(tr("Session total time")); pLabel->setAutoFillBackground(true); m_statusItems[StatusTime] = pLabel; pStatusBar->addPermanentWidget(pLabel); // Session sample rate. pLabel = new QLabel("199999 Hz"); pLabel->setAlignment(Qt::AlignHCenter); pLabel->setMinimumSize(pLabel->sizeHint() + pad); pLabel->setAutoFillBackground(true); pLabel->setToolTip(tr("Session sample rate")); m_statusItems[StatusRate] = pLabel; pStatusBar->addPermanentWidget(pLabel); m_ui.transportLoopAction->setAutoRepeat(false); m_ui.transportLoopSetAction->setAutoRepeat(false); m_ui.transportPlayAction->setAutoRepeat(false); m_ui.transportRecordAction->setAutoRepeat(false); m_ui.transportPunchAction->setAutoRepeat(false); m_ui.transportPunchSetAction->setAutoRepeat(false); // Some actions surely need those // shortcuts firmly attached... addAction(m_ui.viewMenubarAction); #if 0 const QList& actions = findChildren (); QListIterator iter(actions); while (iter.hasNext()) iter.next()->setShortcutContext(Qt::ApplicationShortcut); #else m_ui.viewFilesAction->setShortcutContext(Qt::ApplicationShortcut); m_ui.viewConnectionsAction->setShortcutContext(Qt::ApplicationShortcut); m_ui.viewMixerAction->setShortcutContext(Qt::ApplicationShortcut); m_ui.viewMessagesAction->setShortcutContext(Qt::ApplicationShortcut); #endif // Ah, make it stand right. setFocus(); // UI signal/slot connections... QObject::connect(m_ui.fileNewAction, SIGNAL(triggered(bool)), SLOT(fileNew())); QObject::connect(m_ui.fileOpenAction, SIGNAL(triggered(bool)), SLOT(fileOpen())); QObject::connect(m_ui.fileSaveAction, SIGNAL(triggered(bool)), SLOT(fileSave())); QObject::connect(m_ui.fileSaveAsAction, SIGNAL(triggered(bool)), SLOT(fileSaveAs())); QObject::connect(m_ui.filePropertiesAction, SIGNAL(triggered(bool)), SLOT(fileProperties())); QObject::connect(m_ui.fileExitAction, SIGNAL(triggered(bool)), SLOT(fileExit())); QObject::connect(m_ui.editUndoAction, SIGNAL(triggered(bool)), SLOT(editUndo())); QObject::connect(m_ui.editRedoAction, SIGNAL(triggered(bool)), SLOT(editRedo())); QObject::connect(m_ui.editCutAction, SIGNAL(triggered(bool)), SLOT(editCut())); QObject::connect(m_ui.editCopyAction, SIGNAL(triggered(bool)), SLOT(editCopy())); QObject::connect(m_ui.editPasteAction, SIGNAL(triggered(bool)), SLOT(editPaste())); QObject::connect(m_ui.editPasteRepeatAction, SIGNAL(triggered(bool)), SLOT(editPasteRepeat())); QObject::connect(m_ui.editDeleteAction, SIGNAL(triggered(bool)), SLOT(editDelete())); QObject::connect(m_ui.editSelectModeClipAction, SIGNAL(triggered(bool)), SLOT(editSelectModeClip())); QObject::connect(m_ui.editSelectModeRangeAction, SIGNAL(triggered(bool)), SLOT(editSelectModeRange())); QObject::connect(m_ui.editSelectModeRectAction, SIGNAL(triggered(bool)), SLOT(editSelectModeRect())); QObject::connect(m_ui.editSelectModeCurveAction, SIGNAL(triggered(bool)), SLOT(editSelectModeCurve())); QObject::connect(m_ui.editSelectAllAction, SIGNAL(triggered(bool)), SLOT(editSelectAll())); QObject::connect(m_ui.editSelectNoneAction, SIGNAL(triggered(bool)), SLOT(editSelectNone())); QObject::connect(m_ui.editSelectInvertAction, SIGNAL(triggered(bool)), SLOT(editSelectInvert())); QObject::connect(m_ui.editSelectTrackAction, SIGNAL(triggered(bool)), SLOT(editSelectTrack())); QObject::connect(m_ui.editSelectTrackRangeAction, SIGNAL(triggered(bool)), SLOT(editSelectTrackRange())); QObject::connect(m_ui.editSelectRangeAction, SIGNAL(triggered(bool)), SLOT(editSelectRange())); QObject::connect(m_ui.editInsertRangeAction, SIGNAL(triggered(bool)), SLOT(editInsertRange())); QObject::connect(m_ui.editInsertTrackRangeAction, SIGNAL(triggered(bool)), SLOT(editInsertTrackRange())); QObject::connect(m_ui.editRemoveRangeAction, SIGNAL(triggered(bool)), SLOT(editRemoveRange())); QObject::connect(m_ui.editRemoveTrackRangeAction, SIGNAL(triggered(bool)), SLOT(editRemoveTrackRange())); QObject::connect(m_ui.editSplitAction, SIGNAL(triggered(bool)), SLOT(editSplit())); QObject::connect(m_ui.trackAddAction, SIGNAL(triggered(bool)), SLOT(trackAdd())); QObject::connect(m_ui.trackRemoveAction, SIGNAL(triggered(bool)), SLOT(trackRemove())); QObject::connect(m_ui.trackPropertiesAction, SIGNAL(triggered(bool)), SLOT(trackProperties())); QObject::connect(m_ui.trackInputsAction, SIGNAL(triggered(bool)), SLOT(trackInputs())); QObject::connect(m_ui.trackOutputsAction, SIGNAL(triggered(bool)), SLOT(trackOutputs())); QObject::connect(m_ui.trackStateRecordAction, SIGNAL(triggered(bool)), SLOT(trackStateRecord(bool))); QObject::connect(m_ui.trackStateMuteAction, SIGNAL(triggered(bool)), SLOT(trackStateMute(bool))); QObject::connect(m_ui.trackStateSoloAction, SIGNAL(triggered(bool)), SLOT(trackStateSolo(bool))); QObject::connect(m_ui.trackStateMonitorAction, SIGNAL(triggered(bool)), SLOT(trackStateMonitor(bool))); QObject::connect(m_ui.trackNavigateFirstAction, SIGNAL(triggered(bool)), SLOT(trackNavigateFirst())); QObject::connect(m_ui.trackNavigatePrevAction, SIGNAL(triggered(bool)), SLOT(trackNavigatePrev())); QObject::connect(m_ui.trackNavigateNextAction, SIGNAL(triggered(bool)), SLOT(trackNavigateNext())); QObject::connect(m_ui.trackNavigateLastAction, SIGNAL(triggered(bool)), SLOT(trackNavigateLast())); QObject::connect(m_ui.trackNavigateNoneAction, SIGNAL(triggered(bool)), SLOT(trackNavigateNone())); QObject::connect(m_ui.trackMoveTopAction, SIGNAL(triggered(bool)), SLOT(trackMoveTop())); QObject::connect(m_ui.trackMoveUpAction, SIGNAL(triggered(bool)), SLOT(trackMoveUp())); QObject::connect(m_ui.trackMoveDownAction, SIGNAL(triggered(bool)), SLOT(trackMoveDown())); QObject::connect(m_ui.trackMoveBottomAction, SIGNAL(triggered(bool)), SLOT(trackMoveBottom())); QObject::connect(m_ui.trackHeightUpAction, SIGNAL(triggered(bool)), SLOT(trackHeightUp())); QObject::connect(m_ui.trackHeightDownAction, SIGNAL(triggered(bool)), SLOT(trackHeightDown())); QObject::connect(m_ui.trackHeightResetAction, SIGNAL(triggered(bool)), SLOT(trackHeightReset())); QObject::connect(m_ui.trackAutoMonitorAction, SIGNAL(triggered(bool)), SLOT(trackAutoMonitor(bool))); QObject::connect(m_ui.trackImportAudioAction, SIGNAL(triggered(bool)), SLOT(trackImportAudio())); QObject::connect(m_ui.trackImportMidiAction, SIGNAL(triggered(bool)), SLOT(trackImportMidi())); QObject::connect(m_ui.trackExportAudioAction, SIGNAL(triggered(bool)), SLOT(trackExportAudio())); QObject::connect(m_ui.trackExportMidiAction, SIGNAL(triggered(bool)), SLOT(trackExportMidi())); QObject::connect(m_ui.trackCurveSelectMenu, SIGNAL(triggered(QAction *)), SLOT(trackCurveSelect(QAction *))); QObject::connect(m_ui.trackCurveModeMenu, SIGNAL(triggered(QAction *)), SLOT(trackCurveMode(QAction *))); QObject::connect(m_ui.trackCurveLogarithmicAction, SIGNAL(triggered(bool)), SLOT(trackCurveLogarithmic(bool))); QObject::connect(m_ui.trackCurveColorAction, SIGNAL(triggered(bool)), SLOT(trackCurveColor())); QObject::connect(m_ui.trackCurveLockedAction, SIGNAL(triggered(bool)), SLOT(trackCurveLocked(bool))); QObject::connect(m_ui.trackCurveProcessAction, SIGNAL(triggered(bool)), SLOT(trackCurveProcess(bool))); QObject::connect(m_ui.trackCurveCaptureAction, SIGNAL(triggered(bool)), SLOT(trackCurveCapture(bool))); QObject::connect(m_ui.trackCurveClearAction, SIGNAL(triggered(bool)), SLOT(trackCurveClear())); QObject::connect(m_ui.trackCurveLockedAllAction, SIGNAL(triggered(bool)), SLOT(trackCurveLockedAll(bool))); QObject::connect(m_ui.trackCurveProcessAllAction, SIGNAL(triggered(bool)), SLOT(trackCurveProcessAll(bool))); QObject::connect(m_ui.trackCurveCaptureAllAction, SIGNAL(triggered(bool)), SLOT(trackCurveCaptureAll(bool))); QObject::connect(m_ui.trackCurveClearAllAction, SIGNAL(triggered(bool)), SLOT(trackCurveClearAll())); QObject::connect(m_ui.clipNewAction, SIGNAL(triggered(bool)), SLOT(clipNew())); QObject::connect(m_ui.clipEditAction, SIGNAL(triggered(bool)), SLOT(clipEdit())); QObject::connect(m_ui.clipUnlinkAction, SIGNAL(triggered(bool)), SLOT(clipUnlink())); QObject::connect(m_ui.clipSplitAction, SIGNAL(triggered(bool)), SLOT(clipSplit())); QObject::connect(m_ui.clipMergeAction, SIGNAL(triggered(bool)), SLOT(clipMerge())); QObject::connect(m_ui.clipNormalizeAction, SIGNAL(triggered(bool)), SLOT(clipNormalize())); QObject::connect(m_ui.clipTempoAction, SIGNAL(triggered(bool)), SLOT(clipTempo())); QObject::connect(m_ui.clipRangeSetAction, SIGNAL(triggered(bool)), SLOT(clipRangeSet())); QObject::connect(m_ui.clipLoopSetAction, SIGNAL(triggered(bool)), SLOT(clipLoopSet())); QObject::connect(m_ui.clipImportAction, SIGNAL(triggered(bool)), SLOT(clipImport())); QObject::connect(m_ui.clipExportAction, SIGNAL(triggered(bool)), SLOT(clipExport())); QObject::connect(m_ui.clipToolsQuantizeAction, SIGNAL(triggered(bool)), SLOT(clipToolsQuantize())); QObject::connect(m_ui.clipToolsTransposeAction, SIGNAL(triggered(bool)), SLOT(clipToolsTranspose())); QObject::connect(m_ui.clipToolsNormalizeAction, SIGNAL(triggered(bool)), SLOT(clipToolsNormalize())); QObject::connect(m_ui.clipToolsRandomizeAction, SIGNAL(triggered(bool)), SLOT(clipToolsRandomize())); QObject::connect(m_ui.clipToolsResizeAction, SIGNAL(triggered(bool)), SLOT(clipToolsResize())); QObject::connect(m_ui.clipToolsRescaleAction, SIGNAL(triggered(bool)), SLOT(clipToolsRescale())); QObject::connect(m_ui.clipToolsTimeshiftAction, SIGNAL(triggered(bool)), SLOT(clipToolsTimeshift())); QObject::connect(m_ui.clipTakeSelectMenu, SIGNAL(triggered(QAction *)), SLOT(clipTakeSelect(QAction *))); QObject::connect(m_ui.clipTakeFirstAction, SIGNAL(triggered(bool)), SLOT(clipTakeFirst())); QObject::connect(m_ui.clipTakePrevAction, SIGNAL(triggered(bool)), SLOT(clipTakePrev())); QObject::connect(m_ui.clipTakeNextAction, SIGNAL(triggered(bool)), SLOT(clipTakeNext())); QObject::connect(m_ui.clipTakeLastAction, SIGNAL(triggered(bool)), SLOT(clipTakeLast())); QObject::connect(m_ui.clipTakeResetAction, SIGNAL(triggered(bool)), SLOT(clipTakeReset())); QObject::connect(m_ui.clipTakeRangeAction, SIGNAL(triggered(bool)), SLOT(clipTakeRange())); QObject::connect(m_ui.viewMenubarAction, SIGNAL(triggered(bool)), SLOT(viewMenubar(bool))); QObject::connect(m_ui.viewStatusbarAction, SIGNAL(triggered(bool)), SLOT(viewStatusbar(bool))); QObject::connect(m_ui.viewToolbarFileAction, SIGNAL(triggered(bool)), SLOT(viewToolbarFile(bool))); QObject::connect(m_ui.viewToolbarEditAction, SIGNAL(triggered(bool)), SLOT(viewToolbarEdit(bool))); QObject::connect(m_ui.viewToolbarTrackAction, SIGNAL(triggered(bool)), SLOT(viewToolbarTrack(bool))); QObject::connect(m_ui.viewToolbarViewAction, SIGNAL(triggered(bool)), SLOT(viewToolbarView(bool))); QObject::connect(m_ui.viewToolbarOptionsAction, SIGNAL(triggered(bool)), SLOT(viewToolbarOptions(bool))); QObject::connect(m_ui.viewToolbarTransportAction, SIGNAL(triggered(bool)), SLOT(viewToolbarTransport(bool))); QObject::connect(m_ui.viewToolbarTimeAction, SIGNAL(triggered(bool)), SLOT(viewToolbarTime(bool))); QObject::connect(m_ui.viewToolbarThumbAction, SIGNAL(triggered(bool)), SLOT(viewToolbarThumb(bool))); QObject::connect(m_ui.viewFilesAction, SIGNAL(triggered(bool)), SLOT(viewFiles(bool))); QObject::connect(m_ui.viewMessagesAction, SIGNAL(triggered(bool)), SLOT(viewMessages(bool))); QObject::connect(m_ui.viewConnectionsAction, SIGNAL(triggered(bool)), SLOT(viewConnections(bool))); QObject::connect(m_ui.viewMixerAction, SIGNAL(triggered(bool)), SLOT(viewMixer(bool))); QObject::connect(m_ui.viewZoomInAction, SIGNAL(triggered(bool)), SLOT(viewZoomIn())); QObject::connect(m_ui.viewZoomOutAction, SIGNAL(triggered(bool)), SLOT(viewZoomOut())); QObject::connect(m_ui.viewZoomResetAction, SIGNAL(triggered(bool)), SLOT(viewZoomReset())); QObject::connect(m_ui.viewZoomHorizontalAction, SIGNAL(triggered(bool)), SLOT(viewZoomHorizontal())); QObject::connect(m_ui.viewZoomVerticalAction, SIGNAL(triggered(bool)), SLOT(viewZoomVertical())); QObject::connect(m_ui.viewZoomAllAction, SIGNAL(triggered(bool)), SLOT(viewZoomAll())); QObject::connect(m_ui.viewSnapZebraAction, SIGNAL(triggered(bool)), SLOT(viewSnapZebra(bool))); QObject::connect(m_ui.viewSnapGridAction, SIGNAL(triggered(bool)), SLOT(viewSnapGrid(bool))); QObject::connect(m_ui.viewToolTipsAction, SIGNAL(triggered(bool)), SLOT(viewToolTips(bool))); QObject::connect(m_ui.viewRefreshAction, SIGNAL(triggered(bool)), SLOT(viewRefresh())); QObject::connect(m_ui.viewInstrumentsAction, SIGNAL(triggered(bool)), SLOT(viewInstruments())); QObject::connect(m_ui.viewControllersAction, SIGNAL(triggered(bool)), SLOT(viewControllers())); QObject::connect(m_ui.viewBusesAction, SIGNAL(triggered(bool)), SLOT(viewBuses())); QObject::connect(m_ui.viewTempoMapAction, SIGNAL(triggered(bool)), SLOT(viewTempoMap())); QObject::connect(m_ui.viewOptionsAction, SIGNAL(triggered(bool)), SLOT(viewOptions())); QObject::connect(m_ui.transportBackwardAction, SIGNAL(triggered(bool)), SLOT(transportBackward())); QObject::connect(m_ui.transportRewindAction, SIGNAL(triggered(bool)), SLOT(transportRewind())); QObject::connect(m_ui.transportFastForwardAction, SIGNAL(triggered(bool)), SLOT(transportFastForward())); QObject::connect(m_ui.transportForwardAction, SIGNAL(triggered(bool)), SLOT(transportForward())); QObject::connect(m_ui.transportLoopAction, SIGNAL(triggered(bool)), SLOT(transportLoop())); QObject::connect(m_ui.transportLoopSetAction, SIGNAL(triggered(bool)), SLOT(transportLoopSet())); QObject::connect(m_ui.transportStopAction, SIGNAL(triggered(bool)), SLOT(transportStop())); QObject::connect(m_ui.transportPlayAction, SIGNAL(triggered(bool)), SLOT(transportPlay())); QObject::connect(m_ui.transportRecordAction, SIGNAL(triggered(bool)), SLOT(transportRecord())); QObject::connect(m_ui.transportPunchAction, SIGNAL(triggered(bool)), SLOT(transportPunch())); QObject::connect(m_ui.transportPunchSetAction, SIGNAL(triggered(bool)), SLOT(transportPunchSet())); QObject::connect(m_ui.transportMetroAction, SIGNAL(triggered(bool)), SLOT(transportMetro())); QObject::connect(m_ui.transportFollowAction, SIGNAL(triggered(bool)), SLOT(transportFollow())); QObject::connect(m_ui.transportAutoBackwardAction, SIGNAL(triggered(bool)), SLOT(transportAutoBackward())); QObject::connect(m_ui.transportContinueAction, SIGNAL(triggered(bool)), SLOT(transportContinue())); QObject::connect(m_ui.transportPanicAction, SIGNAL(triggered(bool)), SLOT(transportPanic())); QObject::connect(m_ui.helpShortcutsAction, SIGNAL(triggered(bool)), SLOT(helpShortcuts())); QObject::connect(m_ui.helpAboutAction, SIGNAL(triggered(bool)), SLOT(helpAbout())); QObject::connect(m_ui.helpAboutQtAction, SIGNAL(triggered(bool)), SLOT(helpAboutQt())); QObject::connect(m_ui.fileMenu, SIGNAL(aboutToShow()), SLOT(updateRecentFilesMenu())); QObject::connect(m_ui.trackMenu, SIGNAL(aboutToShow()), SLOT(updateTrackMenu())); QObject::connect(m_ui.clipMenu, SIGNAL(aboutToShow()), SLOT(updateClipMenu())); QObject::connect(m_ui.clipTakeMenu, SIGNAL(aboutToShow()), SLOT(updateTakeMenu())); QObject::connect(m_ui.clipTakeSelectMenu, SIGNAL(aboutToShow()), SLOT(updateTakeSelectMenu())); QObject::connect(m_ui.trackExportMenu, SIGNAL(aboutToShow()), SLOT(updateExportMenu())); QObject::connect(m_ui.trackCurveMenu, SIGNAL(aboutToShow()), SLOT(updateCurveMenu())); QObject::connect(m_ui.trackCurveModeMenu, SIGNAL(aboutToShow()), SLOT(updateCurveModeMenu())); QObject::connect(m_ui.viewZoomMenu, SIGNAL(aboutToShow()), SLOT(updateZoomMenu())); QObject::connect(m_ui.viewSnapMenu, SIGNAL(aboutToShow()), SLOT(updateSnapMenu())); QObject::connect(m_pSession->commands(), SIGNAL(updateNotifySignal(unsigned int)), SLOT(updateNotifySlot(unsigned int))); // Already handled in files widget... // QObject::connect(QApplication::clipboard(), // SIGNAL(dataChanged()), // SLOT(stabilizeForm())); } // Destructor. qtractorMainForm::~qtractorMainForm (void) { #ifdef HAVE_SIGNAL_H if (m_pUsr1Notifier) delete m_pUsr1Notifier; #endif // View/Snap-to-beat actions termination... qDeleteAll(m_snapPerBeatActions); m_snapPerBeatActions.clear(); // Drop any widgets around (not really necessary)... if (m_pMixer) delete m_pMixer; if (m_pConnections) delete m_pConnections; if (m_pFiles) delete m_pFiles; if (m_pMessages) delete m_pMessages; if (m_pTracks) delete m_pTracks; // Get select mode action group down. if (m_pSelectModeActionGroup) delete m_pSelectModeActionGroup; // Reclaim status items palettes... for (int i = 0; i < PaletteItems; ++i) delete m_paletteItems[i]; // Custom tempo cursor. if (m_pTempoCursor) delete m_pTempoCursor; // Remove midi controllers. if (m_pMidiControl) delete m_pMidiControl; // Pseudo-singleton reference shut-down. g_pMainForm = NULL; } // kind of singleton reference. qtractorMainForm *qtractorMainForm::getInstance (void) { return g_pMainForm; } // Make and set a proper setup options step. void qtractorMainForm::setup ( qtractorOptions *pOptions ) { // We got options? m_pOptions = pOptions; // Some child/dockable forms are to be created right now. m_pFiles = new qtractorFiles(this); m_pFiles->audioListView()->setRecentDir(m_pOptions->sAudioDir); m_pFiles->midiListView()->setRecentDir(m_pOptions->sMidiDir); m_pMessages = new qtractorMessages(this); // Setup messages logging appropriately... m_pMessages->setLogging( m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath); // What style do we create tool childs? QWidget *pParent = NULL; Qt::WindowFlags wflags = Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint; if (m_pOptions->bKeepToolsOnTop) { pParent = this; wflags |= Qt::Tool; } // Other child/tools forms are also created right away... m_pConnections = new qtractorConnections(pParent, wflags); m_pMixer = new qtractorMixer(pParent, wflags); // Make those primordially docked... addDockWidget(Qt::RightDockWidgetArea, m_pFiles, Qt::Vertical); addDockWidget(Qt::BottomDockWidgetArea, m_pMessages, Qt::Horizontal); // Time to create the main session track list view... m_pTracks = new qtractorTracks(this); // Make it shine :-) setCentralWidget(m_pTracks); // Set message defaults... updateMessagesFont(); updateMessagesLimit(); updateMessagesCapture(); // Track view select mode... qtractorTrackView::SelectMode selectMode; switch (pOptions->iTrackViewSelectMode) { case 2: selectMode = qtractorTrackView::SelectRect; m_ui.editSelectModeRectAction->setChecked(true); break; case 1: selectMode = qtractorTrackView::SelectRange; m_ui.editSelectModeRangeAction->setChecked(true); break; case 0: default: selectMode = qtractorTrackView::SelectClip; m_ui.editSelectModeClipAction->setChecked(true); break; } qtractorTrackView *pTrackView = m_pTracks->trackView(); pTrackView->setSelectMode(selectMode); pTrackView->setDropSpan(m_pOptions->bTrackViewDropSpan); pTrackView->setSnapGrid(m_pOptions->bTrackViewSnapGrid); pTrackView->setToolTips(m_pOptions->bTrackViewToolTips); pTrackView->setCurveEdit(m_pOptions->bTrackViewCurveEdit); if (pTrackView->isCurveEdit()) m_ui.editSelectModeCurveAction->setChecked(true); // Initial zoom mode... m_pTracks->setZoomMode(m_pOptions->iZoomMode); // Initial auto time-stretching, loop-recording modes... m_pSession->setAutoTimeStretch(m_pOptions->bAudioAutoTimeStretch); m_pSession->setLoopRecordingMode(m_pOptions->iLoopRecordingMode); // Initial decorations toggle state. m_ui.viewMenubarAction->setChecked(m_pOptions->bMenubar); m_ui.viewStatusbarAction->setChecked(m_pOptions->bStatusbar); m_ui.viewToolbarFileAction->setChecked(m_pOptions->bFileToolbar); m_ui.viewToolbarEditAction->setChecked(m_pOptions->bEditToolbar); m_ui.viewToolbarTrackAction->setChecked(m_pOptions->bTrackToolbar); m_ui.viewToolbarViewAction->setChecked(m_pOptions->bViewToolbar); m_ui.viewToolbarOptionsAction->setChecked(m_pOptions->bOptionsToolbar); m_ui.viewToolbarTransportAction->setChecked(m_pOptions->bTransportToolbar); m_ui.viewToolbarTimeAction->setChecked(m_pOptions->bTimeToolbar); m_ui.viewToolbarThumbAction->setChecked(m_pOptions->bThumbToolbar); m_ui.viewSnapZebraAction->setChecked(pOptions->bTrackViewSnapZebra); m_ui.viewSnapGridAction->setChecked(pOptions->bTrackViewSnapGrid); m_ui.viewToolTipsAction->setChecked(pOptions->bTrackViewToolTips); m_ui.transportMetroAction->setChecked(m_pOptions->bMetronome); m_ui.transportFollowAction->setChecked(m_pOptions->bFollowPlayhead); m_ui.transportAutoBackwardAction->setChecked(m_pOptions->bAutoBackward); m_ui.transportContinueAction->setChecked(m_pOptions->bContinuePastEnd); m_ui.trackAutoMonitorAction->setChecked(m_pOptions->bAutoMonitor); // Initial decorations visibility state. viewMenubar(m_pOptions->bMenubar); viewStatusbar(m_pOptions->bStatusbar); viewToolbarFile(m_pOptions->bFileToolbar); viewToolbarEdit(m_pOptions->bEditToolbar); viewToolbarTrack(m_pOptions->bTrackToolbar); viewToolbarView(m_pOptions->bViewToolbar); viewToolbarOptions(m_pOptions->bOptionsToolbar); viewToolbarTransport(m_pOptions->bTransportToolbar); viewToolbarTime(m_pOptions->bTimeToolbar); viewToolbarThumb(m_pOptions->bThumbToolbar); // Restore whole dock windows state. QByteArray aDockables = m_pOptions->settings().value( "/Layout/DockWindows").toByteArray(); if (aDockables.isEmpty()) { // Some windows are forced initially as is... insertToolBarBreak(m_ui.transportToolbar); } else { // Make it as the last time. restoreState(aDockables); } // Try to restore old window positioning. m_pOptions->loadWidgetGeometry(this, true); m_pOptions->loadWidgetGeometry(m_pMixer); m_pOptions->loadWidgetGeometry(m_pConnections); // Load MIDI controller configuration files... QStringListIterator it(m_pOptions->midiControlFiles); while (it.hasNext()) m_pMidiControl->loadDocument(it.next()); // Load instrument definition files... QStringListIterator iter(m_pOptions->instrumentFiles); while (iter.hasNext()) (m_pSession->instruments())->load(iter.next()); // Load custom meter colors, if any... int iColor; for (iColor = 0; iColor < m_pOptions->audioMeterColors.count(); ++iColor) qtractorAudioMeter::setColor(iColor, QColor(m_pOptions->audioMeterColors[iColor])); for (iColor = 0; iColor < m_pOptions->midiMeterColors.count(); ++iColor) qtractorMidiMeter::setColor(iColor, QColor(m_pOptions->midiMeterColors[iColor])); // Primary startup stabilization... updateRecentFilesMenu(); updatePeakAutoRemove(); updateDisplayFormat(); updatePluginPaths(); updateTransportMode(); updateAudioPlayer(); updateAudioMetronome(); updateMidiControlModes(); updateMidiQueueTimer(); updateMidiPlayer(); updateMidiControl(); updateMidiMetronome(); // FIXME: This is what it should ever be, // make it right from this very moment... qtractorAudioFileFactory::setDefaultType( m_pOptions->sAudioCaptureExt, m_pOptions->iAudioCaptureType, m_pOptions->iAudioCaptureFormat, m_pOptions->iAudioCaptureQuality); qtractorMidiClip::setDefaultFormat( m_pOptions->iMidiCaptureFormat); // Set default MIDI (plugin) instrument audio output mode. qtractorMidiManager::setDefaultAudioOutputBus( m_pOptions->bAudioOutputBus); qtractorMidiManager::setDefaultAudioOutputAutoConnect( m_pOptions->bAudioOutputAutoConnect); // Set default audio-buffer quality... qtractorAudioBuffer::setResampleType(m_pOptions->iAudioResampleType); qtractorAudioBuffer::setWsolaTimeStretch(m_pOptions->bAudioWsolaTimeStretch); qtractorAudioBuffer::setWsolaQuickSeek(m_pOptions->bAudioWsolaQuickSeek); // Load (action) keyboard shortcuts... m_pOptions->loadActionShortcuts(this); // Initial thumb-view background (empty) m_pThumbView->updateContents(); // Some special defaults... qtractorAudioEngine *pAudioEngine = m_pSession->audioEngine(); if (pAudioEngine) pAudioEngine->setMasterAutoConnect(m_pOptions->bAudioMasterAutoConnect); // Is any session identification to get loaded? bool bSessionId = !m_pOptions->sSessionId.isEmpty(); if (bSessionId && pAudioEngine) { pAudioEngine->setSessionId(m_pOptions->sSessionId); m_pOptions->sSessionId.clear(); } // Is any session pending to be loaded? if (!m_pOptions->sSessionFile.isEmpty()) { // We're supposedly clean... m_iDirtyCount = 0; // Just load the prabable startup session... if (loadSessionFileEx(m_pOptions->sSessionFile, false, !bSessionId)) { m_pOptions->sSessionFile.clear(); // Take appropriate action when session is loaded from // some foreign session manager (eg. JACK session)... const QString& sLadishAppName = QString::fromLatin1(::getenv("LADISH_APP_NAME")); bool bLadishApp = !sLadishAppName.isEmpty(); if (bSessionId || bLadishApp) { // JACK session manager will take care of audio connections... if (pAudioEngine) pAudioEngine->clearConnects(); // LADISH session manager will take care of MIDI connections... if (bLadishApp) m_pSession->midiEngine()->clearConnects(); } } } else { #ifdef CONFIG_NSM // Check whether to participate into a NSM session... const QString& sNsmUrl = QString::fromLatin1(::getenv("NSM_URL")); if (!sNsmUrl.isEmpty()) { m_pNsmClient = new qtractorNsmClient(sNsmUrl); QObject::connect(m_pNsmClient, SIGNAL(open()), SLOT(openNsmSession())); QObject::connect(m_pNsmClient, SIGNAL(save()), SLOT(saveNsmSession())); QObject::connect(m_pNsmClient, SIGNAL(show()), SLOT(showNsmSession())); QObject::connect(m_pNsmClient, SIGNAL(hide()), SLOT(hideNsmSession())); m_pNsmClient->announce(QTRACTOR_TITLE, ":switch:dirty:optional-gui:"); m_sNsmExt = m_pOptions->sSessionExt; if (m_sNsmExt.isEmpty()) m_sNsmExt = qtractorDocument::defaultExt(); } #endif // Change to last known session dir... if (!m_pOptions->sSessionDir.isEmpty()) { if (!QDir::setCurrent(m_pOptions->sSessionDir)) { appendMessagesError( tr("Could not set default session directory:\n\n" "%1\n\nSorry.").arg(m_pOptions->sSessionDir)); m_pOptions->sSessionDir.clear(); } } // Open up with a new empty session... newSession(); } // Final widget slot connections.... QObject::connect(m_pFiles->toggleViewAction(), SIGNAL(triggered(bool)), SLOT(stabilizeForm())); QObject::connect(m_pMessages->toggleViewAction(), SIGNAL(triggered(bool)), SLOT(stabilizeForm())); QObject::connect(m_pConnections->connectForm(), SIGNAL(connectChanged()), SLOT(contentsChanged())); QObject::connect(m_pMixer->trackRack(), SIGNAL(selectionChanged()), SLOT(mixerSelectionChanged())); QObject::connect(m_pFiles->audioListView(), SIGNAL(selected(const QString&, int, bool)), SLOT(selectAudioFile(const QString&, int, bool))); QObject::connect(m_pFiles->audioListView(), SIGNAL(activated(const QString&, int)), SLOT(activateAudioFile(const QString&, int))); QObject::connect(m_pFiles->midiListView(), SIGNAL(selected(const QString&, int, bool)), SLOT(selectMidiFile(const QString&, int, bool))); QObject::connect(m_pFiles->midiListView(), SIGNAL(activated(const QString&, int)), SLOT(activateMidiFile(const QString&, int))); QObject::connect(m_pFiles->audioListView(), SIGNAL(contentsChanged()), SLOT(contentsChanged())); QObject::connect(m_pFiles->midiListView(), SIGNAL(contentsChanged()), SLOT(contentsChanged())); QObject::connect(m_pTracks->trackList(), SIGNAL(selectionChanged()), SLOT(trackSelectionChanged())); // Other dedicated signal/slot connections... QObject::connect(m_pTracks->trackView(), SIGNAL(contentsMoving(int,int)), m_pThumbView, SLOT(updateThumb())); // Make it ready :-) statusBar()->showMessage(tr("Ready"), 3000); // Register the first timer slot. QTimer::singleShot(QTRACTOR_TIMER_DELAY, this, SLOT(timerSlot())); } // LADISH Level 1 -- SIGUSR1 signal handler. void qtractorMainForm::handle_sigusr1 (void) { #ifdef HAVE_SIGNAL_H char c; if (::read(g_fdUsr1[1], &c, sizeof(c)) > 0) saveSession(false); #endif } // LADISH termination -- SIGTERM signal handler. void qtractorMainForm::handle_sigterm (void) { #ifdef HAVE_SIGNAL_H char c; if (::read(g_fdTerm[1], &c, sizeof(c)) > 0) close(); #endif } // Window close event handlers. bool qtractorMainForm::queryClose (void) { #ifdef CONFIG_NSM if (m_pNsmClient && m_pNsmClient->is_active()) m_iDirtyCount = 0; #endif bool bQueryClose = closeSession(); // Try to save current general state... if (m_pOptions) { // Some windows default fonts is here on demand too. if (bQueryClose && m_pMessages) m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString(); // Save recent directories... if (bQueryClose && m_pFiles) { m_pOptions->sAudioDir = m_pFiles->audioListView()->recentDir(); m_pOptions->sMidiDir = m_pFiles->midiListView()->recentDir(); } // Try to save current positioning. if (bQueryClose) { // Save decorations state. m_pOptions->bMenubar = m_ui.menuBar->isVisible(); m_pOptions->bStatusbar = statusBar()->isVisible(); m_pOptions->bFileToolbar = m_ui.fileToolbar->isVisible(); m_pOptions->bEditToolbar = m_ui.editToolbar->isVisible(); m_pOptions->bTrackToolbar = m_ui.trackToolbar->isVisible(); m_pOptions->bViewToolbar = m_ui.viewToolbar->isVisible(); m_pOptions->bOptionsToolbar = m_ui.optionsToolbar->isVisible(); m_pOptions->bTransportToolbar = m_ui.transportToolbar->isVisible(); m_pOptions->bTimeToolbar = m_ui.timeToolbar->isVisible(); m_pOptions->bThumbToolbar = m_ui.thumbToolbar->isVisible(); m_pOptions->bTrackViewSnapZebra = m_ui.viewSnapZebraAction->isChecked(); m_pOptions->bTrackViewSnapGrid = m_ui.viewSnapGridAction->isChecked(); m_pOptions->bTrackViewToolTips = m_ui.viewToolTipsAction->isChecked(); m_pOptions->bTrackViewCurveEdit = m_ui.editSelectModeCurveAction->isChecked(); m_pOptions->bMetronome = m_ui.transportMetroAction->isChecked(); m_pOptions->bFollowPlayhead = m_ui.transportFollowAction->isChecked(); m_pOptions->bAutoBackward = m_ui.transportAutoBackwardAction->isChecked(); m_pOptions->bContinuePastEnd = m_ui.transportContinueAction->isChecked(); m_pOptions->bAutoMonitor = m_ui.trackAutoMonitorAction->isChecked(); // Final zoom mode... if (m_pTracks) m_pOptions->iZoomMode = m_pTracks->zoomMode(); // Save instrument definition file list... m_pOptions->instrumentFiles = (m_pSession->instruments())->files(); // Save custom meter colors, if any... int iColor; m_pOptions->audioMeterColors.clear(); for (iColor = 0; iColor < qtractorAudioMeter::ColorCount - 2; ++iColor) m_pOptions->audioMeterColors.append( qtractorAudioMeter::color(iColor).name()); m_pOptions->midiMeterColors.clear(); for (iColor = 0; iColor < qtractorMidiMeter::ColorCount - 2; ++iColor) m_pOptions->midiMeterColors.append( qtractorMidiMeter::color(iColor).name()); // Make sure there will be defaults... m_pOptions->iSnapPerBeat = m_pSnapPerBeatComboBox->currentIndex(); m_pOptions->fTempo = m_pTempoSpinBox->tempo(); m_pOptions->iBeatsPerBar = m_pTempoSpinBox->beatsPerBar(); m_pOptions->iBeatDivisor = m_pTempoSpinBox->beatDivisor(); // Save the dock windows state. m_pOptions->settings().setValue("/Layout/DockWindows", saveState()); // Audio master bus auto-connection option... qtractorAudioEngine *pAudioEngine = m_pSession->audioEngine(); if (pAudioEngine) m_pOptions->bAudioMasterAutoConnect = pAudioEngine->isMasterAutoConnect(); // And the main windows state. m_pOptions->saveWidgetGeometry(m_pConnections); m_pOptions->saveWidgetGeometry(m_pMixer); m_pOptions->saveWidgetGeometry(this, true); } } return bQueryClose; } void qtractorMainForm::closeEvent ( QCloseEvent *pCloseEvent ) { // Let's be sure about that... if (queryClose()) { pCloseEvent->accept(); QApplication::quit(); } else { pCloseEvent->ignore(); } } // Window drag-n-drop event handlers. void qtractorMainForm::dragEnterEvent ( QDragEnterEvent *pDragEnterEvent ) { // Accept external drags only... if (pDragEnterEvent->source() == NULL && pDragEnterEvent->mimeData()->hasUrls()) { pDragEnterEvent->accept(); } else { pDragEnterEvent->ignore(); } } void qtractorMainForm::dropEvent ( QDropEvent *pDropEvent ) { // Accept externally originated drops only... if (pDropEvent->source()) return; const QMimeData *pMimeData = pDropEvent->mimeData(); if (pMimeData->hasUrls()) { QString sFilename = pMimeData->urls().first().toLocalFile(); // Close current session and try to load the new one... if (!sFilename.isEmpty() && closeSession()) loadSessionFile(sFilename); } } // Context menu event handler. void qtractorMainForm::contextMenuEvent ( QContextMenuEvent *pEvent ) { stabilizeForm(); // Primordial edit menu should be available... m_ui.editMenu->exec(pEvent->globalPos()); } // Optional main widget visibility handler. void qtractorMainForm::showEvent ( QShowEvent *pShowEvent ) { QMainWindow::showEvent(pShowEvent); #ifdef CONFIG_NSM if (m_pNsmClient) m_pNsmClient->visible(true); #endif } void qtractorMainForm::hideEvent ( QHideEvent *pHideEvent ) { #ifdef CONFIG_NSM if (m_pNsmClient) m_pNsmClient->visible(false); #endif QMainWindow::hideEvent(pHideEvent); } //------------------------------------------------------------------------- // qtractorMainForm -- Brainless public property accessors. // The global session tracks reference. qtractorTracks *qtractorMainForm::tracks (void) const { return m_pTracks; } // The global session file(lists) reference. qtractorFiles *qtractorMainForm::files (void) const { return m_pFiles; } // The global session connections reference. qtractorConnections *qtractorMainForm::connections (void) const { return m_pConnections; } // The global session mixer reference. qtractorMixer *qtractorMainForm::mixer (void) const { return m_pMixer; } // The session thumb-view widget accessor. qtractorThumbView *qtractorMainForm::thumbView (void) const { return m_pThumbView; } // The session transport fast-rolling direction accessor. int qtractorMainForm::rolling (void) const { return m_iTransportRolling; } //------------------------------------------------------------------------- // qtractorMainForm -- Session file stuff. // Format the displayable session filename. QString qtractorMainForm::sessionName ( const QString& sFilename ) { bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath); QString sSessionName = sFilename; if (sSessionName.isEmpty() && m_pSession) sSessionName = m_pSession->sessionName(); if (sSessionName.isEmpty()) sSessionName = tr("Untitled%1").arg(m_iUntitled); else if (!bCompletePath) sSessionName = QFileInfo(sSessionName).baseName(); return sSessionName; } // Create a new session file from scratch. bool qtractorMainForm::newSession (void) { // Check if we can do it. if (!closeSession()) return false; #ifdef CONFIG_LV2 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); qtractorLv2PluginType::lv2_open(); QApplication::restoreOverrideCursor(); #endif // We're supposedly clean... m_iDirtyCount = 0; // Check whether we start the new session // based on existing template... if (m_pOptions && m_pOptions->bSessionTemplate) { const bool bNewSession = loadSessionFileEx(m_pOptions->sSessionTemplatePath, true, false); #ifdef CONFIG_NSM if (m_pNsmClient && m_pNsmClient->is_active()) updateDirtyCount(true); #endif return bNewSession; } // Prepare the session engines... updateSessionPre(); // Ok, increment untitled count. ++m_iUntitled; // Stabilize form. m_sFilename.clear(); // m_iDirtyCount = 0; appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename))); // Give us what we got, right now... updateSessionPost(); return true; } // Open an existing sampler session. bool qtractorMainForm::openSession (void) { if (m_pOptions == NULL) return false; // Ask for the filename to open... QString sFilename; QString sExt("qtr"); QStringList filters; #ifdef CONFIG_LIBZ filters.append(tr("Session files (*.%1 *.%2 *.%3)") .arg(sExt).arg(qtractorDocument::defaultExt()) .arg(qtractorDocument::archiveExt())); #else filters.append(tr("Session files (*.%1 *.%2)") .arg(sExt).arg(qtractorDocument::defaultExt())); #endif filters.append(tr("Template files (*.%1)") .arg(qtractorDocument::templateExt())); #ifdef CONFIG_LIBZ filters.append(tr("Archive files (*.%1)") .arg(qtractorDocument::archiveExt())); #endif sExt = m_pOptions->sSessionExt; // Default session file format... const QString& sTitle = tr("Open Session") + " - " QTRACTOR_TITLE; const QString& sFilter = filters.join(";;"); #if 0//QT_VERSION < 0x040400 sFilename = QFileDialog::getOpenFileName(this, sTitle, m_pOptions->sSessionDir, sFilter); #else // Construct open-file session/template dialog... QFileDialog fileDialog(this, sTitle, m_pOptions->sSessionDir, sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::ExistingFile); fileDialog.setHistory(m_pOptions->recentFiles); fileDialog.setDefaultSuffix(sExt); #ifdef CONFIG_LIBZ // Special case for archive by default... if (sExt == qtractorDocument::archiveExt()) fileDialog.setNameFilter(filters.last()); #endif // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(m_pOptions->sSessionDir)); fileDialog.setSidebarUrls(urls); // Show dialog... if (!fileDialog.exec()) return false; // Have the open-file name... sFilename = fileDialog.selectedFiles().first(); #endif // Have we cancelled? if (sFilename.isEmpty()) return false; // Check if we're going to discard safely the current one... if (!closeSession()) return false; // Load it right away. return loadSessionFile(sFilename); } // Save current sampler session with another name. bool qtractorMainForm::saveSession ( bool bPrompt ) { if (m_pOptions == NULL) return false; // It must be a session name... if (m_pSession->sessionName().isEmpty() && !editSession()) return false; // Suggest a filename, if there's none... QString sFilename = m_sFilename; if (sFilename.isEmpty()) { sFilename = QFileInfo(m_pOptions->sSessionDir, qtractorSession::sanitize(m_pSession->sessionName())).filePath(); bPrompt = true; } // Ask for the file to save... if (bPrompt) { // Prompt the guy... QString sExt("qtr"); QStringList filters; #ifdef CONFIG_LIBZ filters.append(tr("Session files (*.%1 *.%2 *.%3)") .arg(sExt).arg(qtractorDocument::defaultExt()) .arg(qtractorDocument::archiveExt())); #else filters.append(tr("Session files (*.%1 *.%2)") .arg(sExt).arg(qtractorDocument::defaultExt())); #endif filters.append(tr("Template files (*.%1)") .arg(qtractorDocument::templateExt())); #ifdef CONFIG_LIBZ filters.append(tr("Archive files (*.%1)") .arg(qtractorDocument::archiveExt())); #endif sExt = m_pOptions->sSessionExt; // Default session file format... const QString& sTitle = tr("Save Session") + " - " QTRACTOR_TITLE; const QString& sFilter = filters.join(";;"); #if 0//QT_VERSION < 0x040400 sFilename = QFileDialog::getSaveFileName(this, sTitle, sFilename, sFilter); #else // Construct save-file session/template dialog... QFileDialog fileDialog(this, sTitle, sFilename, sFilter); // Set proper save-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptSave); fileDialog.setFileMode(QFileDialog::AnyFile); fileDialog.setHistory(m_pOptions->recentFiles); fileDialog.setDefaultSuffix(sExt); #ifdef CONFIG_LIBZ // Special case for archive by default... if (sExt == qtractorDocument::archiveExt()) fileDialog.setNameFilter(filters.last()); #endif // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(m_pOptions->sSessionDir)); fileDialog.setSidebarUrls(urls); // Show save-file dialog... if (!fileDialog.exec()) return false; // Have the save-file name... sFilename = fileDialog.selectedFiles().first(); // Check whether we're on the template or archive filter... switch (filters.indexOf(fileDialog.selectedNameFilter())) { case 1: sExt = qtractorDocument::templateExt(); break; case 2: sExt = qtractorDocument::archiveExt(); break; } #endif // Have we cancelled it? if (sFilename.isEmpty()) return false; // Enforce extension... if (QFileInfo(sFilename).suffix().isEmpty()) { sFilename += '.' + sExt; // Check if already exists... if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) { if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("The file already exists:\n\n" "\"%1\"\n\n" "Do you want to replace it?") .arg(sFilename), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return false; } } // Reset backup count, anyway... m_iBackupCount = 0; } else // Backup versioning? if (m_pOptions->bSessionBackup) { const QFileInfo f1(sFilename); if (f1.exists()) { int iBackupNo = 0; const QDir& dir = f1.absoluteDir(); QString sNameMask = f1.completeBaseName(); if (m_pOptions->iSessionBackupMode > 0) { QRegExp rxBackupNo("\\.([0-9]+)$"); if (rxBackupNo.indexIn(sNameMask) >= 0) { iBackupNo = rxBackupNo.cap(1).toInt(); sNameMask.remove(rxBackupNo); } } sNameMask += ".%1." + f1.suffix(); QFileInfo f2(dir, sNameMask.arg(++iBackupNo)); while (f2.exists()) f2.setFile(dir, sNameMask.arg(++iBackupNo)); if (m_pOptions->iSessionBackupMode > 0) { // Remove from recent files list... if (m_iBackupCount > 0) { int iIndex = m_pOptions->recentFiles.indexOf(sFilename); if (iIndex >= 0) m_pOptions->recentFiles.removeAt(iIndex); // Also remove from sile system...? QFile::remove(sFilename); } // Make it a brand new one... sFilename = f2.absoluteFilePath(); ++m_iBackupCount; } else if (QFile(sFilename).rename(f2.absoluteFilePath())) { appendMessages( tr("Backup session: \"%1\" as \"%2\".") .arg(sFilename).arg(f2.fileName())); } else { appendMessagesError( tr("Could not backup existing session:\n\n" "%1 as %2\n\nSorry.").arg(sFilename).arg(f2.fileName())); } } } // Save it right away. return saveSessionFile(sFilename); } // Edit session properties. bool qtractorMainForm::editSession (void) { // Session Properties... qtractorSessionForm sessionForm(this); sessionForm.setSession(m_pSession); if (!sessionForm.exec()) return false; // If currently playing, we need to do a stop and go... bool bPlaying = m_pSession->isPlaying(); if (bPlaying) m_pSession->lock(); // Take care of session name changes... const QString sOldSessionName = m_pSession->sessionName(); // Now, express the change as a undoable command... m_pSession->execute( new qtractorSessionEditCommand(m_pSession, sessionForm.properties())); // If session name has changed, we'll prompt // for correct filename when save is triggered... if (m_pSession->sessionName() != sOldSessionName) m_sFilename.clear(); // Restore playback state, if needed... if (bPlaying) m_pSession->unlock(); // Transport status needs an update too... ++m_iTransportUpdate; // Done. return true; } // Close current session. bool qtractorMainForm::closeSession (void) { bool bClose = true; // Are we dirty enough to prompt it? if (bClose && m_iDirtyCount > 0) { switch (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("The current session has been changed:\n\n" "\"%1\"\n\n" "Do you want to save the changes?") .arg(sessionName(m_sFilename)), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel)) { case QMessageBox::Save: bClose = saveSession(false); // Fall thru.... case QMessageBox::Discard: break; default: // Cancel. bClose = false; break; } } // If we may close it, do it! if (bClose) { // Just in case we were in the middle of something... setPlaying(false); // Reset all dependables to default. m_pMixer->clear(); m_pFiles->clear(); // Close session engines. m_pSession->close(); m_pSession->clear(); m_pTempoCursor->clear(); // And last but not least. m_pConnections->clear(); m_pTracks->clear(); // Reset playhead. m_iPlayHead = 0; #ifdef CONFIG_LV2 qtractorLv2PluginType::lv2_close(); #endif #ifdef CONFIG_LIBZ // Is it time to cleanup extracted archives? const QStringList& paths = qtractorDocument::extractedArchives(); if (!paths.isEmpty()) { bool bArchiveRemove = true; bool bConfirmRemove = (m_pOptions && m_pOptions->bConfirmRemove); #ifdef CONFIG_NSM if (m_pNsmClient && m_pNsmClient->is_active()) bConfirmRemove = false; #endif if (bConfirmRemove && QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("About to remove archive directory:\n\n" "\"%1\"\n\n" "Are you sure?") .arg(paths.join("\",\n\"")), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { bArchiveRemove = false; } qtractorDocument::clearExtractedArchives(bArchiveRemove); } #endif // Some defaults are due... if (m_pOptions) { m_pSession->setSessionDir(m_pOptions->sSessionDir); m_pSession->setSnapPerBeat( qtractorTimeScale::snapFromIndex(m_pOptions->iSnapPerBeat)); m_pSession->setTempo(m_pOptions->fTempo); m_pSession->setBeatsPerBar(m_pOptions->iBeatsPerBar); m_pSession->setBeatDivisor(m_pOptions->iBeatDivisor); } // We're now clean, for sure. m_iDirtyCount = 0; m_iBackupCount = 0; appendMessages(tr("Session closed.")); } return bClose; } // Load a session from specific file path. bool qtractorMainForm::loadSessionFileEx ( const QString& sFilename, bool bTemplate, bool bUpdate ) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::loadSessionFileEx(\"%s\", %d, %d)", sFilename.toUtf8().constData(), int(bTemplate), int(bUpdate)); #endif // Flag whether we're about to save as template or archive... QFileInfo info(sFilename); int iFlags = qtractorDocument::Default; const QString& sSuffix = info.suffix(); if (sSuffix == qtractorDocument::templateExt() || bTemplate) { iFlags |= qtractorDocument::Template; bTemplate = true; } #ifdef CONFIG_LIBZ if (sSuffix == qtractorDocument::archiveExt()) { iFlags |= qtractorDocument::Archive; // Take special precaution for already // existing non-temporary archive directory... if (!bUpdate) { iFlags |= qtractorDocument::Temporary; } else { info.setFile(info.path() + QDir::separator() + info.completeBaseName()); if (info.exists() && info.isDir()) { if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("The directory already exists:\n\n" "\"%1\"\n\n" "Do you want to replace it?") .arg(info.filePath()), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) { // Restarting... #ifdef CONFIG_LV2 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); qtractorLv2PluginType::lv2_open(); QApplication::restoreOverrideCursor(); #endif updateSessionPre(); ++m_iUntitled; m_sFilename.clear(); updateSessionPost(); return false; } } } } #endif // Tell the world we'll take some time... appendMessages(tr("Opening \"%1\"...").arg(sFilename)); #ifdef CONFIG_LV2 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); qtractorLv2PluginType::lv2_open(); QApplication::restoreOverrideCursor(); #endif // Warm-up the session engines... updateSessionPre(); // We'll take some time anyhow... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // Read the file. QDomDocument doc("qtractorSession"); bool bResult = qtractorSessionDocument(&doc, m_pSession, m_pFiles) .load(sFilename, qtractorDocument::Flags(iFlags)); // We're formerly done. QApplication::restoreOverrideCursor(); if (bResult) { // Got something loaded... // we're not dirty anymore. if (!bTemplate && bUpdate) { updateRecentFiles(sFilename); // m_iDirtyCount = 0; } // Save as default session directory... if (m_pOptions && bUpdate) { m_pOptions->sSessionDir = QFileInfo(sFilename).absolutePath(); m_pOptions->saveOptions(); } } else { // Something went wrong... appendMessagesError( tr("Session could not be loaded\n" "from \"%1\".\n\n" "Sorry.").arg(sFilename)); } // Stabilize form title... if (bTemplate) { ++m_iUntitled; m_sFilename.clear(); } else if (bUpdate) { m_sFilename = sFilename; } appendMessages(tr("Open session: \"%1\".").arg(sessionName(sFilename))); // Now we'll try to create (update) the whole GUI session. updateSessionPost(); return bResult; } bool qtractorMainForm::loadSessionFile ( const QString& sFilename ) { bool bUpdate = true; // We're supposedly clean... m_iDirtyCount = 0; #ifdef CONFIG_NSM if (m_pNsmClient && m_pNsmClient->is_active()) { m_pSession->setClientName(m_pNsmClient->client_id()); bUpdate = false; } #endif bool bLoadSessionFile = loadSessionFileEx(sFilename, false, bUpdate); #ifdef CONFIG_NSM if (m_pNsmClient && m_pNsmClient->is_active()) { m_pSession->setSessionName(m_pNsmClient->display_name()); m_pSession->setSessionDir(m_pNsmClient->path_name()); m_sNsmExt = QFileInfo(sFilename).suffix(); updateDirtyCount(true); stabilizeForm(); } #endif return bLoadSessionFile; } // Save current session to specific file path. bool qtractorMainForm::saveSessionFileEx ( const QString& sFilename, bool bTemplate, bool bUpdate ) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::saveSessionFileEx(\"%s\", %d, %d)", sFilename.toUtf8().constData(), int(bTemplate), int(bUpdate)); #endif // Flag whether we're about to save as template or archive... int iFlags = qtractorDocument::Default; const QString& sSuffix = QFileInfo(sFilename).suffix(); if (sSuffix == qtractorDocument::templateExt() || bTemplate) { iFlags |= qtractorDocument::Template; bTemplate = true; } #ifdef CONFIG_LIBZ if (sSuffix == qtractorDocument::archiveExt()) iFlags |= qtractorDocument::Archive; #endif // Tell the world we'll take some time... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); appendMessages(tr("Saving \"%1\"...").arg(sFilename)); // Trap dirty clips (only MIDI at this time...) for (qtractorTrack *pTrack = m_pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { // Only MIDI track/clips... if (pTrack->trackType() != qtractorTrack::Midi) continue; for (qtractorClip *pClip = pTrack->clips().first(); pClip; pClip = pClip->next()) { // Are any dirty changes pending commit? if (pClip->isDirty()) { qtractorMidiClip *pMidiClip = static_cast (pClip); if (pMidiClip) pMidiClip->saveCopyFile(); } } } // Soft-house-keeping... m_pSession->files()->cleanup(false); // Write the file... QDomDocument doc("qtractorSession"); bool bResult = qtractorSessionDocument(&doc, m_pSession, m_pFiles) .save(sFilename, qtractorDocument::Flags(iFlags)); #ifdef CONFIG_LIBZ if ((iFlags & qtractorDocument::Archive) == 0) qtractorDocument::clearExtractedArchives(); #endif // We're formerly done. QApplication::restoreOverrideCursor(); if (bResult) { // Got something saved... // we're not dirty anymore. if (!bTemplate && bUpdate) { updateRecentFiles(sFilename); m_iDirtyCount = 0; } // Save some default session properties... if (m_pOptions && bUpdate) { qtractorAudioEngine *pAudioEngine = m_pSession->audioEngine(); if (pAudioEngine) m_pOptions->iTransportMode = int(pAudioEngine->transportMode()); qtractorMidiEngine *pMidiEngine = m_pSession->midiEngine(); if (pMidiEngine) { m_pOptions->iMidiMmcMode = int(pMidiEngine->mmcMode()); m_pOptions->iMidiMmcDevice = int(pMidiEngine->mmcDevice()); m_pOptions->iMidiSppMode = int(pMidiEngine->sppMode()); m_pOptions->iMidiClockMode = int(pMidiEngine->clockMode()); } m_pOptions->sSessionDir = QFileInfo(sFilename).absolutePath(); m_pOptions->saveOptions(); } } else { // Something went wrong... appendMessagesError( tr("Session could not be saved\n" "to \"%1\".\n\n" "Sorry.").arg(sFilename)); } // Stabilize form title... if (!bTemplate && bUpdate) m_sFilename = sFilename; appendMessages(tr("Save session: \"%1\".").arg(sessionName(sFilename))); // Show static results... stabilizeForm(); return bResult; } bool qtractorMainForm::saveSessionFile ( const QString& sFilename ) { return saveSessionFileEx(sFilename, false, true); } //------------------------------------------------------------------------- // qtractorMainForm -- NSM client slots. void qtractorMainForm::openNsmSession (void) { #ifdef CONFIG_NSM if (m_pNsmClient == NULL) return; if (!m_pNsmClient->is_active()) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::openNsmSession()"); #endif // We're supposedly clean... m_iDirtyCount = 0; m_bNsmDirty = false; m_sNsmFile.clear(); bool bLoaded = false; if (closeSession()) { const QString& path_name = m_pNsmClient->path_name(); const QString& display_name = m_pNsmClient->display_name(); const QString& client_id = m_pNsmClient->client_id(); const QDir dir(path_name); if (!dir.exists()) { dir.mkpath(path_name); } else { QStringList filters; const QString& prefix_dot = display_name + "*."; filters << prefix_dot + qtractorDocument::defaultExt(); filters << prefix_dot + qtractorDocument::templateExt(); filters << prefix_dot + qtractorDocument::archiveExt(); filters << prefix_dot + "qtr"; const QStringList& files = dir.entryList(filters, QDir::Files | QDir::NoSymLinks | QDir::Readable, QDir::Time); if (!files.isEmpty()) m_sNsmExt = QFileInfo(files.first()).suffix(); } m_pSession->setClientName(client_id); m_pSession->setSessionName(display_name); m_pSession->setSessionDir(path_name); const QFileInfo fi(path_name, display_name + '.' + m_sNsmExt); const QString& sFilename = fi.absoluteFilePath(); if (fi.exists()) { bLoaded = loadSessionFileEx(sFilename, false, false); if (bLoaded) m_sNsmFile = sFilename; } else { updateSessionPre(); #ifdef CONFIG_LV2 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); qtractorLv2PluginType::lv2_open(); QApplication::restoreOverrideCursor(); #endif appendMessages(tr("New session: \"%1\".") .arg(sessionName(sFilename))); updateSessionPost(); bLoaded = true; } } m_pNsmClient->open_reply(bLoaded ? qtractorNsmClient::ERR_OK : qtractorNsmClient::ERR_GENERAL); if (bLoaded) m_pNsmClient->dirty(false); m_pNsmClient->visible(QMainWindow::isVisible()); #endif // CONFIG_NSM } void qtractorMainForm::saveNsmSession (void) { #ifdef CONFIG_NSM if (m_pNsmClient == NULL) return; if (!m_pNsmClient->is_active()) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::saveNsmSession()"); #endif saveNsmSessionEx(true); #endif // CONFIG_NSM } void qtractorMainForm::saveNsmSessionEx ( bool bSaveReply ) { #ifdef CONFIG_NSM bool bSaved = true; if (!m_sNsmFile.isEmpty()) { const QFileInfo fi(m_sNsmFile); if (fi.exists() && fi.suffix() != m_sNsmExt) { QFile(m_sNsmFile).remove(); m_sNsmFile.clear(); } } if (!bSaveReply || m_bNsmDirty) { m_iDirtyCount = 0; m_bNsmDirty = false; const QString& path_name = m_pNsmClient->path_name(); const QString& display_name = m_pNsmClient->display_name(); // const QString& client_id = m_pNsmClient->client_id(); // m_pSession->setClientName(client_id); m_pSession->setSessionName(display_name); m_pSession->setSessionDir(path_name); const QFileInfo fi(path_name, display_name + '.' + m_sNsmExt); const QString& sFilename = fi.absoluteFilePath(); bSaved = saveSessionFileEx(sFilename, false, false); if (bSaved) m_sNsmFile = sFilename; } if (bSaveReply) { m_pNsmClient->save_reply(bSaved ? qtractorNsmClient::ERR_OK : qtractorNsmClient::ERR_GENERAL); } if (bSaved) m_pNsmClient->dirty(false); #endif // CONFIG_NSM } void qtractorMainForm::showNsmSession (void) { #ifdef CONFIG_NSM if (m_pNsmClient == NULL) return; if (!m_pNsmClient->is_active()) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::showNsmSession()"); #endif QMainWindow::show(); QMainWindow::raise(); QMainWindow::activateWindow(); #endif // CONFIG_NSM } void qtractorMainForm::hideNsmSession (void) { #ifdef CONFIG_NSM if (m_pNsmClient == NULL) return; if (!m_pNsmClient->is_active()) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::hideNsmSession()"); #endif QMainWindow::hide(); #endif // CONFIG_NSM } //------------------------------------------------------------------------- // qtractorMainForm -- File Action slots. // Create a new sampler session. void qtractorMainForm::fileNew (void) { // Of course we'll start clean new. newSession(); } // Open an existing sampler session. void qtractorMainForm::fileOpen (void) { // Open it right away. openSession(); } // Open a recent file session. void qtractorMainForm::fileOpenRecent (void) { // Retrive filename index from action data... QAction *pAction = qobject_cast (sender()); if (pAction && m_pOptions) { int iIndex = pAction->data().toInt(); if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) { QString sFilename = m_pOptions->recentFiles[iIndex]; // Check if we can safely close the current session... if (!sFilename.isEmpty() && closeSession()) loadSessionFile(sFilename); } } } // Save current sampler session. void qtractorMainForm::fileSave (void) { #ifdef CONFIG_NSM if (m_pNsmClient && m_pNsmClient->is_active()) { saveNsmSessionEx(false); return; } #endif // Save it right away. saveSession(false); } // Save current sampler session with another name. void qtractorMainForm::fileSaveAs (void) { #ifdef CONFIG_NSM if (m_pNsmClient && m_pNsmClient->is_active()) { // saveNsmSessionEx(false); return; } #endif // Save it right away, maybe with another name. saveSession(true); } // Edit session properties. void qtractorMainForm::fileProperties (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::fileProperties()"); #endif // Session Properties... editSession(); } // Exit application program. void qtractorMainForm::fileExit (void) { // Go for close the whole thing. close(); } //------------------------------------------------------------------------- // qtractorMainForm -- Edit Action slots. // Undo last action. void qtractorMainForm::editUndo (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editUndo()"); #endif (m_pSession->commands())->undo(); } // Redo last action. void qtractorMainForm::editRedo (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editRedo()"); #endif (m_pSession->commands())->redo(); } // Cut selection to clipboard. void qtractorMainForm::editCut (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editCut()"); #endif // Cut from files... if (m_pFiles && m_pFiles->hasFocus()) m_pFiles->cutItemSlot(); else // Cut selection... if (m_pTracks) m_pTracks->cutClipboard(); } // Copy selection to clipboard. void qtractorMainForm::editCopy (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editCopy()"); #endif // Copy from files... if (m_pFiles && m_pFiles->hasFocus()) m_pFiles->copyItemSlot(); else // Copy selection... if (m_pTracks) m_pTracks->copyClipboard(); stabilizeForm(); } // Paste clipboard contents. void qtractorMainForm::editPaste (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editPaste()"); #endif // Paste to files... if (m_pFiles && m_pFiles->hasFocus()) m_pFiles->pasteItemSlot(); else // Paste selection... if (m_pTracks) m_pTracks->pasteClipboard(); } // Paste/repeat clipboard contents. void qtractorMainForm::editPasteRepeat (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editPasteRepeat()"); #endif // Paste/repeat selection... if (m_pTracks) m_pTracks->pasteRepeatClipboard(); } // Delete selection. void qtractorMainForm::editDelete (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editDelete()"); #endif // Delete from files... if (m_pFiles && m_pFiles->hasFocus()) m_pFiles->removeItemSlot(); else // Delete selection... if (m_pTracks) m_pTracks->deleteSelect(); } // Set selection to whole clip mode. void qtractorMainForm::editSelectModeClip (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editSelectModeClip()"); #endif // Select clip mode... if (m_pTracks) { qtractorTrackView *pTrackView = m_pTracks->trackView(); pTrackView->setSelectMode(qtractorTrackView::SelectClip); pTrackView->setCurveEdit(false); } if (m_pOptions) m_pOptions->iTrackViewSelectMode = 0; stabilizeForm(); } // Set selection to range mode. void qtractorMainForm::editSelectModeRange (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editSelectModeRange()"); #endif // Select clip mode... if (m_pTracks) { qtractorTrackView *pTrackView = m_pTracks->trackView(); pTrackView->setSelectMode(qtractorTrackView::SelectRange); pTrackView->setCurveEdit(false); } if (m_pOptions) m_pOptions->iTrackViewSelectMode = 1; stabilizeForm(); } // Set selection to rectangularmode. void qtractorMainForm::editSelectModeRect (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editSelectModeRect()"); #endif // Select clip mode... if (m_pTracks) { qtractorTrackView *pTrackView = m_pTracks->trackView(); pTrackView->setSelectMode(qtractorTrackView::SelectRect); pTrackView->setCurveEdit(false); } if (m_pOptions) m_pOptions->iTrackViewSelectMode = 2; stabilizeForm(); } // Special automation curve node edit mode. void qtractorMainForm::editSelectModeCurve (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editSelectModeCurve()"); #endif if (m_pTracks) m_pTracks->trackView()->setCurveEdit(true); } // Mark all as selected. void qtractorMainForm::editSelectAll (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editSelectAll()"); #endif // Select all... if (m_pTracks) m_pTracks->selectAll(); stabilizeForm(); } // Mark all as unselected. void qtractorMainForm::editSelectNone (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editSelectNone()"); #endif // Select nothing... if (m_pTracks) m_pTracks->selectNone(); stabilizeForm(); } // Invert current selection. void qtractorMainForm::editSelectInvert (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editSelectInvert()"); #endif // Invert selection... if (m_pTracks) m_pTracks->selectInvert(); stabilizeForm(); } // Mark track as selected. void qtractorMainForm::editSelectTrack (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editSelectTrack()"); #endif // Select current track... if (m_pTracks) m_pTracks->selectCurrentTrack(); stabilizeForm(); } // Mark track-range as selected. void qtractorMainForm::editSelectTrackRange (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editSelectTrackRange()"); #endif // Select track-range... if (m_pTracks) m_pTracks->selectCurrentTrackRange(); stabilizeForm(); } // Mark range as selected. void qtractorMainForm::editSelectRange (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editSelectRange()"); #endif // Select edit-range... if (m_pTracks) m_pTracks->selectEditRange(); stabilizeForm(); } // Insert range as selected. void qtractorMainForm::editInsertRange (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editInsertRange()"); #endif // Insert edit-range... if (m_pTracks) m_pTracks->insertEditRange(); stabilizeForm(); } // Insert track-range as selected. void qtractorMainForm::editInsertTrackRange (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editInsertTrackRange()"); #endif // Select track-range... if (m_pTracks) m_pTracks->insertEditRange(m_pTracks->currentTrack()); stabilizeForm(); } // Remove range as selected. void qtractorMainForm::editRemoveRange (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editRemoveRange()"); #endif // Insert edit-range... if (m_pTracks) m_pTracks->removeEditRange(); stabilizeForm(); } // Remove track-range as selected. void qtractorMainForm::editRemoveTrackRange (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editRemoveTrackRange()"); #endif // Select track-range... if (m_pTracks) m_pTracks->removeEditRange(m_pTracks->currentTrack()); stabilizeForm(); } // Split (clip) selection... void qtractorMainForm::editSplit (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::editSplit()"); #endif // Split selection... if (m_pTracks) m_pTracks->splitSelect(); stabilizeForm(); } //------------------------------------------------------------------------- // qtractorMainForm -- Track Action slots. // Add a new track to session. void qtractorMainForm::trackAdd (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackAdd()"); #endif // Add Track... if (m_pTracks) m_pTracks->addTrack(); } // Remove current track from session. void qtractorMainForm::trackRemove (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackRemove()"); #endif // Remove Track... if (m_pTracks) m_pTracks->removeTrack(); } // Edit track properties on session. void qtractorMainForm::trackProperties (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackProperties()"); #endif // Track Properties... if (m_pTracks) m_pTracks->editTrack(); } // Show current track input bus connections. void qtractorMainForm::trackInputs (void) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; if (pTrack->inputBus() == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackInputs()"); #endif if (m_pConnections) m_pConnections->showBus(pTrack->inputBus(), qtractorBus::Input); } // Show current track output bus connections. void qtractorMainForm::trackOutputs (void) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; if (pTrack->outputBus() == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackOutputs()"); #endif if (m_pConnections) m_pConnections->showBus(pTrack->outputBus(), qtractorBus::Output); } // Arm current track for recording. void qtractorMainForm::trackStateRecord ( bool bOn ) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackStateRecord(%d)", int(bOn)); #endif m_pSession->execute( new qtractorTrackStateCommand(pTrack, qtractorTrack::Record, bOn)); } // Mute current track. void qtractorMainForm::trackStateMute ( bool bOn ) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackStateMute(%d)", int(bOn)); #endif m_pSession->execute( new qtractorTrackStateCommand(pTrack, qtractorTrack::Mute, bOn)); } // Solo current track. void qtractorMainForm::trackStateSolo ( bool bOn ) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackStateSolo(%d)", int(bOn)); #endif m_pSession->execute( new qtractorTrackStateCommand(pTrack, qtractorTrack::Solo, bOn)); } // Monitor current track. void qtractorMainForm::trackStateMonitor ( bool bOn ) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackStateMonitor(%d)", int(bOn)); #endif m_pSession->execute( new qtractorTrackMonitorCommand(pTrack, bOn)); } // Make current the first track on list. void qtractorMainForm::trackNavigateFirst (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackNavigateFirst()"); #endif if (m_pTracks && m_pTracks->trackList()) (m_pTracks->trackList())->setCurrentTrackRow(0); } // Make current the previous track on list. void qtractorMainForm::trackNavigatePrev (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackNavigatePrev()"); #endif if (m_pTracks && m_pTracks->trackList()) { int iTrack = (m_pTracks->trackList())->currentTrackRow(); if (iTrack < 0 && (m_pTracks->trackList())->trackRowCount() > 0) iTrack = 1; if (iTrack > 0) (m_pTracks->trackList())->setCurrentTrackRow(iTrack - 1); } } // Make current the next track on list. void qtractorMainForm::trackNavigateNext (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackNavigateNext()"); #endif if (m_pTracks && m_pTracks->trackList()) { int iTrack = (m_pTracks->trackList())->currentTrackRow(); if (iTrack < (m_pTracks->trackList())->trackRowCount() - 1) (m_pTracks->trackList())->setCurrentTrackRow(iTrack + 1); } } // Make current the last track on list. void qtractorMainForm::trackNavigateLast (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackNavigateLast()"); #endif if (m_pTracks && m_pTracks->trackList()) { int iLastTrack = (m_pTracks->trackList())->trackRowCount() - 1; if (iLastTrack >= 0) (m_pTracks->trackList())->setCurrentTrackRow(iLastTrack); } } // Make none current track on list. void qtractorMainForm::trackNavigateNone (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackNavigateNone()"); #endif if (m_pTracks && m_pTracks->trackList()) (m_pTracks->trackList())->setCurrentTrackRow(-1); } // Move current track to top of list. void qtractorMainForm::trackMoveTop (void) { if (m_pSession == NULL) return; qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackMoveTop()"); #endif m_pSession->execute( new qtractorMoveTrackCommand(pTrack, m_pSession->tracks().first())); } // Move current track up towards the top of list. void qtractorMainForm::trackMoveUp (void) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; qtractorTrack *pNextTrack = pTrack->prev(); if (pNextTrack == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackMoveUp()"); #endif m_pSession->execute( new qtractorMoveTrackCommand(pTrack, pNextTrack)); } // Move current track down towards the bottom of list void qtractorMainForm::trackMoveDown (void) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; qtractorTrack *pNextTrack = pTrack->next(); if (pNextTrack == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackMoveDown()"); #endif m_pSession->execute( new qtractorMoveTrackCommand(pTrack, pNextTrack->next())); } // Move current track to bottom of list. void qtractorMainForm::trackMoveBottom (void) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackMoveBottom()"); #endif m_pSession->execute( new qtractorMoveTrackCommand(pTrack, NULL)); } // Increase current track height. void qtractorMainForm::trackHeightUp (void) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackHeightUp()"); #endif int iZoomHeight = (150 * pTrack->zoomHeight()) / 100; m_pSession->execute( new qtractorResizeTrackCommand(pTrack, iZoomHeight)); } // Decreate current track height. void qtractorMainForm::trackHeightDown (void) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackHeightDown()"); #endif int iZoomHeight = (75 * pTrack->zoomHeight()) / 100; m_pSession->execute( new qtractorResizeTrackCommand(pTrack, iZoomHeight)); } // Reset current track height. void qtractorMainForm::trackHeightReset (void) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackHeightReset()"); #endif int iVerticalZoom = m_pSession->verticalZoom(); int iZoomHeight = (iVerticalZoom * qtractorTrack::HeightBase) / 100; m_pSession->execute( new qtractorResizeTrackCommand(pTrack, iZoomHeight)); } // Auto-monitor current track. void qtractorMainForm::trackAutoMonitor ( bool bOn ) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackAutoMonitor(%d)", int(bOn)); #endif qtractorTrack *pTrack = NULL; if (bOn && m_pTracks) pTrack = m_pTracks->currentTrack(); m_pSession->setCurrentTrack(pTrack); } // Import some tracks from Audio file. void qtractorMainForm::trackImportAudio (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackImportAudio()"); #endif // Import Audio files into tracks... if (m_pTracks) { unsigned long iClipStart = m_pSession->editHead(); m_pTracks->addAudioTracks( m_pFiles->audioListView()->openFileNames(), iClipStart); m_pTracks->trackView()->ensureVisibleFrame(iClipStart); } } // Import some tracks from MIDI file. void qtractorMainForm::trackImportMidi (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackImportMidi()"); #endif // Import MIDI files into tracks... if (m_pTracks) { unsigned long iClipStart = m_pSession->editHead(); m_pTracks->addMidiTracks( m_pFiles->midiListView()->openFileNames(), iClipStart); m_pTracks->trackView()->ensureVisibleFrame(iClipStart); } } // Export tracks to audio file. void qtractorMainForm::trackExportAudio (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackExportAudio()"); #endif qtractorExportForm exportForm(this); exportForm.setExportType(qtractorTrack::Audio); exportForm.exec(); } // Export tracks to MIDI file. void qtractorMainForm::trackExportMidi (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackExportMidi()"); #endif qtractorExportForm exportForm(this); exportForm.setExportType(qtractorTrack::Midi); exportForm.exec(); } // Track automation curve selection menu. Q_DECLARE_METATYPE(qtractorMidiControlObserver *); void qtractorMainForm::trackCurveSelect ( QAction *pAction, bool bOn ) { qtractorSubject *pSubject = NULL; qtractorCurveList *pCurveList = NULL; qtractorMidiControlObserver *pMidiObserver = pAction->data().value (); if (pMidiObserver) { pCurveList = pMidiObserver->curveList(); pSubject = pMidiObserver->subject(); } else { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack) pCurveList = pTrack->curveList(); } if (pCurveList == NULL) return; qtractorCurve *pCurve = NULL; if (bOn && pSubject) { pCurve = pSubject->curve(); if (pCurve == NULL) { qtractorCurve::Mode mode = qtractorCurve::Hold; if (m_pOptions && !pSubject->isToggled()) mode = qtractorCurve::Mode(m_pOptions->iCurveMode); pCurve = new qtractorCurve(pCurveList, pSubject, mode); pCurve->setLogarithmic(pMidiObserver->isLogarithmic()); #if 0 qtractorTrack *pTrack = m_pSession->findTrack(pCurveList); if (pTrack) pCurve->setColor(pTrack->foreground().darker(180)); #endif } } #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackCurveSelect(%p)", pCurve); #endif #if 0 pCurveList->setCurrentCurve(pCurve); m_pTracks->updateTrackList(); m_pTracks->updateTrackView(); updateDirtyCount(true); stabilizeForm(); #else m_pSession->execute(new qtractorCurveSelectCommand(pCurveList, pCurve)); #endif } void qtractorMainForm::trackCurveSelect ( bool bOn ) { QAction *pAction = qobject_cast (sender()); if (pAction) trackCurveSelect(pAction, bOn); } void qtractorMainForm::trackCurveMode ( QAction *pAction ) { int iMode = pAction->data().toInt(); if (iMode < 0) return; qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; qtractorCurve *pCurrentCurve = pTrack->currentCurve(); if (pCurrentCurve == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackCurveMode(%d)", iMode); #endif // Save as future default... if (m_pOptions) m_pOptions->iCurveMode = iMode; qtractorCurve::Mode mode = qtractorCurve::Mode(iMode); #if 0 pCurrentCurve->setMode(mode); pCurrentCurve->update(); if (!m_pSession->isPlaying()) pTrack->process_curve(m_iPlayHead); m_pTracks->updateTrackList(); m_pTracks->updateTrackView(); updateDirtyCount(true); stabilizeForm(); #else m_pSession->execute(new qtractorCurveModeCommand(pCurrentCurve, mode)); #endif } // Track automation curve lock toggle. void qtractorMainForm::trackCurveLocked ( bool bOn ) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; qtractorCurve *pCurrentCurve = pTrack->currentCurve(); if (pCurrentCurve == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackCurveLocked(%d)", int(bOn)); #endif pCurrentCurve->setLocked(bOn); m_pTracks->updateTrackView(); updateDirtyCount(true); stabilizeForm(); } // Track automation curve playback toggle. void qtractorMainForm::trackCurveProcess ( bool bOn ) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; qtractorCurve *pCurrentCurve = pTrack->currentCurve(); if (pCurrentCurve == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackCurveProcess(%d)", int(bOn)); #endif #if 0 if (!bOn) pCurrentCurve->setCapture(false); pCurrentCurve->setProcess(bOn); if (bOn && !m_pSession->isPlaying()) pTrack->process_curve(m_iPlayHead); m_pTracks->updateTrackList(); updateDirtyCount(true); stabilizeForm(); #else m_pSession->execute(new qtractorCurveProcessCommand(pCurrentCurve, bOn)); #endif } // Track automation curve record toggle. void qtractorMainForm::trackCurveCapture ( bool bOn ) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; qtractorCurve *pCurrentCurve = pTrack->currentCurve(); if (pCurrentCurve == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackCurveCapture(%d)", int(bOn)); #endif #if 0 if (bOn) pCurrentCurve->setProcess(true); pCurrentCurve->setCapture(bOn); if (bOn && !m_pSession->isPlaying()) pTrack->process_curve(m_iPlayHead); m_pTracks->updateTrackList(); updateDirtyCount(true); stabilizeForm(); #else m_pSession->execute(new qtractorCurveCaptureCommand(pCurrentCurve, bOn)); #endif } // Track automation curve logarithmic toggle. void qtractorMainForm::trackCurveLogarithmic ( bool bOn ) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; qtractorCurve *pCurrentCurve = pTrack->currentCurve(); if (pCurrentCurve == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackCurveLogarithmic(%d)", int(bOn)); #endif #if 0 pCurrentCurve->setLogarithmic(bOn); m_pTracks->updateTrackView(); updateDirtyCount(true); stabilizeForm(); #else m_pSession->execute(new qtractorCurveLogarithmicCommand(pCurrentCurve, bOn)); #endif } // Track automation curve color picker. void qtractorMainForm::trackCurveColor (void) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; qtractorCurve *pCurrentCurve = pTrack->currentCurve(); if (pCurrentCurve == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackCurveColor()"); #endif const QString sTitle(pCurrentCurve->subject()->name()); const QColor& color = QColorDialog::getColor( pCurrentCurve->color(), this, sTitle + " - " QTRACTOR_TITLE); if (!color.isValid()) return; #if 0 pCurrentCurve->setColor(color); m_pTracks->updateTrackView(); updateDirtyCount(true); stabilizeForm(); #else m_pSession->execute(new qtractorCurveColorCommand(pCurrentCurve, color)); #endif } // Track automation curve clear. void qtractorMainForm::trackCurveClear (void) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; qtractorCurve *pCurrentCurve = pTrack->currentCurve(); if (pCurrentCurve == NULL) return; if (pCurrentCurve->isEmpty()) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackCurveClear()"); #endif if (m_pOptions && m_pOptions->bConfirmRemove) { if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("About to clear automation:\n\n" "\"%1\"\n\n" "Are you sure?") .arg(pCurrentCurve->subject()->name()), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; } #if 0 pCurrentCurve->clear(); if (!m_pSession->isPlaying()) pTrack->process_curve(m_iPlayHead); m_pTracks->updateTrackList(); m_pTracks->updateTrackView(); updateDirtyCount(true); stabilizeForm(); #else m_pSession->execute(new qtractorCurveClearCommand(pCurrentCurve)); #endif } // Track automation all curves lock toggle. void qtractorMainForm::trackCurveLockedAll ( bool bOn ) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; qtractorCurveList *pCurveList = pTrack->curveList(); if (pCurveList == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackCurveLockedAll(%d)", int(bOn)); #endif pCurveList->setLockedAll(bOn); m_pTracks->updateTrackView(); updateDirtyCount(true); stabilizeForm(); } // Track automation all curves playback toggle. void qtractorMainForm::trackCurveProcessAll ( bool bOn ) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; qtractorCurveList *pCurveList = pTrack->curveList(); if (pCurveList == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackCurveProcessAll(%d)", int(bOn)); #endif #if 0 if (!bOn) pCurveList->setCaptureAll(false); pCurveList->setProcessAll(bOn); if (bOn && !m_pSession->isPlaying()) pTrack->process_curve(m_iPlayHead); m_pTracks->updateTrackList(); updateDirtyCount(true); stabilizeForm(); #else m_pSession->execute(new qtractorCurveProcessAllCommand(pCurveList, bOn)); #endif } // Track automation all curves record toggle. void qtractorMainForm::trackCurveCaptureAll ( bool bOn ) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; qtractorCurveList *pCurveList = pTrack->curveList(); if (pCurveList == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackCurveCaptureAll(%d)", int(bOn)); #endif #if 0 if (bOn) pCurveList->setProcessAll(true); pCurveList->setCaptureAll(bOn); if (bOn && !m_pSession->isPlaying()) pTrack->process_curve(m_iPlayHead); m_pTracks->updateTrackList(); updateDirtyCount(true); stabilizeForm(); #else m_pSession->execute(new qtractorCurveCaptureAllCommand(pCurveList, bOn)); #endif } // Track automation all curves clear. void qtractorMainForm::trackCurveClearAll (void) { qtractorTrack *pTrack = NULL; if (m_pTracks) pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return; qtractorCurveList *pCurveList = pTrack->curveList(); if (pCurveList == NULL) return; if (pCurveList->isEmpty()) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::trackCurveClearAll()"); #endif if (m_pOptions && m_pOptions->bConfirmRemove) { if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("About to clear all automation:\n\n" "\"%1\"\n\n" "Are you sure?") .arg(pTrack->trackName()), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return; } #if 0 pCurveList->clearAll(); m_pTracks->updateTrackList(); m_pTracks->updateTrackView(); updateDirtyCount(true); stabilizeForm(); #else m_pSession->execute(new qtractorCurveClearAllCommand(pCurveList)); #endif } //------------------------------------------------------------------------- // qtractorMainForm -- Clip Action slots. // Enter in clip create mode. void qtractorMainForm::clipNew (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipNew()"); #endif // New clip: we must have a session name... if (m_pSession->sessionName().isEmpty() && !editSession()) return; // Start editing a new clip... if (m_pTracks) m_pTracks->newClip(); } // Enter in clip edit mode. void qtractorMainForm::clipEdit (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipEdit()"); #endif // Start editing the current clip, if any... if (m_pTracks) m_pTracks->editClip(); } // Unlink a (MIDI) linked clip. void qtractorMainForm::clipUnlink (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipUnlink()"); #endif // Unlink the current clip, if any... if (m_pTracks) m_pTracks->unlinkClip(); } // Split current clip at playhead. void qtractorMainForm::clipSplit (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipSplit()"); #endif // Split current clip, if any... if (m_pTracks) m_pTracks->splitClip(); } // Merge selected (MIDI) clips. void qtractorMainForm::clipMerge (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipMerge()"); #endif // Merge clip selection, if any... if (m_pTracks) m_pTracks->mergeClips(); } // Normalize current clip. void qtractorMainForm::clipNormalize (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipNormalize()"); #endif // Normalize current clip, if any... if (m_pTracks) m_pTracks->normalizeClip(); } // Adjust current tempo from clip selection or interactive tapping... void qtractorMainForm::clipTempo (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipTempo()"); #endif if (m_pTracks) m_pTracks->tempoClip(); } // Set edit-range from current clip. void qtractorMainForm::clipRangeSet (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipRangeSet()"); #endif // Normalize current clip, if any... if (m_pTracks) m_pTracks->rangeClip(); } // Set loop from current clip range. void qtractorMainForm::clipLoopSet (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipLoopSet()"); #endif // Normalize current clip, if any... if (m_pTracks) m_pTracks->loopClip(); } // Import (audio) clip. void qtractorMainForm::clipImport (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipImport()"); #endif // Import (audio) clip(s)... if (m_pTracks) { // Depending on current track type (default to audio)... unsigned long iClipStart = m_pSession->editHead(); QStringList files; qtractorTrack *pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) pTrack = m_pSession->tracks().first(); if (pTrack && pTrack->trackType() == qtractorTrack::Midi) files = m_pFiles->midiListView()->openFileNames(); else files = m_pFiles->audioListView()->openFileNames(); m_pTracks->importClips(files, iClipStart); m_pTracks->trackView()->ensureVisibleFrame(iClipStart); } } // Export current clip. void qtractorMainForm::clipExport (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipExport()"); #endif // Export current clip, if any... if (m_pTracks) m_pTracks->exportClips(); } // Quantize current clip. void qtractorMainForm::clipToolsQuantize (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipToolsQuantize()"); #endif // Quantize current clip events, if any... if (m_pTracks) m_pTracks->executeClipTool(qtractorMidiEditor::Quantize); } // Transpose current clip. void qtractorMainForm::clipToolsTranspose (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipToolsTranspose()"); #endif // Tranpose current clip events, if any... if (m_pTracks) m_pTracks->executeClipTool(qtractorMidiEditor::Transpose); } // Normalize current clip. void qtractorMainForm::clipToolsNormalize (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipToolsNormalize()"); #endif // Normalize current clip events, if any... if (m_pTracks) m_pTracks->executeClipTool(qtractorMidiEditor::Normalize); } // Randomize current clip. void qtractorMainForm::clipToolsRandomize (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipToolsRandomize()"); #endif // Randomize current clip events, if any... if (m_pTracks) m_pTracks->executeClipTool(qtractorMidiEditor::Randomize); } // Resize current clip. void qtractorMainForm::clipToolsResize (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipToolsResize()"); #endif // Resize current clip events, if any... if (m_pTracks) m_pTracks->executeClipTool(qtractorMidiEditor::Resize); } // Rescale current clip. void qtractorMainForm::clipToolsRescale (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipToolsRescale()"); #endif // Rescale current clip events, if any... if (m_pTracks) m_pTracks->executeClipTool(qtractorMidiEditor::Rescale); } // Timeshift current clip. void qtractorMainForm::clipToolsTimeshift (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipToolsTimeshift()"); #endif // Timeshift current clip events, if any... if (m_pTracks) m_pTracks->executeClipTool(qtractorMidiEditor::Timeshift); } // Select current clip take. void qtractorMainForm::clipTakeSelect ( QAction *pAction ) { int iTake = pAction->data().toInt(); #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipTakeSelect(%d)", iTake); #endif qtractorClip *pClip = NULL; if (m_pTracks) pClip = m_pTracks->currentClip(); qtractorClip::TakeInfo *pTakeInfo = (pClip ? pClip->takeInfo() : NULL); if (pTakeInfo && pTakeInfo->currentTake() != iTake) { m_pSession->execute( new qtractorClipTakeCommand(pTakeInfo, pClip->track(), iTake)); } } // Select first clip take. void qtractorMainForm::clipTakeFirst (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipTakeFirst()"); #endif qtractorClip *pClip = NULL; if (m_pTracks) pClip = m_pTracks->currentClip(); qtractorClip::TakeInfo *pTakeInfo = (pClip ? pClip->takeInfo() : NULL); if (pTakeInfo) { m_pSession->execute( new qtractorClipTakeCommand(pTakeInfo, pClip->track(), 0)); } } // Select previous clip take. void qtractorMainForm::clipTakePrev (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipTakePrev()"); #endif qtractorClip *pClip = NULL; if (m_pTracks) pClip = m_pTracks->currentClip(); qtractorClip::TakeInfo *pTakeInfo = (pClip ? pClip->takeInfo() : NULL); if (pTakeInfo) { int iTake = pTakeInfo->currentTake() - 1; if (iTake < 0) iTake = pTakeInfo->takeCount() - 1; // Wrap to last take. m_pSession->execute( new qtractorClipTakeCommand(pTakeInfo, pClip->track(), iTake)); } } // Select next clip take. void qtractorMainForm::clipTakeNext (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipTakeNext()"); #endif qtractorClip *pClip = NULL; if (m_pTracks) pClip = m_pTracks->currentClip(); qtractorClip::TakeInfo *pTakeInfo = (pClip ? pClip->takeInfo() : NULL); if (pTakeInfo) { int iTake = pTakeInfo->currentTake() + 1; if (iTake >= pTakeInfo->takeCount()) iTake = 0; // Wrap to first take. m_pSession->execute( new qtractorClipTakeCommand(pTakeInfo, pClip->track(), iTake)); } } // Select last clip take. void qtractorMainForm::clipTakeLast (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipTakeLast()"); #endif qtractorClip *pClip = NULL; if (m_pTracks) pClip = m_pTracks->currentClip(); qtractorClip::TakeInfo *pTakeInfo = (pClip ? pClip->takeInfo() : NULL); if (pTakeInfo) { int iTake = pTakeInfo->takeCount() - 1; m_pSession->execute( new qtractorClipTakeCommand(pTakeInfo, pClip->track(), iTake)); } } // Unfold current clip takes. void qtractorMainForm::clipTakeReset (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipTakeReset()"); #endif qtractorClip *pClip = NULL; if (m_pTracks) pClip = m_pTracks->currentClip(); qtractorClip::TakeInfo *pTakeInfo = (pClip ? pClip->takeInfo() : NULL); if (pTakeInfo) { m_pSession->execute( new qtractorClipTakeCommand(pTakeInfo)); } } // Fold current clip into takes. void qtractorMainForm::clipTakeRange (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::clipTakeRange()"); #endif qtractorClip *pClip = NULL; if (m_pTracks) pClip = m_pTracks->currentClip(); qtractorClip::TakeInfo *pTakeInfo = (pClip ? pClip->takeInfo() : NULL); if (pClip && pTakeInfo == NULL) { unsigned long iClipEnd = pClip->clipStart() + pClip->clipLength(); qtractorTakeRangeForm form(this); form.setClip(pClip); if (form.exec() && form.takeEnd() < iClipEnd) { pTakeInfo = new qtractorClip::TakeInfo( pClip->clipStart(), pClip->clipOffset(), pClip->clipLength(), form.takeStart(), form.takeEnd()); qtractorClipCommand *pClipCommand = new qtractorClipCommand(tr("take range")); pClipCommand->takeInfoClip(pClip, pTakeInfo); pTakeInfo->setClipPart(qtractorClip::TakeInfo::ClipTake, pClip); int iTake = form.currentTake(); iTake = pTakeInfo->select(pClipCommand, pClip->track(), iTake); pTakeInfo->setCurrentTake(iTake); m_pSession->execute(pClipCommand); } } } //------------------------------------------------------------------------- // qtractorMainForm -- View Action slots. // Show/hide the main program window menubar. void qtractorMainForm::viewMenubar ( bool bOn ) { #if 0 if (bOn) m_ui.menuBar->show(); else m_ui.menuBar->hide(); #else m_ui.menuBar->setVisible(bOn); #endif } // Show/hide the main program window statusbar. void qtractorMainForm::viewStatusbar ( bool bOn ) { #if 0 if (bOn) statusBar()->show(); else statusBar()->hide(); #else statusBar()->setVisible(bOn); #endif } // Show/hide the file-toolbar. void qtractorMainForm::viewToolbarFile ( bool bOn ) { #if 0 if (bOn) { m_ui.fileToolbar->show(); } else { m_ui.fileToolbar->hide(); } #else m_ui.fileToolbar->setVisible(bOn); #endif } // Show/hide the edit-toolbar. void qtractorMainForm::viewToolbarEdit ( bool bOn ) { #if 0 if (bOn) { m_ui.editToolbar->show(); } else { m_ui.editToolbar->hide(); } #else m_ui.editToolbar->setVisible(bOn); #endif } // Show/hide the track-toolbar. void qtractorMainForm::viewToolbarTrack ( bool bOn ) { #if 0 if (bOn) { m_ui.trackToolbar->show(); } else { m_ui.trackToolbar->hide(); } #else m_ui.trackToolbar->setVisible(bOn); #endif } // Show/hide the view-toolbar. void qtractorMainForm::viewToolbarView ( bool bOn ) { #if 0 if (bOn) { m_ui.viewToolbar->show(); } else { m_ui.viewToolbar->hide(); } #else m_ui.viewToolbar->setVisible(bOn); #endif } // Show/hide the options toolbar. void qtractorMainForm::viewToolbarOptions ( bool bOn ) { #if 0 if (bOn) { m_ui.optionsToolbar->show(); } else { m_ui.optionsToolbar->hide(); } #else m_ui.optionsToolbar->setVisible(bOn); #endif } // Show/hide the transport toolbar. void qtractorMainForm::viewToolbarTransport ( bool bOn ) { #if 0 if (bOn) { m_ui.transportToolbar->show(); } else { m_ui.transportToolbar->hide(); } #else m_ui.transportToolbar->setVisible(bOn); #endif } // Show/hide the time toolbar. void qtractorMainForm::viewToolbarTime ( bool bOn ) { #if 0 if (bOn) { m_ui.timeToolbar->show(); } else { m_ui.timeToolbar->hide(); } #else m_ui.timeToolbar->setVisible(bOn); #endif } // Show/hide the thumb (track-line)ime toolbar. void qtractorMainForm::viewToolbarThumb ( bool bOn ) { #if 0 if (bOn) { m_ui.thumbToolbar->show(); } else { m_ui.thumbToolbar->hide(); } #else m_ui.thumbToolbar->setVisible(bOn); #endif } // Show/hide the files window view. void qtractorMainForm::viewFiles ( bool bOn ) { #if 0 if (bOn) { m_pFiles->show(); } else { m_pFiles->hide(); } #else m_pFiles->setVisible(bOn); #endif } // Show/hide the messages window logger. void qtractorMainForm::viewMessages ( bool bOn ) { #if 0 if (bOn) { m_pMessages->show(); } else { m_pMessages->hide(); } #else m_pMessages->setVisible(bOn); #endif } // Show/hide the mixer window. void qtractorMainForm::viewMixer ( bool bOn ) { if (m_pOptions) m_pOptions->saveWidgetGeometry(m_pMixer); #if 0 if (bOn) { m_pMixer->show(); } else { m_pMixer->hide(); } #else m_pMixer->setVisible(bOn); #endif } // Show/hide the connections window. void qtractorMainForm::viewConnections ( bool bOn ) { if (m_pOptions) m_pOptions->saveWidgetGeometry(m_pConnections); #if 0 if (bOn) { m_pConnections->reset(); m_pConnections->show(); } else { m_pConnections->hide(); } #else if (bOn) m_pConnections->reset(); m_pConnections->setVisible(bOn); #endif } // Horizontal and/or vertical zoom-in. void qtractorMainForm::viewZoomIn (void) { if (m_pTracks) m_pTracks->zoomIn(); } // Horizontal and/or vertical zoom-out. void qtractorMainForm::viewZoomOut (void) { if (m_pTracks) m_pTracks->zoomOut(); } // Reset zoom level to default. void qtractorMainForm::viewZoomReset (void) { if (m_pTracks) m_pTracks->zoomReset(); } // Set horizontal zoom mode void qtractorMainForm::viewZoomHorizontal (void) { if (m_pTracks) m_pTracks->setZoomMode(qtractorTracks::ZoomHorizontal); } // Set vertical zoom mode void qtractorMainForm::viewZoomVertical (void) { if (m_pTracks) m_pTracks->setZoomMode(qtractorTracks::ZoomVertical); } // Set all zoom mode void qtractorMainForm::viewZoomAll (void) { if (m_pTracks) m_pTracks->setZoomMode(qtractorTracks::ZoomAll); } // Set zebra mode void qtractorMainForm::viewSnapZebra ( bool bOn ) { if (m_pTracks) m_pTracks->trackView()->setSnapZebra(bOn); } // Set grid mode void qtractorMainForm::viewSnapGrid ( bool bOn ) { if (m_pTracks) m_pTracks->trackView()->setSnapGrid(bOn); } // Set floating tool-tips view mode void qtractorMainForm::viewToolTips ( bool bOn ) { if (m_pTracks) m_pTracks->trackView()->setToolTips(bOn); } // Change snap-per-beat setting via menu. void qtractorMainForm::viewSnap (void) { // Retrieve snap-per-beat index from from action data... QAction *pAction = qobject_cast (sender()); if (pAction) { // Commit the change as usual... snapPerBeatChanged(pAction->data().toInt()); // Update the other toolbar control... m_pSnapPerBeatComboBox->setCurrentIndex( qtractorTimeScale::indexFromSnap(m_pSession->snapPerBeat())); } } // Refresh view display. void qtractorMainForm::viewRefresh (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::viewRefresh()"); #endif // Tell the world we'll take some time... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // Update the whole session view dependables... m_pSession->updateTimeScale(); m_pSession->updateSession(); if (m_pTracks) m_pTracks->updateContents(true); if (m_pConnections) m_pConnections->refresh(); if (m_pMixer) { m_pMixer->updateBuses(); m_pMixer->updateTracks(); } m_pThumbView->updateContents(); // Update other editors contents... QListIterator iter(m_editors); while (iter.hasNext()) { qtractorMidiEditor *pEditor = (iter.next())->editor(); pEditor->updateTimeScale(); pEditor->updateContents(); } // We're formerly done. QApplication::restoreOverrideCursor(); stabilizeForm(); } // Show instruments dialog. void qtractorMainForm::viewInstruments (void) { // Just set and show the instruments dialog... qtractorInstrumentForm(this).exec(); } // Show MIDI controllers dialog. void qtractorMainForm::viewControllers (void) { // Just set and show the MIDI controllers dialog... qtractorMidiControlForm(this).exec(); } // Show buses dialog. void qtractorMainForm::viewBuses (void) { // Just set and show the buses dialog... qtractorBusForm(this).exec(); } // Show tempo-map dialog. void qtractorMainForm::viewTempoMap (void) { // Just set and show the tempo-map dialog... qtractorTimeScaleForm(this).exec(); } // Show options dialog. void qtractorMainForm::viewOptions (void) { if (m_pOptions == NULL) return; #ifdef CONFIG_LV2 #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) const QString sPathSep(';'); #else const QString sPathSep(':'); #endif QString sOldLv2Path = m_pOptions->lv2Paths.join(sPathSep); QString sOldLv2PresetDir = m_pOptions->sLv2PresetDir; #endif // Check out some initial nullities(tm)... if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages) m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString(); // To track down deferred or immediate changes. bool bOldMessagesLog = m_pOptions->bMessagesLog; QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath; QString sOldMessagesFont = m_pOptions->sMessagesFont; bool bOldStdoutCapture = m_pOptions->bStdoutCapture; int bOldMessagesLimit = m_pOptions->bMessagesLimit; int iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines; bool bOldCompletePath = m_pOptions->bCompletePath; bool bOldPeakAutoRemove = m_pOptions->bPeakAutoRemove; bool bOldKeepToolsOnTop = m_pOptions->bKeepToolsOnTop; int iOldMaxRecentFiles = m_pOptions->iMaxRecentFiles; int iOldDisplayFormat = m_pOptions->iDisplayFormat; int iOldBaseFontSize = m_pOptions->iBaseFontSize; int iOldResampleType = m_pOptions->iAudioResampleType; bool bOldWsolaTimeStretch = m_pOptions->bAudioWsolaTimeStretch; bool bOldWsolaQuickSeek = m_pOptions->bAudioWsolaQuickSeek; bool bOldAudioPlayerAutoConnect = m_pOptions->bAudioPlayerAutoConnect; bool bOldAudioPlayerBus = m_pOptions->bAudioPlayerBus; bool bOldAudioMetronome = m_pOptions->bAudioMetronome; int iOldTransportMode = m_pOptions->iTransportMode; int iOldMidiMmcDevice = m_pOptions->iMidiMmcDevice; int iOldMidiMmcMode = m_pOptions->iMidiMmcMode; int iOldMidiSppMode = m_pOptions->iMidiSppMode; int iOldMidiClockMode = m_pOptions->iMidiClockMode; int iOldMidiCaptureQuantize = m_pOptions->iMidiCaptureQuantize; int iOldMidiQueueTimer = m_pOptions->iMidiQueueTimer; bool bOldMidiPlayerBus = m_pOptions->bMidiPlayerBus; QString sOldMetroBarFilename = m_pOptions->sMetroBarFilename; QString sOldMetroBeatFilename = m_pOptions->sMetroBeatFilename; float fOldMetroBarGain = m_pOptions->fMetroBarGain; float fOldMetroBeatGain = m_pOptions->fMetroBeatGain; bool bOldAudioMetroAutoConnect = m_pOptions->bAudioMetroAutoConnect; bool bOldAudioMetroBus = m_pOptions->bAudioMetroBus; bool bOldMidiControlBus = m_pOptions->bMidiControlBus; bool bOldMidiMetronome = m_pOptions->bMidiMetronome; int iOldMetroChannel = m_pOptions->iMetroChannel; int iOldMetroBarNote = m_pOptions->iMetroBarNote; int iOldMetroBarVelocity = m_pOptions->iMetroBarVelocity; int iOldMetroBarDuration = m_pOptions->iMetroBarDuration; int iOldMetroBeatNote = m_pOptions->iMetroBeatNote; int iOldMetroBeatVelocity = m_pOptions->iMetroBeatVelocity; int iOldMetroBeatDuration = m_pOptions->iMetroBeatDuration; bool bOldMidiMetroBus = m_pOptions->bMidiMetroBus; // Load the current setup settings. qtractorOptionsForm optionsForm(this); optionsForm.setOptions(m_pOptions); // Show the setup dialog... if (optionsForm.exec()) { enum { RestartSession = 1, RestartProgram = 2, RestartAny = 3 }; int iNeedRestart = 0; // Check wheather something immediate has changed. if (iOldResampleType != m_pOptions->iAudioResampleType) { qtractorAudioBuffer::setResampleType(m_pOptions->iAudioResampleType); iNeedRestart |= RestartSession; } if (( bOldWsolaTimeStretch && !m_pOptions->bAudioWsolaTimeStretch) || (!bOldWsolaTimeStretch && m_pOptions->bAudioWsolaTimeStretch)) { qtractorAudioBuffer::setWsolaTimeStretch( m_pOptions->bAudioWsolaTimeStretch); iNeedRestart |= RestartSession; } // Audio engine control modes... if (iOldTransportMode != m_pOptions->iTransportMode) { ++m_iDirtyCount; // Fake session properties change. updateTransportMode(); // iNeedRestart |= RestartSession; } if (iOldMidiQueueTimer != m_pOptions->iMidiQueueTimer) { updateMidiQueueTimer(); iNeedRestart |= RestartSession; } if (( bOldWsolaQuickSeek && !m_pOptions->bAudioWsolaQuickSeek) || (!bOldWsolaQuickSeek && m_pOptions->bAudioWsolaQuickSeek)) { qtractorAudioBuffer::setWsolaQuickSeek( m_pOptions->bAudioWsolaQuickSeek); iNeedRestart |= RestartSession; } #ifdef CONFIG_LV2 if ((sOldLv2Path != m_pOptions->lv2Paths.join(sPathSep)) || (sOldLv2PresetDir != m_pOptions->sLv2PresetDir)) { updatePluginPaths(); iNeedRestart |= RestartSession; } #endif if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) || (!bOldStdoutCapture && m_pOptions->bStdoutCapture)) { updateMessagesCapture(); iNeedRestart |= RestartProgram; } if (iOldBaseFontSize != m_pOptions->iBaseFontSize) iNeedRestart |= RestartProgram; if (( bOldCompletePath && !m_pOptions->bCompletePath) || (!bOldCompletePath && m_pOptions->bCompletePath) || (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles)) updateRecentFilesMenu(); if (( bOldPeakAutoRemove && !m_pOptions->bPeakAutoRemove) || (!bOldPeakAutoRemove && m_pOptions->bPeakAutoRemove)) updatePeakAutoRemove(); if (( bOldKeepToolsOnTop && !m_pOptions->bKeepToolsOnTop) || (!bOldKeepToolsOnTop && m_pOptions->bKeepToolsOnTop)) iNeedRestart |= RestartProgram; if (sOldMessagesFont != m_pOptions->sMessagesFont) updateMessagesFont(); if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) || (!bOldMessagesLimit && m_pOptions->bMessagesLimit) || (iOldMessagesLimitLines != m_pOptions->iMessagesLimitLines)) updateMessagesLimit(); if (iOldDisplayFormat != m_pOptions->iDisplayFormat) updateDisplayFormat(); if (( bOldMessagesLog && !m_pOptions->bMessagesLog) || (!bOldMessagesLog && m_pOptions->bMessagesLog) || (sOldMessagesLogPath != m_pOptions->sMessagesLogPath)) m_pMessages->setLogging( m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath); // FIXME: This is what it should ever be, // make it right from this very moment... qtractorAudioFileFactory::setDefaultType( m_pOptions->sAudioCaptureExt, m_pOptions->iAudioCaptureType, m_pOptions->iAudioCaptureFormat, m_pOptions->iAudioCaptureQuality); qtractorMidiClip::setDefaultFormat( m_pOptions->iMidiCaptureFormat); // Set default MIDI (plugin) instrument audio output mode. qtractorMidiManager::setDefaultAudioOutputBus( m_pOptions->bAudioOutputBus); qtractorMidiManager::setDefaultAudioOutputAutoConnect( m_pOptions->bAudioOutputAutoConnect); // Auto time-stretching, loop-recording global modes... if (m_pSession) { m_pSession->setAutoTimeStretch(m_pOptions->bAudioAutoTimeStretch); m_pSession->setLoopRecordingMode(m_pOptions->iLoopRecordingMode); } // Special track-view drop-span mode... if (m_pTracks) m_pTracks->trackView()->setDropSpan(m_pOptions->bTrackViewDropSpan); // MIDI engine control modes... if ((iOldMidiMmcDevice != m_pOptions->iMidiMmcDevice) || (iOldMidiMmcMode != m_pOptions->iMidiMmcMode) || (iOldMidiSppMode != m_pOptions->iMidiSppMode) || (iOldMidiClockMode != m_pOptions->iMidiClockMode) || (iOldMidiCaptureQuantize != m_pOptions->iMidiCaptureQuantize)) { ++m_iDirtyCount; // Fake session properties change. updateMidiControlModes(); } // Audio engine audition/pre-listening player options... if (( bOldAudioPlayerBus && !m_pOptions->bAudioPlayerBus) || (!bOldAudioPlayerBus && m_pOptions->bAudioPlayerBus) || ( bOldAudioPlayerAutoConnect && !m_pOptions->bAudioPlayerAutoConnect) || (!bOldAudioPlayerAutoConnect && m_pOptions->bAudioPlayerAutoConnect)) updateAudioPlayer(); // MIDI engine player options... if (( bOldMidiPlayerBus && !m_pOptions->bMidiPlayerBus) || (!bOldMidiPlayerBus && m_pOptions->bMidiPlayerBus)) updateMidiPlayer(); // MIDI engine control options... if (( bOldMidiControlBus && !m_pOptions->bMidiControlBus) || (!bOldMidiControlBus && m_pOptions->bMidiControlBus)) updateMidiControl(); // Audio engine metronome options... if (( bOldAudioMetronome && !m_pOptions->bAudioMetronome) || (!bOldAudioMetronome && m_pOptions->bAudioMetronome) || (sOldMetroBarFilename != m_pOptions->sMetroBarFilename) || (sOldMetroBeatFilename != m_pOptions->sMetroBeatFilename) || (fOldMetroBarGain != m_pOptions->fMetroBarGain) || (fOldMetroBeatGain != m_pOptions->fMetroBeatGain) || ( bOldAudioMetroBus && !m_pOptions->bAudioMetroBus) || (!bOldAudioMetroBus && m_pOptions->bAudioMetroBus) || ( bOldAudioMetroAutoConnect && !m_pOptions->bAudioMetroAutoConnect) || (!bOldAudioMetroAutoConnect && m_pOptions->bAudioMetroAutoConnect)) updateAudioMetronome(); // MIDI engine metronome options... if (( bOldMidiMetronome && !m_pOptions->bMidiMetronome) || (!bOldMidiMetronome && m_pOptions->bMidiMetronome) || (iOldMetroChannel != m_pOptions->iMetroChannel) || (iOldMetroBarNote != m_pOptions->iMetroBarNote) || (iOldMetroBarVelocity != m_pOptions->iMetroBarVelocity) || (iOldMetroBarDuration != m_pOptions->iMetroBarDuration) || (iOldMetroBeatNote != m_pOptions->iMetroBeatNote) || (iOldMetroBeatVelocity != m_pOptions->iMetroBeatVelocity) || (iOldMetroBeatDuration != m_pOptions->iMetroBeatDuration) || ( bOldMidiMetroBus && !m_pOptions->bMidiMetroBus) || (!bOldMidiMetroBus && m_pOptions->bMidiMetroBus)) updateMidiMetronome(); // Warn if something will be only effective on next time. if (iNeedRestart & RestartAny) { QString sNeedRestart; if (iNeedRestart & RestartSession) sNeedRestart += tr("session"); if (iNeedRestart & RestartProgram) { if (!sNeedRestart.isEmpty()) sNeedRestart += tr(" or "); sNeedRestart += tr("program"); } // Show restart needed message... QMessageBox::information(this, tr("Information") + " - " QTRACTOR_TITLE, tr("Some settings may be only effective\n" "next time you start this %1.") .arg(sNeedRestart)); } } // This makes it. stabilizeForm(); } //------------------------------------------------------------------------- // qtractorMainForm -- Transport Action slots. // Transport backward. void qtractorMainForm::transportBackward (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportBackward()"); #endif // Make sure session is activated... checkRestartSession(); // Move playhead to edit-tail, head or full session-start. if (QApplication::keyboardModifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) { m_pSession->setPlayHead(0); } else { unsigned long iPlayHead = m_pSession->playHead(); #if 0 if (iPlayHead > m_pSession->editTail() && !m_pSession->isPlaying()) iPlayHead = m_pSession->editTail(); else if (iPlayHead > m_pSession->editHead()) iPlayHead = m_pSession->editHead(); else iPlayHead = 0; #else QList list; list.append(0); if (iPlayHead > m_pSession->editHead()) list.append(m_pSession->editHead()); // if (iPlayHead > m_pSession->editTail() && !m_pSession->isPlaying()) // list.append(m_pSession->editTail()); if (m_pSession->isLooping()) { if (iPlayHead > m_pSession->loopStart()) list.append(m_pSession->loopStart()); // if (iPlayHead > m_pSession->loopEnd() && !m_pSession->isPlaying()) // list.append(m_pSession->loopEnd()); } if (iPlayHead > m_pSession->sessionStart()) list.append(m_pSession->sessionStart()); if (iPlayHead > m_pSession->sessionEnd() && !m_pSession->isPlaying()) list.append(m_pSession->sessionEnd()); qtractorTimeScale::Marker *pMarker = m_pSession->timeScale()->markers().seekFrame(iPlayHead); while (pMarker && pMarker->frame >= iPlayHead) pMarker = pMarker->prev(); if (pMarker && iPlayHead > pMarker->frame) list.append(pMarker->frame); qSort(list.begin(), list.end()); iPlayHead = list.last(); #endif m_pSession->setPlayHead(iPlayHead); } ++m_iTransportUpdate; stabilizeForm(); } // Transport rewind. void qtractorMainForm::transportRewind (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportRewind()"); #endif // Make sure session is activated... if (!checkRestartSession()) return; // Rolling direction and speed (negative)... int iRolling = -1; if (QApplication::keyboardModifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) iRolling -= 2; // Toggle rolling backward... if (setRolling(iRolling) < 0) { // Send MMC STOP command... m_pSession->midiEngine()->sendMmcCommand( qtractorMmcEvent::STOP); } else { // Send MMC REWIND command... m_pSession->midiEngine()->sendMmcCommand( qtractorMmcEvent::REWIND); } stabilizeForm(); } // Transport fast-forward void qtractorMainForm::transportFastForward (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportFastForward()"); #endif // Make sure session is activated... if (!checkRestartSession()) return; // Rolling direction and speed (positive)... int iRolling = +1; if (QApplication::keyboardModifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) iRolling += 2; // Toggle rolling backward... if (setRolling(iRolling) > 0) { // Send MMC STOP command... m_pSession->midiEngine()->sendMmcCommand( qtractorMmcEvent::STOP); } else { // Send MMC FAST_FORWARD command... m_pSession->midiEngine()->sendMmcCommand( qtractorMmcEvent::FAST_FORWARD); } stabilizeForm(); } // Transport forward void qtractorMainForm::transportForward (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportForward()"); #endif // Make sure session is activated... checkRestartSession(); // Move playhead to edit-head, tail or full session-end. if (QApplication::keyboardModifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) { m_pSession->setPlayHead(m_pSession->sessionEnd()); } else { unsigned long iPlayHead = m_pSession->playHead(); #if 0 if (iPlayHead < m_pSession->editHead()) iPlayHead = m_pSession->editHead(); else if (iPlayHead < m_pSession->editTail()) iPlayHead = m_pSession->editTail(); else iPlayHead = m_pSession->sessionLength(); #else QList list; if (iPlayHead < m_pSession->editHead()) list.append(m_pSession->editHead()); if (iPlayHead < m_pSession->editTail()) list.append(m_pSession->editTail()); if (m_pSession->isLooping()) { if (iPlayHead < m_pSession->loopStart()) list.append(m_pSession->loopStart()); if (iPlayHead < m_pSession->loopEnd()) list.append(m_pSession->loopEnd()); } if (iPlayHead < m_pSession->sessionStart()) list.append(m_pSession->sessionStart()); if (iPlayHead < m_pSession->sessionEnd()) list.append(m_pSession->sessionEnd()); qtractorTimeScale::Marker *pMarker = m_pSession->timeScale()->markers().seekFrame(iPlayHead); while (pMarker && iPlayHead >= pMarker->frame) pMarker = pMarker->next(); if (pMarker && iPlayHead < pMarker->frame) list.append(pMarker->frame); qSort(list.begin(), list.end()); iPlayHead = list.first(); #endif m_pSession->setPlayHead(iPlayHead); } ++m_iTransportUpdate; stabilizeForm(); } // Transport loop. void qtractorMainForm::transportLoop (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportLoop()"); #endif // Make sure session is activated... checkRestartSession(); // Do the loop toggle switch... unsigned long iLoopStart = 0; unsigned long iLoopEnd = 0; if (!m_pSession->isLooping()) { iLoopStart = m_pSession->editHead(); iLoopEnd = m_pSession->editTail(); } // Now, express the change as an undoable command... m_pSession->execute( new qtractorSessionLoopCommand(m_pSession, iLoopStart, iLoopEnd)); } // Transport loop setting. void qtractorMainForm::transportLoopSet (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportLoopSet()"); #endif // Make sure session is activated... checkRestartSession(); // Now, express the change as an undoable command... m_pSession->execute( new qtractorSessionLoopCommand(m_pSession, m_pSession->editHead(), m_pSession->editTail())); } // Transport stop. void qtractorMainForm::transportStop (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportStop()"); #endif // Make sure session is activated... if (!checkRestartSession()) return; // Stop playing... if (setPlaying(false)) { qtractorMidiEngine *pMidiEngine = m_pSession->midiEngine(); if (pMidiEngine) { // Send MMC PLAY/STOP command... pMidiEngine->sendMmcCommand(qtractorMmcEvent::STOP); pMidiEngine->sendSppCommand(SND_SEQ_EVENT_STOP); } } stabilizeForm(); } // Transport play. void qtractorMainForm::transportPlay (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportPlay()"); #endif // Make sure session is activated... if (!checkRestartSession()) return; // Toggle playing... bool bPlaying = !m_pSession->isPlaying(); if (setPlaying(bPlaying)) { qtractorMidiEngine *pMidiEngine = m_pSession->midiEngine(); if (pMidiEngine) { // Send MMC PLAY/STOP command... pMidiEngine->sendMmcCommand(bPlaying ? qtractorMmcEvent::PLAY : qtractorMmcEvent::STOP); pMidiEngine->sendSppCommand(bPlaying ? (m_pSession->playHead() > 0 ? SND_SEQ_EVENT_CONTINUE : SND_SEQ_EVENT_START) : SND_SEQ_EVENT_STOP); } } stabilizeForm(); } // Transport record. void qtractorMainForm::transportRecord (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportRecord()"); #endif // Make sure session is activated... if (!checkRestartSession()) return; // Toggle recording... bool bRecording = !m_pSession->isRecording(); if (setRecording(bRecording)) { // Send MMC RECORD_STROBE/EXIT command... m_pSession->midiEngine()->sendMmcCommand(bRecording ? qtractorMmcEvent::RECORD_STROBE : qtractorMmcEvent::RECORD_EXIT); } stabilizeForm(); } // Transport punch in/out. void qtractorMainForm::transportPunch (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportPunch()"); #endif // Make sure session is activated... checkRestartSession(); // Do the punch in/out toggle switch... unsigned long iPunchIn = 0; unsigned long iPunchOut = 0; if (!m_pSession->isPunching()) { iPunchIn = m_pSession->editHead(); iPunchOut = m_pSession->editTail(); } // Now, express the change as an undoable command... m_pSession->execute( new qtractorSessionPunchCommand(m_pSession, iPunchIn, iPunchOut)); } // Transport punch set. void qtractorMainForm::transportPunchSet (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportPunchSet()"); #endif // Make sure session is activated... checkRestartSession(); // Now, express the change as an undoable command... m_pSession->execute( new qtractorSessionPunchCommand(m_pSession, m_pSession->editHead(), m_pSession->editTail())); } // Metronome transport option. void qtractorMainForm::transportMetro (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportMetro()"); #endif // Toggle Audio metronome... if (m_pOptions->bAudioMetronome) { qtractorAudioEngine *pAudioEngine = m_pSession->audioEngine(); if (pAudioEngine) pAudioEngine->setMetronome(!pAudioEngine->isMetronome()); } // Toggle MIDI metronome... if (m_pOptions->bMidiMetronome) { qtractorMidiEngine *pMidiEngine = m_pSession->midiEngine(); if (pMidiEngine) pMidiEngine->setMetronome(!pMidiEngine->isMetronome()); } stabilizeForm(); } // Follow playhead transport option. void qtractorMainForm::transportFollow (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportFollow()"); #endif // Toggle follow-playhead... stabilizeForm(); } // Auto-backward transport option. void qtractorMainForm::transportAutoBackward (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportAutoBackward()"); #endif // Toggle auto-backward... stabilizeForm(); } // Continue past end transport option. void qtractorMainForm::transportContinue (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportContinue()"); #endif // Toggle continue-past-end... stabilizeForm(); } // All tracks shut-off (panic). void qtractorMainForm::transportPanic (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportPanic()"); #endif // All (MIDI) tracks shut-off (panic)... m_pSession->midiEngine()->shutOffAllTracks(); stabilizeForm(); } //------------------------------------------------------------------------- // qtractorMainForm -- Help Action slots. // Show (and edit) keyboard shortcuts. void qtractorMainForm::helpShortcuts (void) { if (m_pOptions == NULL) return; qtractorShortcutForm shortcutForm(findChildren (), this); if (shortcutForm.exec()) m_pOptions->saveActionShortcuts(this); } // Show information about application program. void qtractorMainForm::helpAbout (void) { QStringList list; #ifdef CONFIG_DEBUG list << tr("Debugging option enabled."); #endif #ifndef CONFIG_LIBVORBIS list << tr("Ogg Vorbis (libvorbis) file support disabled."); #endif #ifndef CONFIG_LIBMAD list << tr("MPEG-1 Audio Layer 3 (libmad) file support disabled."); #endif #ifndef CONFIG_LIBSAMPLERATE list << tr("Sample-rate conversion (libsamplerate) disabled."); #endif #ifndef CONFIG_LIBRUBBERBAND list << tr("Pitch-shifting support (librubberband) disabled."); #endif #ifndef CONFIG_LIBLO list << tr("OSC service support (liblo) disabled."); #endif #ifndef CONFIG_LADSPA list << tr("LADSPA Plug-in support disabled."); #endif #ifndef CONFIG_DSSI list << tr("DSSI Plug-in support disabled."); #endif #ifndef CONFIG_VST list << tr("VST Plug-in support disabled."); #endif #ifdef CONFIG_VESTIGE list << tr("VeSTige header support enabled."); #endif #ifndef CONFIG_LV2 list << tr("LV2 Plug-in support disabled."); #else #ifndef CONFIG_LIBLILV list << tr("LV2 Plug-in support (liblilv) disabled."); #endif #ifndef CONFIG_LV2_UI list << tr("LV2 Plug-in UI support disabled."); #else #ifndef CONFIG_LIBSUIL list << tr("LV2 Plug-in UI support (libsuil) disabled."); #endif #ifndef CONFIG_LV2_EXTERNAL_UI list << tr("LV2 Plug-in External UI support disabled."); #endif #endif // CONFIG_LV2_UI #ifndef CONFIG_LV2_EVENT list << tr("LV2 Plug-in MIDI/Event support disabled."); #endif #ifndef CONFIG_LV2_ATOM list << tr("LV2 Plug-in MIDI/Atom support disabled."); #endif #ifndef CONFIG_LV2_WORKER list << tr("LV2 Plug-in Worker/Schedule support disabled."); #endif #ifndef CONFIG_LV2_STATE list << tr("LV2 Plug-in State support disabled."); #endif #ifndef CONFIG_LV2_STATE_FILES list << tr("LV2 Plug-in State Files support disabled."); #endif #ifndef CONFIG_LV2_PROGRAMS list << tr("LV2 Plug-in Programs support disabled."); #endif #ifndef CONFIG_LV2_PRESETS list << tr("LV2 Plug-in Presets support disabled."); #endif #ifndef CONFIG_LV2_TIME list << tr("LV2 Plug-in Time/position support disabled."); #endif #ifndef CONFIG_LV2_OPTIONS list << tr("LV2 Plug-in Options support disabled."); #endif #ifndef CONFIG_LV2_BUF_SIZE list << tr("LV2 Plug-in Buf-size support disabled."); #endif #endif // CONFIG_LV2 #ifndef CONFIG_JACK_SESSION list << tr("JACK Session support disabled."); #endif #ifndef CONFIG_JACK_LATENCY list << tr("JACK Latency support disabled."); #endif #ifndef CONFIG_NSM list << tr("NSM support disabled."); #endif // Stuff the about box text... QString sText = "

\n"; sText += "" QTRACTOR_TITLE " - " + tr(QTRACTOR_SUBTITLE) + "
\n"; sText += "
\n"; sText += tr("Version") + ": " QTRACTOR_VERSION "
\n"; sText += "" + tr("Build") + ": " __DATE__ " " __TIME__ "
\n"; QStringListIterator iter(list); while (iter.hasNext()) { sText += ""; sText += iter.next(); sText += "
"; } sText += "
\n"; sText += tr("Website") + ": " QTRACTOR_WEBSITE "
\n"; sText += "
\n"; sText += ""; sText += QTRACTOR_COPYRIGHT "
\n"; sText += "
\n"; sText += tr("This program is free software; you can redistribute it and/or modify it") + "
\n"; sText += tr("under the terms of the GNU General Public License version 2 or later."); sText += "
"; sText += "

\n"; QMessageBox::about(this, tr("About") + " " QTRACTOR_TITLE, sText); } // Show information about the Qt toolkit. void qtractorMainForm::helpAboutQt (void) { QMessageBox::aboutQt(this); } //------------------------------------------------------------------------- // qtractorMainForm -- Internal transport stabilization. bool qtractorMainForm::setPlaying ( bool bPlaying ) { // In case of (re)starting playback, send now // all tracks MIDI bank select/program changes... if (bPlaying) m_pSession->setMidiPatch(true); // Force conditional! // Toggle engine play status... m_pSession->setPlaying(bPlaying); // We must start/stop certain things... if (!bPlaying) { // Shutdown recording anyway... if (m_pSession->isRecording()) setRecording(false); // Stop transport rolling, immediately... setRolling(0); // Session tracks automation recording. qtractorCurveCaptureListCommand *pCurveCommand = NULL; for (qtractorTrack *pTrack = m_pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { qtractorCurveList *pCurveList = pTrack->curveList(); if (pCurveList && pCurveList->isCapture() && !pCurveList->isEditListEmpty()) { if (pCurveCommand == NULL) pCurveCommand = new qtractorCurveCaptureListCommand(); pCurveCommand->addCurveList(pCurveList); } } if (pCurveCommand) m_pSession->commands()->push(pCurveCommand); // Auto-backward reset feature... if (m_ui.transportAutoBackwardAction->isChecked()) { unsigned long iPlayHead = m_pSession->playHead(); if (iPlayHead > m_pSession->editHead()) iPlayHead = m_pSession->editHead(); else iPlayHead = 0; m_pSession->setPlayHead(iPlayHead); } } // Start something... ;) else ++m_iTransportUpdate; // Done with playback switch... return true; } bool qtractorMainForm::setRecording ( bool bRecording ) { // Avoid if no tracks are armed... if (m_pSession->recordTracks() < 1) return false; if (bRecording) { // Starting recording: we must have a session name... if (m_pSession->sessionName().isEmpty() && !editSession()) return false; // Will start recording... } else { // Stopping recording: fetch and commit // all new clips as a composite command... int iUpdate = 0; qtractorClipCommand *pClipCommand = new qtractorClipCommand(tr("record clip")); // For all non-empty clip on record... unsigned long iFrameTime = m_pSession->frameTimeEx(); for (qtractorTrack *pTrack = m_pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { if (pClipCommand->addClipRecord(pTrack, iFrameTime)) ++iUpdate; } // Put it in the form of an undoable command... if (iUpdate > 0) { m_pSession->execute(pClipCommand); } else { // The allocated command is unhelpful... delete pClipCommand; // Try to postpone an overall refresh... if (m_iPeakTimer < QTRACTOR_TIMER_DELAY) m_iPeakTimer += QTRACTOR_TIMER_DELAY; } } // Finally, toggle session record status... m_pSession->setRecording(bRecording); // Done with record switch... return true; } int qtractorMainForm::setRolling ( int iRolling ) { int iOldRolling = m_iTransportRolling; // Avoid if recording is armed... if (m_pSession->isRecording() || iOldRolling == iRolling) iRolling = 0; // Set the rolling flag. m_iTransportRolling = iRolling; m_fTransportShuttle = float(iRolling); m_iTransportStep = 0; // We've started/stopped something... if (m_iTransportRolling) { if (!m_bTransportPlaying) m_bTransportPlaying = m_pSession->isPlaying(); if (m_bTransportPlaying) m_pSession->setPlaying(false); ++m_iTransportUpdate; } else { if (m_bTransportPlaying) m_pSession->setPlaying(true); m_bTransportPlaying = false; } // Done with rolling switch... return iOldRolling; } void qtractorMainForm::setLocate ( unsigned long iLocate ) { m_pSession->setPlayHead(m_pSession->frameFromLocate(iLocate)); ++m_iTransportUpdate; } void qtractorMainForm::setShuttle ( float fShuttle ) { float fOldShuttle = m_fTransportShuttle; if (fShuttle < 0.0f && fOldShuttle >= 0.0f) setRolling(-1); else if (fShuttle > 0.0f && 0.0f >= fOldShuttle) setRolling(+1); m_fTransportShuttle = fShuttle; ++m_iTransportUpdate; } void qtractorMainForm::setStep ( int iStep ) { m_iTransportStep += iStep; ++m_iTransportUpdate; } void qtractorMainForm::setTrack ( int scmd, int iTrack, bool bOn ) { if (m_pTracks) { // Find which ordinal track... qtractorTrack *pTrack = m_pTracks->trackList()->track(iTrack); if (pTrack) { // Set session track mode state... switch (qtractorMmcEvent::SubCommand(scmd)) { case qtractorMmcEvent::TRACK_RECORD: pTrack->setRecord(bOn); break; case qtractorMmcEvent::TRACK_MUTE: pTrack->setMute(bOn); break; case qtractorMmcEvent::TRACK_SOLO: pTrack->setSolo(bOn); break; default: break; } // Done. stabilizeForm(); } } } void qtractorMainForm::setSongPos ( unsigned short iSongPos ) { m_pSession->setPlayHead(m_pSession->frameFromSongPos(iSongPos)); ++m_iTransportUpdate; } //------------------------------------------------------------------------- // qtractorMainForm -- Main window stabilization. void qtractorMainForm::updateTransportTime ( unsigned long iPlayHead ) { m_pTimeSpinBox->setValue(iPlayHead, false); m_pThumbView->updatePlayHead(iPlayHead); // Tricky stuff: node's non-null iif tempo changes... qtractorTimeScale::Node *pNode = m_pTempoCursor->seek(m_pSession, iPlayHead); if (pNode) { m_pTempoSpinBox->setTempo(pNode->tempo, false); m_pTempoSpinBox->setBeatsPerBar(pNode->beatsPerBar, false); m_pTempoSpinBox->setBeatDivisor(pNode->beatDivisor, false); } #ifdef CONFIG_VST #if 0 // !VST_FORCE_DEPRECATED qtractorVstPlugin::idleTimerAll(); #endif #endif } void qtractorMainForm::stabilizeForm (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMainForm::stabilizeForm()"); #endif // Update the main application caption... QString sSessionName = sessionName(m_sFilename); if (m_iDirtyCount > 0) sSessionName += ' ' + tr("[modified]"); setWindowTitle(sSessionName + " - " QTRACTOR_TITLE); // Update the main menu state... m_ui.fileSaveAction->setEnabled(m_iDirtyCount > 0); #ifdef CONFIG_NSM m_ui.fileSaveAsAction->setEnabled(m_pNsmClient == NULL); #endif // Update edit menu state... qtractorCommandList *pCommands = m_pSession->commands(); pCommands->updateAction(m_ui.editUndoAction, pCommands->lastCommand()); pCommands->updateAction(m_ui.editRedoAction, pCommands->nextCommand()); unsigned long iPlayHead = m_pSession->playHead(); unsigned long iSessionEnd = m_pSession->sessionEnd(); qtractorTrack *pTrack = NULL; bool bTracks = (m_pTracks && m_pSession->tracks().count() > 0); if (bTracks) pTrack = m_pTracks->currentTrack(); bool bEnabled = (pTrack != NULL); bool bSelected = (m_pTracks && m_pTracks->isSelected()); bool bSelectable = (m_pSession->editHead() < m_pSession->editTail()); bool bPlaying = m_pSession->isPlaying(); bool bRecording = m_pSession->isRecording(); bool bPunching = m_pSession->isPunching(); bool bLooping = m_pSession->isLooping(); bool bRolling = (bPlaying && bRecording); bool bBumped = (!bRolling && (iPlayHead > 0 || bPlaying)); if (m_pFiles && m_pFiles->hasFocus() && m_pFiles->isFileSelected()) bSelected = true; // m_ui.editCutAction->setEnabled(bSelected); // m_ui.editCopyAction->setEnabled(bSelected); m_ui.editPasteAction->setEnabled(qtractorTrackView::isClipboard() || QApplication::clipboard()->mimeData()->hasUrls()); m_ui.editPasteRepeatAction->setEnabled(qtractorTrackView::isClipboard()); // m_ui.editDeleteAction->setEnabled(bSelected); m_ui.editSelectAllAction->setEnabled(iSessionEnd > 0); m_ui.editSelectInvertAction->setEnabled(iSessionEnd > 0); m_ui.editSelectTrackRangeAction->setEnabled(bEnabled && bSelectable); m_ui.editSelectTrackAction->setEnabled(bEnabled); m_ui.editSelectRangeAction->setEnabled(iSessionEnd > 0 && bSelectable); m_ui.editSelectNoneAction->setEnabled(bSelected); bool bInsertable = m_pSession->editHead() < iSessionEnd; m_ui.editInsertTrackRangeAction->setEnabled(bEnabled && bInsertable); m_ui.editInsertRangeAction->setEnabled(bInsertable); m_ui.editRemoveTrackRangeAction->setEnabled(bEnabled && bInsertable); m_ui.editRemoveRangeAction->setEnabled(bInsertable); m_ui.editSplitAction->setEnabled(bSelected); // Top-level menu/toolbar items stabilization... updateTrackMenu(); updateClipMenu(); // Update view menu state... m_ui.viewFilesAction->setChecked( m_pFiles && m_pFiles->isVisible()); m_ui.viewMessagesAction->setChecked( m_pMessages && m_pMessages->isVisible()); m_ui.viewConnectionsAction->setChecked( m_pConnections && m_pConnections->isVisible()); m_ui.viewMixerAction->setChecked( m_pMixer && m_pMixer->isVisible()); // Recent files menu. m_ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0); // Always make the latest message visible. if (m_pMessages) m_pMessages->flushStdoutBuffer(); // Session status... updateTransportTime(iPlayHead); if (pTrack) m_statusItems[StatusName]->setText(pTrack->trackName().simplified()); else m_statusItems[StatusName]->clear(); if (m_iDirtyCount > 0) m_statusItems[StatusMod]->setText(tr("MOD")); else m_statusItems[StatusMod]->clear(); if (bRecording && m_pSession->recordTracks() > 0) m_statusItems[StatusRec]->setText(tr("REC")); else m_statusItems[StatusRec]->clear(); if (m_pSession->muteTracks() > 0) m_statusItems[StatusMute]->setText(tr("MUTE")); else m_statusItems[StatusMute]->clear(); if (m_pSession->soloTracks() > 0) m_statusItems[StatusSolo]->setText(tr("SOLO")); else m_statusItems[StatusSolo]->clear(); if (m_pSession->isLooping()) m_statusItems[StatusLoop]->setText(tr("LOOP")); else m_statusItems[StatusLoop]->clear(); m_statusItems[StatusTime]->setText( m_pSession->timeScale()->textFromFrame(0, true, iSessionEnd)); m_statusItems[StatusRate]->setText( tr("%1 Hz").arg(m_pSession->sampleRate())); m_statusItems[StatusRec]->setPalette(*m_paletteItems[ bRecording && bRolling ? PaletteRed : PaletteNone]); m_statusItems[StatusMute]->setPalette(*m_paletteItems[ m_pSession->muteTracks() > 0 ? PaletteYellow : PaletteNone]); m_statusItems[StatusSolo]->setPalette(*m_paletteItems[ m_pSession->soloTracks() > 0 ? PaletteCyan : PaletteNone]); m_statusItems[StatusLoop]->setPalette(*m_paletteItems[ bLooping ? PaletteGreen : PaletteNone]); // Transport stuff... m_ui.transportBackwardAction->setEnabled(bBumped); m_ui.transportRewindAction->setEnabled(bBumped); m_ui.transportFastForwardAction->setEnabled(!bRolling); m_ui.transportForwardAction->setEnabled( !bRolling && (iPlayHead < iSessionEnd || iPlayHead < m_pSession->editHead() || iPlayHead < m_pSession->editTail())); m_ui.transportLoopAction->setEnabled( !bRolling && (bLooping || bSelectable)); m_ui.transportLoopSetAction->setEnabled( !bRolling && bSelectable); m_ui.transportStopAction->setEnabled(bPlaying); m_ui.transportRecordAction->setEnabled(m_pSession->recordTracks() > 0); m_ui.transportPunchAction->setEnabled(bPunching || bSelectable); m_ui.transportPunchSetAction->setEnabled(bSelectable); m_ui.transportMetroAction->setEnabled( m_pOptions->bAudioMetronome || m_pOptions->bMidiMetronome); m_ui.transportPanicAction->setEnabled(bTracks); m_ui.transportRewindAction->setChecked(m_iTransportRolling < 0); m_ui.transportFastForwardAction->setChecked(m_iTransportRolling > 0); m_ui.transportLoopAction->setChecked(bLooping); m_ui.transportPlayAction->setChecked(bPlaying); m_ui.transportRecordAction->setChecked(bRecording); m_ui.transportPunchAction->setChecked(bPunching); // Special record mode settlement. m_pTimeSpinBox->setReadOnly(bRecording); m_pTempoSpinBox->setReadOnly(bRecording); m_pThumbView->update(); m_pThumbView->updateThumb(); // Update editors too... QListIterator iter(m_editors); while (iter.hasNext()) (iter.next())->stabilizeForm(); } // Actually start all session engines. bool qtractorMainForm::startSession (void) { m_iTransportUpdate = 0; m_iTransportRolling = 0; m_bTransportPlaying = false; m_fTransportShuttle = 0.0f; m_iTransportStep = 0; m_iXrunCount = 0; m_iXrunSkip = 0; m_iXrunTimer = 0; m_iAudioRefreshTimer = 0; m_iMidiRefreshTimer = 0; m_iPlayerTimer = 0; QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); bool bResult = m_pSession->init(); QApplication::restoreOverrideCursor(); if (bResult) { appendMessages(tr("Session started.")); } else { // Uh-oh, we can't go on like this... appendMessagesError( tr("The audio/MIDI engine could not be started.\n\n" "Make sure the JACK audio server (jackd) and/or\n" "the ALSA Sequencer kernel module (snd-seq-midi)\n" "are up and running and then restart the session.")); } return bResult; } // Check and restart session, if applicable. bool qtractorMainForm::checkRestartSession (void) { // Whether session is currently activated, // try to (re)open the whole thing... if (!m_pSession->isActivated()) { // Save current playhead position, if any... unsigned long iPlayHead = m_pSession->playHead(); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); m_pSession->close(); QApplication::restoreOverrideCursor(); // Bail out if can't start it... if (!startSession()) { // Can go on with no-business... stabilizeForm(); return false; } QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); m_pSession->open(); QApplication::restoreOverrideCursor(); // Restore previous playhead position... m_pSession->setPlayHead(iPlayHead); } return true; } // Prepare session start. void qtractorMainForm::updateSessionPre (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::updateSessionPre()"); #endif // Initialize toolbar widgets... // m_pTempoSpinBox->setTempo(m_pSession->tempo(), false); // m_pTempoSpinBox->setBeatsPerBar(m_pSession->beatsPerBar(), false); // m_pTempoSpinBox->setBeatDivisor(m_pSession->beatDivisor(), false); m_pSnapPerBeatComboBox->setCurrentIndex( qtractorTimeScale::indexFromSnap(m_pSession->snapPerBeat())); // Actually (re)start session engines... if (startSession()) { // (Re)set playhead... if (m_ui.transportAutoBackwardAction->isChecked()) { if (m_iPlayHead > m_pSession->editHead()) m_pSession->setPlayHead(m_pSession->editHead()); else m_pSession->setPlayHead(0); } // (Re)initialize MIDI instrument patching... m_pSession->setMidiPatch(false); // Deferred++ // Get on with the special ALSA sequencer notifier... if (m_pSession->midiEngine()->alsaNotifier()) { QObject::connect(m_pSession->midiEngine()->alsaNotifier(), SIGNAL(activated(int)), SLOT(alsaNotify())); } } } // Finalize session start. void qtractorMainForm::updateSessionPost (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::updateSessionPost()"); #endif QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); m_pSession->open(); QApplication::restoreOverrideCursor(); // HACK: Special treatment for disparate sample rates, // and only for (just loaded) non empty sessions... unsigned int iSampleRate = m_pSession->audioEngine()->sampleRate(); if (m_pSession->sampleRate() != iSampleRate) { appendMessagesError( tr("The original session sample rate (%1 Hz)\n" "is not the same of the current audio engine (%2 Hz).\n\n" "Saving and reloading from a new session file\n" "is highly recommended.") .arg(m_pSession->sampleRate()) .arg(iSampleRate)); // We'll doing the conversion right here and right now... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); m_pSession->updateSampleRate(iSampleRate); QApplication::restoreOverrideCursor(); updateDirtyCount(true); } // Update the session views... viewRefresh(); // We're definitely clean... qtractorSubject::resetQueue(); // Sync all process-enabled automation curves... m_pSession->process_curve(m_iPlayHead); // Ah, make it stand right. if (m_pTracks) m_pTracks->trackView()->setFocus(); // Of course!... ++m_iTransportUpdate; } // Update the track export menu. void qtractorMainForm::updateExportMenu (void) { // Special export enablement... int iAudioClips = 0; int iMidiClips = 0; if (!m_pSession->isPlaying()) { for (qtractorTrack *pTrack = m_pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { switch (pTrack->trackType()) { case qtractorTrack::Audio: iAudioClips += pTrack->clips().count(); break; case qtractorTrack::Midi: iMidiClips += pTrack->clips().count(); break; default: break; } } } m_ui.trackExportAudioAction->setEnabled(iAudioClips > 0); m_ui.trackExportMidiAction->setEnabled(iMidiClips > 0); } // Update the recent files list and menu. void qtractorMainForm::updateRecentFiles ( const QString& sFilename ) { if (m_pOptions == NULL) return; // Remove from list if already there (avoid duplicates) int iIndex = m_pOptions->recentFiles.indexOf(sFilename); if (iIndex >= 0) m_pOptions->recentFiles.removeAt(iIndex); // Put it to front... m_pOptions->recentFiles.push_front(sFilename); } // Update the recent files list and menu. void qtractorMainForm::updateRecentFilesMenu (void) { if (m_pOptions == NULL) return; // Time to keep the list under limits. int iRecentFiles = m_pOptions->recentFiles.count(); while (iRecentFiles > m_pOptions->iMaxRecentFiles) { m_pOptions->recentFiles.pop_back(); --iRecentFiles; } // Rebuild the recent files menu... m_ui.fileOpenRecentMenu->clear(); for (int i = 0; i < iRecentFiles; ++i) { const QString& sFilename = m_pOptions->recentFiles[i]; if (QFileInfo(sFilename).exists()) { QAction *pAction = m_ui.fileOpenRecentMenu->addAction( QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)), this, SLOT(fileOpenRecent())); pAction->setData(i); } } // Settle as enabled? m_ui.fileOpenRecentMenu->setEnabled(!m_ui.fileOpenRecentMenu->isEmpty()); } // Force update of the peak-files auto-remove mode. void qtractorMainForm::updatePeakAutoRemove (void) { if (m_pOptions == NULL) return; qtractorAudioPeakFactory *pAudioPeakFactory = m_pSession->audioPeakFactory(); if (pAudioPeakFactory) pAudioPeakFactory->setAutoRemove(m_pOptions->bPeakAutoRemove); } // Update main transport-time display format. void qtractorMainForm::updateDisplayFormat (void) { if (m_pOptions == NULL) return; // Main transport display format is due... qtractorTimeScale::DisplayFormat displayFormat; switch (m_pOptions->iDisplayFormat) { case 2: displayFormat = qtractorTimeScale::BBT; break; case 1: displayFormat = qtractorTimeScale::Time; break; case 0: default: displayFormat = qtractorTimeScale::Frames; break; } m_pSession->timeScale()->setDisplayFormat(displayFormat); m_pTimeSpinBox->setDisplayFormat(displayFormat); } // Update plugins search paths (LV2_PATH). void qtractorMainForm::updatePluginPaths (void) { if (m_pOptions == NULL) return; #ifdef CONFIG_LV2 // HACK: reset special environment for LV2... if (m_pOptions->lv2Paths.isEmpty()) ::unsetenv("LV2_PATH"); qtractorPluginPath path(qtractorPluginType::Lv2); path.setPaths(qtractorPluginType::Lv2, m_pOptions->lv2Paths); path.open(); #endif } // Update audio player parameters. void qtractorMainForm::updateAudioPlayer (void) { if (m_pOptions == NULL) return; // Configure the Audio engine player handling... qtractorAudioEngine *pAudioEngine = m_pSession->audioEngine(); if (pAudioEngine == NULL) return; pAudioEngine->setPlayerAutoConnect(m_pOptions->bAudioPlayerAutoConnect); pAudioEngine->setPlayerBus(m_pOptions->bAudioPlayerBus); } // Update Audio engine control mode settings. void qtractorMainForm::updateTransportMode (void) { if (m_pOptions == NULL) return; // Configure the Audio engine handling... qtractorAudioEngine *pAudioEngine = m_pSession->audioEngine(); if (pAudioEngine == NULL) return; pAudioEngine->setTransportMode( qtractorBus::BusMode(m_pOptions->iTransportMode)); } // Update MIDI engine control mode settings. void qtractorMainForm::updateMidiControlModes (void) { if (m_pOptions == NULL) return; // Configure the MIDI engine handling... qtractorMidiEngine *pMidiEngine = m_pSession->midiEngine(); if (pMidiEngine == NULL) return; pMidiEngine->setCaptureQuantize( qtractorTimeScale::snapFromIndex(m_pOptions->iMidiCaptureQuantize)); pMidiEngine->setMmcDevice(m_pOptions->iMidiMmcDevice); pMidiEngine->setMmcMode(qtractorBus::BusMode(m_pOptions->iMidiMmcMode)); pMidiEngine->setSppMode(qtractorBus::BusMode(m_pOptions->iMidiSppMode)); pMidiEngine->setClockMode(qtractorBus::BusMode(m_pOptions->iMidiClockMode)); } // Update MIDI playback queue timersetting. void qtractorMainForm::updateMidiQueueTimer (void) { if (m_pOptions == NULL) return; // Configure the MIDI engine player handling... m_pSession->midiEngine()->setAlsaTimer(m_pOptions->iMidiQueueTimer); } // Update MIDI player parameters. void qtractorMainForm::updateMidiPlayer (void) { if (m_pOptions == NULL) return; // Configure the MIDI engine player handling... m_pSession->midiEngine()->setPlayerBus(m_pOptions->bMidiPlayerBus); } // Update MIDI control parameters. void qtractorMainForm::updateMidiControl (void) { if (m_pOptions == NULL) return; // Configure the MIDI engine control handling... m_pSession->midiEngine()->setControlBus(m_pOptions->bMidiControlBus); } // Update audio metronome parameters. void qtractorMainForm::updateAudioMetronome (void) { if (m_pOptions == NULL) return; // Configure the Audio engine metronome handling... qtractorAudioEngine *pAudioEngine = m_pSession->audioEngine(); if (pAudioEngine == NULL) return; pAudioEngine->setMetroBarFilename(m_pOptions->sMetroBarFilename); pAudioEngine->setMetroBeatFilename(m_pOptions->sMetroBeatFilename); pAudioEngine->setMetroBarGain(m_pOptions->fMetroBarGain); pAudioEngine->setMetroBeatGain(m_pOptions->fMetroBeatGain); bool bAudioMetronome = m_pOptions->bAudioMetronome; pAudioEngine->setMetroAutoConnect(m_pOptions->bAudioMetroAutoConnect); pAudioEngine->setMetroBus( bAudioMetronome && m_pOptions->bAudioMetroBus); pAudioEngine->setMetroEnabled(bAudioMetronome); pAudioEngine->setMetronome( bAudioMetronome && m_ui.transportMetroAction->isChecked()); } // Update MIDI metronome parameters. void qtractorMainForm::updateMidiMetronome (void) { if (m_pOptions == NULL) return; // Configure the MIDI engine metronome handling... qtractorMidiEngine *pMidiEngine = m_pSession->midiEngine(); if (pMidiEngine == NULL) return; pMidiEngine->setMetroChannel(m_pOptions->iMetroChannel); pMidiEngine->setMetroBar( m_pOptions->iMetroBarNote, m_pOptions->iMetroBarVelocity, m_pOptions->iMetroBarDuration); pMidiEngine->setMetroBeat( m_pOptions->iMetroBeatNote, m_pOptions->iMetroBeatVelocity, m_pOptions->iMetroBeatDuration); bool bMidiMetronome = m_pOptions->bMidiMetronome; pMidiEngine->setMetroBus( bMidiMetronome && m_pOptions->bMidiMetroBus); pMidiEngine->setMetroEnabled(bMidiMetronome); pMidiEngine->setMetronome( bMidiMetronome && m_ui.transportMetroAction->isChecked()); } // Track menu stabilizer. void qtractorMainForm::updateTrackMenu (void) { qtractorTrack *pTrack = NULL; bool bTracks = (m_pTracks && m_pSession->tracks().count() > 0); if (bTracks) pTrack = m_pTracks->currentTrack(); bool bEnabled = (pTrack != NULL); bool bPlaying = m_pSession->isPlaying(); bool bRecording = m_pSession->isRecording(); bool bRolling = (bPlaying && bRecording); // Update track menu state... m_ui.trackRemoveAction->setEnabled( bEnabled && (!bRolling || !pTrack->isRecord())); m_ui.trackPropertiesAction->setEnabled( bEnabled && (!bRolling || !pTrack->isRecord())); m_ui.trackInputsAction->setEnabled( bEnabled && pTrack->inputBus() != NULL); m_ui.trackOutputsAction->setEnabled( bEnabled && pTrack->outputBus() != NULL); m_ui.trackStateMenu->setEnabled(bEnabled); m_ui.trackNavigateMenu->setEnabled(bTracks); m_ui.trackNavigateFirstAction->setEnabled(bTracks); m_ui.trackNavigatePrevAction->setEnabled(bEnabled && pTrack->prev() != NULL); m_ui.trackNavigateNextAction->setEnabled(bEnabled && pTrack->next() != NULL); m_ui.trackNavigateLastAction->setEnabled(bTracks); m_ui.trackNavigateNoneAction->setEnabled(bEnabled); m_ui.trackMoveMenu->setEnabled(bEnabled); m_ui.trackMoveTopAction->setEnabled(bEnabled && pTrack->prev() != NULL); m_ui.trackMoveUpAction->setEnabled(bEnabled && pTrack->prev() != NULL); m_ui.trackMoveDownAction->setEnabled(bEnabled && pTrack->next() != NULL); m_ui.trackMoveBottomAction->setEnabled(bEnabled && pTrack->next() != NULL); m_ui.trackHeightMenu->setEnabled(bEnabled); m_ui.trackCurveMenu->setEnabled(bEnabled); // m_ui.trackImportAudioAction->setEnabled(m_pTracks != NULL); // m_ui.trackImportMidiAction->setEnabled(m_pTracks != NULL); // m_ui.trackAutoMonitorAction->setEnabled(m_pTracks != NULL); // Update track menu state... if (bEnabled) { m_ui.trackStateRecordAction->setChecked(pTrack->isRecord()); m_ui.trackStateMuteAction->setChecked(pTrack->isMute()); m_ui.trackStateSoloAction->setChecked(pTrack->isSolo()); m_ui.trackStateMonitorAction->setChecked(pTrack->isMonitor()); } } // Curve/automation menu stabilizer. void qtractorMainForm::updateCurveMenu (void) { qtractorTrack *pTrack = (m_pTracks ? m_pTracks->currentTrack(): NULL); qtractorCurveList *pCurveList = (pTrack ? pTrack->curveList() : NULL); qtractorCurve *pCurrentCurve = (pCurveList ? pCurveList->currentCurve() : NULL); bool bEnabled = trackCurveSelectMenuReset(m_ui.trackCurveSelectMenu); m_ui.trackCurveMenu->setEnabled(bEnabled); m_ui.trackCurveSelectMenu->setEnabled(bEnabled); if (bEnabled) bEnabled = (pCurveList && !pCurveList->isEmpty()); bool bCurveEnabled = bEnabled && pCurrentCurve != NULL; m_ui.trackCurveModeMenu->setEnabled(bCurveEnabled); m_ui.trackCurveLockedAction->setEnabled(bCurveEnabled); m_ui.trackCurveLockedAction->setChecked( pCurrentCurve && pCurrentCurve->isLocked()); m_ui.trackCurveProcessAction->setEnabled(bCurveEnabled); m_ui.trackCurveProcessAction->setChecked( pCurrentCurve && pCurrentCurve->isProcess()); m_ui.trackCurveCaptureAction->setEnabled(bCurveEnabled); m_ui.trackCurveCaptureAction->setChecked( pCurrentCurve && pCurrentCurve->isCapture()); m_ui.trackCurveClearAction->setEnabled(bCurveEnabled); m_ui.trackCurveLockedAllAction->setEnabled(bEnabled); m_ui.trackCurveLockedAllAction->setChecked( pCurveList && pCurveList->isLockedAll()); m_ui.trackCurveLockedAllAction->setEnabled(bEnabled); m_ui.trackCurveProcessAllAction->setEnabled(bEnabled); m_ui.trackCurveProcessAllAction->setChecked( pCurveList && pCurveList->isProcessAll()); m_ui.trackCurveProcessAllAction->setEnabled(bEnabled); m_ui.trackCurveCaptureAllAction->setEnabled(bEnabled); m_ui.trackCurveCaptureAllAction->setChecked( pCurveList && pCurveList->isCaptureAll()); m_ui.trackCurveCaptureAllAction->setEnabled(bEnabled); m_ui.trackCurveClearAllAction->setEnabled( pCurveList && !pCurveList->isEmpty()); } // Curve/automation mode menu stabilizer. void qtractorMainForm::updateCurveModeMenu (void) { trackCurveModeMenuReset(m_ui.trackCurveModeMenu); } // Track curve/automation select item builder. void qtractorMainForm::trackCurveSelectMenuAction ( QMenu *pMenu, qtractorMidiControlObserver *pObserver, qtractorSubject *pCurrentSubject ) const { QIcon icon(":images/trackCurveNone.png"); QString text(tr("&None")); qtractorSubject *pSubject = (pObserver ? pObserver->subject() : NULL); if (pSubject) { text = pSubject->name(); qtractorCurve *pCurve = pSubject->curve(); if (pCurve) { if (pCurve->isCapture()) icon = QIcon(":images/trackCurveCapture.png"); else if (pCurve->isProcess()) icon = QIcon(":images/trackCurveProcess.png"); else // if (pCurve->isEnabled()) icon = QIcon(":images/trackCurveEnabled.png"); } } QAction *pAction = pMenu->addAction(icon, text); pAction->setCheckable(true); pAction->setChecked(pCurrentSubject == pSubject); pAction->setData(qVariantFromValue(pObserver)); } // Track curve/automation select menu builder. bool qtractorMainForm::trackCurveSelectMenuReset ( QMenu *pMenu ) const { pMenu->clear(); if (m_pTracks == NULL) return false; qtractorTrack *pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return false; qtractorCurveList *pCurveList = pTrack->curveList(); if (pCurveList == NULL) return false; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return false; qtractorMixer *pMixer = pMainForm->mixer(); if (pMixer == NULL) return false; qtractorMixerStrip *pMixerStrip = pMixer->trackRack()->findStrip(pTrack->monitor()); if (pMixerStrip == NULL) return false; qtractorCurve *pCurrentCurve = pCurveList->currentCurve(); qtractorSubject *pCurrentSubject = (pCurrentCurve ? pCurrentCurve->subject() : NULL); trackCurveSelectMenuAction(pMenu, pTrack->monitorObserver(), pCurrentSubject); trackCurveSelectMenuAction(pMenu, pMixerStrip->meter()->panningObserver(), pCurrentSubject); trackCurveSelectMenuAction(pMenu, pMixerStrip->meter()->gainObserver(), pCurrentSubject); pMenu->addSeparator(); trackCurveSelectMenuAction(pMenu, pTrack->recordObserver(), pCurrentSubject); trackCurveSelectMenuAction(pMenu, pTrack->muteObserver(), pCurrentSubject); trackCurveSelectMenuAction(pMenu, pTrack->soloObserver(), pCurrentSubject); qtractorPluginList *pPluginList = pTrack->pluginList(); if (pPluginList->count() > 0) { pMenu->addSeparator(); qtractorPlugin *pPlugin = pPluginList->first(); while (pPlugin) { const qtractorPlugin::Params& params = pPlugin->params(); if (params.count() > 0) { QMenu *pParamMenu = pMenu->addMenu(pPlugin->type()->name()); qtractorPlugin::Params::ConstIterator param = params.constBegin(); const qtractorPlugin::Params::ConstIterator& param_end = params.constEnd(); for ( ; param != param_end; ++param) { trackCurveSelectMenuAction(pParamMenu, param.value()->observer(), pCurrentSubject); } } pPlugin = pPlugin->next(); } } pMenu->addSeparator(); trackCurveSelectMenuAction(pMenu, NULL, pCurrentSubject); return true; } bool qtractorMainForm::trackCurveModeMenuReset ( QMenu *pMenu ) const { pMenu->clear(); qtractorTrack *pTrack = m_pTracks->currentTrack(); if (pTrack == NULL) return false; qtractorCurve *pCurrentCurve = pTrack->currentCurve(); if (pCurrentCurve == NULL) return false; qtractorCurve::Mode mode = pCurrentCurve->mode(); bool bToggled = (pCurrentCurve->subject())->isToggled(); QAction *pAction; pAction = pMenu->addAction(tr("&Hold")); pAction->setCheckable(true); pAction->setChecked(mode == qtractorCurve::Hold); pAction->setData(int(qtractorCurve::Hold)); pAction = pMenu->addAction(tr("&Linear")); pAction->setCheckable(true); pAction->setChecked(mode == qtractorCurve::Linear); pAction->setData(int(qtractorCurve::Linear)); pAction->setEnabled(!bToggled); pAction = pMenu->addAction(tr("&Spline")); pAction->setCheckable(true); pAction->setChecked(mode == qtractorCurve::Spline); pAction->setData(int(qtractorCurve::Spline)); pAction->setEnabled(!bToggled); pMenu->addSeparator(); pMenu->addAction(m_ui.trackCurveLogarithmicAction); m_ui.trackCurveLogarithmicAction->setChecked( pCurrentCurve && pCurrentCurve->isLogarithmic()); m_ui.trackCurveLogarithmicAction->setData(-1); // m_ui.trackCurveLogarithmicAction->setEnabled( // pCurrentCurve && pCurrentCurve->isEnabled()); pMenu->addAction(m_ui.trackCurveColorAction); m_ui.trackCurveColorAction->setData(-1); // m_ui.trackCurveColorAction->setEnabled( // pCurrentCurve && pCurrentCurve->isEnabled()); return true; } // Clip menu stabilizer. void qtractorMainForm::updateClipMenu (void) { unsigned long iPlayHead = m_pSession->playHead(); qtractorClip *pClip = NULL; qtractorTrack *pTrack = NULL; bool bTracks = (m_pTracks && m_pSession->tracks().count() > 0); if (bTracks) { pClip = m_pTracks->currentClip(); pTrack = (pClip ? pClip->track() : m_pTracks->currentTrack()); } bool bEnabled = (pTrack != NULL); bool bSelected = (m_pTracks && m_pTracks->isSelected()); bool bClipSelected = (pClip != NULL) || (m_pTracks && m_pTracks->isClipSelected()); bool bClipSelectable = (pClip != NULL) || (m_pSession->editHead() < m_pSession->editTail()); bool bSingleTrackSelected = bClipSelected && (pTrack && m_pTracks->singleTrackSelected() == pTrack); m_ui.editCutAction->setEnabled(bSelected); m_ui.editCopyAction->setEnabled(bSelected); m_ui.editDeleteAction->setEnabled(bSelected); m_ui.clipNewAction->setEnabled(bEnabled); m_ui.clipEditAction->setEnabled(pClip != NULL); // Special unlink (MIDI) clip... qtractorMidiClip *pMidiClip = NULL; if (pTrack && pTrack->trackType() == qtractorTrack::Midi) pMidiClip = static_cast (pClip); m_ui.clipUnlinkAction->setEnabled(pMidiClip && pMidiClip->isHashLinked()); m_ui.clipSplitAction->setEnabled(pClip != NULL && iPlayHead > pClip->clipStart() && iPlayHead < pClip->clipStart() + pClip->clipLength()); m_ui.clipMergeAction->setEnabled(bSingleTrackSelected); m_ui.clipNormalizeAction->setEnabled(bClipSelected); m_ui.clipTempoAction->setEnabled(bClipSelectable); m_ui.clipRangeSetAction->setEnabled(bClipSelected); m_ui.clipLoopSetAction->setEnabled(bClipSelected); // m_ui.clipImportAction->setEnabled(bTracks); m_ui.clipExportAction->setEnabled(bSingleTrackSelected); m_ui.clipToolsMenu->setEnabled(bClipSelected && pTrack && pTrack->trackType() == qtractorTrack::Midi); m_ui.clipTakeMenu->setEnabled(pClip != NULL); } // Take menu stabilizers. void qtractorMainForm::updateTakeMenu (void) { qtractorClip *pClip = NULL; if (m_pTracks) pClip = m_pTracks->currentClip(); qtractorClip::TakeInfo *pTakeInfo = (pClip ? pClip->takeInfo() : NULL); int iCurrentTake = (pTakeInfo ? pTakeInfo->currentTake() : -1); int iTakeCount = (pTakeInfo ? pTakeInfo->takeCount() : 0); // m_ui.clipTakeMenu->setEnabled(pTakeInfo != NULL); m_ui.clipTakeSelectMenu->setEnabled(iTakeCount > 0); m_ui.clipTakeFirstAction->setEnabled(iCurrentTake != 0 && iTakeCount > 0); m_ui.clipTakePrevAction->setEnabled(iTakeCount > 0); m_ui.clipTakeNextAction->setEnabled(iTakeCount > 0); m_ui.clipTakeLastAction->setEnabled(iCurrentTake < iTakeCount - 1); m_ui.clipTakeResetAction->setEnabled(iCurrentTake >= 0); m_ui.clipTakeRangeAction->setEnabled(pTakeInfo == NULL); } // Take selection menu stabilizer. void qtractorMainForm::updateTakeSelectMenu (void) { m_ui.clipTakeSelectMenu->clear(); qtractorClip *pClip = NULL; if (m_pTracks) pClip = m_pTracks->currentClip(); qtractorClip::TakeInfo *pTakeInfo = (pClip ? pClip->takeInfo() : NULL); if (pTakeInfo) { QAction *pAction; int iCurrentTake = pTakeInfo->currentTake(); int iTakeCount = pTakeInfo->takeCount(); for (int iTake = 0; iTake < iTakeCount; ++iTake) { pAction = m_ui.clipTakeSelectMenu->addAction( tr("Take %1").arg(iTake + 1)); pAction->setCheckable(true); pAction->setChecked(iTake == iCurrentTake); pAction->setData(iTake); } if (iTakeCount > 0) m_ui.clipTakeSelectMenu->addSeparator(); pAction = m_ui.clipTakeSelectMenu->addAction( tr("None")); pAction->setCheckable(true); pAction->setChecked(iCurrentTake < 0); pAction->setData(-1); } } // Zoom view menu stabilizer. void qtractorMainForm::updateZoomMenu (void) { int iZoomMode = qtractorTracks::ZoomNone; if (m_pTracks) iZoomMode = m_pTracks->zoomMode(); m_ui.viewZoomHorizontalAction->setChecked( iZoomMode == qtractorTracks::ZoomHorizontal); m_ui.viewZoomVerticalAction->setChecked( iZoomMode == qtractorTracks::ZoomVertical); m_ui.viewZoomAllAction->setChecked( iZoomMode == qtractorTracks::ZoomAll); } // Snap-per-beat view menu builder. void qtractorMainForm::updateSnapMenu (void) { m_ui.viewSnapMenu->clear(); int iSnapCurrent = qtractorTimeScale::indexFromSnap(m_pSession->snapPerBeat()); int iSnap = 0; QListIterator iter(m_snapPerBeatActions); while (iter.hasNext()) { QAction *pAction = iter.next(); pAction->setChecked(iSnap == iSnapCurrent); m_ui.viewSnapMenu->addAction(pAction); ++iSnap; } m_ui.viewSnapMenu->addSeparator(); m_ui.viewSnapMenu->addAction(m_ui.viewSnapZebraAction); m_ui.viewSnapMenu->addAction(m_ui.viewSnapGridAction); } //------------------------------------------------------------------------- // qtractorMainForm -- Messages window form handlers. // Messages output methods. void qtractorMainForm::appendMessages( const QString& s ) { if (m_pMessages) m_pMessages->appendMessages(s); statusBar()->showMessage(s, 3000); } void qtractorMainForm::appendMessagesColor( const QString& s, const QString& c ) { if (m_pMessages) m_pMessages->appendMessagesColor(s, c); statusBar()->showMessage(s, 3000); } void qtractorMainForm::appendMessagesText( const QString& s ) { if (m_pMessages) m_pMessages->appendMessagesText(s); } void qtractorMainForm::appendMessagesError( const QString& s ) { if (m_pMessages) m_pMessages->show(); appendMessagesColor(s.simplified(), "#ff0000"); QMessageBox::critical(this, tr("Error") + " - " QTRACTOR_TITLE, s); } // Force update of the messages font. void qtractorMainForm::updateMessagesFont (void) { if (m_pOptions == NULL) return; if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) { QFont font; if (font.fromString(m_pOptions->sMessagesFont)) m_pMessages->setMessagesFont(font); } } // Update messages window line limit. void qtractorMainForm::updateMessagesLimit (void) { if (m_pOptions == NULL) return; if (m_pMessages) { if (m_pOptions->bMessagesLimit) m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines); else m_pMessages->setMessagesLimit(-1); } } // Enablement of the messages capture feature. void qtractorMainForm::updateMessagesCapture (void) { if (m_pOptions == NULL) return; if (m_pMessages) m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture); } //------------------------------------------------------------------------- // qtractorMainForm -- Editors stuff. void qtractorMainForm::addEditorForm ( qtractorMidiEditorForm *pEditorForm ) { if (m_editors.indexOf(pEditorForm) < 0) m_editors.append(pEditorForm); } void qtractorMainForm::removeEditorForm ( qtractorMidiEditorForm *pEditorForm ) { int iEditorForm = m_editors.indexOf(pEditorForm); if (iEditorForm >= 0) m_editors.removeAt(iEditorForm); } //------------------------------------------------------------------------- // qtractorMainForm -- Timer stuff. // Timer slot funtion. void qtractorMainForm::timerSlot (void) { // Avoid stabilize re-entrancy... if (m_pSession->isBusy()) { // Register the next timer slot. QTimer::singleShot(QTRACTOR_TIMER_DELAY, this, SLOT(timerSlot())); return; } // Currrent state... bool bPlaying = m_pSession->isPlaying(); long iPlayHead = long(m_pSession->playHead()); qtractorAudioEngine *pAudioEngine = m_pSession->audioEngine(); qtractorMidiEngine *pMidiEngine = m_pSession->midiEngine(); // Playhead status... if (iPlayHead != long(m_iPlayHead)) { if (m_pTracks) { // Update tracks-view play-head... m_pTracks->trackView()->setPlayHead(iPlayHead, m_ui.transportFollowAction->isChecked()); // Update editors play-head... QListIterator iter(m_editors); while (iter.hasNext()) (iter.next()->editor())->setPlayHead(iPlayHead); } if (!bPlaying && m_iTransportRolling == 0 && m_iTransportStep == 0) { // Update transport status anyway... ++m_iTransportUpdate; // Send MMC LOCATE command... if (!pAudioEngine->isFreewheel()) { pMidiEngine->sendMmcLocate( m_pSession->locateFromFrame(iPlayHead)); pMidiEngine->sendSppCommand(SND_SEQ_EVENT_SONGPOS, m_pSession->songPosFromFrame(iPlayHead)); } } else if (iPlayHead < long(m_iPlayHead) && m_pSession->isLooping()) { // On probable loop turn-around: // Send MMC LOCATE command... pMidiEngine->sendMmcLocate( m_pSession->locateFromFrame(iPlayHead)); } // Current position update... m_iPlayHead = iPlayHead; } // Transport status... if (m_iTransportUpdate > 0) { // Do some transport related tricks... if (m_iTransportRolling == 0) { m_iTransportUpdate = 0; if (m_iTransportStep) { // Transport stepping over... iPlayHead += (m_iTransportStep * long(m_pSession->frameFromTick(m_pSession->ticksPerBeat()))); if (iPlayHead < 0) iPlayHead = 0; m_iTransportStep = 0; // Make it thru... m_pSession->setPlayHead(m_pSession->frameSnap(iPlayHead)); } } else { // Transport rolling over... iPlayHead += long(m_fTransportShuttle * float(m_pSession->sampleRate())) >> 1; if (iPlayHead < 0) { iPlayHead = 0; m_iTransportUpdate = 0; // Stop playback for sure... if (setPlaying(false)) { // Send MMC STOP command... pMidiEngine->sendMmcCommand(qtractorMmcEvent::STOP); pMidiEngine->sendSppCommand(SND_SEQ_EVENT_STOP); } } // Make it thru... m_pSession->setPlayHead(iPlayHead); } // Ensure track-view into visibility... if (m_pTracks && m_ui.transportFollowAction->isChecked()) m_pTracks->trackView()->ensureVisibleFrame(iPlayHead); // Take the change to give some visual feedback... if (m_iTransportUpdate > 0) { updateTransportTime(iPlayHead); m_pThumbView->updateThumb(); } else { stabilizeForm(); } // Done with transport tricks. } else { // Read JACK transport state and react if out-of-sync.. jack_client_t *pJackClient = NULL; if (pAudioEngine->transportMode() & qtractorBus::Input) pJackClient = pAudioEngine->jackClient(); if (pJackClient && !pAudioEngine->isFreewheel()) { jack_position_t pos; jack_transport_state_t state = jack_transport_query(pJackClient, &pos); // 1. Check on external transport state request changes... if ((state == JackTransportStopped && bPlaying) || (state == JackTransportRolling && !bPlaying)) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::timerSlot()" " playing=%d state=%d", int(bPlaying), int(state == JackTransportRolling)); #endif iPlayHead = pos.frame; if (!bPlaying) m_pSession->seek(iPlayHead, true); transportPlay(); // Toggle playing! // if (bPlaying) // m_pSession->seek(iPlayHead, true); } // 2. Watch for temp/time-sig changes on JACK transport... if (bPlaying && (pos.valid & JackPositionBBT)) { unsigned int iBufferSize = (pAudioEngine->bufferSize() << 1); qtractorTimeScale *pTimeScale = m_pSession->timeScale(); qtractorTimeScale::Cursor& cursor = pTimeScale->cursor(); qtractorTimeScale::Node *pNode = cursor.seekFrame(iPlayHead); if (pNode && iPlayHead > long(pNode->frame + iBufferSize) && ( ::fabs(pNode->tempo - pos.beats_per_minute) > 0.01f || pNode->beatsPerBar != (unsigned short) pos.beats_per_bar || (1 << pNode->beatDivisor) != (unsigned short) pos.beat_type)) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::timerSlot() tempo=%g %u/%u", pos.beats_per_minute, (unsigned short) pos.beats_per_bar, (unsigned short) pos.beat_type); #endif if (m_pTracks) m_pTracks->clearSelect(); m_pSession->lock(); pNode->tempo = pos.beats_per_minute; pNode->beatsPerBar = pos.beats_per_bar; pNode->beatDivisor = 0; unsigned short i = pos.beat_type; while (i > 1) { ++(pNode->beatDivisor); i >>= 1; } pTimeScale->updateNode(pNode); m_pTempoSpinBox->setTempo(pNode->tempo, false); m_pTempoSpinBox->setBeatsPerBar(pNode->beatsPerBar, false); m_pTempoSpinBox->setBeatDivisor(pNode->beatDivisor, false); pAudioEngine->resetMetro(); pMidiEngine->resetTempo(); m_pSession->unlock(); updateContents(NULL, true); } } #ifdef CONFIG_LIBLILV #ifdef CONFIG_LV2_TIME // Update LV2 Time from JACK transport position... qtractorLv2Plugin::updateTime(state, &pos); #endif #endif } // Check if its time to refresh playhead timer... if (bPlaying && m_iPlayTimer < QTRACTOR_TIMER_DELAY) { m_iPlayTimer += QTRACTOR_TIMER_MSECS; if (m_iPlayTimer >= QTRACTOR_TIMER_DELAY) { m_iPlayTimer = 0; updateTransportTime(iPlayHead); // If recording update track view and session length, anyway... if (m_pTracks && m_pSession->isRecording()) { // HACK: Care of punch-out... if (m_pSession->isPunching()) { unsigned long iPunchOut = m_pSession->punchOut(); unsigned long iLoopStart = m_pSession->loopStart(); unsigned long iLoopEnd = m_pSession->loopEnd(); if (iLoopStart < iLoopEnd && iPunchOut >= iLoopEnd) iPunchOut = iLoopEnd; unsigned long iFrameTime = m_pSession->frameTimeEx(); if (iFrameTime >= iPunchOut && setRecording(false)) { // Send MMC RECORD_EXIT command... pMidiEngine->sendMmcCommand( qtractorMmcEvent::RECORD_EXIT); ++m_iTransportUpdate; } } // Recording visual feedback... m_pTracks->trackView()->updateContentsRecord(); m_pSession->updateSession(0, iPlayHead); m_statusItems[StatusTime]->setText( m_pSession->timeScale()->textFromFrame( 0, true, m_pSession->sessionEnd())); } else // Whether to continue past end... if (!m_ui.transportContinueAction->isChecked() && m_iPlayHead > m_pSession->sessionEnd() && m_iPlayHead > m_pSession->loopEnd()) { if (m_pSession->isLooping()) { // Maybe it's better go on with looping, eh? m_pSession->setPlayHead(m_pSession->loopStart()); ++m_iTransportUpdate; } else // Auto-backward reset feature... if (m_ui.transportAutoBackwardAction->isChecked()) { if (m_iPlayHead > m_pSession->editHead()) m_pSession->setPlayHead(m_pSession->editHead()); else m_pSession->setPlayHead(0); ++m_iTransportUpdate; } else { // Stop at once! transportPlay(); } } } } } // Check if its time to refresh some tracks... if (m_iPeakTimer > 0) { m_iPeakTimer -= QTRACTOR_TIMER_MSECS; if (m_iPeakTimer < QTRACTOR_TIMER_MSECS) { m_iPeakTimer = 0; if (m_pTracks && m_pTracks->trackView()) m_pTracks->trackView()->updateContents(); } } // Check if we've got some XRUN callbacks... if (m_iXrunTimer > 0) { m_iXrunTimer -= QTRACTOR_TIMER_MSECS; if (m_iXrunTimer < QTRACTOR_TIMER_MSECS) { m_iXrunTimer = 0; // Did we skip any? if (m_iXrunSkip > 0) { appendMessagesColor( tr("XRUN(%1 skipped)").arg(m_iXrunSkip), "#cc99cc"); m_iXrunSkip = 0; } // Just post an informative message... appendMessagesColor( tr("XRUN(%1): some frames might have been lost.") .arg(m_iXrunCount), "#cc0033"); } } // Check if its time to refresh Audio connections... if (m_iAudioRefreshTimer > 0) { m_iAudioRefreshTimer -= QTRACTOR_TIMER_MSECS; if (m_iAudioRefreshTimer < QTRACTOR_TIMER_MSECS) { m_iAudioRefreshTimer = 0; if (pAudioEngine->updateConnects() == 0) { appendMessagesColor( tr("Audio connections change."), "#cc9966"); if (m_pConnections) m_pConnections->connectForm()->audioRefresh(); } } } // MIDI connections should be checked too... if (m_iMidiRefreshTimer > 0) { m_iMidiRefreshTimer -= QTRACTOR_TIMER_MSECS; if (m_iMidiRefreshTimer < QTRACTOR_TIMER_MSECS) { m_iMidiRefreshTimer = 0; if (pMidiEngine->updateConnects() == 0) { appendMessagesColor( tr("MIDI connections change."), "#66cc99"); if (m_pConnections) m_pConnections->connectForm()->midiRefresh(); } } } // Check if its time to refresh audition/pre-listening status... if (m_iPlayerTimer > 0) { m_iPlayerTimer -= QTRACTOR_TIMER_MSECS; if (m_iPlayerTimer < QTRACTOR_TIMER_MSECS) { m_iPlayerTimer = 0; if (pAudioEngine->isPlayerOpen() || pMidiEngine->isPlayerOpen()) { if (m_pFiles && m_pFiles->isPlayState()) m_iPlayerTimer += QTRACTOR_TIMER_DELAY << 2; } if (m_iPlayerTimer < QTRACTOR_TIMER_MSECS) { if (m_pFiles && m_pFiles->isPlayState()) m_pFiles->setPlayState(false); appendMessages(tr("Playing ended.")); pAudioEngine->closePlayer(); pMidiEngine->closePlayer(); } } } // Always update mixer monitoring... if (m_pMixer) m_pMixer->refresh(); // Asynchronous observer update... qtractorSubject::flushQueue(true); if ((m_iIdleTimer += QTRACTOR_TIMER_MSECS) >= QTRACTOR_TIMER_DELAY) { m_iIdleTimer = 0; #ifdef CONFIG_DSSI #ifdef CONFIG_LIBLO qtractorDssiPlugin::idleEditorAll(); #endif #endif #ifdef CONFIG_VST qtractorVstPlugin::idleEditorAll(); #endif } #ifdef CONFIG_LV2_UI qtractorLv2Plugin::idleEditorAll(); #endif // Register the next timer slot. QTimer::singleShot(QTRACTOR_TIMER_MSECS, this, SLOT(timerSlot())); } //------------------------------------------------------------------------- // qtractorMainForm -- MIDI engine notifications. // Audio file peak notification slot. void qtractorMainForm::peakNotify (void) { // A peak file has just been (re)created; // try to postpone the event effect a little more... if (m_iPeakTimer < QTRACTOR_TIMER_DELAY) m_iPeakTimer += QTRACTOR_TIMER_DELAY; } // ALSA sequencer notification slot. void qtractorMainForm::alsaNotify (void) { // This specialty needs acknowledgement... m_pSession->midiEngine()->alsaNotifyAck(); // A MIDI graph change has just been occurred; // try to postpone the event effect a little more... if (m_iMidiRefreshTimer < QTRACTOR_TIMER_DELAY) m_iMidiRefreshTimer += QTRACTOR_TIMER_DELAY; } // Custom audio shutdown event handler. void qtractorMainForm::audioShutNotify (void) { // Engine shutdown is on demand... m_pSession->shutdown(); m_pConnections->clear(); // Send an informative message box... appendMessagesError( tr("The audio engine has been shutdown.\n\n" "Make sure the JACK audio server (jackd)\n" "is up and running and then restart session.")); // Make things just bearable... stabilizeForm(); } // Custom audio XRUN event handler. void qtractorMainForm::audioXrunNotify (void) { // An XRUN has just been notified... ++m_iXrunCount; // Skip this one, maybe we're under some kind of storm; if (m_iXrunTimer > 0) ++m_iXrunSkip; // Defer the informative effect... if (m_iXrunTimer < QTRACTOR_TIMER_DELAY) m_iXrunTimer += QTRACTOR_TIMER_DELAY; } // Custom audio port/graph change event handler. void qtractorMainForm::audioPortNotify (void) { // An Audio graph change has just been issued; // try to postpone the event effect a little more... if (m_iAudioRefreshTimer < QTRACTOR_TIMER_DELAY) m_iAudioRefreshTimer += QTRACTOR_TIMER_DELAY; } // Custom audio buffer size change event handler. void qtractorMainForm::audioBuffNotify (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::audioBuffNotify()"); #endif audioShutNotify(); } // Custom (JACK) session event handler. void qtractorMainForm::audioSessNotify ( void *pvSessionArg ) { #ifdef CONFIG_JACK_SESSION if (m_pOptions == NULL) return; qtractorAudioEngine *pAudioEngine = m_pSession->audioEngine(); if (pAudioEngine == NULL) return; jack_client_t *pJackClient = pAudioEngine->jackClient(); if (pJackClient == NULL) return; jack_session_event_t *pJackSessionEvent = (jack_session_event_t *) pvSessionArg; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::audioSessNotify()" " type=%d client_uuid=\"%s\" session_dir=\"%s\"", int(pJackSessionEvent->type), pJackSessionEvent->client_uuid, pJackSessionEvent->session_dir); #endif bool bTemplate = (pJackSessionEvent->type == JackSessionSaveTemplate); bool bQuit = (pJackSessionEvent->type == JackSessionSaveAndQuit); if (m_pSession->sessionName().isEmpty()) m_pSession->setSessionName(::getenv("LADISH_PROJECT_NAME")); if (m_pSession->sessionName().isEmpty()) editSession(); QString sSessionName = m_pSession->sessionName(); if (sSessionName.isEmpty()) sSessionName = tr("Untitled%1").arg(m_iUntitled); const QString sSessionDir = QString::fromUtf8(pJackSessionEvent->session_dir); const QString sSessionExt = (bTemplate ? qtractorDocument::templateExt() : m_pOptions->sSessionExt); const QString sSessionFile = sSessionName + '.' + sSessionExt; QStringList args; args << QApplication::applicationFilePath(); args << QString("--session-id=%1").arg(pJackSessionEvent->client_uuid); const QString sFilename = QFileInfo(sSessionDir, sSessionFile).absoluteFilePath(); if (saveSessionFileEx(sFilename, bTemplate, false)) args << QString("\"${SESSION_DIR}%1\"").arg(sSessionFile); const QByteArray aCmdLine = args.join(" ").toUtf8(); pJackSessionEvent->command_line = ::strdup(aCmdLine.constData()); jack_session_reply(pJackClient, pJackSessionEvent); jack_session_event_free(pJackSessionEvent); if (bQuit) { m_iDirtyCount = 0; close(); } #endif } // Custom (JACK) transport sync event handler. void qtractorMainForm::audioSyncNotify ( unsigned long iPlayHead ) { if (m_pSession->isBusy()) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::audioSyncNotify(%lu)", iPlayHead); #endif m_pSession->setPlayHead(iPlayHead); ++m_iTransportUpdate; } // Custom MMC event handler. void qtractorMainForm::midiMmcNotify ( const qtractorMmcEvent& mmce ) { QString sMmcText("MIDI MMC: "); switch (mmce.cmd()) { case qtractorMmcEvent::STOP: case qtractorMmcEvent::PAUSE: sMmcText += tr("STOP"); setPlaying(false); break; case qtractorMmcEvent::PLAY: case qtractorMmcEvent::DEFERRED_PLAY: sMmcText += tr("PLAY"); setPlaying(true); break; case qtractorMmcEvent::FAST_FORWARD: sMmcText += tr("FFWD"); setRolling(+1); break; case qtractorMmcEvent::REWIND: sMmcText += tr("REW"); setRolling(-1); break; case qtractorMmcEvent::RECORD_STROBE: case qtractorMmcEvent::RECORD_PAUSE: sMmcText += tr("REC ON"); if (!setRecording(true)) { // Send MMC RECORD_EXIT command immediate reply... m_pSession->midiEngine()->sendMmcCommand( qtractorMmcEvent::RECORD_EXIT); } break; case qtractorMmcEvent::RECORD_EXIT: sMmcText += tr("REC OFF"); setRecording(false); break; case qtractorMmcEvent::MMC_RESET: sMmcText += tr("RESET"); setRolling(0); break; case qtractorMmcEvent::LOCATE: sMmcText += tr("LOCATE %1").arg(mmce.locate()); setLocate(mmce.locate()); break; case qtractorMmcEvent::SHUTTLE: sMmcText += tr("SHUTTLE %1").arg(mmce.shuttle()); setShuttle(mmce.shuttle()); break; case qtractorMmcEvent::STEP: sMmcText += tr("STEP %1").arg(mmce.step()); setStep(mmce.step()); break; case qtractorMmcEvent::MASKED_WRITE: switch (mmce.scmd()) { case qtractorMmcEvent::TRACK_RECORD: sMmcText += tr("TRACK RECORD %1 %2") .arg(mmce.track()) .arg(mmce.isOn()); break; case qtractorMmcEvent::TRACK_MUTE: sMmcText += tr("TRACK MUTE %1 %2") .arg(mmce.track()) .arg(mmce.isOn()); break; case qtractorMmcEvent::TRACK_SOLO: sMmcText += tr("TRACK SOLO %1 %2") .arg(mmce.track()) .arg(mmce.isOn()); break; default: sMmcText += tr("Unknown sub-command"); break; } setTrack(mmce.scmd(), mmce.track(), mmce.isOn()); break; default: sMmcText += tr("Not implemented"); break; } appendMessages(sMmcText); stabilizeForm(); } // Custom controller event handler. void qtractorMainForm::midiCtlNotify ( const qtractorCtlEvent& ctle ) { QString sCtlText(tr("MIDI CTL: %1, Channel %2, Param %3, Value %4") .arg(qtractorMidiControl::nameFromType(ctle.type())) .arg(ctle.channel() + 1) .arg(ctle.param()) .arg(ctle.value())); #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::midiCtlNotify() %s.", sCtlText.toUtf8().constData()); #endif // Check if controller is used as MIDI controller... if (m_pMidiControl->processEvent(ctle)) { appendMessages(sCtlText); return; } if (ctle.type() == qtractorMidiEvent::CONTROLLER) { /* FIXME: JLCooper faders (as from US-224)... if (ctle.channel() == 15) { // Event translation... int iTrack = int(ctle.controller()) & 0x3f; float fGain = float(ctle.value()) / 127.0f; // Find the track by number... qtractorTrack *pTrack = m_pSession->tracks().at(iTrack); if (pTrack) { m_pSession->execute( new qtractorTrackGainCommand(pTrack, fGain, true)); sCtlText += ' '; sCtlText += tr("(track %1, gain %2)") .arg(iTrack).arg(fGain); appendMessages(sCtlText); } } else */ // Handle volume controls... if (ctle.param() == 7) { int iTrack = 0; float fGain = float(ctle.value()) / 127.0f; for (qtractorTrack *pTrack = m_pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { if (pTrack->trackType() == qtractorTrack::Midi && pTrack->midiChannel() == ctle.channel()) { m_pSession->execute( new qtractorTrackGainCommand(pTrack, fGain, true)); sCtlText += ' '; sCtlText += tr("(track %1, gain %2)") .arg(iTrack).arg(fGain); appendMessages(sCtlText); } ++iTrack; } } else // Handle pan controls... if (ctle.param() == 10) { int iTrack = 0; float fPanning = (float(ctle.value()) - 64.0f) / 63.0f; for (qtractorTrack *pTrack = m_pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { if (pTrack->trackType() == qtractorTrack::Midi && pTrack->midiChannel() == ctle.channel()) { m_pSession->execute( new qtractorTrackPanningCommand(pTrack, fPanning, true)); sCtlText += ' '; sCtlText += tr("(track %1, panning %2)") .arg(iTrack).arg(fPanning); appendMessages(sCtlText); } ++iTrack; } } } } // Custom MIDI SPP event handler. void qtractorMainForm::midiSppNotify ( int iSppCmd, unsigned short iSongPos ) { QString sSppText("MIDI SPP: "); switch (iSppCmd) { case SND_SEQ_EVENT_START: sSppText += tr("START"); setSongPos(0); setPlaying(true); break; case SND_SEQ_EVENT_STOP: sSppText += tr("STOP"); setPlaying(false); break; case SND_SEQ_EVENT_CONTINUE: sSppText += tr("CONTINUE"); setPlaying(true); break; case SND_SEQ_EVENT_SONGPOS: sSppText += tr("SONGPOS %1").arg(iSongPos); setSongPos(iSongPos); break; default: sSppText += tr("Not implemented"); break; } appendMessages(sSppText); stabilizeForm(); } // Custom MIDI Clock event handler. void qtractorMainForm::midiClkNotify ( float fTempo ) { QString sClkText("MIDI CLK: "); sClkText += tr("%1 BPM").arg(fTempo); appendMessages(sClkText); if (m_pTracks) m_pTracks->clearSelect(); // Find appropriate node... qtractorTimeScale *pTimeScale = m_pSession->timeScale(); qtractorTimeScale::Cursor& cursor = pTimeScale->cursor(); qtractorTimeScale::Node *pNode = cursor.seekFrame(m_pSession->playHead()); // Now, express the change immediately... if (pNode->prev()) { pNode->tempo = fTempo; pTimeScale->updateNode(pNode); } else { m_pSession->setTempo(fTempo); } ++m_iTransportUpdate; updateContents(NULL, true); stabilizeForm(); } //------------------------------------------------------------------------- // qtractorMainForm -- General contents change stuff. // Audio file addition slot funtion. void qtractorMainForm::addAudioFile ( const QString& sFilename, bool bAutoRemove ) { // Add the just dropped audio file... if (m_pFiles) m_pFiles->addAudioFile(sFilename, bAutoRemove); stabilizeForm(); } // Audio file selection slot funtion. void qtractorMainForm::selectAudioFile ( const QString& sFilename, int iTrackChannel, bool bSelect ) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::selectAudioFile(\"%s\", %d, %d)", sFilename.toUtf8().constData(), iTrackChannel, int(bSelect)); #endif // Select audio file... if (m_pTracks) { m_pTracks->trackView()->selectClipFile( qtractorTrack::Audio, sFilename, iTrackChannel, bSelect); } stabilizeForm(); } // Audio file activation slot funtion. void qtractorMainForm::activateAudioFile ( const QString& sFilename, int /*iTrackChannel*/ ) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::selectAudioFile(\"%s\")", sFilename.toUtf8().constData()); #endif // Make sure session is activated... checkRestartSession(); // We'll start playing if the file is valid, otherwise // the player is stopped (eg. empty filename)... qtractorAudioEngine *pAudioEngine = m_pSession->audioEngine(); if (pAudioEngine && pAudioEngine->openPlayer(sFilename)) { if (m_pFiles) m_pFiles->setPlayState(true); appendMessages(tr("Playing \"%1\"...") .arg(QFileInfo(sFilename).fileName())); } // Try updating player status anyway... if (m_iPlayerTimer < QTRACTOR_TIMER_DELAY) m_iPlayerTimer += QTRACTOR_TIMER_DELAY; stabilizeForm(); } // MIDI file addition slot funtion. void qtractorMainForm::addMidiFile ( const QString& sFilename, bool bAutoRemove ) { // Add the just dropped MIDI file... if (m_pFiles) m_pFiles->addMidiFile(sFilename, bAutoRemove); stabilizeForm(); } // MIDI file selection slot funtion. void qtractorMainForm::selectMidiFile ( const QString& sFilename, int iTrackChannel, bool bSelect ) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::selectMidiFile(\"%s\", %d, %d)", sFilename.toUtf8().constData(), iTrackChannel, int(bSelect)); #endif // Select MIDI file track/channel... if (m_pTracks) { m_pTracks->trackView()->selectClipFile( qtractorTrack::Midi, sFilename, iTrackChannel, bSelect); } stabilizeForm(); } // MIDI file activation slot funtion. void qtractorMainForm::activateMidiFile ( const QString& sFilename, int iTrackChannel ) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::activateMidiFile(\"%s\", %d)", sFilename.toUtf8().constData(), iTrackChannel); #endif // Make sure session is activated... checkRestartSession(); // We'll start playing if the file is valid, otherwise // the player is stopped (eg. empty filename)... qtractorMidiEngine *pMidiEngine = m_pSession->midiEngine(); if (pMidiEngine && pMidiEngine->openPlayer(sFilename, iTrackChannel)) { if (m_pFiles) m_pFiles->setPlayState(true); appendMessages(tr("Playing \"%1\"...") .arg(QFileInfo(sFilename).fileName())); } // Try updating player status anyway... if (m_iPlayerTimer < QTRACTOR_TIMER_DELAY) m_iPlayerTimer += QTRACTOR_TIMER_DELAY; stabilizeForm(); } // Tracks view selection change slot. void qtractorMainForm::trackSelectionChanged (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMainForm::trackSelectionChanged()"); #endif // Select sync to mixer... if (m_pTracks && m_pMixer && m_pMixer->trackRack()) { qtractorMixerStrip *pStrip = NULL; qtractorTrack *pTrack = m_pTracks->trackList()->currentTrack(); if (pTrack) pStrip = (m_pMixer->trackRack())->findStrip(pTrack->monitor()); if (pStrip) { int wm = (pStrip->width() >> 1); (m_pMixer->trackRack())->ensureVisible( pStrip->pos().x() + wm, 0, wm, 0); } // Doesn't matter whether strip is null... (m_pMixer->trackRack())->setSelectedStrip(pStrip); // HACK: Set current session track for monitoring purposes... if (m_ui.trackAutoMonitorAction->isChecked()) m_pSession->setCurrentTrack(pTrack); } stabilizeForm(); } // Mixer view selection change slot. void qtractorMainForm::mixerSelectionChanged (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMainForm::mixerSelectionChanged()"); #endif // Select sync to tracks... if (m_pTracks && m_pMixer && m_pMixer->trackRack()) { qtractorTrack *pTrack = NULL; qtractorMixerStrip *pStrip = (m_pMixer->trackRack())->selectedStrip(); if (pStrip) pTrack = pStrip->track(); (m_pTracks->trackList())->setCurrentTrack(pTrack); } stabilizeForm(); } // Tracks view selection change slot. void qtractorMainForm::selectionNotifySlot ( qtractorMidiEditor *pMidiEditor ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMainForm::selectionNotifySlot()"); #endif // Read session edit-head/tails... unsigned long iEditHead = m_pSession->editHead(); unsigned long iEditTail = m_pSession->editTail(); // Track-view is due... if (m_pTracks) { m_pTracks->trackView()->setEditHead(iEditHead); m_pTracks->trackView()->setEditTail(iEditTail); if (pMidiEditor) m_pTracks->clearSelect(); } // Update editors edit-head/tails... QListIterator iter(m_editors); while (iter.hasNext()) { qtractorMidiEditor *pEditor = (iter.next())->editor(); if (pEditor != pMidiEditor) { pEditor->setEditHead(iEditHead, false); pEditor->setEditTail(iEditTail, false); } } // Normal status ahead... stabilizeForm(); } // Clip editors update helper. void qtractorMainForm::changeNotifySlot ( qtractorMidiEditor *pMidiEditor ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMainForm::changeNotifySlot()"); #endif updateContents(pMidiEditor, true); } // Command update helper. void qtractorMainForm::updateNotifySlot ( unsigned int flags ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMainForm::updateNotifySlot(%d)", int(bRefresh)); #endif // Always reset any track view selection... // (avoid change/update notifications, again) if (m_pTracks && (flags & qtractorCommand::ClearSelect)) m_pTracks->clearSelect(); // Proceed as usual... updateContents(NULL, (flags & qtractorCommand::Refresh)); } // Common update helper. void qtractorMainForm::updateContents ( qtractorMidiEditor *pMidiEditor, bool bRefresh ) { // Maybe, just maybe, we've made things larger... m_pSession->updateTimeScale(); m_pSession->updateSession(); // Refresh track-view? if (m_pTracks) m_pTracks->updateContents(bRefresh); // Update other editors contents... QListIterator iter(m_editors); while (iter.hasNext()) { qtractorMidiEditor *pEditor = (iter.next())->editor(); if (pEditor != pMidiEditor) { pEditor->updateTimeScale(); pEditor->updateContents(); } } // Notify who's watching... contentsChanged(); } void qtractorMainForm::updateDirtyCount ( bool bDirtyCount ) { if (bDirtyCount) { ++m_iDirtyCount; } else { m_iDirtyCount = 0; } #ifdef CONFIG_NSM if (m_pNsmClient && m_pNsmClient->is_active()) { if (!m_bNsmDirty/* && bDirtyCount*/) { m_pNsmClient->dirty(true); m_bNsmDirty = true; } } #endif } // Tracks view contents change slot. void qtractorMainForm::contentsChanged (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMainForm::contentsChanged()"); #endif // HACK: Force play-head position update... // m_iPlayHead = 0; m_pTempoCursor->clear(); // Stabilize session toolbar widgets... // m_pTempoSpinBox->setTempo(m_pSession->tempo(), false); // m_pTempoSpinBox->setBeatsPerBar(m_pSession->beatsPerBar(), false); // m_pTempoSpinBox->setBeatDivisor(m_pSession->beatDivisor(), false); m_pSnapPerBeatComboBox->setCurrentIndex( qtractorTimeScale::indexFromSnap(m_pSession->snapPerBeat())); m_pThumbView->updateContents(); dirtyNotifySlot(); } // Tracks view contents dirty up slot. void qtractorMainForm::dirtyNotifySlot (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorMainForm::dirtyNotifySlot()"); #endif updateDirtyCount(true); selectionNotifySlot(NULL); } // Tempo spin-box change slot. void qtractorMainForm::transportTempoChanged ( float fTempo, unsigned short iBeatsPerBar, unsigned short iBeatDivisor ) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportTempoChanged(%g, %u, %u)", fTempo, iBeatsPerBar, iBeatDivisor); #endif // Find appropriate node... qtractorTimeScale *pTimeScale = m_pSession->timeScale(); qtractorTimeScale::Cursor& cursor = pTimeScale->cursor(); qtractorTimeScale::Node *pNode = cursor.seekFrame(m_pSession->playHead()); // Now, express the change as a undoable command... m_pSession->execute(new qtractorTimeScaleUpdateNodeCommand( pTimeScale, pNode->frame, fTempo, 2, iBeatsPerBar, iBeatDivisor)); ++m_iTransportUpdate; } void qtractorMainForm::transportTempoFinished (void) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportTempoFinished()"); #endif bool bBlockSignals = m_pTempoSpinBox->blockSignals(true); m_pTempoSpinBox->clearFocus(); // if (m_pTracks) // m_pTracks->trackView()->setFocus(); m_pTempoSpinBox->blockSignals(bBlockSignals); } // Snap-per-beat spin-box change slot. void qtractorMainForm::snapPerBeatChanged ( int iSnap ) { // Avoid bogus changes... unsigned short iSnapPerBeat = qtractorTimeScale::snapFromIndex(iSnap); if (iSnapPerBeat == m_pSession->snapPerBeat()) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::snapPerBeatChanged(%u)", iSnapPerBeat); #endif // No need to express this change as a undoable command... m_pSession->setSnapPerBeat(iSnapPerBeat); } // Time format custom context menu. void qtractorMainForm::transportTimeFormatChanged ( int iDisplayFormat ) { #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportTimeFormatChanged(%d)", iDisplayFormat); #endif if (m_pOptions) { m_pOptions->iDisplayFormat = iDisplayFormat; updateDisplayFormat(); } stabilizeForm(); } // Real thing: the playhead has been changed manually! void qtractorMainForm::transportTimeChanged ( unsigned long iPlayHead ) { if (m_iTransportUpdate > 0) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportTimeChanged(%lu)", iPlayHead); #endif m_pSession->setPlayHead(iPlayHead); ++m_iTransportUpdate; stabilizeForm(); } void qtractorMainForm::transportTimeFinished (void) { static int s_iTimeFinished = 0; if (s_iTimeFinished > 0) return; #ifdef CONFIG_DEBUG qDebug("qtractorMainForm::transportTimeFinished()"); #endif ++s_iTimeFinished; m_pTimeSpinBox->clearFocus(); // if (m_pTracks) // m_pTracks->trackView()->setFocus(); --s_iTimeFinished; } // Tempo-map custom context menu. void qtractorMainForm::transportTempoContextMenu ( const QPoint& /*pos*/ ) { viewTempoMap(); } // end of qtractorMainForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTrackForm.cpp0000644000175000001440000000012312166526620021425 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134667.16208 30 ctime=1381134667.162080051 qtractor-0.5.11/src/qtractorTrackForm.cpp0000644000175000001440000011242712166526620020723 0ustar00rncbcusers00000000000000// qtractorTrackForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorTrackForm.h" #include "qtractorAbout.h" #include "qtractorTrack.h" #include "qtractorSession.h" #include "qtractorInstrument.h" #include "qtractorAudioEngine.h" #include "qtractorMidiEngine.h" #include "qtractorMidiBuffer.h" #include "qtractorPlugin.h" #include "qtractorCommand.h" #include "qtractorBusForm.h" #include #include #include #include #include //---------------------------------------------------------------------- // class qtractorColorItemDelegate -- Custom color view item delegate. // class qtractorColorItemDelegate : public QItemDelegate { public: // Constructor. qtractorColorItemDelegate ( QComboBox *pComboBox ) : QItemDelegate(pComboBox), m_pComboBox(pComboBox) {} // Overridden paint method. void paint(QPainter *pPainter, const QStyleOptionViewItem& option, const QModelIndex& index) const { // Item data has the color... const QPoint delta(2, 2); QRect rect(option.rect); rect.setTopLeft(rect.topLeft() + delta); rect.setBottomRight(rect.bottomRight() - delta); QColor color(m_pComboBox->itemText(index.row())); pPainter->save(); if (option.state & QStyle::State_Selected) pPainter->setPen(QPen(option.palette.highlight().color(), 2)); else pPainter->setPen(QPen(option.palette.base().color(), 2)); pPainter->setBrush(color); pPainter->drawRect(rect); pPainter->restore(); if (option.state & QStyle::State_HasFocus) QItemDelegate::drawFocus(pPainter, option, option.rect); } private: // Item color spec. QComboBox *m_pComboBox; }; //---------------------------------------------------------------------------- // qtractorTrackForm::MidiProgramObserver -- Local dedicated observer. class qtractorTrackForm::MidiProgramObserver : public qtractorObserver { public: // Constructor. MidiProgramObserver(qtractorTrackForm *pTrackForm, qtractorSubject *pSubject) : qtractorObserver(pSubject), m_pTrackForm(pTrackForm) {} protected: // Update feedback. void update(bool bUpdate) { if (bUpdate) { const int iValue = int(value()); const int iBank = (iValue >> 7) & 0x3fff; const int iProg = (iValue & 0x7f); m_pTrackForm->setMidiProgram(iBank, iProg); } } private: // Members. qtractorTrackForm *m_pTrackForm; }; //---------------------------------------------------------------------------- // qtractorTrackForm -- UI wrapper form. // Constructor. qtractorTrackForm::qtractorTrackForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::WindowModal); // No settings descriptor initially (the caller will set it). m_pTrack = NULL; // Current MIDI output bus to be cached. m_pMidiBus = NULL; // Set some dialog validators... m_ui.BankComboBox->setValidator(new QIntValidator(m_ui.BankComboBox)); m_ui.ProgComboBox->setValidator(new QIntValidator(m_ui.ProgComboBox)); // Bank select methods. const QIcon& icon = QIcon(":/images/itemProperty.png"); m_ui.BankSelMethodComboBox->clear(); m_ui.BankSelMethodComboBox->addItem(icon, tr("Normal")); m_ui.BankSelMethodComboBox->addItem(icon, tr("Bank MSB")); m_ui.BankSelMethodComboBox->addItem(icon, tr("Bank LSB")); m_ui.BankSelMethodComboBox->addItem(icon, tr("Patch")); // Custom colors. m_ui.ForegroundColorComboBox->setItemDelegate( new qtractorColorItemDelegate(m_ui.ForegroundColorComboBox)); m_ui.BackgroundColorComboBox->setItemDelegate( new qtractorColorItemDelegate(m_ui.BackgroundColorComboBox)); m_ui.ForegroundColorComboBox->clear(); m_ui.BackgroundColorComboBox->clear(); for (int i = 1; i < 28; ++i) { const QColor& rgbBack = qtractorTrack::trackColor(i); const QColor& rgbFore = rgbBack.darker(); m_ui.ForegroundColorComboBox->addItem(rgbFore.name()); m_ui.BackgroundColorComboBox->addItem(rgbBack.name()); } // To save and keep bus/channel patching consistency. m_pOldMidiBus = NULL; m_iOldChannel = -1; m_sOldInstrumentName.clear(); m_iOldBankSelMethod = -1; m_iOldBank = -1; m_iOldProg = -1; // No last acceptable command yet. m_pLastCommand = NULL; // MIDI ban/program observer. m_pMidiProgramObserver = NULL; // Initialize dirty control state. m_iDirtySetup = 0; m_iDirtyCount = 0; m_iDirtyPatch = 0; // UI signal/slot connections... QObject::connect(m_ui.TrackNameTextEdit, SIGNAL(textChanged()), SLOT(changed())); QObject::connect(m_ui.AudioRadioButton, SIGNAL(toggled(bool)), SLOT(trackTypeChanged())); QObject::connect(m_ui.MidiRadioButton, SIGNAL(toggled(bool)), SLOT(trackTypeChanged())); QObject::connect(m_ui.InputBusNameComboBox, SIGNAL(activated(const QString &)), SLOT(inputBusNameChanged(const QString&))); QObject::connect(m_ui.OutputBusNameComboBox, SIGNAL(activated(const QString &)), SLOT(outputBusNameChanged(const QString&))); QObject::connect(m_ui.BusNameToolButton, SIGNAL(clicked()), SLOT(busNameClicked())); QObject::connect(m_ui.OmniCheckBox, SIGNAL(clicked()), SLOT(changed())); QObject::connect(m_ui.ChannelSpinBox, SIGNAL(valueChanged(int)), SLOT(channelChanged(int))); QObject::connect(m_ui.InstrumentComboBox, SIGNAL(activated(const QString &)), SLOT(instrumentChanged(const QString&))); QObject::connect(m_ui.BankSelMethodComboBox, SIGNAL(activated(int)), SLOT(bankSelMethodChanged(int))); QObject::connect(m_ui.BankComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(bankChanged())); QObject::connect(m_ui.ProgComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(progChanged())); QObject::connect(m_ui.ForegroundColorComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(foregroundColorChanged(const QString&))); QObject::connect(m_ui.ForegroundColorToolButton, SIGNAL(clicked()), SLOT(selectForegroundColor())); QObject::connect(m_ui.BackgroundColorComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(backgroundColorChanged(const QString&))); QObject::connect(m_ui.BackgroundColorToolButton, SIGNAL(clicked()), SLOT(selectBackgroundColor())); QObject::connect(m_ui.PluginListView, SIGNAL(currentRowChanged(int)), SLOT(stabilizeForm())); QObject::connect(m_ui.PluginListView, SIGNAL(contentsChanged()), SLOT(pluginListChanged())); QObject::connect(m_ui.AddPluginToolButton, SIGNAL(clicked()), SLOT(addPlugin())); QObject::connect(m_ui.RemovePluginToolButton, SIGNAL(clicked()), SLOT(removePlugin())); QObject::connect(m_ui.MoveUpPluginToolButton, SIGNAL(clicked()), SLOT(moveUpPlugin())); QObject::connect(m_ui.MoveDownPluginToolButton, SIGNAL(clicked()), SLOT(moveDownPlugin())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); } // Destructor. qtractorTrackForm::~qtractorTrackForm (void) { // Free up the MIDI bank/program observer... if (m_pMidiProgramObserver) delete m_pMidiProgramObserver; } // Populate (setup) dialog controls from settings descriptors. void qtractorTrackForm::setTrack ( qtractorTrack *pTrack ) { // Avoid dirty this all up. ++m_iDirtySetup; // Set target track reference descriptor. m_pTrack = pTrack; // Track properties cloning... m_props = m_pTrack->properties(); // Get reference of the last acceptable command... qtractorCommandList *pCommands = (m_pTrack->session())->commands(); m_pLastCommand = pCommands->lastCommand(); // Set plugin list... m_ui.PluginListView->setPluginList(m_pTrack->pluginList()); // Initialize dialog widgets... m_ui.TrackNameTextEdit->setPlainText(m_props.trackName); qtractorEngine *pEngine = NULL; switch (m_props.trackType) { case qtractorTrack::Audio: pEngine = (m_pTrack->session())->audioEngine(); m_ui.AudioRadioButton->setChecked(true); break; case qtractorTrack::Midi: pEngine = (m_pTrack->session())->midiEngine(); m_ui.MidiRadioButton->setChecked(true); break; default: break; } updateTrackType(m_props.trackType); if (pEngine && pEngine->findInputBus(m_props.inputBusName)) m_ui.InputBusNameComboBox->setCurrentIndex( m_ui.InputBusNameComboBox->findText(m_props.inputBusName)); if (pEngine && pEngine->findOutputBus(m_props.outputBusName)) m_ui.OutputBusNameComboBox->setCurrentIndex( m_ui.OutputBusNameComboBox->findText(m_props.outputBusName)); // Force MIDI output bus recaching. m_pMidiBus = midiBus(); // Make sure this will be remembered for backup. m_pOldMidiBus = m_pMidiBus; m_iOldChannel = m_props.midiChannel; // m_sOldInstrumentName initially blank... m_iOldBankSelMethod = m_props.midiBankSelMethod; m_iOldBank = m_props.midiBank; m_iOldProg = m_props.midiProg; // Already time for instrument cacheing... updateInstruments(); m_ui.OmniCheckBox->setChecked(m_props.midiOmni); m_ui.ChannelSpinBox->setValue(m_props.midiChannel + 1); updateChannel(m_ui.ChannelSpinBox->value(), m_props.midiBankSelMethod, m_props.midiBank, m_props.midiProg); // Update colors... updateColorItem(m_ui.ForegroundColorComboBox, m_props.foreground); updateColorItem(m_ui.BackgroundColorComboBox, m_props.background); // Cannot change track type, if track is already chained in session.. m_ui.AudioRadioButton->setEnabled(m_props.trackType != qtractorTrack::Midi); m_ui.MidiRadioButton->setEnabled(m_props.trackType != qtractorTrack::Audio); // A bit of parental control... QObject::connect(pCommands, SIGNAL(updateNotifySignal(unsigned int)), SLOT(changed())); // Backup clean. m_iDirtyCount = 0; --m_iDirtySetup; // Done. stabilizeForm(); } // Retrieve the editing track, if the case arises. qtractorTrack *qtractorTrackForm::track (void) const { return m_pTrack; } // Retrieve the accepted track properties, if the case arises. const qtractorTrack::Properties& qtractorTrackForm::properties (void) const { return m_props; } // Selected track type determinator. qtractorTrack::TrackType qtractorTrackForm::trackType (void) const { qtractorTrack::TrackType trackType = qtractorTrack::None; if (m_ui.AudioRadioButton->isChecked()) trackType = qtractorTrack::Audio; else if (m_ui.MidiRadioButton->isChecked()) trackType = qtractorTrack::Midi; return trackType; } // Accept settings (OK button slot). void qtractorTrackForm::accept (void) { // Save options... if (m_iDirtyCount > 0) { // Make changes permanent... m_props.trackName = m_ui.TrackNameTextEdit->toPlainText(); m_props.trackType = trackType(); m_props.inputBusName = m_ui.InputBusNameComboBox->currentText(); m_props.outputBusName = m_ui.OutputBusNameComboBox->currentText(); // Special case for MIDI settings... m_props.midiOmni = m_ui.OmniCheckBox->isChecked(); m_props.midiChannel = (m_ui.ChannelSpinBox->value() - 1); m_props.midiBankSelMethod = m_ui.BankSelMethodComboBox->currentIndex(); m_props.midiBank = midiBank(); m_props.midiProg = midiProg(); // View colors... m_props.foreground = colorItem(m_ui.ForegroundColorComboBox); m_props.background = colorItem(m_ui.BackgroundColorComboBox); m_props.background.setAlpha(192); // Reset dirty flag. m_iDirtyCount = 0; } // Just go with dialog acceptance. QDialog::accept(); } // Reject settings (Cancel button slot). void qtractorTrackForm::reject (void) { bool bReject = true; // Check if there's any pending changes... if (m_iDirtyCount > 0) { QMessageBox::StandardButtons buttons = QMessageBox::Discard | QMessageBox::Cancel; if (m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->isEnabled()) buttons |= QMessageBox::Apply; switch (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Some settings have been changed.\n\n" "Do you want to apply the changes?"), buttons)) { case QMessageBox::Apply: accept(); return; case QMessageBox::Discard: break; default: // Cancel. bReject = false; } } if (bReject) { // Bogus track? Unlikely, but... if (m_pTrack) { // Backout all commands made this far... ((m_pTrack->session())->commands())->backout(m_pLastCommand); // Try to restore the previously saved patch... if (m_pOldMidiBus && m_iDirtyPatch > 0) { m_pOldMidiBus->setPatch(m_iOldChannel, m_sOldInstrumentName, m_iOldBankSelMethod, m_iOldBank, m_iOldProg, m_pTrack); } } // Reset plugin list, before too late... m_ui.PluginListView->setPluginList(NULL); // Just go away. QDialog::reject(); } } // Stabilize current form state. void qtractorTrackForm::stabilizeForm (void) { bool bValid = (m_iDirtyCount > 0); bValid = bValid && !m_ui.TrackNameTextEdit->toPlainText().isEmpty(); bValid = bValid && trackType() != qtractorTrack::None; m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(bValid); // Stabilize current plugin list state. int iItem = -1; int iItemCount = m_ui.PluginListView->count(); qtractorPlugin *pPlugin = NULL; qtractorPluginListItem *pItem = static_cast ( m_ui.PluginListView->currentItem()); if (pItem) { iItem = m_ui.PluginListView->row(pItem); pPlugin = pItem->plugin(); } // m_ui.AddPluginToolButton->setEnabled(true); m_ui.RemovePluginToolButton->setEnabled(pPlugin != NULL); m_ui.MoveUpPluginToolButton->setEnabled(pItem && iItem > 0); m_ui.MoveDownPluginToolButton->setEnabled(pItem && iItem < iItemCount - 1); } // Retrieve currently assigned MIDI output-bus, if applicable. qtractorMidiBus *qtractorTrackForm::midiBus (void) const { if (m_pTrack == NULL) return NULL; // If it ain't MIDI, bail out... if (trackType() != qtractorTrack::Midi) return NULL; // MIDI engine... qtractorMidiEngine *pMidiEngine = m_pTrack->session()->midiEngine(); if (pMidiEngine == NULL) return NULL; // MIDI bus... const QString& sOutputBusName = m_ui.OutputBusNameComboBox->currentText(); return static_cast ( pMidiEngine->findOutputBus(sOutputBusName)); } // Retrieve currently selected MIDI bank number. int qtractorTrackForm::midiBank (void) const { const QString& sBankText = m_ui.BankComboBox->currentText(); int iBankIndex = m_ui.BankComboBox->findText(sBankText); if (iBankIndex >= 0 && m_banks.contains(iBankIndex) && m_ui.BankComboBox->itemText(iBankIndex) == sBankText) return m_banks[iBankIndex]; return sBankText.toInt(); } // Retrieve currently selected MIDI program number. int qtractorTrackForm::midiProg (void) const { const QString& sProgText = m_ui.ProgComboBox->currentText(); int iProgIndex = m_ui.ProgComboBox->findText(sProgText); if (iProgIndex >= 0 && m_progs.contains(iProgIndex) && m_ui.ProgComboBox->itemText(iProgIndex) == sProgText) return m_progs[iProgIndex]; return sProgText.toInt(); } // Refresh instrument list. void qtractorTrackForm::updateInstruments (void) { if (m_pTrack == NULL) return; qtractorSession *pSession = m_pTrack->session(); if (pSession == NULL) return; qtractorInstrumentList *pInstruments = pSession->instruments(); if (pInstruments == NULL) return; // Avoid superfluous change notifications... ++m_iDirtySetup; m_ui.InstrumentComboBox->clear(); m_ui.InstrumentComboBox->addItem(tr("(No instrument)")); const QIcon& icon = QIcon(":/images/itemInstrument.png"); // Take care of MIDI plugin instrument names... updateInstrumentsAdd(icon, (m_pTrack->pluginList())->midiManager()); // And, maybe some from the MIDI output bus... if (m_pMidiBus && m_pMidiBus->pluginList_out()) updateInstrumentsAdd(icon, (m_pMidiBus->pluginList_out())->midiManager()); // Regular instrument names... qtractorInstrumentList::ConstIterator iter = pInstruments->constBegin(); const qtractorInstrumentList::ConstIterator& iter_end = pInstruments->constEnd(); for ( ; iter != iter_end; ++iter) m_ui.InstrumentComboBox->addItem(icon, iter.value().instrumentName()); // Done. --m_iDirtySetup; } // Refresh instrument list of given MIDI buffer manager. void qtractorTrackForm::updateInstrumentsAdd ( const QIcon& icon, qtractorMidiManager *pMidiManager ) { if (pMidiManager == NULL) return; pMidiManager->updateInstruments(); const qtractorMidiManager::Instruments& list = pMidiManager->instruments(); qtractorMidiManager::Instruments::ConstIterator iter = list.constBegin(); const qtractorMidiManager::Instruments::ConstIterator& iter_end = list.constEnd(); for ( ; iter != iter_end; ++iter) m_ui.InstrumentComboBox->addItem(icon, iter.key()); } // Update track type and buses. void qtractorTrackForm::updateTrackType ( qtractorTrack::TrackType trackType ) { // Avoid superfluos change notifications... ++m_iDirtySetup; // Renew the MIDI bank/program observer. if (m_pMidiProgramObserver) { delete m_pMidiProgramObserver; m_pMidiProgramObserver = NULL; } // Make changes due to track type change. qtractorEngine *pEngine = NULL; QIcon icon; switch (trackType) { case qtractorTrack::Audio: pEngine = m_pTrack->session()->audioEngine(); icon = QIcon(":/images/trackAudio.png"); m_ui.MidiGroupBox->hide(); m_ui.MidiGroupBox->setEnabled(false); m_ui.InputBusNameComboBox->setEnabled(true); m_ui.OutputBusNameComboBox->setEnabled(true); break; case qtractorTrack::Midi: pEngine = m_pTrack->session()->midiEngine(); icon = QIcon(":/images/trackMidi.png"); m_ui.MidiGroupBox->show(); m_ui.MidiGroupBox->setEnabled(true); m_ui.InputBusNameComboBox->setEnabled(true); m_ui.OutputBusNameComboBox->setEnabled(true); if (m_pTrack->pluginList() && (m_pTrack->pluginList())->midiProgramSubject()) { m_pMidiProgramObserver = new MidiProgramObserver(this, (m_pTrack->pluginList())->midiProgramSubject()); } break; case qtractorTrack::None: default: m_ui.MidiGroupBox->hide(); m_ui.MidiGroupBox->setEnabled(false); m_ui.InputBusNameComboBox->setEnabled(false); m_ui.OutputBusNameComboBox->setEnabled(false); break; } m_ui.InputBusNameComboBox->clear(); m_ui.OutputBusNameComboBox->clear(); if (pEngine) { for (qtractorBus *pBus = pEngine->buses().first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Input) m_ui.InputBusNameComboBox->addItem(icon, pBus->busName()); if (pBus->busMode() & qtractorBus::Output) m_ui.OutputBusNameComboBox->addItem(icon, pBus->busName()); } } // Shake it a little bit first, but // make it as tight as possible... resize(width() - 1, height() - 1); adjustSize(); // Done. --m_iDirtySetup; } // Refresh channel instrument banks list. void qtractorTrackForm::updateChannel ( int iChannel, int iBankSelMethod, int iBank, int iProg ) { // Regular channel offset if (--iChannel < 0) return; // MIDI bus... if (m_pMidiBus == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorTrackForm::updateChannel(%d, %d, %d, %d)", iChannel, iBankSelMethod, iBank, iProg); #endif // Avoid superfluos change notifications... ++m_iDirtySetup; // MIDI channel patch... const qtractorMidiBus::Patch& patch = m_pMidiBus->patch(iChannel); QString sInstrumentName = patch.instrumentName; if (sInstrumentName.isEmpty()) sInstrumentName = m_pMidiBus->instrumentName(); if (iBankSelMethod < 0) iBankSelMethod = patch.bankSelMethod; #if 0 if (iBank < 0) iBank = patch.bank; if (iProg < 0) iProg = patch.prog; #endif // Select instrument... int iInstrumentIndex = m_ui.InstrumentComboBox->findText(sInstrumentName); if (iInstrumentIndex < 0) { iInstrumentIndex = 0; sInstrumentName.clear(); } m_ui.InstrumentComboBox->setCurrentIndex(iInstrumentIndex); // Go and update the bank and program listings... updateBanks(sInstrumentName, iBankSelMethod, iBank, iProg); // Done. --m_iDirtySetup; } // Refresh instrument banks list. void qtractorTrackForm::updateBanks ( const QString& sInstrumentName, int iBankSelMethod, int iBank, int iProg ) { if (m_pTrack == NULL) return; qtractorSession *pSession = m_pTrack->session(); if (pSession == NULL) return; // if (sInstrumentName.isEmpty()) // return; #ifdef CONFIG_DEBUG qDebug("qtractorTrackForm::updateBanks(\"%s\", %d, %d, %d)", sInstrumentName.toUtf8().constData(), iBankSelMethod, iBank, iProg); #endif qtractorInstrumentList *pInstruments = pSession->instruments(); if (pInstruments == NULL) return; // Avoid superfluos change notifications... ++m_iDirtySetup; // Default (none) patch bank list... int iBankIndex = 0; const QIcon& icon = QIcon(":/images/itemPatches.png"); m_banks.clear(); m_ui.BankComboBox->clear(); m_ui.BankComboBox->addItem(icon, tr("(None)")); m_banks[iBankIndex++] = -1; // Care of MIDI plugin instrument banks... bool bMidiManager = updateBanksAdd(icon, (m_pTrack->pluginList())->midiManager(), sInstrumentName, iBank, iBankIndex); if (!bMidiManager && m_pMidiBus && m_pMidiBus->pluginList_out()) { bMidiManager = updateBanksAdd(icon, (m_pMidiBus->pluginList_out())->midiManager(), sInstrumentName, iBank, iBankIndex); } // Get instrument set alright... if (!bMidiManager && pInstruments->contains(sInstrumentName)) { // Instrument reference... const qtractorInstrument& instr = (*pInstruments)[sInstrumentName]; // Bank selection method... if (iBankSelMethod < 0) iBankSelMethod = instr.bankSelMethod(); // Refresh patch bank mapping... const qtractorInstrumentPatches& patches = instr.patches(); qtractorInstrumentPatches::ConstIterator it = patches.constBegin(); const qtractorInstrumentPatches::ConstIterator& it_end = patches.constEnd(); for (; it != it_end; ++it) { if (it.key() >= 0) { m_ui.BankComboBox->addItem(icon, it.value().name()); m_banks[iBankIndex++] = it.key(); } } #if 0 // In case bank address is generic... if (m_ui.BankComboBox->count() < 2) { const qtractorInstrumentData& patch = instr.patch(iBank); if (!patch.name().isEmpty()) { m_ui.BankComboBox->addItem(icon, patch.name()); m_banks[iBankIndex] = iBank; } } #endif // For proper bank selection... iBankIndex = -1; if (iBank >= 0) { const qtractorInstrumentData& patch = instr.patch(iBank); if (!patch.name().isEmpty()) iBankIndex = m_ui.BankComboBox->findText(patch.name()); } } else if (!bMidiManager) iBankIndex = -1; // Bank selection method... if (iBankSelMethod < 0) iBankSelMethod = 0; m_ui.BankSelMethodComboBox->setCurrentIndex(iBankSelMethod); // If there's banks we must choose at least one... if (iBank < 0 && m_banks.count() > 1) { iBankIndex = 1; iBank = m_banks[iBankIndex]; } // Do the proper bank selection... if (iBank < 0) { m_ui.BankComboBox->setCurrentIndex(0); } else if (iBankIndex < 0) { m_ui.BankComboBox->setEditText(QString::number(iBank)); } else { m_ui.BankComboBox->setCurrentIndex(iBankIndex); } // And update the bank and program listing... updatePrograms(sInstrumentName, iBank, iProg); // Done. --m_iDirtySetup; } // Refresh bank programs list. void qtractorTrackForm::updatePrograms ( const QString& sInstrumentName, int iBank, int iProg ) { if (m_pTrack == NULL) return; qtractorSession *pSession = m_pTrack->session(); if (pSession == NULL) return; // if (sInstrumentName.isEmpty()) // return; #ifdef CONFIG_DEBUG qDebug("qtractorTrackForm::updatePrograms(\"%s\", %d, %d)", sInstrumentName.toUtf8().constData(), iBank, iProg); #endif qtractorInstrumentList *pInstruments = pSession->instruments(); if (pInstruments == NULL) return; // Avoid superfluos change notifications... ++m_iDirtySetup; // Default (none) patch program list... // Refresh patch program mapping... int iProgIndex = 0; const QIcon& icon = QIcon(":/images/itemChannel.png"); m_progs.clear(); m_ui.ProgComboBox->clear(); m_ui.ProgComboBox->addItem(icon, tr("(None)")); m_progs[iProgIndex++] = -1; // Take care of MIDI plugin instrument programs... bool bMidiManager = updateProgramsAdd(icon, (m_pTrack->pluginList())->midiManager(), sInstrumentName, iBank, iProg, iProgIndex); if (!bMidiManager && m_pMidiBus && m_pMidiBus->pluginList_out()) { bMidiManager = updateProgramsAdd(icon, (m_pMidiBus->pluginList_out())->midiManager(), sInstrumentName, iBank, iProg, iProgIndex); } // Get instrument set alright... if (!bMidiManager && pInstruments->contains(sInstrumentName)) { // Instrument reference... const qtractorInstrument& instr = (*pInstruments)[sInstrumentName]; // Bank reference... const qtractorInstrumentData& bank = instr.patch(iBank); // Enumerate the explicit given program list... qtractorInstrumentData::ConstIterator it = bank.constBegin(); const qtractorInstrumentData::ConstIterator& it_end = bank.constEnd(); for (; it != it_end; ++it) { if (it.key() >= 0 && !it.value().isEmpty()) { m_ui.ProgComboBox->addItem(icon, it.value()); m_progs[iProgIndex++] = it.key(); } } // For proper program selection... iProgIndex = -1; if (iProg >= 0 && bank.contains(iProg)) iProgIndex = m_ui.ProgComboBox->findText(bank[iProg]); } else if (!bMidiManager) iProgIndex = -1; #if 0 // If there's programs we must choose at least one... if (iProg < 0 && m_progs.count() > 1) { iProgIndex = 1; iProg = m_progs[iProgIndex]; } #endif // In case program address is generic... if (m_ui.ProgComboBox->count() < 2) { // Just make a generic program list... for (int i = 0; i < 128; ++i) { m_ui.ProgComboBox->addItem(icon, QString("%1 - -").arg(i + 1)); m_progs[i + 1] = i; } if (iProg >= 0) iProgIndex = iProg + 1; } // Do the proper program selection... if (iProg < 0) { m_ui.ProgComboBox->setCurrentIndex(0); } else if (iProgIndex < 0) { m_ui.ProgComboBox->setEditText(QString::number(iProg)); } else { m_ui.ProgComboBox->setCurrentIndex(iProgIndex); } // Done. --m_iDirtySetup; } // Update instrument banks. bool qtractorTrackForm::updateBanksAdd ( const QIcon& icon, qtractorMidiManager *pMidiManager, const QString& sInstrumentName, int iBank, int& iBankIndex ) { if (pMidiManager == NULL) return false; const qtractorMidiManager::Instruments& list = pMidiManager->instruments(); if (!list.contains(sInstrumentName)) return false; // Refresh bank mapping... const qtractorMidiManager::Banks& banks = list[sInstrumentName]; qtractorMidiManager::Banks::ConstIterator iter = banks.constBegin(); const qtractorMidiManager::Banks::ConstIterator& iter_end = banks.constEnd(); for ( ; iter != iter_end; ++iter) { m_ui.BankComboBox->addItem(icon, iter.value().name); m_banks[iBankIndex++] = iter.key(); } // Reset given bank combobox index. iBankIndex = -1; // For proper bank selection... if (banks.contains(iBank)) { const qtractorMidiManager::Bank& bank = banks[iBank]; iBankIndex = m_ui.BankComboBox->findText(bank.name); } // Mark that we've have something. return true; } // Update instrument programs. bool qtractorTrackForm::updateProgramsAdd ( const QIcon& icon, qtractorMidiManager *pMidiManager, const QString& sInstrumentName, int iBank, int iProg, int& iProgIndex ) { if (pMidiManager == NULL) return false; const qtractorMidiManager::Instruments& list = pMidiManager->instruments(); if (!list.contains(sInstrumentName)) return false; // Bank reference... const qtractorMidiManager::Banks& banks = list[sInstrumentName]; if (banks.contains(iBank)) { const qtractorMidiManager::Progs& progs = banks[iBank].progs; // Refresh program mapping... const QString sProg("%1 - %2"); qtractorMidiManager::Progs::ConstIterator iter = progs.constBegin(); const qtractorMidiManager::Progs::ConstIterator& iter_end = progs.constEnd(); for ( ; iter != iter_end; ++iter) { m_ui.ProgComboBox->addItem(icon, sProg.arg(iter.key()).arg(iter.value())); m_progs[iProgIndex++] = iter.key(); } // Reset given program combobox index. iProgIndex = -1; // For proper program selection... if (progs.contains(iProg)) { iProgIndex = m_ui.ProgComboBox->findText( sProg.arg(iProg).arg(progs[iProg])); } } else iProgIndex = -1; // Mark that we've have something. return true; } // Update and set a color item. void qtractorTrackForm::updateColorItem ( QComboBox *pComboBox, const QColor& color ) { // Have some immediate feedback... updateColorText(pComboBox, color); // Check if already exists... int iItem = pComboBox->findText(color.name()); if (iItem >= 0) { pComboBox->setCurrentIndex(iItem); return; } // Nope, we'll add it custom... pComboBox->addItem(color.name()); pComboBox->setCurrentIndex(pComboBox->count() - 1); } // Update color item visual text. void qtractorTrackForm::updateColorText ( QComboBox *pComboBox, const QColor& color ) { QPalette pal; // pal.setColor(QPalette::Window, color); pal.setColor(QPalette::Base, color); pal.setColor(QPalette::Text, color.value() < 0x7f ? color.lighter(200) : color.darker(300)); // pComboBox->lineEdit()->setPalette(pal); pComboBox->setPalette(pal); } // Retreieve currently selected color item. QColor qtractorTrackForm::colorItem ( QComboBox *pComboBox ) { return QColor(pComboBox->currentText()); } // Make more changes due. void qtractorTrackForm::foregroundColorChanged ( const QString& sText ) { if (m_iDirtySetup > 0) return; updateColorText(m_ui.ForegroundColorComboBox, QColor(sText)); ++m_iDirtyCount; stabilizeForm(); } void qtractorTrackForm::backgroundColorChanged ( const QString& sText ) { if (m_iDirtySetup > 0) return; updateColorText(m_ui.BackgroundColorComboBox, QColor(sText)); ++m_iDirtyCount; stabilizeForm(); } void qtractorTrackForm::pluginListChanged (void) { updateInstruments(); changed(); } void qtractorTrackForm::changed (void) { if (m_iDirtySetup > 0) return; ++m_iDirtyCount; stabilizeForm(); } // Make changes due to track type. void qtractorTrackForm::trackTypeChanged (void) { if (m_iDirtySetup > 0) return; if (m_pOldMidiBus) { // Restore previously current/saved patch... m_pOldMidiBus->setPatch(m_iOldChannel, m_sOldInstrumentName, m_iOldBankSelMethod, m_iOldBank, m_iOldProg, m_pTrack); // Reset restorable patch reference... m_pOldMidiBus = NULL; m_iOldChannel = -1; m_sOldInstrumentName.clear(); m_iOldBankSelMethod = -1; m_iOldBank = -1; m_iOldProg = -1; } updateTrackType(trackType()); // inputBusNameChanged(m_ui.InputBusNameComboBox->currentText()); outputBusNameChanged(m_ui.OutputBusNameComboBox->currentText()); } // Make changes due to input-bus name. void qtractorTrackForm::inputBusNameChanged ( const QString& /* sBusName */ ) { changed(); } // Make changes due to output-bus name. void qtractorTrackForm::outputBusNameChanged ( const QString& sBusName ) { if (m_iDirtySetup > 0) return; if (m_pTrack == NULL) return; // It all depends on the track type we're into... qtractorTrack::TrackType trackType = qtractorTrackForm::trackType(); // (Re)initialize plugin-list audio output bus properly... qtractorSession *pSession = m_pTrack->session(); qtractorAudioEngine *pAudioEngine = NULL; if (pSession) pAudioEngine = pSession->audioEngine(); if (pAudioEngine) { // Get the audio bus applicable for the plugin list... qtractorAudioBus *pAudioBus = NULL; if (trackType == qtractorTrack::Audio) pAudioBus = static_cast ( pAudioEngine->findOutputBus(sBusName)); // FIXME: Master audio bus as reference, still... if (pAudioBus == NULL) pAudioBus = static_cast ( pAudioEngine->buses().first()); // If an audio bus has been found applicable, // must set plugin-list channel buffers... if (pAudioBus) { m_pTrack->pluginList()->setBuffer(pAudioBus->channels(), pAudioEngine->bufferSize(), pAudioEngine->sampleRate(), trackType == qtractorTrack::Audio ? qtractorPluginList::AudioTrack : qtractorPluginList::MidiTrack); } } // Recache the applicable MIDI output bus ... if (trackType == qtractorTrack::Midi) { m_pMidiBus = midiBus(); updateInstruments(); } channelChanged(m_ui.ChannelSpinBox->value()); } // Manage buses. void qtractorTrackForm::busNameClicked (void) { if (m_iDirtySetup > 0) return; // Depending on track type... qtractorEngine *pEngine = NULL; switch (trackType()) { case qtractorTrack::Audio: pEngine = m_pTrack->session()->audioEngine(); break; case qtractorTrack::Midi: pEngine = m_pTrack->session()->midiEngine(); break; case qtractorTrack::None: default: break; } // Call here the bus management form. qtractorBusForm busForm(this); // Pre-select bus... const QString& sBusName = m_ui.OutputBusNameComboBox->currentText(); if (pEngine && !sBusName.isEmpty()) busForm.setBus(pEngine->findBus(sBusName)); // Go for it... busForm.exec(); // Check if any buses have changed... if (busForm.isDirty()) { // Try to preserve current selected names... const QString sInputBusName = m_ui.InputBusNameComboBox->currentText(); const QString sOutputBusName = m_ui.OutputBusNameComboBox->currentText(); // Update the comboboxes... trackTypeChanged(); // Restore old current selected ones... if (pEngine->findInputBus(sInputBusName)) m_ui.InputBusNameComboBox->setCurrentIndex( m_ui.InputBusNameComboBox->findText(sInputBusName)); if (pEngine->findOutputBus(sOutputBusName)) m_ui.OutputBusNameComboBox->setCurrentIndex( m_ui.OutputBusNameComboBox->findText(sOutputBusName)); } } // Make changes due to MIDI channel. void qtractorTrackForm::channelChanged ( int iChannel ) { if (m_iDirtySetup > 0) return; // First update channel instrument mapping... updateChannel(iChannel, -1, // m_ui.BankSelMethodComboBox->currentItem(), -1, // midiBank(), -1);// midiProgram()); progChanged(); } // Make changes due to MIDI instrument. void qtractorTrackForm::instrumentChanged ( const QString& sInstrumentName ) { if (m_iDirtySetup > 0) return; updateBanks(sInstrumentName, -1, // m_ui.BankSelMethodComboBox->currentItem(), midiBank(), midiProg()); progChanged(); } // Make changes due to MIDI bank selection method. void qtractorTrackForm::bankSelMethodChanged ( int /* iBankSelMethod */ ) { if (m_iDirtySetup > 0) return; progChanged(); } // Make changes due to MIDI bank. void qtractorTrackForm::bankChanged (void) { if (m_iDirtySetup > 0) return; QString sInstrumentName; if (m_ui.InstrumentComboBox->currentIndex() > 0) sInstrumentName = m_ui.InstrumentComboBox->currentText(); updatePrograms(sInstrumentName, midiBank(), midiProg()); progChanged(); } // Make changes due to MIDI program. void qtractorTrackForm::progChanged (void) { if (m_iDirtySetup > 0) return; // Of course, only applicable on MIDI tracks... if (m_pMidiBus) { // Patch parameters... unsigned short iChannel = m_ui.ChannelSpinBox->value() - 1; QString sInstrumentName; if (m_ui.InstrumentComboBox->currentIndex() > 0) sInstrumentName = m_ui.InstrumentComboBox->currentText(); int iBankSelMethod = m_ui.BankSelMethodComboBox->currentIndex(); int iBank = midiBank(); int iProg = midiProg(); // Keep old bus/channel patching consistency. if (m_pMidiBus != m_pOldMidiBus || iChannel != m_iOldChannel) { // Restore previously saved patch... if (m_pOldMidiBus) { m_pOldMidiBus->setPatch(m_iOldChannel, m_sOldInstrumentName, m_iOldBankSelMethod, m_iOldBank, m_iOldProg, m_pTrack); } // Save current channel patch... const qtractorMidiBus::Patch& patch = m_pMidiBus->patch(iChannel); if (!patch.instrumentName.isEmpty()) { m_pOldMidiBus = m_pMidiBus; m_iOldChannel = iChannel; m_sOldInstrumentName = patch.instrumentName; m_iOldBankSelMethod = patch.bankSelMethod; m_iOldBank = patch.bank; m_iOldProg = patch.prog; } } // Patch it directly... m_pMidiBus->setPatch(iChannel, sInstrumentName, iBankSelMethod, iBank, iProg, m_pTrack); // Make it dirty. ++m_iDirtyPatch; } // Flag that it changed anyhow! changed(); } // Select custom track foreground color. void qtractorTrackForm::selectForegroundColor (void) { QColor color = QColorDialog::getColor( colorItem(m_ui.ForegroundColorComboBox), this); if (color.isValid()) { updateColorItem(m_ui.ForegroundColorComboBox, color); changed(); } } // Select custom track background color. void qtractorTrackForm::selectBackgroundColor (void) { QColor color = QColorDialog::getColor( colorItem(m_ui.BackgroundColorComboBox), this); if (color.isValid()) { updateColorItem(m_ui.BackgroundColorComboBox, color); changed(); } } // Plugin list slots. void qtractorTrackForm::addPlugin (void) { m_ui.PluginListView->addPlugin(); } void qtractorTrackForm::removePlugin (void) { m_ui.PluginListView->removePlugin(); } void qtractorTrackForm::moveUpPlugin (void) { m_ui.PluginListView->moveUpPlugin(); } void qtractorTrackForm::moveDownPlugin (void) { m_ui.PluginListView->moveDownPlugin(); } // MIDI bank/program settlers. void qtractorTrackForm::setMidiProgram ( int iBank, int iProg ) { QString sInstrumentName; if (m_ui.InstrumentComboBox->currentIndex() > 0) sInstrumentName = m_ui.InstrumentComboBox->currentText(); updateBanks( sInstrumentName, -1, // m_ui.BankSelMethodComboBox->currentIndex() iBank, iProg ); changed(); } // end of qtractorTrackForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditorForm.h0000644000175000001440000000012112163602733022052 xustar000000000000000025 mtime=1372521947.2674 26 atime=1381134667.46008 30 ctime=1381134667.460080056 qtractor-0.5.11/src/qtractorMidiEditorForm.h0000644000175000001440000001331412163602733021345 0ustar00rncbcusers00000000000000// qtractorMidiEditorForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiEditorForm_h #define __qtractorMidiEditorForm_h #include "ui_qtractorMidiEditorForm.h" // Forward declarations... class qtractorMidiEditor; class qtractorMidiClip; class qtractorMidiSequence; class qtractorTimeScale; class qtractorMidiEventList; class QContextMenuEvent; class QActionGroup; class QComboBox; class QLabel; //---------------------------------------------------------------------------- // qtractorMidiEditorForm -- UI wrapper form. class qtractorMidiEditorForm : public QMainWindow { Q_OBJECT public: // Constructor. qtractorMidiEditorForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorMidiEditorForm(); // MIDI editor widget accessor. qtractorMidiEditor *editor() const; // Local time-scale accessor. qtractorTimeScale *timeScale() const; unsigned long timeOffset() const; // MIDI clip sequence accessors. qtractorMidiClip *midiClip() const; // MIDI clip properties accessors. const QString& filename() const; unsigned short trackChannel() const; unsigned short format() const; qtractorMidiSequence *sequence() const; // Special executive setup method. void setup(qtractorMidiClip *pMidiClip = NULL); // Reset coomposite dirty flag. void resetDirtyCount(); // Instrument/controller names update. void updateInstrumentNames(); // Pre-close event handler. bool queryClose(); // Edit menu accessor. QMenu *editMenu() const; // Save(as) warning message box. static int querySave(const QString& sFilename); public slots: void stabilizeForm(); protected slots: void fileSave(); void fileSaveAs(); void fileUnlink(); void fileTrackInputs(); void fileTrackOutputs(); void fileTrackProperties(); void fileProperties(); void fileRangeSet(); void fileLoopSet(); void fileClose(); void editUndo(); void editRedo(); void editCut(); void editCopy(); void editPaste(); void editPasteRepeat(); void editDelete(); void editModeOn(); void editModeOff(); void editModeDraw(bool bOn); void editSelectAll(); void editSelectNone(); void editSelectInvert(); void editSelectRange(); void editInsertRange(); void editRemoveRange(); void toolsQuantize(); void toolsTranspose(); void toolsNormalize(); void toolsRandomize(); void toolsResize(); void toolsRescale(); void toolsTimeshift(); void viewMenubar(bool bOn); void viewStatusbar(bool bOn); void viewToolbarFile(bool bOn); void viewToolbarEdit(bool bOn); void viewToolbarView(bool bOn); void viewToolbarTransport(bool bOn); void viewToolbarScale(bool bOn); void viewNoteDuration(bool bOn); void viewNoteColor(bool bOn); void viewValueColor(bool bOn); void viewEvents(bool bOn); void viewPreview(bool bOn); void viewFollow(bool bOn); void viewZoomIn(); void viewZoomOut(); void viewZoomReset(); void viewZoomHorizontal(); void viewZoomVertical(); void viewZoomAll(); void viewSnap(); void viewScaleKey(); void viewScaleType(); void viewSnapZebra(bool bOn); void viewSnapGrid(bool bOn); void viewToolTips(bool bOn); void viewRefresh(); void helpShortcuts(); void helpAbout(); void helpAboutQt(); void updateZoomMenu(); void updateSnapMenu(); void updateScaleMenu(); void sendNote(int iNote, int iVelocity); void selectionChanged(qtractorMidiEditor *); void contentsChanged(qtractorMidiEditor *); // Event type selection slots. void viewTypeChanged(int); void eventTypeChanged(int); void controllerChanged(int); void snapToScaleKeyChanged(int iSnapToScaleKey); void snapToScaleTypeChanged(int iSnapToScaleType); void snapPerBeatChanged(int iSnapPerBeat); protected: // On-open/close event handlers. void showEvent(QShowEvent *pShowEvent); void closeEvent(QCloseEvent *pCloseEvent); // Context menu request. void contextMenuEvent(QContextMenuEvent *pContextMenuEvent); // Save current clip track-channel sequence. bool saveClipFile(bool bPrompt); private: // The Qt-designer UI struct... Ui::qtractorMidiEditorForm m_ui; // Instance variables... qtractorMidiEditor *m_pMidiEditor; // Event list dockable widget. qtractorMidiEventList *m_pMidiEventList; int m_iDirtyCount; // Edit-mode action group up. QActionGroup *m_pEditModeActionGroup; // View/Snap-to-beat actions (for shortcuts access) QList m_snapPerBeatActions; // Edit snap mode. QComboBox *m_pSnapPerBeatComboBox; // Event type selection widgets... QComboBox *m_pViewTypeComboBox; QComboBox *m_pEventTypeComboBox; QComboBox *m_pControllerComboBox; // Snap-to-scale/quantize selection widgets... QComboBox *m_pSnapToScaleKeyComboBox; QComboBox *m_pSnapToScaleTypeComboBox; // Status items. QLabel *m_pTrackNameLabel; QLabel *m_pFileNameLabel; QLabel *m_pTrackChannelLabel; QLabel *m_pStatusModLabel; QLabel *m_pDurationLabel; }; #endif // __qtractorMidiEditorForm_h // end of qtractorMidiEditorForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorExportForm.h0000644000175000001440000000012212166134117021302 xustar000000000000000027 mtime=1373157455.942698 26 atime=1381134668.98808 29 ctime=1381134668.98808008 qtractor-0.5.11/src/qtractorExportForm.h0000644000175000001440000000370412166134117020576 0ustar00rncbcusers00000000000000// qtractorExportForm.h // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorExportForm_h #define __qtractorExportForm_h #include "ui_qtractorExportForm.h" #include "qtractorTrack.h" //---------------------------------------------------------------------------- // qtractorExportForm -- UI wrapper form. class qtractorExportForm : public QDialog { Q_OBJECT public: // Constructor. qtractorExportForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorExportForm(); void setExportType(qtractorTrack::TrackType exportType); qtractorTrack::TrackType exportType() const; protected slots: void accept(); void reject(); void browseExportPath(); void rangeChanged(); void formatChanged(int); void valueChanged(); void stabilizeForm(); private: // The Qt-designer UI struct... Ui::qtractorExportForm m_ui; // Instance variables... qtractorTrack::TrackType m_exportType; QString m_sExportType; QString m_sExportExt; qtractorTimeScale *m_pTimeScale; }; #endif // __qtractorExportForm_h // end of qtractorExportForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorPluginSelectForm.h0000644000175000001440000000012312166526620022424 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134667.31708 30 ctime=1381134667.317080054 qtractor-0.5.11/src/qtractorPluginSelectForm.h0000644000175000001440000000420212166526620021711 0ustar00rncbcusers00000000000000// qtractorPluginSelectForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorPluginSelectForm_h #define __qtractorPluginSelectForm_h #include "ui_qtractorPluginSelectForm.h" #include "qtractorPlugin.h" //---------------------------------------------------------------------------- // qtractorPluginSelectForm -- UI wrapper form. class qtractorPluginSelectForm : public QDialog { Q_OBJECT public: // Constructor. qtractorPluginSelectForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorPluginSelectForm(); void setChannels(unsigned short iChannels, bool bMidi = false); unsigned short channels() const; bool isMidi() const; int pluginCount() const; QString pluginFilename(int iPlugin) const; unsigned long pluginIndex(int iPlugin) const; qtractorPluginType::Hint pluginTypeHint(int iPlugin) const; bool isPluginActivated() const; protected slots: void typeHintChanged(int iTypeHint); void reset(); void refresh(); void stabilize(); void accept(); private: // The Qt-designer UI struct... Ui::qtractorPluginSelectForm m_ui; unsigned short m_iChannels; bool m_bMidi; QList m_selectedItems; }; #endif // __qtractorPluginSelectForm_h // end of qtractorPluginSelectForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioEngine.cpp0000644000175000001440000000012312216644736021731 xustar000000000000000027 mtime=1379617246.061437 26 atime=1381134670.52708 30 ctime=1381134670.527080105 qtractor-0.5.11/src/qtractorAudioEngine.cpp0000644000175000001440000021541612216644736021231 0ustar00rncbcusers00000000000000// qtractorAudioEngine.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorAudioEngine.h" #include "qtractorAudioMonitor.h" #include "qtractorAudioBuffer.h" #include "qtractorAudioClip.h" #include "qtractorSession.h" #include "qtractorDocument.h" #include "qtractorMonitor.h" #include "qtractorSessionCursor.h" #include "qtractorMidiEngine.h" #include "qtractorMidiBuffer.h" #include "qtractorPlugin.h" #include "qtractorClip.h" #include "qtractorCurveFile.h" #include "qtractorMainForm.h" #ifdef CONFIG_JACK_SESSION #include #endif #include #include #include #if defined(__SSE__) #include // SSE detection. static inline bool sse_enabled (void) { #if defined(__GNUC__) unsigned int eax, ebx, ecx, edx; #if defined(__x86_64__) || (!defined(PIC) && !defined(__PIC__)) __asm__ __volatile__ ( "cpuid\n\t" \ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ : "a" (1) : "cc"); #else __asm__ __volatile__ ( "push %%ebx\n\t" \ "cpuid\n\t" \ "movl %%ebx,%1\n\t" \ "pop %%ebx\n\t" \ : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) \ : "a" (1) : "cc"); #endif return (edx & (1 << 25)); #else return false; #endif } // SSE enabled mix-down processor version. static inline void sse_buffer_add ( float **ppBuffer, float **ppFrames, unsigned int iFrames, unsigned short iBuffers, unsigned short iChannels, unsigned int iOffset ) { unsigned short j = 0; for (unsigned short i = 0; i < iChannels; ++i) { float *pBuffer = ppBuffer[j] + iOffset; float *pFrames = ppFrames[i] + iOffset; unsigned int nframes = iFrames; for (; (long(pBuffer) & 15) && (nframes > 0); --nframes) *pBuffer++ += *pFrames++; for (; nframes >= 4; nframes -= 4) { _mm_store_ps(pBuffer, _mm_add_ps( _mm_loadu_ps(pBuffer), _mm_loadu_ps(pFrames))); pFrames += 4; pBuffer += 4; } for (; nframes > 0; --nframes) *pBuffer++ += *pFrames++; if (++j >= iBuffers) j = 0; } } #endif // Standard mix-down processor version. static inline void std_buffer_add ( float **ppBuffer, float **ppFrames, unsigned int iFrames, unsigned short iBuffers, unsigned short iChannels, unsigned int iOffset ) { unsigned short j = 0; for (unsigned short i = 0; i < iChannels; ++i) { float *pBuffer = ppBuffer[j] + iOffset; float *pFrames = ppFrames[i] + iOffset; for (unsigned int n = 0; n < iFrames; ++n) *pBuffer++ += *pFrames++; if (++j >= iBuffers) j = 0; } } //---------------------------------------------------------------------- // qtractorAudioEngine_process -- JACK client process callback. // static int qtractorAudioEngine_process ( jack_nframes_t nframes, void *pvArg ) { qtractorAudioEngine *pAudioEngine = static_cast (pvArg); return pAudioEngine->process(nframes); } //---------------------------------------------------------------------- // qtractorAudioEngine_timebase -- JACK timebase master callback. // static void qtractorAudioEngine_timebase ( jack_transport_state_t, jack_nframes_t, jack_position_t *pPos, int, void *pvArg ) { qtractorAudioEngine *pAudioEngine = static_cast (pvArg); qtractorSession *pSession = pAudioEngine->session(); qtractorTimeScale::Cursor& cursor = pSession->timeScale()->cursor(); qtractorTimeScale::Node *pNode = cursor.seekFrame(pPos->frame); unsigned short bars = 0; unsigned int beats = 0; unsigned long ticks = pNode->tickFromFrame(pPos->frame) - pNode->tick; if (ticks >= (unsigned long) pNode->ticksPerBeat) { beats = (unsigned int) (ticks / pNode->ticksPerBeat); ticks -= (unsigned long) (beats * pNode->ticksPerBeat); } if (beats >= (unsigned int) pNode->beatsPerBar) { bars = (unsigned short) (beats / pNode->beatsPerBar); beats -= (unsigned int) (bars * pNode->beatsPerBar); } // Time frame code in bars.beats.ticks ... pPos->valid = JackPositionBBT; pPos->bar = pNode->bar + bars + 1; pPos->beat = beats + 1; pPos->tick = ticks; // Keep current tempo (BPM)... pPos->beats_per_bar = pNode->beatsPerBar; pPos->ticks_per_beat = pNode->ticksPerBeat; pPos->beats_per_minute = pNode->tempo; pPos->beat_type = float(1 << pNode->beatDivisor); } //---------------------------------------------------------------------- // qtractorAudioEngine_shutdown -- JACK client shutdown callback. // static void qtractorAudioEngine_shutdown ( void *pvArg ) { qtractorAudioEngine *pAudioEngine = static_cast (pvArg); pAudioEngine->notifyShutEvent(); } //---------------------------------------------------------------------- // qtractorAudioEngine_xrun -- JACK client XRUN callback. // static int qtractorAudioEngine_xrun ( void *pvArg ) { qtractorAudioEngine *pAudioEngine = static_cast (pvArg); pAudioEngine->notifyXrunEvent(); return 0; } //---------------------------------------------------------------------- // qtractorAudioEngine_graph_order -- JACK graph change callback. // static int qtractorAudioEngine_graph_order ( void *pvArg ) { qtractorAudioEngine *pAudioEngine = static_cast (pvArg); pAudioEngine->notifyPortEvent(); return 0; } //---------------------------------------------------------------------- // qtractorAudioEngine_graph_port -- JACK port registration callback. // static void qtractorAudioEngine_graph_port ( jack_port_id_t, int, void *pvArg ) { qtractorAudioEngine *pAudioEngine = static_cast (pvArg); pAudioEngine->notifyPortEvent(); } //---------------------------------------------------------------------- // qtractorAudioEngine_buffer_size -- JACK buffer-size change callback. // static int qtractorAudioEngine_buffer_size ( jack_nframes_t nframes, void *pvArg ) { qtractorAudioEngine *pAudioEngine = static_cast (pvArg); if (pAudioEngine->bufferSize() < (unsigned int) nframes) pAudioEngine->notifyBuffEvent(); return 0; } //---------------------------------------------------------------------- // qtractorAudioEngine_freewheel -- Audio export process callback. // static void qtractorAudioEngine_freewheel ( int iStarting, void *pvArg ) { qtractorAudioEngine *pAudioEngine = static_cast (pvArg); pAudioEngine->setFreewheel(bool(iStarting)); } #ifdef CONFIG_JACK_SESSION //---------------------------------------------------------------------- // qtractorAudioEngine_session_event -- JACK session event callabck // static void qtractorAudioEngine_session_event ( jack_session_event_t *pSessionEvent, void *pvArg ) { qtractorAudioEngine *pAudioEngine = static_cast (pvArg); pAudioEngine->notifySessEvent(pSessionEvent); } #endif //---------------------------------------------------------------------- // qtractorAudioEngine_sync -- JACK transport sync event callabck // static int qtractorAudioEngine_sync ( jack_transport_state_t /*state*/, jack_position_t *pos, void *pvArg ) { qtractorAudioEngine *pAudioEngine = static_cast (pvArg); if (pAudioEngine->isFreewheel()) return 0; long iDeltaFrames = long(pos->frame) - long(pAudioEngine->sessionCursor()->frame()); unsigned int iBufferSize = pAudioEngine->bufferSize(); if (labs(iDeltaFrames) > long(iBufferSize << 1)) { unsigned long iPlayHead = pos->frame; if (pAudioEngine->isPlaying()) iPlayHead += iBufferSize; pAudioEngine->notifySyncEvent(iPlayHead); } return 1; } //---------------------------------------------------------------------- // class qtractorAudioEngine -- JACK client instance (singleton). // // Constructor. qtractorAudioEngine::qtractorAudioEngine ( qtractorSession *pSession ) : qtractorEngine(pSession, qtractorTrack::Audio) { m_pJackClient = NULL; m_iSampleRate = 44100; // A sensible default, always. m_iBufferSize = 0; m_iBufferOffset = 0; m_bMasterAutoConnect = true; // Audio-export freewheeling (internal) state. m_bFreewheel = false; // Common audio buffer sync thread. m_pSyncThread = NULL; // Audio-export (in)active state. m_bExporting = false; m_pExportBus = NULL; m_pExportFile = NULL; m_iExportStart = 0; m_iExportEnd = 0; m_bExportDone = true; // Audio metronome stuff. m_bMetronome = false; m_bMetroBus = false; m_pMetroBus = NULL; m_bMetroAutoConnect = true; m_pMetroBarBuff = NULL; m_pMetroBeatBuff = NULL; m_fMetroBarGain = 1.0f; m_fMetroBeatGain = 1.0f; m_iMetroBeatStart = 0; m_iMetroBeat = 0; m_bMetroEnabled = false; // Audition/pre-listening player stuff. ATOMIC_SET(&m_playerLock, 0); m_bPlayerOpen = false; m_bPlayerBus = false; m_bPlayerAutoConnect = true; m_pPlayerBus = NULL; m_pPlayerBuff = NULL; m_iPlayerFrame = 0; // JACK transport mode. m_transportMode = qtractorBus::Duplex; } // Special event notifier proxy object. const qtractorAudioEngineProxy *qtractorAudioEngine::proxy (void) const { return &m_proxy; } // Event notifications. void qtractorAudioEngine::notifyShutEvent (void) { m_proxy.notifyShutEvent(); } void qtractorAudioEngine::notifyXrunEvent (void) { m_proxy.notifyXrunEvent(); } void qtractorAudioEngine::notifyPortEvent (void) { m_proxy.notifyPortEvent(); } void qtractorAudioEngine::notifyBuffEvent (void) { m_proxy.notifyBuffEvent(); } void qtractorAudioEngine::notifySessEvent ( void *pvSessionArg ) { m_proxy.notifySessEvent(pvSessionArg); } void qtractorAudioEngine::notifySyncEvent ( unsigned long iPlayHead ) { m_proxy.notifySyncEvent(iPlayHead); } // JACK client descriptor accessor. jack_client_t *qtractorAudioEngine::jackClient (void) const { return m_pJackClient; } // Internal sample-rate accessor. unsigned int qtractorAudioEngine::sampleRate (void) const { return m_iSampleRate; } // Buffer size accessor. unsigned int qtractorAudioEngine::bufferSize (void) const { return m_iBufferSize; } // Buffer offset accessor. unsigned int qtractorAudioEngine::bufferOffset (void) const { return m_iBufferOffset; } // Audio (Master) bus defaults accessors. void qtractorAudioEngine::setMasterAutoConnect ( bool bMasterAutoConnect ) { m_bMasterAutoConnect = bMasterAutoConnect; } bool qtractorAudioEngine::isMasterAutoConnect (void) const { return m_bMasterAutoConnect; } // Device engine initialization method. bool qtractorAudioEngine::init (void) { // There must a session reference... qtractorSession *pSession = session(); if (pSession == NULL) return false; // Try open a new client... const QByteArray aClientName = pSession->clientName().toUtf8(); int opts = JackNullOption; #ifdef CONFIG_XUNIQUE opts |= JackUseExactName; #endif #ifdef CONFIG_JACK_SESSION if (!m_sSessionId.isEmpty()) { opts |= JackSessionID; const QByteArray aSessionId = m_sSessionId.toLocal8Bit(); m_pJackClient = jack_client_open( aClientName.constData(), jack_options_t(opts), NULL, aSessionId.constData()); // Reset JACK session UUID. m_sSessionId.clear(); } else #endif m_pJackClient = jack_client_open( aClientName.constData(), jack_options_t(opts), NULL); if (m_pJackClient == NULL) return false; // ATTN: First thing to remember is initial sample-rate and buffer size. m_iSampleRate = jack_get_sample_rate(m_pJackClient); m_iBufferSize = jack_get_buffer_size(m_pJackClient); // ATTN: Second is setting proper session client name. pSession->setClientName( QString::fromUtf8(jack_get_client_name(m_pJackClient))); // ATTN: Third is setting session sample rate. pSession->setSampleRate(m_iSampleRate); // Our dedicated audio buffer thread... m_pSyncThread = new qtractorAudioBufferThread(); m_pSyncThread->start(QThread::HighPriority); return true; } // Device engine activation method. bool qtractorAudioEngine::activate (void) { // There must a session reference... qtractorSession *pSession = session(); if (pSession == NULL) return false; // Let remaining buses get a life... openPlayerBus(); openMetroBus(); // MIDI plugin managers output buses... qtractorMidiManager *pMidiManager = pSession->midiManagers().first(); while (pMidiManager) { qtractorAudioBus *pAudioBus = pMidiManager->audioOutputBus(); if (pAudioBus && pMidiManager->isAudioOutputBus()) pAudioBus->open(); pMidiManager = pMidiManager->next(); } // Ensure (not) freewheeling state... jack_set_freewheel(m_pJackClient, 0); // Set our main engine processor callbacks. jack_set_process_callback(m_pJackClient, qtractorAudioEngine_process, this); // Trnsport timebase callbacks... if (m_transportMode & qtractorBus::Output) { jack_set_timebase_callback(m_pJackClient, 0 /* FIXME: un-conditional! */, qtractorAudioEngine_timebase, this); } // And some other event callbacks... jack_set_xrun_callback(m_pJackClient, qtractorAudioEngine_xrun, this); jack_on_shutdown(m_pJackClient, qtractorAudioEngine_shutdown, this); jack_set_graph_order_callback(m_pJackClient, qtractorAudioEngine_graph_order, this); jack_set_port_registration_callback(m_pJackClient, qtractorAudioEngine_graph_port, this); jack_set_buffer_size_callback(m_pJackClient, qtractorAudioEngine_buffer_size, this); // Set audio export processor callback. jack_set_freewheel_callback(m_pJackClient, qtractorAudioEngine_freewheel, this); #ifdef CONFIG_JACK_SESSION // Set JACK session event callback. if (jack_set_session_callback) { jack_set_session_callback(m_pJackClient, qtractorAudioEngine_session_event, this); } #endif // Set transport sync callback. if (m_transportMode & qtractorBus::Input) { jack_set_sync_callback(m_pJackClient, qtractorAudioEngine_sync, this); } // Reset all dependable monitoring... resetAllMonitors(); // Time to activate ourselves... jack_activate(m_pJackClient); // Now, do all auto-connection stuff (if applicable...) if (m_bPlayerBus && m_pPlayerBus) m_pPlayerBus->autoConnect(); if (m_bMetroBus && m_pMetroBus) m_pMetroBus->autoConnect(); for (qtractorBus *pBus = buses().first(); pBus; pBus = pBus->next()) { qtractorAudioBus *pAudioBus = static_cast(pBus); if (pAudioBus) pAudioBus->autoConnect(); } // MIDI plugin managers output buses... pMidiManager = session()->midiManagers().first(); while (pMidiManager) { qtractorAudioBus *pAudioBus = pMidiManager->audioOutputBus(); if (pAudioBus && pMidiManager->isAudioOutputBus()) pAudioBus->autoConnect(); pMidiManager = pMidiManager->next(); } // We're now ready and running... return true; } // Device engine start method. bool qtractorAudioEngine::start (void) { if (!isActivated()) return false; // Reset all dependables... resetAllMonitors(); // Make sure we have an actual session cursor... resetMetro(); // Start transport rolling... if (m_transportMode & qtractorBus::Output) jack_transport_start(m_pJackClient); // We're now ready and running... return true; } // Device engine stop method. void qtractorAudioEngine::stop (void) { if (!isActivated()) return; if (m_transportMode & qtractorBus::Output) { jack_transport_stop(m_pJackClient); jack_transport_locate(m_pJackClient, sessionCursor()->frame()); } // MIDI plugin managers reset... qtractorMidiManager *pMidiManager = session()->midiManagers().first(); while (pMidiManager) { pMidiManager->reset(); pMidiManager = pMidiManager->next(); } } // Device engine deactivation method. void qtractorAudioEngine::deactivate (void) { // We're stopping now... // setPlaying(false); // Deactivate the JACK client first. if (m_pJackClient) jack_deactivate(m_pJackClient); } // Device engine cleanup method. void qtractorAudioEngine::clean (void) { // Audio master bus auto-connection option... qtractorAudioBus *pMasterBus = static_cast (buses().first()); if (pMasterBus) m_bMasterAutoConnect = pMasterBus->isAutoConnect(); // Clean player/metronome buses... deletePlayerBus(); deleteMetroBus(); // Terminate common player/metro sync thread... if (m_pSyncThread) { if (m_pSyncThread->isRunning()) do { m_pSyncThread->setRunState(false); // m_pSyncThread->terminate(); m_pSyncThread->sync(); } while (!m_pSyncThread->wait(100)); delete m_pSyncThread; m_pSyncThread = NULL; } // Audio-export stilll around? weird... if (m_pExportFile) { delete m_pExportFile; m_pExportFile = NULL; } // Close the JACK client, finally. if (m_pJackClient) { jack_client_close(m_pJackClient); m_pJackClient = NULL; } // Null sample-rate/period. // m_iSampleRate = 0; // m_iBufferSize = 0; } // Process cycle executive. int qtractorAudioEngine::process ( unsigned int nframes ) { // Don't bother with a thing, if not running. if (!isActivated()) return 0; // Must have a valid session... qtractorSession *pSession = session(); if (pSession == NULL) return 0; // Make sure we have an actual session cursor... qtractorSessionCursor *pAudioCursor = sessionCursor(); if (pAudioCursor == NULL) return 0; // Reset buffer offset. m_iBufferOffset = 0; // Are we actually freewheeling for export?... // notice that freewheeling has no RT requirements. if (m_bFreewheel) { // Make sure we're in a valid state... if (m_pExportFile && m_pExportBus && !m_bExportDone) { // This the legal process cycle frame range... unsigned long iFrameStart = pAudioCursor->frame(); unsigned long iFrameEnd = iFrameStart + nframes; // Write output bus buffer to export audio file... if (iFrameStart < m_iExportEnd && iFrameEnd > m_iExportStart) { // Force/sync every audio clip approaching... syncExport(iFrameStart, iFrameEnd); // Prepare the output bus first... m_pExportBus->process_prepare(nframes); // Prepare all extra audio buses... for (qtractorBus *pBusEx = busesEx().first(); pBusEx; pBusEx = pBusEx->next()) { qtractorAudioBus *pAudioBusEx = static_cast (pBusEx); if (pAudioBusEx) pAudioBusEx->process_prepare(nframes); } // Export cycle... pSession->process(pAudioCursor, iFrameStart, iFrameEnd); // Commit the output bus only... m_pExportBus->process_commit(nframes); // Write to export file... if (iFrameEnd > m_iExportEnd) nframes -= (iFrameEnd - m_iExportEnd); m_pExportFile->write(m_pExportBus->out(), nframes); // Prepare advance for next cycle... pAudioCursor->seek(iFrameEnd); // HACK! Freewheeling observers update (non RT safe!)... qtractorSubject::flushQueue(false); } // Are we trough? else m_bExportDone = true; } // Done with this one export cycle... return 0; } // Session RT-safeness lock... if (!pSession->acquire()) return 0; // Track whether audio output buses // buses needs monitoring while idle... int iOutputBus = 0; qtractorBus *pBus; qtractorAudioBus *pAudioBus; // Prepare all current audio buses... for (pBus = buses().first(); pBus; pBus = pBus->next()) { pAudioBus = static_cast (pBus); if (pAudioBus) pAudioBus->process_prepare(nframes); } // Prepare all extra audio buses... for (pBus = busesEx().first(); pBus; pBus = pBus->next()) { pAudioBus = static_cast (pBus); if (pAudioBus) pAudioBus->process_prepare(nframes); } // Monitor all current audio buses... for (pBus = buses().first(); pBus; pBus = pBus->next()) { pAudioBus = static_cast (pBus); if (pAudioBus) pAudioBus->process_monitor(nframes); } // The owned buses too, if any... if (m_bMetroBus && m_pMetroBus) m_pMetroBus->process_prepare(nframes); if (m_bPlayerBus && m_pPlayerBus) m_pPlayerBus->process_prepare(nframes); // Process audition/pre-listening... if (m_bPlayerOpen && ATOMIC_TAS(&m_playerLock)) { m_pPlayerBuff->readMix(m_pPlayerBus->out(), nframes, m_pPlayerBus->channels(), 0, 1.0f); m_bPlayerOpen = (m_iPlayerFrame < m_pPlayerBuff->length()); m_iPlayerFrame += nframes; if (m_bPlayerBus && m_pPlayerBus) m_pPlayerBus->process_commit(nframes); else ++iOutputBus; ATOMIC_SET(&m_playerLock, 0); } // MIDI plugin manager processing... qtractorMidiManager *pMidiManager = pSession->midiManagers().first(); if (pMidiManager) { unsigned long iFrameTimeStart = pAudioCursor->frameTime(); unsigned long iFrameTimeEnd = iFrameTimeStart + nframes; while (pMidiManager) { pMidiManager->process(iFrameTimeStart, iFrameTimeEnd); if (!pMidiManager->isAudioOutputBus()) ++iOutputBus; pMidiManager = pMidiManager->next(); } } // Don't go any further, if not playing. if (!isPlaying()) { // Do the idle processing... for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { // Audio-buffers needs some preparation... if (pTrack->trackType() == qtractorTrack::Audio) { qtractorAudioBus *pInputBus = static_cast (pTrack->inputBus()); qtractorAudioMonitor *pAudioMonitor = static_cast (pTrack->monitor()); // Pre-monitoring... if (pAudioMonitor && pInputBus) { // Record non-passthru metering... if (pTrack->isRecord()) { pAudioMonitor->process_meter( pInputBus->in(), nframes, pInputBus->channels()); } // Monitor passthru processing... if (pSession->isTrackMonitor(pTrack)) { pAudioMonitor->process( pInputBus->in(), nframes, pInputBus->channels()); // Plugin-chain processing... qtractorAudioBus *pOutputBus = static_cast (pTrack->outputBus()); if (pOutputBus) { pOutputBus->buffer_prepare(nframes, pInputBus); if ((pTrack->pluginList())->activated() > 0) (pTrack->pluginList())->process( pOutputBus->buffer(), nframes); pOutputBus->buffer_commit(nframes); ++iOutputBus; } } } } } // Process audition/pre-listening bus... if (m_bPlayerBus && m_pPlayerBus) m_pPlayerBus->process_commit(nframes); // Pass-thru current audio buses... for (pBus = buses().first(); pBus; pBus = pBus->next()) { pAudioBus = static_cast (pBus); if (pAudioBus && (iOutputBus > 0 || pAudioBus->isMonitor())) pAudioBus->process_commit(nframes); } // Done as idle... pAudioCursor->process(nframes); pSession->release(); return 0; } // This the legal process cycle frame range... unsigned long iFrameStart = pAudioCursor->frame(); unsigned long iFrameEnd = iFrameStart + nframes; // Metronome stuff... qtractorTimeScale::Cursor& cursor = pSession->timeScale()->cursor(); qtractorTimeScale::Node *pNode = cursor.seekFrame(iFrameStart); if (m_bMetronome && m_pMetroBus && iFrameEnd > m_iMetroBeatStart) { qtractorAudioBuffer *pMetroBuff = NULL; float fMetroGain = 1.0f; if (pNode->beatIsBar(m_iMetroBeat)) { pMetroBuff = m_pMetroBarBuff; fMetroGain = m_fMetroBarGain; } else { pMetroBuff = m_pMetroBeatBuff; fMetroGain = m_fMetroBeatGain; } if (iFrameStart < m_iMetroBeatStart) { pMetroBuff->readMix(m_pMetroBus->out(), iFrameEnd - m_iMetroBeatStart, m_pMetroBus->channels(), m_iMetroBeatStart - iFrameStart, fMetroGain); } else if (iFrameStart < m_iMetroBeatStart + pMetroBuff->length()) { pMetroBuff->readMix(m_pMetroBus->out(), nframes, m_pMetroBus->channels(), 0, fMetroGain); } else { m_iMetroBeatStart = pNode->frameFromBeat(++m_iMetroBeat); pMetroBuff->reset(false); } if (m_bMetroBus && m_pMetroBus) m_pMetroBus->process_commit(nframes); } // Split processing, in case we're looping... if (pSession->isLooping()) { unsigned long iLoopEnd = pSession->loopEnd(); if (iFrameStart < iLoopEnd) { // Loop-length might be shorter than the buffer-period... while (iFrameEnd >= iLoopEnd + nframes) { // Process the remaining until end-of-loop... pSession->process(pAudioCursor, iFrameStart, iLoopEnd); m_iBufferOffset += (iLoopEnd - iFrameStart); // Reset to start-of-loop... iFrameStart = pSession->loopStart(); iFrameEnd = iFrameStart + (iFrameEnd - iLoopEnd); // Set to new transport location... if (m_transportMode & qtractorBus::Output) jack_transport_locate(m_pJackClient, iFrameStart); pAudioCursor->seek(iFrameStart); } } } // Regular range playback... pSession->process(pAudioCursor, iFrameStart, iFrameEnd); m_iBufferOffset += (iFrameEnd - iFrameStart); // Commit current audio buses... for (pBus = buses().first(); pBus; pBus = pBus->next()) { pAudioBus = static_cast (pBus); if (pAudioBus) pAudioBus->process_commit(nframes); } // Regular range recording (if and when applicable)... if (pSession->isRecording()) pSession->process_record(iFrameStart, iFrameEnd); // Sync with loop boundaries (unlikely?) if (pSession->isLooping() && iFrameStart < pSession->loopEnd() && iFrameEnd >= pSession->loopEnd()) { iFrameEnd = pSession->loopStart() + (iFrameEnd - pSession->loopEnd()); // Set to new transport location... if (m_transportMode & qtractorBus::Output) jack_transport_locate(m_pJackClient, iFrameEnd); // Take special care on metronome too... if (m_bMetronome) { m_iMetroBeat = pSession->beatFromFrame(iFrameEnd); m_iMetroBeatStart = pSession->frameFromBeat(m_iMetroBeat); } } // Prepare advance for next cycle... pAudioCursor->seek(iFrameEnd); pAudioCursor->process(nframes); // Always sync to MIDI output thread... // (sure we have a MIDI engine, no?) pSession->midiEngine()->sync(); // Release RT-safeness lock... pSession->release(); // Process session stuff... return 0; } // Document element methods. bool qtractorAudioEngine::loadElement ( qtractorDocument *pDocument, QDomElement *pElement ) { qtractorEngine::clear(); createPlayerBus(); createMetroBus(); // Load session children... for (QDomNode nChild = pElement->firstChild(); !nChild.isNull(); nChild = nChild.nextSibling()) { // Convert node to element... QDomElement eChild = nChild.toElement(); if (eChild.isNull()) continue; if (eChild.tagName() == "audio-control") { for (QDomNode nProp = eChild.firstChild(); !nProp.isNull(); nProp = nProp.nextSibling()) { QDomElement eProp = nProp.toElement(); if (eProp.isNull()) continue; if (eProp.tagName() == "transport-mode") { qtractorAudioEngine::setTransportMode( qtractorBus::busModeFromText(eProp.text())); } } } else if (eChild.tagName() == "audio-bus") { QString sBusName = eChild.attribute("name"); qtractorBus::BusMode busMode = qtractorBus::busModeFromText(eChild.attribute("mode")); qtractorAudioBus *pAudioBus = new qtractorAudioBus(this, sBusName, busMode); if (!pAudioBus->loadElement(pDocument, &eChild)) return false; qtractorEngine::addBus(pAudioBus); } else if (eChild.tagName() == "metronome-outputs") { if (m_bMetroBus && m_pMetroBus) { m_pMetroBus->loadConnects( m_pMetroBus->outputs(), pDocument, &eChild); } } else if (eChild.tagName() == "player-outputs") { if (m_bPlayerBus && m_pPlayerBus) { m_pPlayerBus->loadConnects( m_pPlayerBus->outputs(), pDocument, &eChild); } } } return true; } bool qtractorAudioEngine::saveElement ( qtractorDocument *pDocument, QDomElement *pElement ) const { // Save transport/control modes... QDomElement eControl = pDocument->document()->createElement("audio-control"); pDocument->saveTextElement("transport-mode", qtractorBus::textFromBusMode( qtractorAudioEngine::transportMode()), &eControl); pElement->appendChild(eControl); // Save audio buses... for (qtractorBus *pBus = qtractorEngine::buses().first(); pBus; pBus = pBus->next()) { qtractorAudioBus *pAudioBus = static_cast (pBus); if (pAudioBus) { // Create the new audio bus element... QDomElement eAudioBus = pDocument->document()->createElement("audio-bus"); pAudioBus->saveElement(pDocument, &eAudioBus); pElement->appendChild(eAudioBus); } } // Metronome bus connects... if (m_bMetroBus && m_pMetroBus) { QDomElement eOutputs = pDocument->document()->createElement("metronome-outputs"); qtractorBus::ConnectList outputs; m_pMetroBus->updateConnects(qtractorBus::Output, outputs); m_pMetroBus->saveConnects(outputs, pDocument, &eOutputs); pElement->appendChild(eOutputs); } // Audition/pre-listening player bus connects... if (m_bPlayerBus && m_pPlayerBus) { QDomElement eOutputs = pDocument->document()->createElement("player-outputs"); qtractorBus::ConnectList outputs; m_pPlayerBus->updateConnects(qtractorBus::Output, outputs); m_pPlayerBus->saveConnects(outputs, pDocument, &eOutputs); pElement->appendChild(eOutputs); } return true; } // JACK Session UUID accessors. void qtractorAudioEngine::setSessionId ( const QString& sSessionId ) { m_sSessionId = sSessionId; } const QString& qtractorAudioEngine::sessionId (void) const { return m_sSessionId; } // Audio-exporting freewheel (internal) state accessors. void qtractorAudioEngine::setFreewheel ( bool bFreewheel ) { m_bFreewheel = bFreewheel; } bool qtractorAudioEngine::isFreewheel (void) const { return m_bFreewheel; } // Audio-exporting (freewheeling) state accessors. void qtractorAudioEngine::setExporting ( bool bExporting ) { m_bExporting = bExporting; } bool qtractorAudioEngine::isExporting (void) const { return m_bExporting; } // Audio-export method. bool qtractorAudioEngine::fileExport ( const QString& sExportPath, unsigned long iExportStart, unsigned long iExportEnd, qtractorAudioBus *pExportBus ) { // No simultaneous or foul exports... if (!isActivated() || isPlaying() || isExporting()) return false; // Make sure we have an actual session cursor... qtractorSession *pSession = session(); if (pSession == NULL) return false; // About to show some progress bar... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return false; QProgressBar *pProgressBar = pMainForm->progressBar(); if (pProgressBar == NULL) return false; // Cannot have exports longer than current session. if (iExportStart >= iExportEnd) iExportEnd = pSession->sessionEnd(); if (iExportStart >= iExportEnd) return false; // We'll grab the first bus around, if none is given... if (pExportBus == NULL) pExportBus = static_cast (buses().first()); if (pExportBus == NULL) return false; // Get proper file type class... qtractorAudioFile *pExportFile = qtractorAudioFileFactory::createAudioFile( sExportPath, pExportBus->channels(), sampleRate()); // No file ready for export? if (pExportFile == NULL) return false; // Go open it, for writeing of course... if (!pExportFile->open(sExportPath, qtractorAudioFile::Write)) { delete pExportFile; return false; } // We'll be busy... pSession->lock(); // HACK! reset subject/observers queue... qtractorSubject::resetQueue(); // Start with fixing the export range... m_bExporting = true; m_pExportBus = pExportBus; m_pExportFile = pExportFile; m_iExportStart = iExportStart; m_iExportEnd = iExportEnd; m_bExportDone = false; // Prepare and show some progress... pProgressBar->setRange(iExportStart, iExportEnd); pProgressBar->reset(); pProgressBar->show(); // We'll have to save some session parameters... unsigned long iPlayHead = pSession->playHead(); unsigned long iLoopStart = pSession->loopStart(); unsigned long iLoopEnd = pSession->loopEnd(); bool bMonitor = pExportBus->isMonitor(); // Because we'll have to set the export conditions... pSession->setLoop(0, 0); pSession->setPlayHead(m_iExportStart); pExportBus->setMonitor(false); // Force initial full-sync... syncExport(m_iExportStart, m_iExportEnd); // Special initialization. m_iBufferOffset = 0; // Start export (freewheeling)... jack_set_freewheel(m_pJackClient, 1); // Wait for the export to end. while (m_bExporting && !m_bExportDone) { qtractorSession::stabilize(200); pProgressBar->setValue(pSession->playHead()); } // Stop export (freewheeling)... jack_set_freewheel(m_pJackClient, 0); // May close the file... m_pExportFile->close(); // Restore session at ease... pSession->setLoop(iLoopStart, iLoopEnd); pSession->setPlayHead(iPlayHead); pExportBus->setMonitor(bMonitor); // Check user cancellation... bool bResult = m_bExporting; // Free up things here. delete m_pExportFile; // Made some progress... pProgressBar->hide(); m_bExporting = false; m_pExportBus = NULL; m_pExportFile = NULL; m_iExportStart = 0; m_iExportEnd = 0; m_bExportDone = true; // Back to business.. pSession->unlock(); // Done whether successfully. return bResult; } // Direct sync method (needed for export) void qtractorAudioEngine::syncExport ( unsigned long iFrameStart, unsigned long iFrameEnd ) { qtractorSession *pSession = session(); if (pSession == NULL) return; qtractorSessionCursor *pAudioCursor = sessionCursor(); if (pAudioCursor == NULL) return; int iTrack = 0; for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { if (pTrack->trackType() == qtractorTrack::Audio) { qtractorClip *pClip = pAudioCursor->clip(iTrack); while (pClip && pClip->clipStart() < iFrameEnd && pClip->clipStart() + pClip->clipLength() > iFrameStart) { qtractorAudioClip *pAudioClip = static_cast (pClip); if (pAudioClip) pAudioClip->syncExport(); pClip = pClip->next(); } } ++iTrack; } } // Special track-immediate methods. void qtractorAudioEngine::trackMute ( qtractorTrack *pTrack, bool bMute ) { if (bMute) (pTrack->pluginList())->resetBuffer(); sessionCursor()->updateTrackClip(pTrack); } // Metronome switching. void qtractorAudioEngine::setMetronome ( bool bMetronome ) { m_bMetronome = bMetronome; if (isPlaying()) resetMetro(); } bool qtractorAudioEngine::isMetronome (void) const { return m_bMetronome; } // Metronome enabled accessors. void qtractorAudioEngine::setMetroEnabled ( bool bMetroEnabled ) { m_bMetroEnabled = bMetroEnabled; openMetroBus(); } bool qtractorAudioEngine::isMetroEnabled (void) const { return m_bMetroEnabled; } // Metronome bus mode accessors. void qtractorAudioEngine::setMetroBus ( bool bMetroBus ) { deleteMetroBus(); m_bMetroBus = bMetroBus; createMetroBus(); if (isActivated()) { openMetroBus(); if (m_bMetroBus && m_pMetroBus) m_pMetroBus->autoConnect(); } } bool qtractorAudioEngine::isMetroBus (void) const { return m_bMetroBus; } void qtractorAudioEngine::resetMetroBus (void) { if (m_bMetronome && m_bMetroBus && m_pMetroBus) return; createMetroBus(); if (isActivated()) openMetroBus(); } // Metronome bus defaults accessors. void qtractorAudioEngine::setMetroAutoConnect ( bool bMetroAutoConnect ) { m_bMetroAutoConnect = bMetroAutoConnect; } bool qtractorAudioEngine::isMetroAutoConnect (void) const { return m_bMetroAutoConnect; } // Metronome bar audio sample. void qtractorAudioEngine::setMetroBarFilename ( const QString& sFilename ) { m_sMetroBarFilename = sFilename; } const QString& qtractorAudioEngine::metroBarFilename (void) const { return m_sMetroBarFilename; } // Metronome bar audio sample gain. void qtractorAudioEngine::setMetroBarGain ( float fGain ) { m_fMetroBarGain = fGain; } float qtractorAudioEngine::metroBarGain (void) const { return m_fMetroBarGain; } // Metronome beat audio sample. void qtractorAudioEngine::setMetroBeatFilename ( const QString& sFilename ) { m_sMetroBeatFilename = sFilename; } const QString& qtractorAudioEngine::metroBeatFilename() const { return m_sMetroBeatFilename; } // Metronome beat audio sample gain. void qtractorAudioEngine::setMetroBeatGain ( float fGain ) { m_fMetroBeatGain = fGain; } float qtractorAudioEngine::metroBeatGain (void) const { return m_fMetroBeatGain; } // Create audio metronome stuff... void qtractorAudioEngine::createMetroBus (void) { deleteMetroBus(); if (!m_bMetroEnabled) return; // Whether metronome bus is here owned, or... if (m_bMetroBus) { m_pMetroBus = new qtractorAudioBus(this, "Metronome", qtractorBus::BusMode(qtractorBus::Output | qtractorBus::Ex)); m_pMetroBus->setAutoConnect(m_bMetroAutoConnect); } else { // Metronome bus gets to be the first available output bus... for (qtractorBus *pBus = qtractorEngine::buses().first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Output) { m_pMetroBus = static_cast (pBus); break; } } } } // Open audio metronome stuff... bool qtractorAudioEngine::openMetroBus (void) { closeMetroBus(); if (!m_bMetroEnabled) return false; // Is there any? if (m_pMetroBus == NULL) createMetroBus(); if (m_pMetroBus == NULL) return false; // This is it, when dedicated... if (m_bMetroBus) { addBusEx(m_pMetroBus); m_pMetroBus->open(); } // Enough number of channels?... unsigned short iChannels = m_pMetroBus->channels(); if (iChannels < 1) { closeMetroBus(); return false; } // We got it... unsigned int iSampleRate = sampleRate(); m_pMetroBarBuff = new qtractorAudioBuffer( m_pSyncThread, iChannels, iSampleRate); m_pMetroBarBuff->open(m_sMetroBarFilename); m_pMetroBeatBuff = new qtractorAudioBuffer( m_pSyncThread, iChannels, iSampleRate); m_pMetroBeatBuff->open(m_sMetroBeatFilename); return true; } // Close audio metronome stuff. void qtractorAudioEngine::closeMetroBus (void) { if (m_pMetroBeatBuff) { m_pMetroBeatBuff->close(); delete m_pMetroBeatBuff; m_pMetroBeatBuff = NULL; } if (m_pMetroBarBuff) { m_pMetroBarBuff->close(); delete m_pMetroBarBuff; m_pMetroBarBuff = NULL; } if (m_bMetroBus && m_pMetroBus) { m_pMetroBus->close(); removeBusEx(m_pMetroBus); } m_iMetroBeatStart = 0; m_iMetroBeat = 0; } // Destroy audio metronome stuff. void qtractorAudioEngine::deleteMetroBus (void) { closeMetroBus(); if (m_bMetroBus && m_pMetroBus) delete m_pMetroBus; m_pMetroBus = NULL; } // Reset Audio metronome. void qtractorAudioEngine::resetMetro (void) { if (!m_bMetroEnabled) return; if (!m_bMetronome) return; qtractorSessionCursor *pAudioCursor = sessionCursor(); if (pAudioCursor == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Reset to the next beat position... unsigned long iFrame = pAudioCursor->frame(); qtractorTimeScale::Cursor& cursor = pSession->timeScale()->cursor(); qtractorTimeScale::Node *pNode = cursor.seekFrame(iFrame); // FIXME: Each sample buffer must be bounded properly... unsigned long iMaxLength = 0; unsigned short iNextBeat = pNode->beatFromFrame(iFrame); if (iNextBeat > 0) { m_iMetroBeat = iNextBeat; m_iMetroBeatStart = pNode->frameFromBeat(m_iMetroBeat); iMaxLength = (m_iMetroBeatStart / m_iMetroBeat); } else { m_iMetroBeat = 0; m_iMetroBeatStart = 0; iMaxLength = pNode->frameFromBeat(1); } if (m_pMetroBarBuff) { unsigned long iMetroBarLength = m_pMetroBarBuff->frames(); m_pMetroBarBuff->setLength( iMetroBarLength > iMaxLength ? iMaxLength : iMetroBarLength); m_pMetroBarBuff->reset(false); } if (m_pMetroBeatBuff) { unsigned long iMetroBeatLength = m_pMetroBeatBuff->frames(); m_pMetroBeatBuff->setLength( iMetroBeatLength > iMaxLength ? iMaxLength : iMetroBeatLength); m_pMetroBeatBuff->reset(false); } } // Audition/pre-listening bus mode accessors. void qtractorAudioEngine::setPlayerBus ( bool bPlayerBus ) { deletePlayerBus(); m_bPlayerBus = bPlayerBus; createPlayerBus(); if (isActivated()) { openPlayerBus(); if (m_bPlayerBus && m_pPlayerBus) m_pPlayerBus->autoConnect(); } } bool qtractorAudioEngine::isPlayerBus (void) const { return m_bPlayerBus; } void qtractorAudioEngine::resetPlayerBus (void) { if (m_bPlayerBus && m_pPlayerBus) return; createPlayerBus(); if (isActivated()) openPlayerBus(); } // Audition/pre-listening bus defaults accessors. void qtractorAudioEngine::setPlayerAutoConnect ( bool bPlayerAutoConnect ) { m_bPlayerAutoConnect = bPlayerAutoConnect; } bool qtractorAudioEngine::isPlayerAutoConnect (void) const { return m_bPlayerAutoConnect; } // Create audition/pre-listening stuff... void qtractorAudioEngine::createPlayerBus (void) { deletePlayerBus(); // Whether audition/pre-listening bus is here owned, or... if (m_bPlayerBus) { m_pPlayerBus = new qtractorAudioBus(this, "Player", qtractorBus::BusMode(qtractorBus::Output | qtractorBus::Ex)); m_pPlayerBus->setAutoConnect(m_bPlayerAutoConnect); } else { // Audition/pre-listening bus gets to be // the first available output bus... for (qtractorBus *pBus = qtractorEngine::buses().first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Output) { m_pPlayerBus = static_cast (pBus); break; } } } } // Open audition/pre-listening player stuff... bool qtractorAudioEngine::openPlayerBus (void) { closePlayerBus(); // Is there any? if (m_pPlayerBus == NULL) createPlayerBus(); if (m_pPlayerBus == NULL) return false; if (m_bPlayerBus) { addBusEx(m_pPlayerBus); m_pPlayerBus->open(); } // Enough number of channels?... unsigned short iChannels = m_pPlayerBus->channels(); if (iChannels < 1) { closePlayerBus(); return false; } // We got it... m_pPlayerBuff = new qtractorAudioBuffer( m_pSyncThread, iChannels, sampleRate()); return true; } // Close audition/pre-listening stuff... void qtractorAudioEngine::closePlayerBus (void) { if (m_pPlayerBuff) { m_pPlayerBuff->close(); delete m_pPlayerBuff; m_pPlayerBuff = NULL; } if (m_bPlayerBus && m_pPlayerBus) { m_pPlayerBus->close(); removeBusEx(m_pPlayerBus); } } // Destroy audition/pre-listening stuff... void qtractorAudioEngine::deletePlayerBus (void) { closePlayerBus(); if (m_bPlayerBus && m_pPlayerBus) delete m_pPlayerBus; m_pPlayerBus = NULL; } // Tell whether audition/pre-listening is active... bool qtractorAudioEngine::isPlayerOpen (void) const { return m_bPlayerOpen; } // Open and start audition/pre-listening... bool qtractorAudioEngine::openPlayer ( const QString& sFilename ) { // Must have a valid session... qtractorSession *pSession = session(); if (pSession == NULL) return false; // Acquire proper locking... while (!ATOMIC_TAS(&m_playerLock)) pSession->stabilize(); // May close it logically... m_bPlayerOpen = false; // Is there any? if (m_pPlayerBuff) { m_pPlayerBuff->close(); m_pPlayerBuff->setLength(0); m_bPlayerOpen = m_pPlayerBuff->open(sFilename); } m_iPlayerFrame = 0; // Release player lock... ATOMIC_SET(&m_playerLock, 0); return m_bPlayerOpen; } // Stop and close audition/pre-listening... void qtractorAudioEngine::closePlayer (void) { // Must have a valid session... qtractorSession *pSession = session(); if (pSession == NULL) return; // Acquire proper locking... while (!ATOMIC_TAS(&m_playerLock)) pSession->stabilize(); m_bPlayerOpen = false; if (m_pPlayerBuff) m_pPlayerBuff->close(); m_iPlayerFrame = 0; // Release player lock... ATOMIC_SET(&m_playerLock, 0); } // Retrieve/restore all connections, on all audio buses. // return the total number of effective (re)connection attempts... int qtractorAudioEngine::updateConnects (void) { // Do it as usual, on all standard owned dependable buses... return qtractorEngine::updateConnects(); } // JACK Transport mode accessors. void qtractorAudioEngine::setTransportMode ( qtractorBus::BusMode transportMode ) { m_transportMode = transportMode; } qtractorBus::BusMode qtractorAudioEngine::transportMode (void) const { return m_transportMode; } // Absolute number of frames elapsed since engine start. unsigned long qtractorAudioEngine::jackFrame (void) const { return (m_pJackClient ? jack_frame_time(m_pJackClient) : 0); } // Reset all audio monitoring... void qtractorAudioEngine::resetAllMonitors (void) { // There must a session reference... qtractorSession *pSession = session(); if (pSession == NULL) return; // Reset all audio bus monitors... for (qtractorBus *pBus = buses().first(); pBus; pBus = pBus->next()) { qtractorAudioBus *pAudioBus = static_cast (pBus); if (pAudioBus) { // if (pAudioBus->audioMonitor_in()) // pAudioBus->audioMonitor_in()->reset(); if (pAudioBus->audioMonitor_out()) pAudioBus->audioMonitor_out()->reset(); } } // Reset all audio track channel monitors... for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { if (pTrack->trackType() == qtractorTrack::Audio) { qtractorAudioMonitor *pAudioMonitor = static_cast (pTrack->monitor()); if (pAudioMonitor) pAudioMonitor->reset(); } } } //---------------------------------------------------------------------- // class qtractorAudioBus -- Managed JACK port set // // Constructor. qtractorAudioBus::qtractorAudioBus ( qtractorAudioEngine *pAudioEngine, const QString& sBusName, BusMode busMode, bool bMonitor, unsigned short iChannels ) : qtractorBus(pAudioEngine, sBusName, busMode, bMonitor) { m_iChannels = iChannels; if ((busMode & qtractorBus::Input) && !(busMode & qtractorBus::Ex)) { m_pIAudioMonitor = new qtractorAudioMonitor(iChannels); m_pIPluginList = createPluginList(qtractorPluginList::AudioInBus); m_pICurveFile = new qtractorCurveFile(m_pIPluginList->curveList()); } else { m_pIAudioMonitor = NULL; m_pIPluginList = NULL; m_pICurveFile = NULL; } if ((busMode & qtractorBus::Output) && !(busMode & qtractorBus::Ex)) { m_pOAudioMonitor = new qtractorAudioMonitor(iChannels); m_pOPluginList = createPluginList(qtractorPluginList::AudioOutBus); m_pOCurveFile = new qtractorCurveFile(m_pOPluginList->curveList()); } else { m_pOAudioMonitor = NULL; m_pOPluginList = NULL; m_pOCurveFile = NULL; } m_bAutoConnect = false; m_ppIPorts = NULL; m_ppOPorts = NULL; m_ppIBuffer = NULL; m_ppOBuffer = NULL; m_ppXBuffer = NULL; m_ppYBuffer = NULL; m_bEnabled = false; #if defined(__SSE__) if (sse_enabled()) m_pfnBufferAdd = sse_buffer_add; else #endif m_pfnBufferAdd = std_buffer_add; } // Destructor. qtractorAudioBus::~qtractorAudioBus (void) { close(); if (m_pIAudioMonitor) delete m_pIAudioMonitor; if (m_pOAudioMonitor) delete m_pOAudioMonitor; if (m_pICurveFile) delete m_pICurveFile; if (m_pOCurveFile) delete m_pOCurveFile; if (m_pIPluginList) delete m_pIPluginList; if (m_pOPluginList) delete m_pOPluginList; } // Channel number property accessor. void qtractorAudioBus::setChannels ( unsigned short iChannels ) { qtractorAudioEngine *pAudioEngine = static_cast (engine()); if (pAudioEngine == NULL) return; m_iChannels = iChannels; if (m_pIAudioMonitor) m_pIAudioMonitor->setChannels(iChannels); if (m_pOAudioMonitor) m_pOAudioMonitor->setChannels(iChannels); #if 0 if (m_pIPluginList) updatePluginList(m_pIPluginList, qtractorPluginList::AudioInBus); if (m_pOPluginList) updatePluginList(m_pOPluginList, qtractorPluginList::AudioOutBus); #endif } unsigned short qtractorAudioBus::channels (void) const { return m_iChannels; } // Auto-connection predicate. void qtractorAudioBus::setAutoConnect ( bool bAutoConnect ) { m_bAutoConnect = bAutoConnect; } bool qtractorAudioBus::isAutoConnect (void) const { return m_bAutoConnect; } // Register and pre-allocate bus port buffers. bool qtractorAudioBus::open (void) { // close(); qtractorAudioEngine *pAudioEngine = static_cast (engine()); if (pAudioEngine == NULL) return false; if (pAudioEngine->jackClient() == NULL) return false; unsigned short i; unsigned short iDisabled = 0; if (busMode() & qtractorBus::Input) { // Register and allocate input port buffers... m_ppIPorts = new jack_port_t * [m_iChannels]; m_ppIBuffer = new float * [m_iChannels]; const QString sIPortName(busName() + "/in_%1"); for (i = 0; i < m_iChannels; ++i) { m_ppIPorts[i] = jack_port_register( pAudioEngine->jackClient(), sIPortName.arg(i + 1).toUtf8().constData(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); m_ppIBuffer[i] = NULL; if (m_ppIPorts[i] == NULL) ++iDisabled; } } if (busMode() & qtractorBus::Output) { // Register and allocate output port buffers... m_ppOPorts = new jack_port_t * [m_iChannels]; m_ppOBuffer = new float * [m_iChannels]; const QString sOPortName(busName() + "/out_%1"); for (i = 0; i < m_iChannels; ++i) { m_ppOPorts[i] = jack_port_register( pAudioEngine->jackClient(), sOPortName.arg(i + 1).toUtf8().constData(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); m_ppOBuffer[i] = NULL; if (m_ppOPorts[i] == NULL) ++iDisabled; } } // Allocate internal working bus buffers... unsigned int iBufferSize = pAudioEngine->bufferSize(); m_ppXBuffer = new float * [m_iChannels]; m_ppYBuffer = new float * [m_iChannels]; for (i = 0; i < m_iChannels; ++i) { m_ppXBuffer[i] = new float [iBufferSize]; m_ppYBuffer[i] = NULL; } // Plugin lists need some buffer (re)allocation too... if (m_pIPluginList) updatePluginList(m_pIPluginList, qtractorPluginList::AudioInBus); if (m_pOPluginList) updatePluginList(m_pOPluginList, qtractorPluginList::AudioOutBus); // Finally, open for biz... m_bEnabled = (iDisabled == 0); return true; } // Unregister and post-free bus port buffers. void qtractorAudioBus::close (void) { // Close for biz, immediate... m_bEnabled = false; qtractorAudioEngine *pAudioEngine = static_cast (engine()); if (pAudioEngine == NULL) return; unsigned short i; if (busMode() & qtractorBus::Input) { // Free input ports. if (m_ppIPorts) { // Unregister, if we're not shutdown... if (pAudioEngine->jackClient()) { for (i = 0; i < m_iChannels; ++i) { if (m_ppIPorts[i]) { jack_port_unregister( pAudioEngine->jackClient(), m_ppIPorts[i]); m_ppIPorts[i] = NULL; } } } delete [] m_ppIPorts; m_ppIPorts = NULL; } // Free input Buffers. if (m_ppIBuffer) delete [] m_ppIBuffer; m_ppIBuffer = NULL; } if (busMode() & qtractorBus::Output) { // Free output ports. if (m_ppOPorts) { // Unregister, if we're not shutdown... if (pAudioEngine->jackClient()) { for (i = 0; i < m_iChannels; ++i) { if (m_ppOPorts[i]) { jack_port_unregister( pAudioEngine->jackClient(), m_ppOPorts[i]); m_ppOPorts[i] = NULL; } } } delete [] m_ppOPorts; m_ppOPorts = NULL; } // Free output Buffers. if (m_ppOBuffer) delete [] m_ppOBuffer; m_ppOBuffer = NULL; } // Free internal buffers. if (m_ppXBuffer) { for (i = 0; i < m_iChannels; ++i) delete [] m_ppXBuffer[i]; delete [] m_ppXBuffer; m_ppXBuffer = NULL; } if (m_ppYBuffer) { delete [] m_ppYBuffer; m_ppYBuffer = NULL; } } // Auto-connect to physical ports. void qtractorAudioBus::autoConnect (void) { qtractorAudioEngine *pAudioEngine = static_cast (engine()); if (pAudioEngine == NULL) return; if (pAudioEngine->jackClient() == NULL) return; if (!m_bAutoConnect) return; unsigned short i; if ((busMode() & qtractorBus::Input) && inputs().isEmpty()) { const char **ppszOPorts = jack_get_ports(pAudioEngine->jackClient(), 0, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsPhysical); if (ppszOPorts) { const QString sIPortName = pAudioEngine->clientName() + ':' + busName() + "/in_%1"; for (i = 0; i < m_iChannels && ppszOPorts[i]; ++i) { jack_connect(pAudioEngine->jackClient(), ppszOPorts[i], sIPortName.arg(i + 1).toUtf8().constData()); } ::free(ppszOPorts); } } if ((busMode() & qtractorBus::Output) && outputs().isEmpty()) { const char **ppszIPorts = jack_get_ports(pAudioEngine->jackClient(), 0, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsPhysical); if (ppszIPorts) { const QString sOPortName = pAudioEngine->clientName() + ':' + busName() + "/out_%1"; for (i = 0; i < m_iChannels && ppszIPorts[i]; ++i) { jack_connect(pAudioEngine->jackClient(), sOPortName.arg(i + 1).toUtf8().constData(), ppszIPorts[i]); } ::free(ppszIPorts); } } } // Bus mode change event. void qtractorAudioBus::updateBusMode (void) { const qtractorBus::BusMode mode = busMode(); // Have a new/old input monitor? if ((mode & qtractorBus::Input) && !(mode & qtractorBus::Ex)) { if (m_pIAudioMonitor == NULL) m_pIAudioMonitor = new qtractorAudioMonitor(m_iChannels); if (m_pIPluginList == NULL) m_pIPluginList = createPluginList(qtractorPluginList::AudioInBus); if (m_pICurveFile == NULL) m_pICurveFile = new qtractorCurveFile(m_pIPluginList->curveList()); } else { if (m_pIAudioMonitor) { delete m_pIAudioMonitor; m_pIAudioMonitor = NULL; } if (m_pICurveFile) { delete m_pICurveFile; m_pICurveFile = NULL; } if (m_pIPluginList) { delete m_pIPluginList; m_pIPluginList = NULL; } } // Have a new/old output monitor? if ((mode & qtractorBus::Output) && !(mode & qtractorBus::Ex)) { if (m_pOAudioMonitor == NULL) m_pOAudioMonitor = new qtractorAudioMonitor(m_iChannels); if (m_pOPluginList == NULL) m_pOPluginList = createPluginList(qtractorPluginList::AudioOutBus); if (m_pOCurveFile == NULL) m_pOCurveFile = new qtractorCurveFile(m_pOPluginList->curveList()); } else { if (m_pOAudioMonitor) { delete m_pOAudioMonitor; m_pOAudioMonitor = NULL; } if (m_pOCurveFile) { delete m_pOCurveFile; m_pOCurveFile = NULL; } if (m_pOPluginList) { delete m_pOPluginList; m_pOPluginList = NULL; } } } // Process cycle preparator. void qtractorAudioBus::process_prepare ( unsigned int nframes ) { if (!m_bEnabled) return; unsigned short i; if (busMode() & qtractorBus::Input) { for (i = 0; i < m_iChannels; ++i) { m_ppIBuffer[i] = static_cast (jack_port_get_buffer(m_ppIPorts[i], nframes)); } } if (busMode() & qtractorBus::Output) { for (i = 0; i < m_iChannels; ++i) { m_ppOBuffer[i] = static_cast (jack_port_get_buffer(m_ppOPorts[i], nframes)); // Zero-out output buffer... ::memset(m_ppOBuffer[i], 0, nframes * sizeof(float)); } } } // Process cycle monitor. void qtractorAudioBus::process_monitor ( unsigned int nframes ) { if (!m_bEnabled) return; if (busMode() & qtractorBus::Input) { if (m_pIPluginList && m_pIPluginList->activated()) m_pIPluginList->process(m_ppIBuffer, nframes); if (m_pIAudioMonitor) m_pIAudioMonitor->process(m_ppIBuffer, nframes); if (isMonitor() && (busMode() & qtractorBus::Output)) { (*m_pfnBufferAdd)(m_ppOBuffer, m_ppIBuffer, nframes, m_iChannels, m_iChannels, 0); } } } // Process cycle commitment. void qtractorAudioBus::process_commit ( unsigned int nframes ) { if (!m_bEnabled) return; if (m_pOPluginList && m_pOPluginList->activated()) m_pOPluginList->process(m_ppOBuffer, nframes); if (m_pOAudioMonitor) m_pOAudioMonitor->process(m_ppOBuffer, nframes); } // Bus-buffering methods. void qtractorAudioBus::buffer_prepare ( unsigned int nframes, qtractorAudioBus *pInputBus ) { if (!m_bEnabled) return; qtractorAudioEngine *pAudioEngine = static_cast (engine()); if (pAudioEngine == NULL) return; unsigned int offset = pAudioEngine->bufferOffset(); unsigned int nbytes = nframes * sizeof(float); if (pInputBus == NULL) { for (unsigned short i = 0; i < m_iChannels; ++i) { m_ppYBuffer[i] = m_ppXBuffer[i] + offset; ::memset(m_ppYBuffer[i], 0, nbytes); } return; } unsigned short iBuffers = pInputBus->channels(); float **ppBuffer = pInputBus->in(); if (m_iChannels == iBuffers) { // Exact buffer copy... for (unsigned short i = 0; i < iBuffers; ++i) { m_ppYBuffer[i] = m_ppXBuffer[i] + offset; ::memcpy(m_ppYBuffer[i], ppBuffer[i] + offset, nbytes); } } else { // Buffer merge/multiplex... unsigned short i; for (i = 0; i < m_iChannels; ++i) { m_ppYBuffer[i] = m_ppXBuffer[i] + offset; ::memset(m_ppYBuffer[i], 0, nbytes); } if (m_iChannels > iBuffers) { unsigned short j = 0; for (i = 0; i < m_iChannels; ++i) { ::memcpy(m_ppYBuffer[i], ppBuffer[j] + offset, nbytes); if (++j >= iBuffers) j = 0; } } else { // (m_iChannels < iBuffers) (*m_pfnBufferAdd)(m_ppXBuffer, ppBuffer, nframes, m_iChannels, iBuffers, offset); } } } void qtractorAudioBus::buffer_commit ( unsigned int nframes ) { if (!m_bEnabled || (busMode() & qtractorBus::Output) == 0) return; qtractorAudioEngine *pAudioEngine = static_cast (engine()); if (pAudioEngine == NULL) return; (*m_pfnBufferAdd)(m_ppOBuffer, m_ppXBuffer, nframes, m_iChannels, m_iChannels, pAudioEngine->bufferOffset()); } float **qtractorAudioBus::buffer (void) const { return m_ppYBuffer; } // Frame buffer accessors. float **qtractorAudioBus::in (void) const { return m_ppIBuffer; } float **qtractorAudioBus::out (void) const { return m_ppOBuffer; } // Virtual I/O bus-monitor accessors. qtractorMonitor *qtractorAudioBus::monitor_in (void) const { return audioMonitor_in(); } qtractorMonitor *qtractorAudioBus::monitor_out (void) const { return audioMonitor_out(); } // Audio I/O bus-monitor accessors. qtractorAudioMonitor *qtractorAudioBus::audioMonitor_in (void) const { return m_pIAudioMonitor; } qtractorAudioMonitor *qtractorAudioBus::audioMonitor_out (void) const { return m_pOAudioMonitor; } // Plugin-chain accessors. qtractorPluginList *qtractorAudioBus::pluginList_in (void) const { return m_pIPluginList; } qtractorPluginList *qtractorAudioBus::pluginList_out (void) const { return m_pOPluginList; } // Automation curve list accessors. qtractorCurveList *qtractorAudioBus::curveList_in (void) const { return (m_pIPluginList ? m_pIPluginList->curveList() : NULL); } qtractorCurveList *qtractorAudioBus::curveList_out (void) const { return (m_pOPluginList ? m_pOPluginList->curveList() : NULL); } // Automation curve serializer accessors. qtractorCurveFile *qtractorAudioBus::curveFile_in (void) const { return m_pICurveFile; } qtractorCurveFile *qtractorAudioBus::curveFile_out (void) const { return m_pOCurveFile; } // Audio I/O port latency accessors. unsigned int qtractorAudioBus::latency_in (void) const { if (m_ppIPorts == NULL) return 0; qtractorAudioEngine *pAudioEngine = static_cast (engine()); if (pAudioEngine == NULL) return 0; unsigned int iLatencyIn = pAudioEngine->bufferSize(); #ifdef CONFIG_JACK_LATENCY jack_nframes_t range_min = 0; jack_latency_range_t range; for (unsigned int i = 0; i < m_iChannels; ++i) { if (m_ppIPorts[i] == NULL) continue; jack_port_get_latency_range(m_ppIPorts[i], JackCaptureLatency, &range); if (range_min > range.min || i == 0) range_min = range.min; } iLatencyIn += range_min; #else jack_nframes_t lat, lat_min = 0; for (unsigned int i = 0; i < m_iChannels; ++i) { if (m_ppIPorts[i] == NULL) continue; lat = jack_port_get_latency(m_ppIPorts[i]); if (lat_min > lat || i == 0) lat_min = lat; } iLatencyIn += lat_min; #endif return iLatencyIn; } unsigned int qtractorAudioBus::latency_out (void) const { if (m_ppOPorts == NULL) return 0; qtractorAudioEngine *pAudioEngine = static_cast (engine()); if (pAudioEngine == NULL) return 0; unsigned int iLatencyOut = pAudioEngine->bufferSize(); #ifdef CONFIG_JACK_LATENCY jack_nframes_t range_min = 0; jack_latency_range_t range; for (unsigned int i = 0; i < m_iChannels; ++i) { if (m_ppOPorts[i] == NULL) continue; jack_port_get_latency_range(m_ppOPorts[i], JackPlaybackLatency, &range); if (range_min > range.min || i == 0) range_min = range.min; } iLatencyOut += range_min; #else jack_nframes_t lat, lat_min = 0; for (unsigned int i = 0; i < m_iChannels; ++i) { if (m_ppOPorts[i] == NULL) continue; lat = jack_port_get_latency(m_ppOPorts[i]); if (lat_min > lat || i == 0) lat_min = lat; } iLatencyOut += lat_min; #endif return iLatencyOut; } // Create plugin-list properly. qtractorPluginList *qtractorAudioBus::createPluginList ( int iFlags ) const { qtractorSession *pSession = engine()->session(); if (pSession == NULL) return NULL; // Create plugin-list alright... unsigned int iSampleRate = 0; qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine) iSampleRate = pAudioEngine->sampleRate(); qtractorPluginList *pPluginList = new qtractorPluginList(0, 0, iSampleRate, iFlags); // Set plugin-list title name... updatePluginListName(pPluginList, iFlags); return pPluginList; } // Update plugin-list title name... void qtractorAudioBus::updatePluginListName ( qtractorPluginList *pPluginList, int iFlags ) const { pPluginList->setName((iFlags & qtractorPluginList::In ? QObject::tr("%1 In") : QObject::tr("%1 Out")).arg(busName())); } // Update plugin-list name/buffers properly. void qtractorAudioBus::updatePluginList ( qtractorPluginList *pPluginList, int iFlags ) { // Sanity checks... qtractorAudioEngine *pAudioEngine = static_cast (engine()); if (pAudioEngine == NULL) return; // Set plugin-list title name... updatePluginListName(pPluginList, iFlags); // Set plugin-list buffer alright... pPluginList->setBuffer(m_iChannels, pAudioEngine->bufferSize(), pAudioEngine->sampleRate(), iFlags); } // Retrieve all current JACK connections for a given bus mode interface; // return the effective number of connection attempts... int qtractorAudioBus::updateConnects ( qtractorBus::BusMode busMode, ConnectList& connects, bool bConnect ) const { qtractorAudioEngine *pAudioEngine = static_cast (engine()); if (pAudioEngine == NULL) return 0; if (pAudioEngine->jackClient() == NULL) return 0; // Modes must match, at least... if ((busMode & qtractorAudioBus::busMode()) == 0) return 0; if (bConnect && connects.isEmpty()) return 0; // Which kind of ports? jack_port_t **ppPorts = (busMode == qtractorBus::Input ? m_ppIPorts : m_ppOPorts); if (ppPorts == NULL) return 0; // For each channel... ConnectItem item; for (item.index = 0; item.index < m_iChannels; ++item.index) { // Get port connections... const char **ppszClientPorts = jack_port_get_all_connections( pAudioEngine->jackClient(), ppPorts[item.index]); if (ppszClientPorts) { // Now, for each port... int iClientPort = 0; while (ppszClientPorts[iClientPort]) { // Check if already in list/connected... const QString sClientPort = QString::fromUtf8(ppszClientPorts[iClientPort]); item.clientName = sClientPort.section(':', 0, 0); item.portName = sClientPort.section(':', 1, 1); ConnectItem *pItem = connects.findItem(item); if (pItem && bConnect) { int iItem = connects.indexOf(pItem); if (iItem >= 0) { connects.removeAt(iItem); delete pItem; } } else if (!bConnect) connects.append(new ConnectItem(item)); ++iClientPort; } ::free(ppszClientPorts); } } // Shall we proceed for actual connections? if (!bConnect) return 0; // Our client:port prefix template... QString sClientPort = pAudioEngine->clientName() + ':'; sClientPort += busName() + '/'; sClientPort += (busMode == qtractorBus::Input ? "in" : "out"); sClientPort += "_%1"; QString sOutputPort; QString sInputPort; // For each (remaining) connection, try... int iUpdate = 0; QListIterator iter(connects); while (iter.hasNext()) { ConnectItem *pItem = iter.next(); // Mangle which is output and input... if (busMode == qtractorBus::Input) { sOutputPort = pItem->clientName + ':' + pItem->portName; sInputPort = sClientPort.arg(pItem->index + 1); } else { sOutputPort = sClientPort.arg(pItem->index + 1); sInputPort = pItem->clientName + ':' + pItem->portName; } #ifdef CONFIG_DEBUG qDebug("qtractorAudioBus[%p]::updateConnects(%d): " "jack_connect: [%s] => [%s]", this, (int) busMode, sOutputPort.toUtf8().constData(), sInputPort.toUtf8().constData()); #endif // Do it... if (jack_connect(pAudioEngine->jackClient(), sOutputPort.toUtf8().constData(), sInputPort.toUtf8().constData()) == 0) { int iItem = connects.indexOf(pItem); if (iItem >= 0) { connects.removeAt(iItem); delete pItem; ++iUpdate; } } } // Done. return iUpdate; } // Document element methods. bool qtractorAudioBus::loadElement ( qtractorDocument *pDocument, QDomElement *pElement ) { for (QDomNode nProp = pElement->firstChild(); !nProp.isNull(); nProp = nProp.nextSibling()) { // Convert audio-bus property to element... QDomElement eProp = nProp.toElement(); if (eProp.isNull()) continue; if (eProp.tagName() == "pass-through" || // Legacy compat. eProp.tagName() == "audio-thru" || eProp.tagName() == "monitor") { qtractorAudioBus::setMonitor( qtractorDocument::boolFromText(eProp.text())); } else if (eProp.tagName() == "channels") { qtractorAudioBus::setChannels(eProp.text().toUShort()); } else if (eProp.tagName() == "auto-connect") { qtractorAudioBus::setAutoConnect( qtractorDocument::boolFromText(eProp.text())); } else if (eProp.tagName() == "input-gain") { if (qtractorAudioBus::monitor_in()) qtractorAudioBus::monitor_in()->setGain( eProp.text().toFloat()); } else if (eProp.tagName() == "input-panning") { if (qtractorAudioBus::monitor_in()) qtractorAudioBus::monitor_in()->setPanning( eProp.text().toFloat()); } else if (eProp.tagName() == "input-controllers") { qtractorAudioBus::loadControllers(&eProp, qtractorBus::Input); } else if (eProp.tagName() == "input-curve-file") { qtractorAudioBus::loadCurveFile(&eProp, qtractorBus::Input, qtractorAudioBus::curveFile_in()); } else if (eProp.tagName() == "input-plugins") { if (qtractorAudioBus::pluginList_in()) qtractorAudioBus::pluginList_in()->loadElement( pDocument, &eProp); } else if (eProp.tagName() == "input-connects") { qtractorAudioBus::loadConnects( qtractorAudioBus::inputs(), pDocument, &eProp); } else if (eProp.tagName() == "output-gain") { if (qtractorAudioBus::monitor_out()) qtractorAudioBus::monitor_out()->setGain( eProp.text().toFloat()); } else if (eProp.tagName() == "output-panning") { if (qtractorAudioBus::monitor_out()) qtractorAudioBus::monitor_out()->setPanning( eProp.text().toFloat()); } else if (eProp.tagName() == "output-controllers") { qtractorAudioBus::loadControllers(&eProp, qtractorBus::Output); } else if (eProp.tagName() == "output-curve-file") { qtractorAudioBus::loadCurveFile(&eProp, qtractorBus::Output, qtractorAudioBus::curveFile_out()); } else if (eProp.tagName() == "output-plugins") { if (qtractorAudioBus::pluginList_out()) qtractorAudioBus::pluginList_out()->loadElement( pDocument, &eProp); } else if (eProp.tagName() == "output-connects") { qtractorAudioBus::loadConnects( qtractorAudioBus::outputs(), pDocument, &eProp); } } return true; } bool qtractorAudioBus::saveElement ( qtractorDocument *pDocument, QDomElement *pElement ) const { pElement->setAttribute("name", qtractorAudioBus::busName()); pElement->setAttribute("mode", qtractorBus::textFromBusMode(qtractorAudioBus::busMode())); pDocument->saveTextElement("monitor", qtractorDocument::textFromBool( qtractorAudioBus::isMonitor()), pElement); pDocument->saveTextElement("channels", QString::number(qtractorAudioBus::channels()), pElement); pDocument->saveTextElement("auto-connect", qtractorDocument::textFromBool( qtractorAudioBus::isAutoConnect()), pElement); if (qtractorAudioBus::busMode() & qtractorBus::Input) { if (qtractorAudioBus::monitor_in()) { pDocument->saveTextElement("input-gain", QString::number(qtractorAudioBus::monitor_in()->gain()), pElement); pDocument->saveTextElement("input-panning", QString::number(qtractorAudioBus::monitor_in()->panning()), pElement); } // Save input bus controllers... QDomElement eInputControllers = pDocument->document()->createElement("input-controllers"); qtractorAudioBus::saveControllers(pDocument, &eInputControllers, qtractorBus::Input); pElement->appendChild(eInputControllers); // Save input bus automation curves... qtractorCurveList *pInputCurveList = qtractorAudioBus::curveList_in(); if (pInputCurveList && !pInputCurveList->isEmpty()) { qtractorCurveFile cfile(pInputCurveList); QDomElement eInputCurveFile = pDocument->document()->createElement("input-curve-file"); qtractorAudioBus::saveCurveFile(pDocument, &eInputCurveFile, qtractorBus::Input, &cfile); pElement->appendChild(eInputCurveFile); } // Save input bus plugins... if (qtractorAudioBus::pluginList_in()) { QDomElement eInputPlugins = pDocument->document()->createElement("input-plugins"); qtractorAudioBus::pluginList_in()->saveElement( pDocument, &eInputPlugins); pElement->appendChild(eInputPlugins); } // Save input bus connections... QDomElement eAudioInputs = pDocument->document()->createElement("input-connects"); qtractorBus::ConnectList inputs; qtractorAudioBus::updateConnects(qtractorBus::Input, inputs); qtractorAudioBus::saveConnects(inputs, pDocument, &eAudioInputs); pElement->appendChild(eAudioInputs); } if (qtractorAudioBus::busMode() & qtractorBus::Output) { if (qtractorAudioBus::monitor_out()) { pDocument->saveTextElement("output-gain", QString::number(qtractorAudioBus::monitor_out()->gain()), pElement); pDocument->saveTextElement("output-panning", QString::number(qtractorAudioBus::monitor_out()->panning()), pElement); } // Save output bus controllers... QDomElement eOutputControllers = pDocument->document()->createElement("output-controllers"); qtractorAudioBus::saveControllers(pDocument, &eOutputControllers, qtractorBus::Output); pElement->appendChild(eOutputControllers); // Save output bus automation curves... qtractorCurveList *pOutputCurveList = qtractorAudioBus::curveList_out(); if (pOutputCurveList && !pOutputCurveList->isEmpty()) { qtractorCurveFile cfile(pOutputCurveList); QDomElement eOutputCurveFile = pDocument->document()->createElement("output-curve-file"); qtractorAudioBus::saveCurveFile(pDocument, &eOutputCurveFile, qtractorBus::Output, &cfile); pElement->appendChild(eOutputCurveFile); } // Save output bus plugins... if (qtractorAudioBus::pluginList_out()) { QDomElement eOutputPlugins = pDocument->document()->createElement("output-plugins"); qtractorAudioBus::pluginList_out()->saveElement( pDocument, &eOutputPlugins); pElement->appendChild(eOutputPlugins); } // Save output bus connections... QDomElement eAudioOutputs = pDocument->document()->createElement("output-connects"); qtractorBus::ConnectList outputs; qtractorAudioBus::updateConnects(qtractorBus::Output, outputs); qtractorAudioBus::saveConnects(outputs, pDocument, &eAudioOutputs); pElement->appendChild(eAudioOutputs); } return true; } // end of qtractorAudioEngine.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorEngine.h0000644000175000001440000000012212217361266020406 xustar000000000000000026 mtime=1379787446.61859 26 atime=1381134671.21108 30 ctime=1381134671.211080116 qtractor-0.5.11/src/qtractorEngine.h0000644000175000001440000002002512217361266017675 0ustar00rncbcusers00000000000000// qtractorEngine.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorEngine_h #define __qtractorEngine_h #include "qtractorTrack.h" // Forward declarations. class qtractorBus; class qtractorSessionCursor; class qtractorCurveFile; class QDomElement; //---------------------------------------------------------------------- // class qtractorEngine -- Abstract device engine instance (singleton). // class qtractorEngine { public: // Constructor. qtractorEngine(qtractorSession *pSession, qtractorTrack::TrackType syncType); // Destructor. virtual ~qtractorEngine(); // Device engine activation methods. bool open(); void close(); // Buses list clear. void clear(); // Session helper accessor. qtractorSession *session() const; // Session cursor accessor. qtractorSessionCursor *sessionCursor() const; // Engine type method. qtractorTrack::TrackType syncType() const; // Client name accessor. const QString& clientName() const; // Engine status methods. bool isActivated() const; // Engine state methods. void setPlaying(bool bPlaying); bool isPlaying() const; // Buses list managament methods. const qtractorList& buses() const; void addBus(qtractorBus *pBus); void removeBus(qtractorBus *pBus); qtractorBus *findBus(const QString& sBusName) const; qtractorBus *findInputBus(const QString& sInputBusName) const; qtractorBus *findOutputBus(const QString& sOutputBusName) const; // Exo-buses list managament methods. const qtractorList& busesEx() const; void addBusEx(qtractorBus *pBus); void removeBusEx(qtractorBus *pBus); qtractorBus *findBusEx(const QString& sBusName) const; // Retrieve/restore all connections, on all buses; // return the effective number of connection attempts. virtual int updateConnects(); // Document element methods. virtual bool loadElement(qtractorDocument *pDocument, QDomElement *pElement) = 0; virtual bool saveElement(qtractorDocument *pDocument, QDomElement *pElement) const = 0; // Clear/reset all pending connections. void clearConnects(); protected: // Derived classes must set on this... virtual bool init() = 0; virtual bool activate() = 0; virtual bool start() = 0; virtual void stop() = 0; virtual void deactivate() = 0; virtual void clean() = 0; // Retrieve/restore connections, on given buses; // return the effective number of connection attempts. int updateConnects(qtractorBus *pBus); private: // Device instance variables. qtractorSession *m_pSession; qtractorSessionCursor *m_pSessionCursor; // Engine running flags. bool m_bActivated; bool m_bPlaying; qtractorList m_buses; qtractorList m_busesEx; }; //---------------------------------------------------------------------- // class qtractorBus -- Abstract device bus. // class qtractorBus : public qtractorList::Link { public: // Bus operation mode bit-flags. enum BusMode { None = 0, Input = 1, Output = 2, Duplex = 3, Ex = 4 }; // Constructor. qtractorBus(qtractorEngine *pEngine, const QString& sBusName, BusMode busMode, bool bMonitor = false); // Destructor. virtual ~qtractorBus(); // Device accessor. qtractorEngine *engine() const; // Bus type method. qtractorTrack::TrackType busType() const; // Bus name accessors. void setBusName(const QString& sBusName); const QString& busName() const; // Bus mode property accessor. void setBusMode(BusMode busMode); BusMode busMode() const; // Pass-thru mode accessor. void setMonitor(bool bMonitor); bool isMonitor() const; // Pure virtual activation methods. virtual bool open() = 0; virtual void close() = 0; // I/O bus-monitor accessors. virtual qtractorMonitor *monitor_in() const = 0; virtual qtractorMonitor *monitor_out() const = 0; // State (monitor) button setup. qtractorSubject *monitorSubject() const; qtractorMidiControlObserver *monitorObserver() const; // State (monitor) notifier (proto-slot). void monitorChangeNotify(bool bOn); // Load/save bus (monitor, gain, pan) controllers (MIDI). void loadControllers( QDomElement *pElement, BusMode busMode); void saveControllers(qtractorDocument *pDocument, QDomElement *pElement, BusMode busMode) const; // Map bus (monitor, gain, pan) controllers (MIDI). void mapControllers(BusMode busMode); // Bus automation curve serialization methods. static void loadCurveFile( QDomElement *pElement, BusMode busMode, qtractorCurveFile *pCurveFile); void saveCurveFile(qtractorDocument *pDocument, QDomElement *pElement, BusMode busMode, qtractorCurveFile *pCurveFile) const; void applyCurveFile(BusMode busMode, qtractorCurveFile *pCurveFile) const; // Connection list stuff. struct ConnectItem { // Default contructor ConnectItem() : index(0), client(-1), port (-1) {} // Copy contructor ConnectItem(const ConnectItem& item) : index(item.index), client(item.client), port(item.port), clientName(item.clientName), portName(item.portName) {} // Item members. unsigned short index; int client, port; QString clientName; QString portName; }; class ConnectList : public QList { public: // Constructor. ConnectList() {} // Copy onstructor. ConnectList(const ConnectList& connects) : QList() { copy(connects); } // Destructor. ~ConnectList() { clear(); } // Item cleaner... void clear() { qDeleteAll(*this); QList::clear(); } // List copy... void copy (const ConnectList& connects) { clear(); QListIterator iter(connects); while (iter.hasNext()) append(new ConnectItem(*iter.next())); } // Item finder... ConnectItem *findItem(const ConnectItem& item) { QListIterator iter(*this); while (iter.hasNext()) { ConnectItem *pItem = iter.next(); if (pItem->index == item.index && pItem->clientName == item.clientName && pItem->portName == item.portName) { return pItem; } } return NULL; } }; // Connection lists accessors. ConnectList& inputs() { return m_inputs; } ConnectList& outputs() { return m_outputs; } // Retrieve/restore client:port connections; // return the effective number of connection attempts. virtual int updateConnects(BusMode busMode, ConnectList& connects, bool bConnect = false) const = 0; // Document element methods. static bool loadConnects(ConnectList& connects, qtractorDocument *pDocument, QDomElement *pElement); static bool saveConnects(ConnectList& connects, qtractorDocument *pDocument, QDomElement *pElement); // Bus mode textual helper methods. static BusMode busModeFromText (const QString& sText); static QString textFromBusMode (BusMode busMode); protected: // Bus mode change event. virtual void updateBusMode() = 0; private: // Instance variables. qtractorEngine *m_pEngine; QString m_sBusName; BusMode m_busMode; // Connections stuff. ConnectList m_inputs; ConnectList m_outputs; // State (monitor) observer stuff. qtractorSubject *m_pMonitorSubject; qtractorMidiControlObserver *m_pMonitorObserver; qtractorMidiControl::Controllers m_controllers_in; qtractorMidiControl::Controllers m_controllers_out; }; #endif // __qtractorEngine_h // end of qtractorEngine.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioMeter.cpp0000644000175000001440000000012111604341312021556 xustar000000000000000026 mtime=1309786826.32631 26 atime=1381134670.87708 29 ctime=1381134670.87808011 qtractor-0.5.11/src/qtractorAudioMeter.cpp0000644000175000001440000003630711604341312021060 0ustar00rncbcusers00000000000000// qtractorAudioMeter.cpp // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorAudioMeter.h" #include "qtractorAudioMonitor.h" #include "qtractorObserverWidget.h" #include "qtractorMidiControlObserver.h" #include #include #include #include #include #include #include // Meter level limits (in dB). #define QTRACTOR_AUDIO_METER_MAXDB +6.0f #define QTRACTOR_AUDIO_METER_MINDB -70.0f // The decay rates (magic goes here :). // - value decay rate (faster) #define QTRACTOR_AUDIO_METER_DECAY_RATE1 (1.0f - 1E-2f) // - peak decay rate (slower) #define QTRACTOR_AUDIO_METER_DECAY_RATE2 (1.0f - 1E-6f) // Number of cycles the peak stays on hold before fall-off. #define QTRACTOR_AUDIO_METER_PEAK_FALLOFF 32 // Possible 20 * log10(x) optimization // (borrowed from musicdsp.org) static inline float log10f2_opt ( float x ) { #ifdef CONFIG_FLOAT32 # define M_LOG10F20 6.0205999132796239042f // (= 20.0f * M_LN2 / M_LN10) // Avoid strict-aliasing optimization (gcc -O2). union { float f; int i; } u; u.f = x; return M_LOG10F20 * ((((u.i & 0x7f800000) >> 23) - 0x7f) + (u.i & 0x007fffff) / (float) 0x800000); #else return 20.0f * ::log10f(x); #endif } static inline float log10f2 ( float x ) { return (x > 0.0f ? 20.0f * ::log10f(x) : QTRACTOR_AUDIO_METER_MINDB); } static inline float pow10f2 ( float x ) { return ::powf(10.0f, 0.05f * x); } // Audio meter default color array. QColor qtractorAudioMeter::g_defaultColors[qtractorAudioMeter::ColorCount] = { QColor(240, 0, 20), // ColorOver QColor(240,160, 20), // Color0dB QColor(220,220, 20), // Color3dB QColor(160,220, 20), // Color6dB QColor( 40,160, 40), // Color10dB QColor( 20, 40, 20), // ColorBack QColor( 80, 80, 80) // ColorFore }; // Audio meter color array. QColor qtractorAudioMeter::g_currentColors[qtractorAudioMeter::ColorCount] = { g_defaultColors[ColorOver], g_defaultColors[Color0dB], g_defaultColors[Color3dB], g_defaultColors[Color6dB], g_defaultColors[Color10dB], g_defaultColors[ColorBack], g_defaultColors[ColorFore] }; //---------------------------------------------------------------------------- // IEC standard dB scaling -- as borrowed from meterbridge (c) Steve Harris static inline float IEC_Scale ( float dB ) { float fScale = 1.0f; if (dB < -70.0f) fScale = 0.0f; else if (dB < -60.0f) fScale = (dB + 70.0f) * 0.0025f; else if (dB < -50.0f) fScale = (dB + 60.0f) * 0.005f + 0.025f; else if (dB < -40.0) fScale = (dB + 50.0f) * 0.0075f + 0.075f; else if (dB < -30.0f) fScale = (dB + 40.0f) * 0.015f + 0.15f; else if (dB < -20.0f) fScale = (dB + 30.0f) * 0.02f + 0.3f; else if (dB < -0.001f || dB > 0.001f) /* if (dB < 0.0f) */ fScale = (dB + 20.0f) * 0.025f + 0.5f; return fScale; } static inline float IEC_dB ( float fScale ) { float dB = 0.0f; if (fScale < 0.025f) // IEC_Scale(-60.0f) dB = (fScale / 0.0025f) - 70.0f; else if (fScale < 0.075f) // IEC_Scale(-50.0f) dB = (fScale - 0.025f) / 0.005f - 60.0f; else if (fScale < 0.15f) // IEC_Scale(-40.0f) dB = (fScale - 0.075f) / 0.0075f - 50.0f; else if (fScale < 0.3f) // IEC_Scale(-30.0f) dB = (fScale - 0.15f) / 0.015f - 40.0f; else if (fScale < 0.5f) // IEC_Scale(-20.0f) dB = (fScale - 0.3f) / 0.02f - 30.0f; else /* if (fScale < 1.0f) // IED_Scale(0.0f)) */ dB = (fScale - 0.5f) / 0.025f - 20.0f; return (dB > -0.001f && dB < 0.001f ? 0.0f : dB); } //---------------------------------------------------------------------------- // qtractorAudioMeterScale -- Meter bridge scale widget. // Constructor. qtractorAudioMeterScale::qtractorAudioMeterScale ( qtractorAudioMeter *pAudioMeter, QWidget *pParent ) : qtractorMeterScale(pAudioMeter, pParent) { pAudioMeter->boxLayout()->addWidget(this); } // Actual scale drawing method. void qtractorAudioMeterScale::paintScale ( QPainter *p ) { qtractorAudioMeter *pAudioMeter = static_cast (meter()); if (pAudioMeter == NULL) return; // p->setWindow(0, -4, QWidget::width(), QWidget::height() + 8); drawLineLabel(p, pAudioMeter->iec_level(qtractorAudioMeter::Color0dB), "0"); drawLineLabel(p, pAudioMeter->iec_level(qtractorAudioMeter::Color3dB), "3"); drawLineLabel(p, pAudioMeter->iec_level(qtractorAudioMeter::Color6dB), "6"); drawLineLabel(p, pAudioMeter->iec_level(qtractorAudioMeter::Color10dB), "10"); for (float dB = -20.0f; dB > QTRACTOR_AUDIO_METER_MINDB; dB -= 10.0f) drawLineLabel(p, pAudioMeter->iec_scale(dB), QString::number(-int(dB))); } //---------------------------------------------------------------------------- // qtractorAudioMeterValue -- Meter bridge value widget. // Constructor. qtractorAudioMeterValue::qtractorAudioMeterValue ( qtractorAudioMeter *pAudioMeter, unsigned short iChannel, QWidget *pParent ) : QWidget(pParent), m_pAudioMeter(pAudioMeter), m_iChannel(iChannel) { // Avoid intensively annoying repaints... QWidget::setAttribute(Qt::WA_StaticContents); QWidget::setAttribute(Qt::WA_OpaquePaintEvent); m_iValue = 0; m_fValueDecay = QTRACTOR_AUDIO_METER_DECAY_RATE1; m_iPeak = 0; m_iPeakHold = 0; m_fPeakDecay = QTRACTOR_AUDIO_METER_DECAY_RATE2; m_iPeakColor = qtractorAudioMeter::Color6dB; QWidget::setFixedWidth(10); QWidget::setBackgroundRole(QPalette::NoRole); pAudioMeter->boxLayout()->addWidget(this); } // Default destructor. qtractorAudioMeterValue::~qtractorAudioMeterValue (void) { } // Reset peak holder. void qtractorAudioMeterValue::peakReset (void) { m_iPeak = 0; } // Value refreshment. void qtractorAudioMeterValue::refresh (void) { qtractorAudioMonitor *pAudioMonitor = m_pAudioMeter->audioMonitor(); if (pAudioMonitor == NULL) return; float fValue = pAudioMonitor->value(m_iChannel); if (fValue < 0.001f && m_iPeak < 1) return; float dB = QTRACTOR_AUDIO_METER_MINDB; if (fValue > 0.0f) dB = log10f2_opt(fValue); if (dB < QTRACTOR_AUDIO_METER_MINDB) dB = QTRACTOR_AUDIO_METER_MINDB; else if (dB > QTRACTOR_AUDIO_METER_MAXDB) dB = QTRACTOR_AUDIO_METER_MAXDB; int iValue = m_pAudioMeter->iec_scale(dB); if (iValue < m_iValue) { iValue = int(m_fValueDecay * float(m_iValue)); m_fValueDecay *= m_fValueDecay; } else { m_fValueDecay = QTRACTOR_AUDIO_METER_DECAY_RATE1; } int iPeak = m_iPeak; if (iPeak < iValue) { iPeak = iValue; m_iPeakHold = 0; m_fPeakDecay = QTRACTOR_AUDIO_METER_DECAY_RATE2; m_iPeakColor = qtractorAudioMeter::Color10dB; for (; m_iPeakColor > qtractorAudioMeter::ColorOver && iPeak >= m_pAudioMeter->iec_level(m_iPeakColor); --m_iPeakColor) /* empty body loop */; } else if (++m_iPeakHold > m_pAudioMeter->peakFalloff()) { iPeak = int(m_fPeakDecay * float(iPeak)); if (iPeak < iValue) { iPeak = iValue; } else { m_fPeakDecay *= m_fPeakDecay; } } if (iValue == m_iValue && iPeak == m_iPeak) return; m_iValue = iValue; m_iPeak = iPeak; update(); } // Paint event handler. void qtractorAudioMeterValue::paintEvent ( QPaintEvent * ) { QPainter painter(this); int w = QWidget::width(); int h = QWidget::height(); int y; if (isEnabled()) { painter.fillRect(0, 0, w, h, m_pAudioMeter->color(qtractorAudioMeter::ColorBack)); y = m_pAudioMeter->iec_level(qtractorAudioMeter::Color0dB); painter.setPen(m_pAudioMeter->color(qtractorAudioMeter::ColorFore)); painter.drawLine(0, h - y, w, h - y); } else { painter.fillRect(0, 0, w, h, Qt::gray); } #ifdef CONFIG_GRADIENT painter.drawPixmap(0, h - m_iValue, m_pAudioMeter->pixmap(), 0, h - m_iValue, w, m_iValue); #else y = m_iValue; int y_over = 0; int y_curr = 0; for (int i = qtractorAudioMeter::Color10dB; i > qtractorAudioMeter::ColorOver && y >= y_over; --i) { y_curr = m_pAudioMeter->iec_level(i); if (y < y_curr) { painter.fillRect(0, h - y, w, y - y_over, m_pAudioMeter->color(i)); } else { painter.fillRect(0, h - y_curr, w, y_curr - y_over, m_pAudioMeter->color(i)); } y_over = y_curr; } if (y > y_over) { painter.fillRect(0, h - y, w, y - y_over, m_pAudioMeter->color(qtractorAudioMeter::ColorOver)); } #endif painter.setPen(m_pAudioMeter->color(m_iPeakColor)); painter.drawLine(0, h - m_iPeak, w, h - m_iPeak); } // Resize event handler. void qtractorAudioMeterValue::resizeEvent (QResizeEvent *pResizeEvent) { m_iPeak = 0; QWidget::resizeEvent(pResizeEvent); // QWidget::repaint(); } //---------------------------------------------------------------------- // class qtractorAudioMeter::GainSpinBoxInterface -- Observer interface. // // Local converter interface. class qtractorAudioMeter::GainSpinBoxInterface : public qtractorObserverSpinBox::Interface { public: // Constructor. GainSpinBoxInterface ( qtractorObserverSpinBox *pSpinBox ) : qtractorObserverSpinBox::Interface(pSpinBox) {} // Formerly Pure virtuals. float scaleFromValue ( float fValue ) const { return log10f2(fValue); } float valueFromScale ( float fScale ) const { return pow10f2(fScale); } }; //---------------------------------------------------------------------- // class qtractorAudioMeter::GainSliderInterface -- Observer interface. // // Local converter interface. class qtractorAudioMeter::GainSliderInterface : public qtractorObserverSlider::Interface { public: // Constructor. GainSliderInterface ( qtractorObserverSlider *pSlider ) : qtractorObserverSlider::Interface(pSlider) {} // Formerly Pure virtuals. float scaleFromValue ( float fValue ) const { return 10000.0f * IEC_Scale(log10f2(fValue)); } float valueFromScale ( float fScale ) const { return pow10f2(IEC_dB(fScale / 10000.0f)); } }; //---------------------------------------------------------------------------- // qtractorAudioMeter -- Audio meter bridge slot widget. // Constructor. qtractorAudioMeter::qtractorAudioMeter ( qtractorAudioMonitor *pAudioMonitor, QWidget *pParent ) : qtractorMeter(pParent) { m_pAudioMonitor = pAudioMonitor; m_iChannels = 0; m_pAudioScale = new qtractorAudioMeterScale(this/*, boxWidget()*/); m_fScale = 0.0f; m_ppAudioValues = NULL; #ifdef CONFIG_GRADIENT m_pPixmap = new QPixmap(); #endif topWidget()->hide(); gainObserver()->setLogarithmic(true); gainSlider()->setInterface(new GainSliderInterface(gainSlider())); gainSpinBox()->setInterface(new GainSpinBoxInterface(gainSpinBox())); gainSlider()->setMaximum(11500); gainSpinBox()->setMinimum(QTRACTOR_AUDIO_METER_MINDB); gainSpinBox()->setMaximum(QTRACTOR_AUDIO_METER_MAXDB); gainSpinBox()->setToolTip(tr("Gain (dB)")); gainSpinBox()->setSuffix(tr(" dB")); setPeakFalloff(QTRACTOR_AUDIO_METER_PEAK_FALLOFF); for (int i = 0; i < LevelCount; ++i) m_levels[i] = 0; reset(); updatePanning(); updateGain(); } // Default destructor. qtractorAudioMeter::~qtractorAudioMeter (void) { #ifdef CONFIG_GRADIENT delete m_pPixmap; #endif // No need to delete child widgets, Qt does it all for us for (unsigned short i = 0; i < m_iChannels; ++i) delete m_ppAudioValues[i]; delete [] m_ppAudioValues; delete m_pAudioScale; } // IEC standard int qtractorAudioMeter::iec_scale ( float dB ) const { return int(m_fScale * IEC_Scale(dB)); } int qtractorAudioMeter::iec_level ( int iIndex ) const { return m_levels[iIndex]; } // Audio monitor reset void qtractorAudioMeter::reset (void) { if (m_pAudioMonitor == NULL) return; setPanningSubject(m_pAudioMonitor->panningSubject()); setGainSubject(m_pAudioMonitor->gainSubject()); unsigned short iChannels = m_pAudioMonitor->channels(); if (m_iChannels == iChannels) return; if (m_ppAudioValues) { for (unsigned short i = 0; i < m_iChannels; ++i) delete m_ppAudioValues[i]; delete [] m_ppAudioValues; m_ppAudioValues = NULL; } m_iChannels = iChannels; if (m_iChannels > 0) { m_ppAudioValues = new qtractorAudioMeterValue *[m_iChannels]; for (unsigned short i = 0; i < m_iChannels; ++i) { m_ppAudioValues[i] = new qtractorAudioMeterValue(this, i); m_ppAudioValues[i]->show(); } } panSlider()->setEnabled(m_iChannels > 1); panSpinBox()->setEnabled(m_iChannels > 1); } // Reset peak holder. void qtractorAudioMeter::peakReset (void) { for (unsigned short i = 0; i < m_iChannels; ++i) m_ppAudioValues[i]->peakReset(); } #ifdef CONFIG_GRADIENT // Gradient pixmap accessor. const QPixmap& qtractorAudioMeter::pixmap (void) const { return *m_pPixmap; } void qtractorAudioMeter::updatePixmap (void) { int w = boxWidget()->width(); int h = boxWidget()->height(); QLinearGradient grad(0, 0, 0, h); grad.setColorAt(0.1f, color(ColorOver)); grad.setColorAt(0.2f, color(Color0dB)); grad.setColorAt(0.3f, color(Color3dB)); grad.setColorAt(0.4f, color(Color6dB)); grad.setColorAt(0.8f, color(Color10dB)); *m_pPixmap = QPixmap(w, h); QPainter(m_pPixmap).fillRect(0, 0, w, h, grad); } #endif // Slot refreshment. void qtractorAudioMeter::refresh (void) { for (unsigned short i = 0; i < m_iChannels; ++i) m_ppAudioValues[i]->refresh(); } // Resize event handler. void qtractorAudioMeter::resizeEvent ( QResizeEvent * ) { m_fScale = 0.85f * float(boxWidget()->height()); m_levels[Color0dB] = iec_scale( 0.0f); m_levels[Color3dB] = iec_scale( -3.0f); m_levels[Color6dB] = iec_scale( -6.0f); m_levels[Color10dB] = iec_scale(-10.0f); #ifdef CONFIG_GRADIENT updatePixmap(); #endif } // Virtual monitor accessor. void qtractorAudioMeter::setMonitor ( qtractorMonitor *pMonitor ) { setAudioMonitor(static_cast (pMonitor)); } qtractorMonitor *qtractorAudioMeter::monitor (void) const { return audioMonitor(); } // Audio monitor accessor. void qtractorAudioMeter::setAudioMonitor ( qtractorAudioMonitor *pAudioMonitor ) { m_pAudioMonitor = pAudioMonitor; reset(); } qtractorAudioMonitor *qtractorAudioMeter::audioMonitor (void) const { return m_pAudioMonitor; } // Common resource accessor (static). void qtractorAudioMeter::setColor ( int iIndex, const QColor& color ) { g_currentColors[iIndex] = color; } const QColor& qtractorAudioMeter::color ( int iIndex ) { return g_currentColors[iIndex]; } const QColor& qtractorAudioMeter::defaultColor ( int iIndex ) { return g_defaultColors[iIndex]; } // Pan-slider value change method. void qtractorAudioMeter::updatePanning (void) { // setPanning(m_pAudioMonitor->panning()); panSlider()->setToolTip( tr("Pan: %1").arg(panning(), 0, 'g', 2)); } // Gain-slider value change method. void qtractorAudioMeter::updateGain (void) { // setGain(m_pAudioMonitor->gain()); gainSlider()->setToolTip( tr("Gain: %1 dB").arg(gainSpinBox()->value(), 0, 'g', 3)); } // end of qtractorAudioMeter.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditor.cpp0000644000175000001440000000012312207130265021556 xustar000000000000000027 mtime=1377611957.072697 26 atime=1381134667.24308 30 ctime=1381134667.244080053 qtractor-0.5.11/src/qtractorMidiEditor.cpp0000644000175000001440000041015412207130265021052 0ustar00rncbcusers00000000000000// qtractorMidiEditor.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiEditor.h" #include "qtractorMidiEditList.h" #include "qtractorMidiEditTime.h" #include "qtractorMidiEditView.h" #include "qtractorMidiEditEvent.h" #include "qtractorMidiEditCommand.h" #include "qtractorMidiEngine.h" #include "qtractorMidiClip.h" #include "qtractorMidiToolsForm.h" #include "qtractorInstrument.h" #include "qtractorRubberBand.h" #include "qtractorTimeScale.h" #include "qtractorSession.h" #include #include #include #include #include #include #include #include #include #include #include #include // Translatable macro contextualizer. #undef _TR #define _TR(x) QT_TR_NOOP(x) //---------------------------------------------------------------------------- // MIDI Note Names - Default note names hash map. static struct { unsigned char note; const char *name; } g_aNoteNames[] = { // Diatonic note map... { 0, _TR("C") }, { 1, _TR("C#/Db") }, { 2, _TR("D") }, { 3, _TR("D#/Eb") }, { 4, _TR("E") }, { 5, _TR("F") }, { 6, _TR("F#/Gb") }, { 7, _TR("G") }, { 8, _TR("G#/Ab") }, { 9, _TR("A") }, { 10, _TR("A#/Bb") }, { 11, _TR("B") }, // GM Drum note map... { 35, _TR("Acoustic Bass Drum") }, { 36, _TR("Bass Drum 1") }, { 37, _TR("Side Stick") }, { 38, _TR("Acoustic Snare") }, { 39, _TR("Hand Clap") }, { 40, _TR("Electric Snare") }, { 41, _TR("Low Floor Tom") }, { 42, _TR("Closed Hi-Hat") }, { 43, _TR("High Floor Tom") }, { 44, _TR("Pedal Hi-Hat") }, { 45, _TR("Low Tom") }, { 46, _TR("Open Hi-Hat") }, { 47, _TR("Low-Mid Tom") }, { 48, _TR("Hi-Mid Tom") }, { 49, _TR("Crash Cymbal 1") }, { 50, _TR("High Tom") }, { 51, _TR("Ride Cymbal 1") }, { 52, _TR("Chinese Cymbal") }, { 53, _TR("Ride Bell") }, { 54, _TR("Tambourine") }, { 55, _TR("Splash Cymbal") }, { 56, _TR("Cowbell") }, { 57, _TR("Crash Cymbal 2") }, { 58, _TR("Vibraslap") }, { 59, _TR("Ride Cymbal 2") }, { 60, _TR("Hi Bongo") }, { 61, _TR("Low Bongo") }, { 62, _TR("Mute Hi Conga") }, { 63, _TR("Open Hi Conga") }, { 64, _TR("Low Conga") }, { 65, _TR("High Timbale") }, { 66, _TR("Low Timbale") }, { 67, _TR("High Agogo") }, { 68, _TR("Low Agogo") }, { 69, _TR("Cabasa") }, { 70, _TR("Maracas") }, { 71, _TR("Short Whistle") }, { 72, _TR("Long Whistle") }, { 73, _TR("Short Guiro") }, { 74, _TR("Long Guiro") }, { 75, _TR("Claves") }, { 76, _TR("Hi Wood Block") }, { 77, _TR("Low Wood Block") }, { 78, _TR("Mute Cuica") }, { 79, _TR("Open Cuica") }, { 80, _TR("Mute Triangle") }, { 81, _TR("Open Triangle") }, { 0, NULL } }; static QHash g_noteNames; // Default note name map accessor. const QString qtractorMidiEditor::defaultNoteName ( unsigned char note, bool fDrums ) { if (fDrums) { // Pre-load drum-names hash table... if (g_noteNames.isEmpty()) { for (int i = 12; g_aNoteNames[i].name; ++i) { g_noteNames.insert(g_aNoteNames[i].note, QObject::tr(g_aNoteNames[i].name, "noteName")); } } // Check whether the drum note exists... QHash::ConstIterator iter = g_noteNames.constFind(note); if (iter != g_noteNames.constEnd()) return iter.value(); } return QObject::tr(g_aNoteNames[note % 12].name, "noteName") + QString::number((note / 12) - 1); } //---------------------------------------------------------------------------- // MIDI Controller Names - Default controller names hash map. static struct { unsigned char controller; const char *name; } g_aControllerNames[] = { { 0, _TR("Bank Select (coarse)") }, { 1, _TR("Modulation Wheel (coarse)") }, { 2, _TR("Breath Controller (coarse)") }, { 4, _TR("Foot Pedal (coarse)") }, { 5, _TR("Portamento Time (coarse)") }, { 6, _TR("Data Entry (coarse)") }, { 7, _TR("Volume (coarse)") }, { 8, _TR("Balance (coarse)") }, { 10, _TR("Pan Position (coarse)") }, { 11, _TR("Expression (coarse)") }, { 12, _TR("Effect Control 1 (coarse)") }, { 13, _TR("Effect Control 2 (coarse)") }, { 16, _TR("General Purpose Slider 1") }, { 17, _TR("General Purpose Slider 2") }, { 18, _TR("General Purpose Slider 3") }, { 19, _TR("General Purpose Slider 4") }, { 32, _TR("Bank Select (fine)") }, { 33, _TR("Modulation Wheel (fine)") }, { 34, _TR("Breath Controller (fine)") }, { 36, _TR("Foot Pedal (fine)") }, { 37, _TR("Portamento Time (fine)") }, { 38, _TR("Data Entry (fine)") }, { 39, _TR("Volume (fine)") }, { 40, _TR("Balance (fine)") }, { 42, _TR("Pan Position (fine)") }, { 43, _TR("Expression (fine)") }, { 44, _TR("Effect Control 1 (fine)") }, { 45, _TR("Effect Control 2 (fine)") }, { 64, _TR("Hold Pedal (on/off)") }, { 65, _TR("Portamento (on/off)") }, { 66, _TR("Sustenuto Pedal (on/off)") }, { 67, _TR("Soft Pedal (on/off)") }, { 68, _TR("Legato Pedal (on/off)") }, { 69, _TR("Hold 2 Pedal (on/off)") }, { 70, _TR("Sound Variation") }, { 71, _TR("Sound Timbre") }, { 72, _TR("Sound Release Time") }, { 73, _TR("Sound Attack Time") }, { 74, _TR("Sound Brightness") }, { 75, _TR("Sound Control 6") }, { 76, _TR("Sound Control 7") }, { 77, _TR("Sound Control 8") }, { 78, _TR("Sound Control 9") }, { 79, _TR("Sound Control 10") }, { 80, _TR("General Purpose Button 1 (on/off)") }, { 81, _TR("General Purpose Button 2 (on/off)") }, { 82, _TR("General Purpose Button 3 (on/off)") }, { 83, _TR("General Purpose Button 4 (on/off)") }, { 91, _TR("Effects Level") }, { 92, _TR("Tremulo Level") }, { 93, _TR("Chorus Level") }, { 94, _TR("Celeste Level") }, { 95, _TR("Phaser Level") }, { 96, _TR("Data Button Increment") }, { 97, _TR("Data Button Decrement") }, { 98, _TR("Non-Registered Parameter (fine)") }, { 99, _TR("Non-Registered Parameter (coarse)") }, {100, _TR("Registered Parameter (fine)") }, {101, _TR("Registered Parameter (coarse)") }, {120, _TR("All Sound Off") }, {121, _TR("All Controllers Off") }, {122, _TR("Local Keyboard (on/off)") }, {123, _TR("All Notes Off") }, {124, _TR("Omni Mode Off") }, {125, _TR("Omni Mode On") }, {126, _TR("Mono Operation") }, {127, _TR("Poly Operation") }, { 0, NULL } }; static QHash g_controllerNames; // Default controller name accessor. const QString& qtractorMidiEditor::defaultControllerName ( unsigned char controller ) { if (g_controllerNames.isEmpty()) { // Pre-load controller-names hash table... for (int i = 0; g_aControllerNames[i].name; ++i) { g_controllerNames.insert(g_aControllerNames[i].controller, QObject::tr(g_aControllerNames[i].name, "controllerName")); } } return g_controllerNames[controller]; } //---------------------------------------------------------------------------- // MIDI Scale Names - Default scale names table. static struct { const char *name; unsigned char note[12]; } g_aScaleTab[] = { { _TR("Chromatic"), { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 } }, { _TR("Major"), { 0, 0, 2, 2, 4, 5, 5, 7, 7, 9, 9,11 } }, { _TR("Minor"), { 0, 0, 2, 3, 3, 5, 5, 7, 8, 8, 8,11 } }, { _TR("Melodic Minor (Asc)"), { 0, 0, 2, 3, 3, 5, 5, 7, 7, 9, 9,11 } }, { _TR("Melodic Minor (Desc)"), { 0, 0, 2, 3, 3, 5, 5, 7, 8, 8,10,10 } }, { _TR("Whole Tone"), { 0, 0, 2, 2, 4, 4, 6, 6, 8, 8,10,10 } }, { _TR("Pentatonic Major"), { 0, 0, 2, 2, 4, 4, 4, 7, 7, 9, 9, 9 } }, { _TR("Pentatonic Minor"), { 0, 0, 0, 3, 3, 5, 5, 7, 7, 7,10,10 } }, { _TR("Pentatonic Blues"), { 0, 0, 0, 3, 3, 5, 6, 7, 7, 7,10,10 } }, { _TR("Pentatonic Neutral"), { 0, 0, 2, 2, 2, 5, 5, 7, 7, 7,10,10 } }, { _TR("Octatonic (H-W)"), { 0, 1, 1, 3, 4, 4, 6, 7, 7, 9,10,10 } }, { _TR("Octatonic (W-H)"), { 0, 0, 2, 3, 3, 5, 6, 6, 8, 9, 9,11 } }, { _TR("Ionian"), { 0, 0, 2, 2, 4, 5, 5, 7, 7, 9, 9,11 } }, // identical to "Major" { _TR("Dorian"), { 0, 0, 2, 3, 3, 5, 5, 7, 7, 9,10,10 } }, { _TR("Phrygian"), { 0, 1, 1, 3, 3, 5, 5, 7, 8, 8,10,10 } }, { _TR("Lydian"), { 0, 0, 2, 2, 4, 4, 6, 7, 7, 9, 9,11 } }, { _TR("Mixolydian"), { 0, 0, 2, 2, 4, 5, 5, 7, 7, 9,10,10 } }, { _TR("Aeolian"), { 0, 0, 2, 3, 3, 5, 5, 7, 8, 8,10,10 } }, // identical to "Melodic Minor (Descending)" { _TR("Locrian"), { 0, 1, 1, 3, 3, 5, 6, 6, 8, 8,10,10 } }, { _TR("Egyptian"), { 0, 0, 2, 2, 2, 5, 5, 7, 7, 7,10,10 } }, // identical to "Pentatonic Neutral" { _TR("Eight Tone Spanish"), { 0, 1, 1, 3, 4, 5, 6, 6, 6, 6,10,10 } }, { _TR("Hawaiian"), { 0, 0, 2, 3, 3, 5, 5, 7, 7, 9, 9,11 } }, // identical to "Melodic Minor (Ascending)" { _TR("Hindu"), { 0, 0, 2, 2, 4, 5, 5, 7, 8, 8,10,10 } }, { _TR("Hirajoshi"), { 0, 0, 2, 3, 3, 3, 3, 7, 8, 8, 8, 8 } }, { _TR("Hungarian Major"), { 0, 0, 0, 3, 4, 4, 6, 7, 7, 9,10,10 } }, { _TR("Hungarian Minor"), { 0, 0, 2, 3, 3, 3, 6, 7, 8, 8, 8,11 } }, { _TR("Hungarian Gypsy"), { 0, 1, 1, 1, 4, 5, 5, 7, 8, 8, 8,11 } }, { _TR("Japanese (A)"), { 0, 1, 1, 1, 1, 5, 5, 7, 8, 8, 8, 8 } }, { _TR("Japanese (B)"), { 0, 0, 2, 2, 2, 5, 5, 7, 8, 8, 8, 8 } }, { _TR("Jewish (Adonai Malakh)"), { 0, 1, 2, 3, 3, 5, 5, 7, 7, 9,10,10 } }, { _TR("Jewish (Ahaba Rabba)"), { 0, 1, 1, 1, 4, 5, 5, 7, 8, 8,10,10 } }, { _TR("Jewish (Magen Abot)"), { 0, 1, 1, 3, 4, 4, 6, 6, 8, 8,10,11 } }, { _TR("Oriental (A)"), { 0, 1, 1, 1, 4, 5, 6, 6, 8, 8,10,10 } }, { _TR("Oriental (B)"), { 0, 1, 1, 1, 1, 1, 6, 6, 6, 9,10,10 } }, { _TR("Oriental (C)"), { 0, 1, 1, 1, 4, 5, 6, 6, 6, 9,10,10 } }, { _TR("Roumanian Minor"), { 0, 0, 2, 3, 3, 3, 6, 7, 7, 9,10,10 } }, { _TR("Neapolitan"), { 0, 1, 1, 3, 3, 5, 5, 7, 8, 8, 8,11 } }, { _TR("Neapolitan Major"), { 0, 1, 1, 3, 3, 5, 5, 7, 7, 9, 9,11 } }, { _TR("Neapolitan Minor"), { 0, 1, 1, 1, 1, 5, 5, 7, 8, 8,10,10 } }, // { _TR("Mohammedan"), { 0, 0, 2, 3, 3, 5, 5, 7, 8, 8, 8,11 } }, // identical to "Harmonic Minor" { _TR("Overtone"), { 0, 0, 2, 2, 4, 4, 6, 7, 7, 9,10,10 } }, // { _TR("Diatonic"), { 0, 0, 2, 2, 4, 4, 4, 7, 7, 9, 9, 9 } }, // identical to "Pentatonic Major" // { _TR("Double Harmonic"), { 0, 1, 1, 1, 4, 5, 5, 7, 8, 8, 8,11 } }, // identical to "Hungarian Gypsy Persian" { _TR("Eight Tone Spanish"), { 0, 1, 1, 3, 4, 5, 6, 6, 8, 8,10,10 } }, { _TR("Leading Whole Tone"), { 0, 0, 2, 2, 4, 4, 6, 6, 8, 8,10,11 } }, { _TR("Nine Tone Scale"), { 0, 0, 2, 3, 4, 4, 6, 7, 8, 9, 9,11 } }, { _TR("Dominant Seventh"), { 0, 0, 2, 2, 2, 5, 5, 7, 7, 9,10,10 } }, { _TR("Augmented"), { 0, 0, 0, 3, 4, 4, 4, 7, 8, 8, 8,11 } }, { _TR("Algerian"), { 0, 0, 2, 3, 3, 5, 6, 7, 8, 8, 8,11 } }, { _TR("Arabian (A)"), { 0, 0, 2, 3, 3, 5, 6, 6, 8, 9, 9,11 } }, // identical to "Octatonic (W-H)" { _TR("Arabian (B)"), { 0, 0, 2, 2, 4, 5, 6, 6, 8, 8,10,10 } }, // { _TR("Asavari Theta"), { 0, 0, 2, 3, 3, 5, 5, 7, 8, 8,10,10 } }, // identical to "Melodic Minor (Descending)" { _TR("Balinese"), { 0, 1, 1, 3, 3, 3, 3, 7, 8, 8, 8, 8 } }, // { _TR("Bilaval Theta"), { 0, 0, 2, 2, 4, 5, 5, 7, 7, 9, 9,11 } }, // identical to "Major" // { _TR("Bhairav Theta"), { 0, 1, 1, 1, 4, 5, 5, 7, 8, 8, 8,11 } }, // identical to "Hungarian Gypsy Persian" // { _TR("Bhairavi Theta"), { 0, 1, 1, 3, 3, 5, 5, 7, 8, 8,10,10 } }, // identical to "Phrygian" // { _TR("Byzantine"), { 0, 1, 1, 1, 4, 5, 5, 7, 8, 8, 8,11 } }, // identical to "Hungarian Gypsy Persian" { _TR("Chinese"), { 0, 0, 0, 0, 4, 4, 6, 7, 7, 7, 7,11 } }, // { _TR("Chinese Mongolian"), { 0, 0, 2, 2, 4, 4, 4, 7, 7, 9, 9, 9 } }, // identical to "Pentatonic Major" { _TR("Diminished"), { 0, 0, 2, 3, 3, 5, 6, 6, 8, 9, 9,11 } }, // identical to "Octatonic (W-H)" // { _TR("Egyptian"), { 0, 0, 2, 2, 2, 5, 5, 7, 7, 7,10,10 } }, // identical to "Pentatonic Neutral" // { _TR("Ethiopian (A Raray)"), { 0, 0, 2, 2, 4, 5, 5, 7, 7, 9, 9,11 } }, // identical to "Major" // { _TR("Ethiopian (Geez & Ezel)"),{ 0, 0, 2, 3, 3, 5, 5, 7, 8, 8,10,10 } }, // identical to "Melodic Minor (Descending)" // { _TR("Hawaiian"), { 0, 0, 2, 3, 3, 5, 5, 7, 7, 9, 9,11 } }, // identical to "Melodic Minor (Ascending)" // { _TR("Hindustan"), { 0, 0, 2, 2, 4, 5, 5, 7, 8, 8,10,10 } }, // identical to "Hindu" { _TR("Japanese (Ichikosucho)"), { 0, 0, 2, 2, 4, 5, 6, 7, 7, 9, 9,11 } }, { _TR("Japanese (Taishikicho)"), { 0, 0, 2, 2, 4, 5, 6, 7, 7, 9,10,11 } }, { _TR("Javaneese"), { 0, 1, 1, 3, 3, 5, 5, 7, 7, 9,10,10 } }, // { _TR("Kafi Theta"), { 0, 0, 2, 3, 3, 5, 5, 7, 7, 9,10,10 } }, // identical to "Dorian" // { _TR("Kalyan Theta"), { 0, 0, 2, 2, 4, 4, 6, 7, 7, 9, 9,11 } }, // identical to "Lydian" // { _TR("Khamaj Theta"), { 0, 0, 2, 2, 4, 5, 5, 7, 7, 9,10,10 } }, // identical to "Mixolydian" // { _TR("Madelynian"), { 0, 1, 1, 3, 3, 5, 6, 6, 8, 8,10,10 } }, // identical to "Locrian" { _TR("Marva Theta"), { 0, 1, 1, 1, 4, 4, 6, 7, 7, 9, 9,11 } }, #ifdef QTRACTOR_MELA_SCALES { _TR("Mela Bhavapriya"), { 0, 1, 2, 2, 2, 5, 5, 7, 8, 9, 9, 9 } }, { _TR("Mela Chakravakam"), { 0, 1, 1, 1, 4, 5, 5, 7, 7, 9,10,10 } }, { _TR("Mela Chalanata"), { 0, 0, 0, 3, 4, 5, 5, 7, 7, 7,10,11 } }, // { _TR("Mela Charukesi"), { 0, 0, 2, 2, 4, 5, 5, 7, 8, 8,10,10 } }, // identical to "Hindu" { _TR("Mela Chitrambari"), { 0, 0, 2, 2, 4, 4, 6, 7, 7, 7,10,11 } }, { _TR("Mela Dharmavati"), { 0, 0, 2, 3, 3, 3, 6, 7, 7, 9, 9,11 } }, { _TR("Mela Dhatuvardhani"), { 0, 0, 0, 3, 4, 4, 6, 7, 8, 8, 8,11 } }, { _TR("Mela Dhavalambari"), { 0, 1, 1, 1, 4, 4, 6, 7, 8, 9, 9, 9 } }, // { _TR("Mela Dhenuka"), { 0, 1, 1, 3, 3, 5, 5, 7, 8, 8, 8,11 } }, // identical to "Neapolitan" // { _TR("Mela Dhirasankarabharana"),{0, 0, 2, 2, 4, 5, 5, 7, 7, 9, 9,11 } }, // identical to "Major" { _TR("Mela Divyamani"), { 0, 1, 1, 1, 4, 4, 6, 7, 7, 7,10,11 } }, // { _TR("Mela Gamanasrama"), { 0, 1, 1, 1, 4, 4, 6, 7, 7, 9, 9,11 } }, // identical to "Marva Theta" { _TR("Mela Ganamurti"), { 0, 1, 2, 2, 2, 5, 5, 7, 8, 8, 8,11 } }, { _TR("Mela Gangeyabhusani"), { 0, 0, 0, 3, 4, 5, 5, 7, 8, 8, 8,11 } }, // { _TR("Mela Gaurimanohari"), { 0, 0, 2, 3, 3, 5, 5, 7, 7, 9, 9,11 } }, // identical to "Melodic Minor (Ascending)" { _TR("Mela Gavambodhi"), { 0, 1, 1, 3, 3, 3, 6, 7, 8, 9, 9, 9 } }, { _TR("Mela Gayakapriya"), { 0, 1, 1, 1, 4, 5, 5, 7, 8, 9, 9, 9 } }, // { _TR("Mela Hanumattodi"), { 0, 1, 1, 3, 3, 5, 5, 7, 8, 8,10,10 } }, // identical to "Phrygian" // { _TR("Mela Harikambhoji"), { 0, 0, 2, 2, 4, 5, 5, 7, 7, 9,10,10 } }, // identical to "Mixolydian" { _TR("Mela Hatakambari"), { 0, 1, 1, 1, 4, 5, 5, 7, 7, 7,10,11 } }, // { _TR("Mela Hemavati"), { 0, 0, 2, 3, 3, 3, 6, 7, 7, 9,10,10 } }, // identical to "Roumanian Minor" { _TR("Mela Jalarnavam"), { 0, 1, 2, 2, 2, 2, 6, 7, 8, 8,10,10 } }, { _TR("Mela Jhalavarali"), { 0, 1, 2, 2, 2, 2, 6, 7, 8, 8, 8,11 } }, { _TR("Mela Jhankaradhvani"), { 0, 0, 2, 3, 3, 5, 5, 7, 8, 9, 9, 9 } }, { _TR("Mela Jyotisvarupini"), { 0, 0, 0, 3, 4, 4, 6, 7, 8, 8,10,10 } }, { _TR("Mela Kamavarardhani"), { 0, 1, 1, 1, 4, 4, 6, 7, 8, 8, 8,11 } }, // { _TR("Mela Kanakangi"), { 0, 1, 2, 2, 2, 5, 5, 7, 8, 9, 9, 9 } }, // identical to "Mela Bhavapriya" { _TR("Mela Kantamani"), { 0, 0, 2, 2, 4, 4, 6, 7, 8, 9, 9, 9 } }, // { _TR("Mela Kharaharapriya"), { 0, 0, 2, 3, 3, 5, 5, 7, 7, 9,10,10 } }, // identical to "Dorian" // { _TR("Mela Kiravani"), { 0, 0, 2, 3, 3, 5, 5, 7, 8, 8, 8,11 } }, // identical to "Harmonic Minor" // { _TR("Mela Kokilapriya"), { 0, 1, 1, 3, 3, 5, 5, 7, 7, 9, 9,11 } }, // identical to "Neapolitan Major" { _TR("Mela Kosalam"), { 0, 0, 0, 3, 4, 4, 6, 7, 7, 9, 9,11 } }, { _TR("Mela Latangi"), { 0, 0, 2, 2, 4, 4, 6, 7, 8, 8, 8,11 } }, { _TR("Mela Manavati"), { 0, 1, 2, 2, 2, 5, 5, 7, 7, 9, 9,11 } }, { _TR("Mela Mararanjani"), { 0, 0, 2, 2, 4, 5, 5, 7, 8, 9, 9, 9 } }, // { _TR("Mela Mayamalavagaula"), { 0, 1, 1, 1, 4, 5, 5, 7, 8, 8, 8,11 } }, // identical to "Hungarian Gypsy Persian" // { _TR("Mela Mechakalyani"), { 0, 0, 2, 2, 4, 4, 6, 7, 7, 9, 9,11 } }, // identical to "Lydian" { _TR("Mela Naganandini"), { 0, 0, 2, 2, 4, 5, 5, 7, 7, 7,10,11 } }, { _TR("Mela Namanarayani"), { 0, 1, 1, 1, 4, 4, 6, 7, 8, 8,10,10 } }, // { _TR("Mela Nasikabhusani"), { 0, 0, 0, 3, 4, 4, 6, 7, 7, 9,10,10 } }, // identical to "Hungarian Major" // { _TR("Mela Natabhairavi"), { 0, 0, 2, 3, 3, 5, 5, 7, 8, 8,10,10 } }, // identical to "Melodic Minor (Descending)" // { _TR("Mela Natakapriya"), { 0, 1, 1, 3, 3, 5, 5, 7, 7, 9,10,10 } }, // identical to "Javaneese" { _TR("Mela Navanitam"), { 0, 1, 2, 2, 2, 2, 6, 7, 7, 9,10,10 } }, { _TR("Mela Nitimati"), { 0, 0, 2, 3, 3, 3, 6, 7, 7, 7,10,11 } }, { _TR("Mela Pavani"), { 0, 1, 2, 2, 2, 2, 6, 7, 7, 9, 9,11 } }, { _TR("Mela Ragavardhani"), { 0, 0, 0, 3, 4, 5, 5, 7, 8, 8,10,10 } }, { _TR("Mela Raghupriya"), { 0, 1, 2, 2, 2, 2, 6, 7, 7, 7,10,11 } }, { _TR("Mela Ramapriya"), { 0, 1, 1, 1, 4, 4, 6, 7, 7, 9,10,10 } }, { _TR("Mela Rasikapriya"), { 0, 0, 0, 3, 4, 4, 6, 7, 7, 7,10,11 } }, { _TR("Mela Ratnangi"), { 0, 1, 2, 2, 2, 5, 5, 7, 8, 8,10,10 } }, { _TR("Mela Risabhapriya"), { 0, 0, 2, 2, 4, 4, 6, 7, 8, 8,10,10 } }, { _TR("Mela Rupavati"), { 0, 1, 1, 3, 3, 5, 5, 7, 7, 7,10,11 } }, { _TR("Mela Sadvidhamargini"), { 0, 1, 1, 3, 3, 3, 6, 7, 7, 9,10,10 } }, { _TR("Mela Salagam"), { 0, 1, 2, 2, 2, 2, 6, 7, 8, 9, 9, 9 } }, { _TR("Mela Sanmukhapriya"), { 0, 0, 2, 3, 3, 3, 6, 7, 8, 8,10,10 } }, { _TR("Mela Sarasangi"), { 0, 0, 2, 2, 4, 5, 5, 7, 8, 8, 8,11 } }, { _TR("Mela Senavati"), { 0, 1, 1, 3, 3, 5, 5, 7, 8, 9, 9, 9 } }, // { _TR("Mela Simhendramadhyama"), { 0, 0, 2, 3, 3, 3, 6, 7, 8, 8, 8,11 } }, // identical to "Hungarian Minor" { _TR("Mela Subhapantuvarali"), { 0, 1, 1, 3, 3, 3, 6, 7, 8, 8, 8,11 } }, { _TR("Mela Sucharitra"), { 0, 0, 0, 3, 4, 4, 6, 7, 8, 9, 9, 9 } }, { _TR("Mela Sulini"), { 0, 0, 0, 3, 4, 5, 5, 7, 7, 9, 9,11 } }, { _TR("Mela Suryakantam"), { 0, 1, 1, 1, 4, 5, 5, 7, 7, 9, 9,11 } }, // { _TR("Mela Suvarnangi"), { 0, 1, 2, 2, 2, 2, 6, 7, 7, 9, 9,11 } }, // identical to "Mela Pavani" { _TR("Mela Syamalangi"), { 0, 0, 2, 3, 3, 3, 6, 7, 8, 9, 9, 9 } }, { _TR("Mela Tanarupi"), { 0, 1, 2, 2, 2, 5, 5, 7, 7, 7,10,11 } }, // { _TR("Mela Vaschaspati"), { 0, 0, 2, 2, 4, 4, 6, 7, 7, 9,10,10 } }, // identical to "Overtone" { _TR("Mela Vagadhisvari"), { 0, 0, 0, 3, 4, 5, 5, 7, 7, 9,10,10 } }, // { _TR("Mela Vakulabharanam"), { 0, 1, 1, 1, 4, 5, 5, 7, 8, 8,10,10 } }, // identical to "Jewish (Ahaba Rabba)" { _TR("Mela Vanaspati"), { 0, 1, 2, 2, 2, 5, 5, 7, 7, 9,10,10 } }, { _TR("Mela Varunapriya"), { 0, 0, 2, 3, 3, 5, 5, 7, 7, 7,10,11 } }, // { _TR("Mela Visvambari"), { 0, 1, 1, 1, 4, 4, 6, 7, 7, 7,10,11 } }, // identical to "Mela Divyamani" { _TR("Mela Yagapriya"), { 0, 0, 0, 3, 4, 5, 5, 7, 8, 9, 9, 9 } }, #endif // QTRACTOR_MELA_SCALES // { _TR("Mohammedan"), { 0, 0, 2, 3, 3, 5, 5, 7, 8, 8, 8,11 } }, // identical to "Harmonic Minor" { _TR("Persian"), { 0, 1, 1, 1, 4, 5, 6, 6, 8, 8, 8,11 } }, { _TR("Purvi Theta"), { 0, 1, 1, 1, 4, 4, 6, 7, 8, 8, 8,11 } }, // identical to "Mela Kamavarardhani" { _TR("Spanish Gypsy"), { 0, 1, 1, 1, 4, 5, 5, 7, 8, 8,10,10 } }, // identical to "Jewish (Ahaba Rabba)" { _TR("Todi Theta"), { 0, 1, 1, 3, 3, 3, 6, 7, 8, 8, 8,11 } }, // identical to "Mela Subhapantuvarali" // { _TR("Aux Diminished"), { 0, 0, 2, 3, 3, 5, 6, 6, 8, 9, 9,11 } }, // identical to "Octatonic (W-H)" // { _TR("Aux Augmented"), { 0, 0, 2, 2, 4, 4, 6, 6, 8, 8,10,10 } }, // identical to "Whole Tone" // { _TR("Aux Diminished Blues"), { 0, 1, 1, 3, 4, 4, 6, 7, 7, 9,10,10 } }, // identical to "Octatonic (H-W)" { _TR("Enigmatic"), { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8,10,11 } }, { _TR("Kumoi"), { 0, 0, 2, 3, 3, 3, 3, 7, 7, 9, 9, 9 } }, { _TR("Lydian Augmented"), { 0, 0, 2, 2, 4, 4, 6, 6, 8, 9, 9,11 } }, { _TR("Pelog"), { 0, 1, 1, 3, 3, 3, 3, 7, 8, 8, 8, 8 } }, // identical to "Balinese" { _TR("Prometheus"), { 0, 0, 2, 2, 4, 4, 6, 6, 6, 9,10,10 } }, { _TR("Prometheus Neapolitan"), { 0, 1, 1, 1, 4, 4, 6, 6, 6, 9,10,10 } }, { _TR("Six Tone Symmetrical"), { 0, 1, 1, 1, 4, 5, 5, 5, 8, 9, 9, 9 } }, { _TR("Super Locrian"), { 0, 1, 1, 3, 4, 4, 6, 6, 8, 8,10,10 } }, { _TR("Lydian Minor"), { 0, 0, 2, 2, 4, 4, 6, 7, 8, 8,10,10 } }, // identical to "Mela Risabhapriya" { _TR("Lydian Diminished"), { 0, 0, 2, 3, 3, 3, 6, 7, 7, 9, 9,11 } }, // identical to "Mela Dharmavati" // { _TR("Major Locrian"), { 0, 0, 2, 2, 4, 5, 6, 6, 8, 8,10,10 } }, // identical to "Arabian (B)" // { _TR("Hindu"), { 0, 0, 2, 2, 4, 5, 5, 7, 8, 8,10,10 } }, // identical to "Hindu" // { _TR("Diminished Whole Tone"), { 0, 1, 1, 3, 4, 4, 6, 6, 8, 8,10,10 } }, // identical to "Super Locrian" { _TR("Half Diminished"), { 0, 0, 2, 3, 3, 5, 6, 6, 8, 8,10,10 } }, { _TR("Bhairav"), { 0, 1, 1, 1, 4, 5, 5, 7, 8, 8, 8,11 } }, // identical to "Hungarian Gypsy Persian" { _TR("Yaman"), { 0, 0, 2, 2, 4, 4, 6, 7, 7, 9, 9,11 } }, // identical to "Lydian" { _TR("Todi"), { 0, 1, 1, 3, 3, 5, 5, 7, 8, 8,10,10 } }, // identical to "Phrygian" { _TR("Jog"), { 0, 0, 0, 3, 4, 5, 5, 7, 7, 7,10,10 } }, { _TR("Multani"), { 0, 1, 1, 3, 3, 3, 6, 7, 8, 8, 8,11 } }, // identical to "Mela Subhapantuvarali" { _TR("Darbari"), { 0, 0, 2, 3, 3, 5, 5, 7, 8, 8,10,10 } }, // identical to "Melodic Minor (Descending)" { _TR("Malkauns"), { 0, 0, 0, 3, 3, 5, 5, 5, 8, 8,10,10 } }, { _TR("Bhoopali"), { 0, 0, 2, 2, 4, 4, 4, 7, 7, 9, 9, 9 } }, // identical to "Pentatonic Major" { _TR("Shivaranjani"), { 0, 0, 2, 3, 3, 3, 3, 7, 7, 9, 9, 9 } }, // identical to "Kumoi" { _TR("Marwa"), { 0, 1, 1, 1, 4, 4, 6, 6, 6, 9, 9,11 } }, // { _TR("Blues"), { 0, 0, 0, 3, 3, 5, 6, 7, 7, 7,10,10 } }, // identical to "Pentatonic Blues" { _TR("Minor 5"), { 0, 0, 0, 3, 3, 5, 5, 7, 7, 7,10,10 } }, // identical to "Pentatonic Minor" { _TR("Major 5"), { 0, 0, 0, 0, 4, 5, 5, 7, 7, 7, 7,11 } }, { _TR("5"), { 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7 } }, { _TR("45"), { 0, 0, 0, 0, 0, 5, 5, 7, 7, 7, 7, 7 } }, { _TR("457"), { 0, 0, 0, 0, 0, 5, 5, 7, 7, 7,10,10 } }, { _TR("M 6"), { 0, 0, 2, 3, 3, 5, 5, 7, 7, 7,10,11 } }, // identical to "Mela Varunapriya" { NULL, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } }; // Default scale key note names accessor. const QStringList& qtractorMidiEditor::scaleKeyNames (void) { static QStringList s_scaleKeys; if (s_scaleKeys.isEmpty()) { for (int i = 0; i < 12; ++i) s_scaleKeys.append(QObject::tr(g_aNoteNames[i].name, "scaleKeyName")); } return s_scaleKeys; } // Default scale type names table accessor. const QStringList& qtractorMidiEditor::scaleTypeNames (void) { static QStringList s_scaleTypes; if (s_scaleTypes.isEmpty()) { for (int i = 0; g_aScaleTab[i].name; ++i) s_scaleTypes.append(QObject::tr(g_aScaleTab[i].name, "scaleTypeName")); } return s_scaleTypes; } // Scale quantizer method. unsigned char qtractorMidiEditor::snapToScale ( unsigned char note, int iKey, int iScale ) { int n = int(note) + (12 - iKey); return 12 * ((n / 12) - 1) + iKey + int(g_aScaleTab[iScale].note[n % 12]); } //---------------------------------------------------------------------------- // qtractorMidiEdit::ClipBoard - MIDI editor clipaboard singleton. // Singleton declaration. qtractorMidiEditor::ClipBoard qtractorMidiEditor::g_clipboard; //---------------------------------------------------------------------------- // qtractorMidiEdit::DragTimeScale - Specialized drag/time-scale (draft)... struct qtractorMidiEditor::DragTimeScale { DragTimeScale(qtractorTimeScale *ts, unsigned long offset) : cursor(ts) { node = cursor.seekFrame(offset); t0 = node->tickFromFrame(offset); x0 = ts->pixelFromFrame(offset); } qtractorTimeScale::Cursor cursor; qtractorTimeScale::Node *node; unsigned long t0; int x0; }; //---------------------------------------------------------------------------- // qtractorMidiEditor -- The main MIDI sequence editor widget. // Constructor. qtractorMidiEditor::qtractorMidiEditor ( QWidget *pParent ) : QSplitter(Qt::Vertical, pParent) { // Initialize instance variables... m_pMidiClip = NULL; // Event fore/background colors. m_foreground = Qt::darkBlue; m_background = Qt::blue; // Common drag state. m_dragState = DragNone; m_dragCursor = DragNone; m_resizeMode = ResizeNone; m_pEventDrag = NULL; m_bEventDragEdit = false; m_pRubberBand = NULL; // Zoom mode flag. m_iZoomMode = ZoomAll; // Edit mode flags. m_bEditMode = false; m_bEditModeDraw = false; // Snap-to-beat/bar grid/zebra mode. m_bSnapZebra = false; m_bSnapGrid = false; // Floating tool-tips mode. m_bToolTips = true; // Last default editing values. m_last.note = 0x3c; // middle-C m_last.value = 0x40; m_last.pitchBend = 0; m_last.duration = 0; // The local mighty command pattern instance. m_pCommands = new qtractorCommandList(); // Local time-scale. m_pTimeScale = new qtractorTimeScale(); // The original clip time-scale length/time. m_iClipLengthTime = 0; // The local time-scale offset/length. m_iOffset = 0; m_iLength = 0; // Local edit-head/tail positioning. m_iEditHead = 0; m_iEditHeadX = 0; m_iEditTail = 0; m_iEditTailX = 0; // Local play-head positioning. m_iPlayHead = 0; m_iPlayHeadX = 0; m_bSyncView = false; // Note autition while editing. m_bSendNotes = false; // Event (note) duration rectangle vs. stick. m_bNoteDuration = false; // Event (note, velocity) coloring. m_bNoteColor = false; m_bValueColor = false; // Which widget holds focus on drag-paste? m_pEditPaste = NULL; // Snap-to-scale (aka.in-place scale-quantize) stuff. m_iSnapToScaleKey = 0; m_iSnapToScaleType = 0; // Create child frame widgets... QSplitter *pSplitter = new QSplitter(Qt::Horizontal, this); QWidget *pVBoxLeft = new QWidget(pSplitter); QWidget *pVBoxRight = new QWidget(pSplitter); QWidget *pHBoxBottom = new QWidget(this); // Create child view widgets... m_pEditListHeader = new QFrame(pVBoxLeft); m_pEditListHeader->setFixedHeight(20); m_pEditList = new qtractorMidiEditList(this, pVBoxLeft); m_pEditList->setMinimumWidth(32); m_pEditTime = new qtractorMidiEditTime(this, pVBoxRight); m_pEditTime->setFixedHeight(20); m_pEditView = new qtractorMidiEditView(this, pVBoxRight); m_pEditEventScale = new qtractorMidiEditEventScale(this, pHBoxBottom); m_pEditEvent = new qtractorMidiEditEvent(this, pHBoxBottom); m_pEditEventFrame = new QFrame(pHBoxBottom); m_pEditList->updateContentsHeight(); // Create child box layouts... QVBoxLayout *pVBoxLeftLayout = new QVBoxLayout(pVBoxLeft); pVBoxLeftLayout->setMargin(0); pVBoxLeftLayout->setSpacing(0); pVBoxLeftLayout->addWidget(m_pEditListHeader); pVBoxLeftLayout->addWidget(m_pEditList); pVBoxLeft->setLayout(pVBoxLeftLayout); QVBoxLayout *pVBoxRightLayout = new QVBoxLayout(pVBoxRight); pVBoxRightLayout->setMargin(0); pVBoxRightLayout->setSpacing(0); pVBoxRightLayout->addWidget(m_pEditTime); pVBoxRightLayout->addWidget(m_pEditView); pVBoxRight->setLayout(pVBoxRightLayout); QHBoxLayout *pHBoxBottomLayout = new QHBoxLayout(pHBoxBottom); pHBoxBottomLayout->setMargin(0); pHBoxBottomLayout->setSpacing(0); pHBoxBottomLayout->addWidget(m_pEditEventScale); pHBoxBottomLayout->addWidget(m_pEditEvent); pHBoxBottomLayout->addWidget(m_pEditEventFrame); pHBoxBottom->setLayout(pHBoxBottomLayout); // pSplitter->setOpaqueResize(false); pSplitter->setStretchFactor(pSplitter->indexOf(pVBoxLeft), 0); pSplitter->setHandleWidth(2); // QSplitter::setOpaqueResize(false); QSplitter::setStretchFactor(QSplitter::indexOf(pHBoxBottom), 0); QSplitter::setHandleWidth(2); QSplitter::setWindowIcon(QIcon(":/images/qtractorMidiEditor.png")); QSplitter::setWindowTitle(tr("MIDI Editor")); // To have all views in positional sync. QObject::connect(m_pEditList, SIGNAL(contentsMoving(int,int)), m_pEditView, SLOT(contentsYMovingSlot(int,int))); QObject::connect(m_pEditView, SIGNAL(contentsMoving(int,int)), m_pEditTime, SLOT(contentsXMovingSlot(int,int))); QObject::connect(m_pEditView, SIGNAL(contentsMoving(int,int)), m_pEditList, SLOT(contentsYMovingSlot(int,int))); QObject::connect(m_pEditView, SIGNAL(contentsMoving(int,int)), m_pEditEvent, SLOT(contentsXMovingSlot(int,int))); QObject::connect(m_pEditEvent, SIGNAL(contentsMoving(int,int)), m_pEditTime, SLOT(contentsXMovingSlot(int,int))); QObject::connect(m_pEditEvent, SIGNAL(contentsMoving(int,int)), m_pEditView, SLOT(contentsXMovingSlot(int,int))); QObject::connect(m_pCommands, SIGNAL(updateNotifySignal(unsigned int)), SLOT(updateNotifySlot(unsigned int))); // FIXME: Initial horizontal splitter sizes. QList sizes; sizes.append(48); sizes.append(752); pSplitter->setSizes(sizes); } // Destructor. qtractorMidiEditor::~qtractorMidiEditor (void) { resetDragState(NULL); // Release local instances. delete m_pTimeScale; delete m_pCommands; } // Editing sequence accessor. void qtractorMidiEditor::setMidiClip ( qtractorMidiClip *pMidiClip ) { // So, this is the brand new object to edit... m_pMidiClip = pMidiClip; if (m_pMidiClip) { // Now set the editing MIDI sequence alright... setClipLength(m_pMidiClip->clipLength()); setOffset(m_pMidiClip->clipStart()); setLength(m_pMidiClip->clipLength()); // Set its most outstanding properties... qtractorTrack *pTrack = m_pMidiClip->track(); if (pTrack) { setForeground(pTrack->foreground()); setBackground(pTrack->background()); } // And the last but not least... qtractorMidiSequence *pSeq = m_pMidiClip->sequence(); if (pSeq) { // Reset some internal state... m_cursor.reset(pSeq); m_cursorAt.reset(pSeq); // Reset as last on middle note and snap duration... m_last.note = (pSeq->noteMin() + pSeq->noteMax()) >> 1; if (m_last.note == 0) m_last.note = 0x3c; // Default to middle-C. } // Got clip! } else { // Reset those little things too.. setClipLength(0); setOffset(0); setLength(0); } // All commands reset. m_pCommands->clear(); } qtractorMidiClip *qtractorMidiEditor::midiClip (void) const { return m_pMidiClip; } // MIDI clip property accessors. const QString& qtractorMidiEditor::filename (void) const { return m_pMidiClip->filename(); } unsigned short qtractorMidiEditor::trackChannel (void) const { return (m_pMidiClip ? m_pMidiClip->trackChannel() : 0); } unsigned short qtractorMidiEditor::format (void) const { return (m_pMidiClip ? m_pMidiClip->format() : 0); } qtractorMidiSequence *qtractorMidiEditor::sequence (void) const { return (m_pMidiClip ? m_pMidiClip->sequence() : NULL); } // Event foreground (outline) color. void qtractorMidiEditor::setForeground ( const QColor& fore ) { m_foreground = fore; } const QColor& qtractorMidiEditor::foreground (void) const { return m_foreground; } // Event background (fill) color. void qtractorMidiEditor::setBackground ( const QColor& back ) { m_background = back; } const QColor& qtractorMidiEditor::background (void) const { return m_background; } // Zoom (view) mode. void qtractorMidiEditor::setZoomMode ( int iZoomMode ) { m_iZoomMode = iZoomMode; } int qtractorMidiEditor::zoomMode (void) const { return m_iZoomMode; } // Zoom ratio accessors. void qtractorMidiEditor::setHorizontalZoom ( unsigned short iHorizontalZoom ) { m_pTimeScale->setHorizontalZoom(iHorizontalZoom); m_pTimeScale->updateScale(); } unsigned short qtractorMidiEditor::horizontalZoom (void) const { return m_pTimeScale->horizontalZoom(); } void qtractorMidiEditor::setVerticalZoom ( unsigned short iVerticalZoom ) { // Hold and try setting new item height... int iZoomStep = int(iVerticalZoom) - int(verticalZoom()); int iItemHeight = (iVerticalZoom * qtractorMidiEditList::ItemHeightBase) / 100; if (iItemHeight < qtractorMidiEditList::ItemHeightMax && iZoomStep > 0) ++iItemHeight; else if (iItemHeight > qtractorMidiEditList::ItemHeightMin && iZoomStep < 0) --iItemHeight; m_pEditList->setItemHeight(iItemHeight); m_pTimeScale->setVerticalZoom(iVerticalZoom); } unsigned short qtractorMidiEditor::verticalZoom (void) const { return m_pTimeScale->verticalZoom(); } // Edit (creational) mode. void qtractorMidiEditor::setEditMode ( bool bEditMode ) { resetDragState(NULL); m_bEditMode = bEditMode; // updateContents(); } bool qtractorMidiEditor::isEditMode (void) const { return m_bEditMode; } // Edit draw (notes) mode. void qtractorMidiEditor::setEditModeDraw ( bool bEditModeDraw ) { m_bEditModeDraw = bEditModeDraw; } bool qtractorMidiEditor::isEditModeDraw (void) const { return m_bEditModeDraw; } // Snap-to-bar zebra mode. void qtractorMidiEditor::setSnapZebra ( bool bSnapZebra ) { m_bSnapZebra = bSnapZebra; // updateContents(); } bool qtractorMidiEditor::isSnapZebra (void) const { return m_bSnapZebra; } // Snap-to-beat grid mode. void qtractorMidiEditor::setSnapGrid ( bool bSnapGrid ) { m_bSnapGrid = bSnapGrid; // updateContents(); } bool qtractorMidiEditor::isSnapGrid (void) const { return m_bSnapGrid; } // Floating tool-tips mode. void qtractorMidiEditor::setToolTips ( bool bToolTips ) { m_bToolTips = bToolTips; } bool qtractorMidiEditor::isToolTips (void) const { return m_bToolTips; } // Local time scale accessor. qtractorTimeScale *qtractorMidiEditor::timeScale (void) const { return m_pTimeScale; } unsigned long qtractorMidiEditor::timeOffset (void) const { return (m_pTimeScale ? m_pTimeScale->tickFromFrame(m_iOffset) : 0); } // The original clip time-scale length/time. void qtractorMidiEditor::setClipLength ( unsigned long iClipLength ) { if (m_pTimeScale) { m_iClipLengthTime = m_pTimeScale->tickFromFrame(m_iOffset + iClipLength) - m_pTimeScale->tickFromFrame(m_iOffset); } else { m_iClipLengthTime = 0; } } unsigned long qtractorMidiEditor::clipLength (void) const { if (m_pTimeScale == NULL) return 0; return m_pTimeScale->frameFromTick( m_pTimeScale->tickFromFrame(m_iOffset) + m_iClipLengthTime) - m_iOffset; } // Reset original clip time-scale length/time. void qtractorMidiEditor::resetClipLength (void) { if (m_pMidiClip) setClipLength(m_pMidiClip->clipLength()); } // Time-scale offset (in frames) accessors. void qtractorMidiEditor::setOffset ( unsigned long iOffset ) { m_iOffset = iOffset; } unsigned long qtractorMidiEditor::offset (void) const { return m_iOffset; } // Time-scale length (in frames) accessors. void qtractorMidiEditor::setLength ( unsigned long iLength ) { m_iLength = iLength; } unsigned long qtractorMidiEditor::length (void) const { return m_iLength; } // Edit-head/tail positioning. void qtractorMidiEditor::setEditHead ( unsigned long iEditHead, bool bSyncView ) { if (iEditHead > m_iEditTail) setEditTail(iEditHead, bSyncView); if (bSyncView) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) pSession->setEditHead(iEditHead); } m_iEditHead = iEditHead; int iEditHeadX = m_pTimeScale->pixelFromFrame(iEditHead) - m_pTimeScale->pixelFromFrame(m_iOffset); drawPositionX(m_iEditHeadX, iEditHeadX, bSyncView); } unsigned long qtractorMidiEditor::editHead (void) const { return m_iEditHead; } int qtractorMidiEditor::editHeadX (void) const { return m_iEditHeadX; } void qtractorMidiEditor::setEditTail ( unsigned long iEditTail, bool bSyncView ) { if (iEditTail < m_iEditHead) setEditHead(iEditTail, bSyncView); if (bSyncView) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) pSession->setEditTail(iEditTail); } m_iEditTail = iEditTail; int iEditTailX = m_pTimeScale->pixelFromFrame(iEditTail) - m_pTimeScale->pixelFromFrame(m_iOffset); drawPositionX(m_iEditTailX, iEditTailX, bSyncView); } unsigned long qtractorMidiEditor::editTail (void) const { return m_iEditTail; } int qtractorMidiEditor::editTailX (void) const { return m_iEditTailX; } // Play-head positioning. void qtractorMidiEditor::setPlayHead ( unsigned long iPlayHead, bool bSyncView ) { if (bSyncView) bSyncView = m_bSyncView; m_iPlayHead = iPlayHead; int iPlayHeadX = m_pTimeScale->pixelFromFrame(iPlayHead) - m_pTimeScale->pixelFromFrame(m_iOffset); drawPositionX(m_iPlayHeadX, iPlayHeadX, bSyncView); } unsigned long qtractorMidiEditor::playHead (void) const { return m_iPlayHead; } int qtractorMidiEditor::playHeadX (void) const { return m_iPlayHeadX; } // Update time-scale to master session. void qtractorMidiEditor::updateTimeScale (void) { if (m_pMidiClip == NULL) return; if (m_pTimeScale == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; m_pTimeScale->sync(*pSession->timeScale()); setOffset(m_pMidiClip->clipStart()); setLength(m_pMidiClip->clipLength()); setPlayHead(pSession->playHead(), false); setEditHead(pSession->editHead(), false); setEditTail(pSession->editTail(), false); } // Play-head follow-ness. void qtractorMidiEditor::setSyncView ( bool bSyncView ) { m_bSyncView = bSyncView; } bool qtractorMidiEditor::isSyncView (void) const { return m_bSyncView; } // Note autition while editing. void qtractorMidiEditor::setSendNotes ( bool bSendNotes ) { m_bSendNotes = bSendNotes; } bool qtractorMidiEditor::isSendNotes (void) const { return m_bSendNotes; } // Event value stick vs. duration rectangle. void qtractorMidiEditor::setNoteDuration ( bool bNoteDuration ) { m_bNoteDuration = bNoteDuration; } bool qtractorMidiEditor::isNoteDuration (void) const { return m_bNoteDuration; } // Event (note, velocity) coloring. void qtractorMidiEditor::setNoteColor ( bool bNoteColor ) { m_bNoteColor = bNoteColor; } bool qtractorMidiEditor::isNoteColor (void) const { return m_bNoteColor; } void qtractorMidiEditor::setValueColor ( bool bValueColor ) { m_bValueColor = bValueColor; } bool qtractorMidiEditor::isValueColor (void) const { return m_bValueColor; } // Snap-to-scale/quantize key accessor. void qtractorMidiEditor::setSnapToScaleKey ( int iSnapToScaleKey ) { m_iSnapToScaleKey = iSnapToScaleKey; } int qtractorMidiEditor::snapToScaleKey (void) const { return m_iSnapToScaleKey; } // Snap-to-scale/quantize type accessor. void qtractorMidiEditor::setSnapToScaleType ( int iSnapToScaleType ) { m_iSnapToScaleType = iSnapToScaleType; } int qtractorMidiEditor::snapToScaleType (void) const { return m_iSnapToScaleType; } // Vertical line position drawing. void qtractorMidiEditor::drawPositionX ( int& iPositionX, int x, bool bSyncView ) { // Update track-view position... int x0 = m_pEditView->contentsX(); int x1 = iPositionX - x0; int w = m_pEditView->width(); int h1 = m_pEditView->height(); int h2 = m_pEditEvent->height(); int wm = (w >> 3); // Time-line header extents... int h0 = m_pEditTime->height(); int d0 = (h0 >> 1); // Restore old position... if (iPositionX != x && x1 >= 0 && x1 < w + d0) { // Override old view line... (m_pEditEvent->viewport())->update(QRect(x1, 0, 1, h2)); (m_pEditView->viewport())->update(QRect(x1, 0, 1, h1)); (m_pEditTime->viewport())->update(QRect(x1 - d0, d0, h0, d0)); } // New position is in... iPositionX = x; // Force position to be in view? if (bSyncView && (x < x0 || x > x0 + w - wm) && m_dragState == DragNone && m_dragCursor == DragNone) { // Move it... m_pEditView->setContentsPos(x - wm, m_pEditView->contentsY()); } else { // Draw the line, by updating the new region... x1 = x - x0; if (x1 >= 0 && x1 < w + d0) { (m_pEditEvent->viewport())->update(QRect(x1, 0, 1, h2)); (m_pEditView->viewport())->update(QRect(x1, 0, 1, h1)); (m_pEditTime->viewport())->update(QRect(x1 - d0, d0, h0, d0)); } } } // Child widgets accessors. QFrame *qtractorMidiEditor::editListHeader (void) const { return m_pEditListHeader; } qtractorMidiEditList *qtractorMidiEditor::editList (void) const { return m_pEditList; } qtractorMidiEditTime *qtractorMidiEditor::editTime (void) const { return m_pEditTime; } qtractorMidiEditView *qtractorMidiEditor::editView (void) const { return m_pEditView; } qtractorMidiEditEvent *qtractorMidiEditor::editEvent (void) const { return m_pEditEvent; } qtractorMidiEditEventScale *qtractorMidiEditor::editEventScale (void) const { return m_pEditEventScale; } QFrame *qtractorMidiEditor::editEventFrame (void) const { return m_pEditEventFrame; } // Horizontal zoom factor. void qtractorMidiEditor::horizontalZoomStep ( int iZoomStep ) { int iHorizontalZoom = horizontalZoom() + iZoomStep; if (iHorizontalZoom < ZoomMin) iHorizontalZoom = ZoomMin; else if (iHorizontalZoom > ZoomMax) iHorizontalZoom = ZoomMax; if (iHorizontalZoom == horizontalZoom()) return; // Fix the local horizontal view zoom. setHorizontalZoom(iHorizontalZoom); } // Vertical zoom factor. void qtractorMidiEditor::verticalZoomStep ( int iZoomStep ) { int iVerticalZoom = verticalZoom() + iZoomStep; if (iVerticalZoom < ZoomMin) iVerticalZoom = ZoomMin; else if (iVerticalZoom > ZoomMax) iVerticalZoom = ZoomMax; if (iVerticalZoom == verticalZoom()) return; // Fix the local vertical view zoom. setVerticalZoom(iVerticalZoom); } // Zoom view slots. void qtractorMidiEditor::zoomIn (void) { ZoomCenter zc; zoomCenterPre(zc); if (m_iZoomMode & ZoomHorizontal) horizontalZoomStep(+ ZoomStep); if (m_iZoomMode & ZoomVertical) verticalZoomStep(+ ZoomStep); zoomCenterPost(zc); } void qtractorMidiEditor::zoomOut (void) { ZoomCenter zc; zoomCenterPre(zc); if (m_iZoomMode & ZoomHorizontal) horizontalZoomStep(- ZoomStep); if (m_iZoomMode & ZoomVertical) verticalZoomStep(- ZoomStep); zoomCenterPost(zc); } void qtractorMidiEditor::zoomReset (void) { ZoomCenter zc; zoomCenterPre(zc); if (m_iZoomMode & ZoomHorizontal) horizontalZoomStep(ZoomBase - m_pTimeScale->horizontalZoom()); if (m_iZoomMode & ZoomVertical) verticalZoomStep(ZoomBase - m_pTimeScale->verticalZoom()); zoomCenterPost(zc); } void qtractorMidiEditor::horizontalZoomInSlot (void) { ZoomCenter zc; zoomCenterPre(zc); horizontalZoomStep(+ ZoomStep); zoomCenterPost(zc); } void qtractorMidiEditor::horizontalZoomOutSlot (void) { ZoomCenter zc; zoomCenterPre(zc); horizontalZoomStep(- ZoomStep); zoomCenterPost(zc); } void qtractorMidiEditor::verticalZoomInSlot (void) { ZoomCenter zc; zoomCenterPre(zc); verticalZoomStep(+ ZoomStep); zoomCenterPost(zc); } void qtractorMidiEditor::verticalZoomOutSlot (void) { ZoomCenter zc; zoomCenterPre(zc); verticalZoomStep(- ZoomStep); zoomCenterPost(zc); } void qtractorMidiEditor::horizontalZoomResetSlot (void) { ZoomCenter zc; zoomCenterPre(zc); horizontalZoomStep(ZoomBase - m_pTimeScale->horizontalZoom()); zoomCenterPost(zc); } void qtractorMidiEditor::verticalZoomResetSlot (void) { ZoomCenter zc; zoomCenterPre(zc); verticalZoomStep(ZoomBase - m_pTimeScale->verticalZoom()); zoomCenterPost(zc); } // Alterrnate command action update helper... void qtractorMidiEditor::updateUndoAction ( QAction *pAction ) const { m_pCommands->updateAction(pAction, m_pCommands->lastCommand()); } void qtractorMidiEditor::updateRedoAction ( QAction *pAction ) const { m_pCommands->updateAction(pAction, m_pCommands->nextCommand()); } // Tell whether we can undo last command... bool qtractorMidiEditor::canUndo (void) const { return (m_pCommands->lastCommand() != NULL); } // Tell whether we can redo last command... bool qtractorMidiEditor::canRedo (void) const { return (m_pCommands->nextCommand() != NULL); } // Undo last edit command. void qtractorMidiEditor::undoCommand (void) { m_pCommands->undo(); } // Redo last edit command. void qtractorMidiEditor::redoCommand (void) { m_pCommands->redo(); } // Whether there's any item currently selected. bool qtractorMidiEditor::isSelected (void) const { return (m_select.items().count() > 0); } // Whether there's any item on the clipboard. bool qtractorMidiEditor::isClipboard (void) { // Tell whether there's any item on the clipboard. return (g_clipboard.items.count() > 0); } // Cut current selection to clipboard. void qtractorMidiEditor::cutClipboard (void) { if (m_pMidiClip == NULL) return; if (!isSelected()) return; g_clipboard.clear(); qtractorMidiEditCommand *pEditCommand = new qtractorMidiEditCommand(m_pMidiClip, tr("cut")); const qtractorMidiEditSelect::ItemList& items = m_select.items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorMidiEvent *pEvent = iter.key(); g_clipboard.items.append(new qtractorMidiEvent(*pEvent)); pEditCommand->removeEvent(pEvent); } // Make it as an undoable command... m_pCommands->exec(pEditCommand); } // Copy current selection to clipboard. void qtractorMidiEditor::copyClipboard (void) { if (m_pMidiClip == NULL) return; if (!isSelected()) return; g_clipboard.clear(); const qtractorMidiEditSelect::ItemList& items = m_select.items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) g_clipboard.items.append(new qtractorMidiEvent(*iter.key())); selectionChangeNotify(); } // Retrieve current paste period. // (as from current clipboard width) unsigned long qtractorMidiEditor::pastePeriod (void) const { unsigned long t0 = m_pTimeScale->tickFromFrame(m_iOffset); unsigned long t1 = 0; unsigned long t2 = 0; int k = 0; QListIterator iter(g_clipboard.items); while (iter.hasNext()) { qtractorMidiEvent *pEvent = iter.next(); unsigned long t = t0 + pEvent->time(); if (t1 > t || k == 0) t1 = t; t += pEvent->duration(); if (t2 < t) t2 = t; ++k; } return m_pTimeScale->frameFromTick(t2) - m_pTimeScale->frameFromTick(t1); } // Paste from clipboard. void qtractorMidiEditor::pasteClipboard ( unsigned short iPasteCount, unsigned long iPastePeriod ) { if (m_pMidiClip == NULL) return; if (!isClipboard()) return; // Reset any current selection, whatsoever... clearSelect(); resetDragState(NULL); // Multi-paste period... if (iPastePeriod < 1) iPastePeriod = pastePeriod(); qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(m_iOffset); unsigned long t0 = pNode->tickFromFrame(m_iOffset); int x0 = m_pTimeScale->pixelFromFrame(m_iOffset); int dx = m_pTimeScale->pixelFromFrame(iPastePeriod); // This is the edit-view spacifics... int h1 = m_pEditList->itemHeight(); int ch = m_pEditView->contentsHeight(); // + 1; // This is the edit-event zero-line... const qtractorMidiEvent::EventType etype = m_pEditEvent->eventType(); const int h0 = ((m_pEditEvent->viewport())->height() & ~1); // even. const int y0 = (etype == qtractorMidiEvent::PITCHBEND ? h0 >> 1 : h0); int k, x1; unsigned long d0 = t0; QListIterator iter(g_clipboard.items); for (unsigned short i = 0; i < iPasteCount; ++i) { iter.toFront(); k = x1 = 0; while (iter.hasNext()) { qtractorMidiEvent *pEvent = iter.next(); // Common event coords... int y; unsigned long t1 = t0 + pEvent->time(); unsigned long t2 = t1 + pEvent->duration(); pNode = cursor.seekTick(t1); int x = pNode->pixelFromTick(t1) - 1; int w1 = pNode->pixelFromTick(t2) - x; if (w1 < 5) w1 = 5; // View item... QRect rectView; if (pEvent->type() == m_pEditView->eventType()) { y = ch - h1 * (pEvent->note() + 1); rectView.setRect(x - x0, y, w1, h1); } // Event item... QRect rectEvent; if (pEvent->type() == m_pEditEvent->eventType()) { if (pEvent->type() == qtractorMidiEvent::PITCHBEND) y = y0 - (y0 * pEvent->pitchBend()) / 8192; else y = y0 - (y0 * pEvent->value()) / 128; if (!m_bNoteDuration) w1 = 5; if (y < y0) rectEvent.setRect(x - x0, y, w1, y0 - y); else if (y > y0) rectEvent.setRect(x - x0, y0, w1, y - y0); else rectEvent.setRect(x - x0, y0 - 2, w1, 4); } m_select.addItem(pEvent, rectEvent, rectView, t0 - d0); if (x1 > x || k == 0) x1 = x; ++k; } pNode = cursor.seekTick(x1 + dx); t0 += pNode->tickFromPixel(x1 + dx); pNode = cursor.seekTick(x1); t0 -= pNode->tickFromPixel(x1); } // Make sure we've a anchor... if (m_pEventDrag == NULL) m_pEventDrag = m_select.anchorEvent(); // Formally ellect this one as the target view... qtractorScrollView *pScrollView = NULL; qtractorMidiEditSelect::Item *pItem = m_select.findItem(m_pEventDrag); if (pItem) { if (m_pEventDrag->type() == m_pEditView->eventType()) { m_rectDrag = pItem->rectView; pScrollView = m_pEditView; } else { m_rectDrag = pItem->rectEvent; pScrollView = m_pEditEvent; } } // That's right :) if (pScrollView == NULL) { m_dragState = DragStep; // HACK: Force selection clearance! clearSelect(); resetDragState(NULL); return; } // We'll start a brand new floating state... m_dragState = m_dragCursor = DragPaste; m_posDrag = m_rectDrag.topLeft(); m_posStep = QPoint(0, 0); // This is the one which is holding focus on drag-paste. m_pEditPaste = pScrollView; // It doesn't matter which one, both pasteable views are due... QCursor cursr(QPixmap(":/images/editPaste.png"), 20, 20); m_pEditView->setCursor(cursr); m_pEditEvent->setCursor(cursr); // Make sure the mouse pointer is properly located... const QPoint& pos = pScrollView->viewportToContents( pScrollView->viewport()->mapFromGlobal(QCursor::pos())); // Let's-a go... updateDragMove(pScrollView, pos + m_posStep); } // Execute event removal. void qtractorMidiEditor::deleteSelect (void) { if (m_pMidiClip == NULL) return; if (!isSelected()) return; qtractorMidiEditCommand *pEditCommand = new qtractorMidiEditCommand(m_pMidiClip, tr("delete")); const qtractorMidiEditSelect::ItemList& items = m_select.items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) pEditCommand->removeEvent(iter.key()); m_pCommands->exec(pEditCommand); } // Select all/none contents. void qtractorMidiEditor::selectAll ( qtractorScrollView *pScrollView, bool bSelect, bool bToggle ) { // Select all/none view contents. if (bSelect) { const QRect rect(0, 0, pScrollView->contentsWidth(), pScrollView->contentsHeight()); selectRect(pScrollView, rect, bToggle, true); } else { clearSelect(); resetDragState(pScrollView); selectionChangeNotify(); } // Make sure main view keeps focus... QWidget::activateWindow(); pScrollView->setFocus(); } // Select range view contents. void qtractorMidiEditor::selectRange ( qtractorScrollView *pScrollView, bool bToggle, bool bCommit ) { int x = m_iEditHeadX; int y = 0; int w = m_iEditTailX - m_iEditHeadX; int h = pScrollView->contentsHeight(); selectRect(pScrollView, QRect(x, y, w, h), bToggle, bCommit); } // Select everything between a given view rectangle. void qtractorMidiEditor::selectRect ( qtractorScrollView *pScrollView, const QRect& rect, bool bToggle, bool bCommit ) { int flags = SelectNone; if (bToggle) flags |= SelectToggle; if (bCommit) flags |= SelectCommit; updateDragSelect(pScrollView, rect.normalized(), flags); resetDragState(pScrollView); selectionChangeNotify(); } // Add/remove one single event to current selection. void qtractorMidiEditor::selectEvent ( qtractorMidiEvent *pEvent, bool bSelect ) { if (pEvent == NULL) return; if (!isEventSelectable(pEvent)) return; QRect rectUpdateView(m_select.rectView()); QRect rectUpdateEvent(m_select.rectEvent()); // Select item (or toggle)... QRect rectEvent, rectView; updateEventRects(pEvent, rectEvent, rectView); m_select.selectItem(pEvent, rectEvent, rectView, true, !bSelect); // Commit selection... m_select.update(true); rectUpdateView = rectUpdateView.united(m_select.rectView()); m_pEditView->viewport()->update(QRect( m_pEditView->contentsToViewport(rectUpdateView.topLeft()), rectUpdateView.size())); rectUpdateEvent = rectUpdateEvent.united(m_select.rectEvent()); m_pEditEvent->viewport()->update(QRect( m_pEditEvent->contentsToViewport(rectUpdateEvent.topLeft()), rectUpdateEvent.size())); } // Retrieve current selection. QList qtractorMidiEditor::selectedEvents (void) const { QList list; const qtractorMidiEditSelect::ItemList& items = m_select.items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) list.append(iter.key()); return list; } // Selectable event predicate. bool qtractorMidiEditor::isEventSelectable ( qtractorMidiEvent *pEvent ) const { return (pEvent->type() == m_pEditView->eventType() || (pEvent->type() == m_pEditEvent->eventType() && (m_pEditEvent->eventType() != qtractorMidiEvent::CONTROLLER || pEvent->controller() == m_pEditEvent->controller()))); } // Ensuere point visibility depending on view. void qtractorMidiEditor::ensureVisible ( qtractorScrollView *pScrollView, const QPoint& pos ) { if (static_cast (pScrollView) == m_pEditEvent) pScrollView->ensureVisible(pos.x(), 0, 16, 0); else pScrollView->ensureVisible(pos.x(), pos.y(), 16, 16); } // Clear all selection. void qtractorMidiEditor::clearSelect (void) { const QRect rectUpdateView(m_select.rectView()); const QRect rectUpdateEvent(m_select.rectEvent()); m_select.clear(); m_pEditView->viewport()->update(QRect( m_pEditView->contentsToViewport(rectUpdateView.topLeft()), rectUpdateView.size())); m_pEditEvent->viewport()->update(QRect( m_pEditEvent->contentsToViewport(rectUpdateEvent.topLeft()), rectUpdateEvent.size())); } // Update all selection rectangular areas. void qtractorMidiEditor::updateSelect ( bool bSelectReset ) { qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(m_iOffset); unsigned long t0 = pNode->tickFromFrame(m_iOffset); int x0 = m_pTimeScale->pixelFromFrame(m_iOffset); // This is the edit-view specifics... int h1 = m_pEditList->itemHeight(); int ch = m_pEditView->contentsHeight(); // + 1; // This is the edit-event zero-line... const qtractorMidiEvent::EventType etype = m_pEditEvent->eventType(); const int h0 = ((m_pEditEvent->viewport())->height() & ~1); // even. const int y0 = (etype == qtractorMidiEvent::PITCHBEND ? h0 >> 1 : h0); const qtractorMidiEditSelect::ItemList& items = m_select.items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorMidiEvent *pEvent = iter.key(); qtractorMidiEditSelect::Item *pItem = iter.value(); // Common event coords... int y; unsigned long t1 = t0 + pEvent->time(); unsigned long t2 = t1 + pEvent->duration(); pNode = cursor.seekTick(t1); int x = pNode->pixelFromTick(t1) - 1; int w1 = pNode->pixelFromTick(t2) - x; if (w1 < 5) w1 = 5; // View item... if (pEvent->type() == m_pEditView->eventType()) { y = ch - h1 * (pEvent->note() + 1); pItem->rectView.setRect(x - x0, y, w1, h1); } else pItem->rectView.setRect(0, 0, 0, 0); // Event item... if (pEvent->type() == m_pEditEvent->eventType()) { if (pEvent->type() == qtractorMidiEvent::PITCHBEND) y = y0 - (y0 * pEvent->pitchBend()) / 8192; else y = y0 - (y0 * pEvent->value()) / 128; if (!m_bNoteDuration) w1 = 5; if (y < y0) pItem->rectEvent.setRect(x - x0, y, w1, y0 - y); else if (y > y0) pItem->rectEvent.setRect(x - x0, y0, w1, y - y0); else pItem->rectEvent.setRect(x - x0, y0 - 2, w1, 4); } else pItem->rectEvent.setRect(0, 0, 0, 0); } // Final touch. m_select.commit(); if (bSelectReset) { m_rectDrag = m_select.rectView(); m_posDrag = m_rectDrag.topLeft(); resetDragState(NULL); } } // Whether there's any events beyond the insertion point (edit-head). bool qtractorMidiEditor::isInsertable (void) const { if (m_pMidiClip == NULL) return false; qtractorMidiSequence *pSeq = m_pMidiClip->sequence(); if (pSeq == NULL) return false; return m_pTimeScale->tickFromFrame(m_iEditHead) < m_pTimeScale->tickFromFrame(m_iOffset) + pSeq->duration(); } // Whether there's any selected range (edit-head/tail). bool qtractorMidiEditor::isSelectable (void) const { return (m_iEditHead < m_iEditTail); } // Insert edit range. void qtractorMidiEditor::insertEditRange (void) { if (m_pMidiClip == NULL) return; qtractorMidiSequence *pSeq = m_pMidiClip->sequence(); if (pSeq == NULL) return; unsigned long iInsertStart = m_pTimeScale->tickFromFrame(m_iEditHead); unsigned long iInsertEnd = 0; if (m_iEditHead < m_iEditTail) { iInsertEnd = m_pTimeScale->tickFromFrame(m_iEditTail); } else { unsigned short iBar = m_pTimeScale->barFromFrame(m_iEditHead); iInsertEnd = m_pTimeScale->tickFromFrame(m_pTimeScale->frameFromBar(iBar + 1)); } if (iInsertStart >= iInsertEnd) return; unsigned long iInsertDuration = iInsertEnd - iInsertStart; unsigned long t0 = m_pTimeScale->tickFromFrame(m_iOffset); int iUpdate = 0; qtractorMidiEditCommand *pEditCommand = new qtractorMidiEditCommand(m_pMidiClip, tr("insert range")); qtractorMidiEvent *pEvent = pSeq->events().first(); while (pEvent) { unsigned long iTime = pEvent->time(); unsigned long iDuration = pEvent->duration(); unsigned long iEventStart = t0 + iTime; unsigned long iEventEnd = iEventStart + iDuration; // Slip/move event... if (iEventEnd >= iInsertStart) { if (iEventStart < iInsertStart) { if (iEventEnd > iInsertStart) { // Resize left-event... pEditCommand->resizeEventTime(pEvent, iTime, iInsertStart - iEventStart); // Insert right-event... qtractorMidiEvent *pEventEx = new qtractorMidiEvent(*pEvent); pEventEx->setTime(iInsertEnd - t0); pEventEx->setDuration(iEventEnd - iInsertStart); pEditCommand->insertEvent(pEventEx); ++iUpdate; } } else { // Move whole-event... pEditCommand->resizeEventTime(pEvent, iTime + iInsertDuration, iDuration); ++iUpdate; } } pEvent = pEvent->next(); } if (iUpdate > 0) m_pCommands->exec(pEditCommand); else delete pEditCommand; } // Remove edit range. void qtractorMidiEditor::removeEditRange (void) { if (m_pMidiClip == NULL) return; qtractorMidiSequence *pSeq = m_pMidiClip->sequence(); if (pSeq == NULL) return; unsigned long iRemoveStart = m_pTimeScale->tickFromFrame(m_iEditHead); unsigned long iRemoveEnd = 0; if (m_iEditHead < m_iEditTail) { iRemoveEnd = m_pTimeScale->tickFromFrame(m_iEditTail); } else { unsigned short iBar = m_pTimeScale->barFromFrame(m_iEditHead); iRemoveEnd = m_pTimeScale->tickFromFrame(m_pTimeScale->frameFromBar(iBar + 1)); } if (iRemoveStart >= iRemoveEnd) return; unsigned long iRemoveDuration = iRemoveEnd - iRemoveStart; unsigned long t0 = m_pTimeScale->tickFromFrame(m_iOffset); int iUpdate = 0; qtractorMidiEditCommand *pEditCommand = new qtractorMidiEditCommand(m_pMidiClip, tr("remove range")); qtractorMidiEvent *pEvent = pSeq->events().first(); while (pEvent) { unsigned long iTime = pEvent->time(); unsigned long iDuration = pEvent->duration(); unsigned long iEventStart = t0 + iTime; unsigned long iEventEnd = iEventStart + iDuration; // Slip/move event... if (iEventEnd >= iRemoveStart) { if (iEventStart < iRemoveStart) { // Resize left-event... pEditCommand->resizeEventTime(pEvent, iTime, iRemoveStart - iEventStart); if (iEventEnd > iRemoveEnd) { // Insert right-event... qtractorMidiEvent *pEventEx = new qtractorMidiEvent(*pEvent); pEventEx->setTime(iRemoveStart - t0); pEventEx->setDuration(iEventEnd - iRemoveEnd); pEditCommand->insertEvent(pEventEx); } } else if (iEventEnd > iRemoveEnd) { if (iEventStart < iRemoveEnd) { pEditCommand->resizeEventTime(pEvent, iRemoveStart - t0, iEventEnd - iRemoveEnd); } else { pEditCommand->resizeEventTime(pEvent, iTime - iRemoveDuration, iDuration); } } else pEditCommand->removeEvent(pEvent); ++iUpdate; } pEvent = pEvent->next(); } if (iUpdate > 0) m_pCommands->exec(pEditCommand); else delete pEditCommand; } // Update/sync integral contents. void qtractorMidiEditor::updateContents (void) { // Update dependant views. m_pEditList->updateContentsHeight(); m_pEditView->updateContentsWidth(); updateSelect(false); // Trigger a complete view update... m_pEditList->updateContents(); m_pEditTime->updateContents(); m_pEditView->updateContents(); m_pEditEvent->updateContents(); } // Try to center vertically the edit-view... void qtractorMidiEditor::centerContents (void) { // Update dependant views. m_pEditList->updateContentsHeight(); m_pEditView->updateContentsWidth(); updateSelect(true); // Do the centering... qtractorMidiSequence *pSeq = NULL; if (m_pMidiClip) pSeq = m_pMidiClip->sequence(); if (pSeq) { int cy = m_pEditView->contentsHeight(); int h2 = m_pEditList->itemHeight() * (pSeq->noteMin() + pSeq->noteMax()); if (h2 > 0) cy -= ((h2 + (m_pEditView->viewport())->height()) >> 1); else cy >>= 1; if (cy < 0) cy = 0; m_pEditView->setContentsPos(m_pEditView->contentsX(), cy); } // Update visual cursors anyway... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { setPlayHead(pSession->playHead(), false); setEditHead(pSession->editHead(), false); setEditTail(pSession->editTail(), false); } // Trigger a complete view update... m_pEditList->updateContents(); m_pEditTime->updateContents(); m_pEditView->updateContents(); m_pEditEvent->updateContents(); } // Zoom centering prepare method. // (usually before zoom change) void qtractorMidiEditor::zoomCenterPre ( ZoomCenter& zc ) const { if (m_pTimeScale == NULL) return; QWidget *pViewport = m_pEditView->viewport(); const QRect& rect = pViewport->rect(); const QPoint& pos = pViewport->mapFromGlobal(QCursor::pos()); if (rect.contains(pos)) { zc.x = pos.x(); zc.y = pos.y(); } else { #if 0 zc.x = 0; zc.y = 0; #else zc.x = (rect.width() >> 1); zc.y = (rect.height() >> 1); #endif } int x0 = m_pTimeScale->pixelFromFrame(m_iOffset); int cx = m_pEditView->contentsX(); zc.frame = m_pTimeScale->frameFromPixel(x0 + cx + zc.x); int cy = m_pEditView->contentsY(); zc.item = (cy + zc.y) / m_pEditList->itemHeight(); } // Zoom centering post methods. // (usually after zoom change) void qtractorMidiEditor::zoomCenterPost ( const ZoomCenter& zc ) { if (m_pTimeScale == NULL) return; int x0 = m_pTimeScale->pixelFromFrame(m_iOffset); int cx = m_pTimeScale->pixelFromFrame(zc.frame); int cy = zc.item * m_pEditList->itemHeight(); if (cx > zc.x + x0) cx -= zc.x + x0; else cx = 0; if (cy > zc.y) cy -= zc.y; else cy = 0; // Update dependant views. m_pEditList->updateContentsHeight(); m_pEditView->updateContentsWidth(); updateSelect(true); // Do the centering... m_pEditView->setContentsPos(cx, cy); // Update visual cursors anyway... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { setPlayHead(pSession->playHead(), false); setEditHead(pSession->editHead(), false); setEditTail(pSession->editTail(), false); } // Trigger a complete view update... m_pEditList->updateContents(); m_pEditTime->updateContents(); m_pEditView->updateContents(); m_pEditEvent->updateContents(); } // Reset event cursors. void qtractorMidiEditor::reset ( bool bSelectClear ) { if (bSelectClear) m_select.clear(); // Reset some internal state... if (m_pMidiClip) { qtractorMidiSequence *pSeq = m_pMidiClip->sequence(); if (pSeq) { m_cursor.reset(pSeq); m_cursorAt.reset(pSeq); } } } // Clear all contents. void qtractorMidiEditor::clear (void) { m_pCommands->clear(); if (m_pMidiClip) m_pMidiClip->sequence()->clear(); reset(true); } // Intra-clip tick/time positioning reset. qtractorMidiEvent *qtractorMidiEditor::seekEvent ( unsigned long iTime ) { // Reset seek-forward... return m_cursor.reset(m_pMidiClip->sequence(), iTime); } // Get event from given contents position. qtractorMidiEvent *qtractorMidiEditor::eventAt ( qtractorScrollView *pScrollView, const QPoint& pos, QRect *pRect ) { if (m_pMidiClip == NULL) return NULL; qtractorMidiSequence *pSeq = m_pMidiClip->sequence(); if (pSeq == NULL) return NULL; const bool bEditView = (static_cast (m_pEditView) == pScrollView); qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(m_iOffset); unsigned long t0 = pNode->tickFromFrame(m_iOffset); int x0 = m_pTimeScale->pixelFromFrame(m_iOffset); pNode = cursor.seekPixel(x0 + pos.x()); unsigned long iTime = pNode->tickFromPixel(x0 + pos.x()); iTime = (iTime > t0 ? iTime - t0 : 0); // This is the edit-view spacifics... int h1 = m_pEditList->itemHeight(); int ch = m_pEditView->contentsHeight(); // + 1; // This is the edit-event zero-line... const qtractorMidiEvent::EventType etype = m_pEditEvent->eventType(); const int h0 = ((m_pEditEvent->viewport())->height() & ~1); // even. const int y0 = (etype == qtractorMidiEvent::PITCHBEND ? h0 >> 1 : h0); bool bController = (m_pEditEvent->eventType() == qtractorMidiEvent::CONTROLLER); unsigned char controller = m_pEditEvent->controller(); qtractorMidiEvent *pEvent = m_cursorAt.reset(pSeq, iTime); qtractorMidiEvent *pEventAt = NULL; while (pEvent && iTime >= pEvent->time()) { if (((bEditView && pEvent->type() == m_pEditView->eventType()) || (!bEditView && (pEvent->type() == m_pEditEvent->eventType() && (!bController || pEvent->controller() == controller))))) { // Common event coords... int y; unsigned long t1 = t0 + pEvent->time(); unsigned long t2 = t1 + pEvent->duration(); pNode = cursor.seekTick(t1); int x = pNode->pixelFromTick(t1) - 1; int w1 = pNode->pixelFromTick(t2) - x; if (w1 < 5) w1 = 5; QRect rect; if (bEditView) { // View item... y = ch - h1 * (pEvent->note() + 1); rect.setRect(x - x0, y, w1, h1); } else { // Event item... if (pEvent->type() == qtractorMidiEvent::PITCHBEND) y = y0 - (y0 * pEvent->pitchBend()) / 8192; else y = y0 - (y0 * pEvent->value()) / 128; if (!m_bNoteDuration) w1 = 5; if (y < y0) rect.setRect(x - x0, y, w1, y0 - y); else if (y > y0) rect.setRect(x - x0, y0, w1, y - y0); else rect.setRect(x - x0, y0 - 2, w1, 4); } // Do we have a point? if (rect.contains(pos)) { if (pRect) *pRect = rect; pEventAt = pEvent; // Whether event is also selected... if (m_select.findItem(pEventAt)) break; } } // Maybe next one... pEvent = pEvent->next(); } return pEventAt; } // Start immediate some drag-edit mode... qtractorMidiEvent *qtractorMidiEditor::dragEditEvent ( qtractorScrollView *pScrollView, const QPoint& pos, Qt::KeyboardModifiers modifiers ) { if (m_pMidiClip == NULL) return NULL; qtractorMidiSequence *pSeq = m_pMidiClip->sequence(); if (pSeq == NULL) return NULL; const bool bEditView = (static_cast (m_pEditView) == pScrollView); qtractorMidiEvent::EventType etype = (bEditView ? m_pEditView->eventType() : m_pEditEvent->eventType()); int ch = m_pEditView->contentsHeight(); int h1 = m_pEditList->itemHeight(); unsigned char note = (ch - pos.y()) / h1; if (m_iSnapToScaleType > 0) note = snapToScale(note, m_iSnapToScaleKey, m_iSnapToScaleType); // Check for note/pitch changes... if (bEditView && m_bEventDragEdit && m_pEventDrag && (etype == qtractorMidiEvent::NOTEON || etype == qtractorMidiEvent::KEYPRESS) && m_pEventDrag->note() == note) return NULL; // Must be inside the visible event canvas and // not about to drag(draw) event-value resizing... if (!bEditView && !m_bEventDragEdit && m_pEventDrag == NULL && isDragEventResize(modifiers)) return NULL; const int h0 = ((m_pEditEvent->viewport())->height() & ~1); // even. const int y0 = (etype == qtractorMidiEvent::PITCHBEND ? h0 >> 1 : h0); const int ymin = 1; const int ymax = h0; int y = pos.y(); if (y < ymin) y = ymin; else if (y > ymax) y = ymax; // Compute onset time from given horizontal position... int x0 = m_pTimeScale->pixelFromFrame(m_iOffset); int x1 = x0 + pos.x(); int y1 = 0; qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(m_iOffset); unsigned long t0 = pNode->tickFromFrame(m_iOffset); // This would the new event onset time... pNode = cursor.seekPixel(x1); unsigned long t1 = pNode->tickSnap(pNode->tickFromPixel(x1), 8) - t0; // Check for time/onset changes and whether it's already drawn... if (m_bEventDragEdit && m_pEventDrag) { const qtractorMidiEditSelect::ItemList& items = m_select.items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorMidiEvent *pEvent = iter.key(); qtractorMidiEditSelect::Item *pItem = iter.value(); if (bEditView && pEvent->type() == qtractorMidiEvent::NOTEON) { if (pEvent->note() == note) { if (t1 >= pEvent->time() && t1 < pEvent->time() + pEvent->duration()) { m_rectDrag = pItem->rectView; m_posDrag = pos; // m_rectDrag.topLeft(); return pEvent; } } else if (!m_bEditModeDraw && pEvent == m_pEventDrag) { // Bump pitch... pEvent->setNote(note); pItem->rectView.moveTop(ch - h1 * (note + 1)); m_select.updateItem(pItem); m_rectDrag = pItem->rectView; m_posDrag = pos; // m_rectDrag.topLeft(); resizeEvent(pEvent, timeDelta(pScrollView), 0); // m_posDelta = QPoint(0, 0); if (m_bSendNotes) m_pEditList->dragNoteOn(note, pEvent->velocity()); // Bumped. return NULL; } } else if (t1 == pEvent->time()) { m_rectDrag = (bEditView ? pItem->rectView : pItem->rectEvent); // m_posDrag = pos; // m_rectDrag.topLeft(); return pEvent; } } // No new events if ain't drawing... if (!m_bEditModeDraw) return NULL; } // Create a brand new event... qtractorMidiEvent *pEvent = new qtractorMidiEvent(t1, etype); x1 = pNode->pixelFromTick(t0 + t1); switch (pEvent->type()) { case qtractorMidiEvent::NOTEON: case qtractorMidiEvent::KEYPRESS: // Set note event value... if (bEditView) { pEvent->setNote(note); pEvent->setVelocity(m_last.value); } else { pEvent->setNote(m_last.note); if (y0 > 0) pEvent->setVelocity((128 * (y0 - y)) / y0); else pEvent->setVelocity(m_last.value); } // Default duration... if (pEvent->type() == qtractorMidiEvent::NOTEON) { unsigned long iDuration = m_pTimeScale->ticksPerBeat(); if (m_pTimeScale->snapPerBeat() > 0) iDuration /= m_pTimeScale->snapPerBeat(); pEvent->setDuration(iDuration); // Mark that we've a note pending... if (m_bSendNotes) m_pEditList->dragNoteOn(pEvent->note(), pEvent->velocity()); } break; case qtractorMidiEvent::PITCHBEND: // Set pitchbend event value... if (y0 > 0) pEvent->setPitchBend((8192 * (y0 - y)) / y0); else pEvent->setPitchBend(m_last.pitchBend); break; case qtractorMidiEvent::CONTROLLER: // Set controller event... pEvent->setController(m_pEditEvent->controller()); // Fall thru... default: // Set generic event value... if (y0 > 0) pEvent->setValue((128 * (y0 - y)) / y0); else pEvent->setValue(m_last.value); break; } // Now try to get the visual rectangular coordinates... int w1 = pNode->pixelFromTick( t0 + pEvent->time() + pEvent->duration()) - x1; if (w1 < 5) w1 = 5; // View item... QRect rectView; if (pEvent->type() == m_pEditView->eventType() && (pEvent->type() == qtractorMidiEvent::NOTEON || pEvent->type() == qtractorMidiEvent::KEYPRESS)) { y1 = ch - h1 * (pEvent->note() + 1); rectView.setRect(x1 - x0, y1, w1, h1); } // Event item... QRect rectEvent; if (pEvent->type() == m_pEditEvent->eventType()) { if (pEvent->type() == qtractorMidiEvent::PITCHBEND) { y1 = y0 - (y0 * pEvent->pitchBend()) / 8192; if (y1 > y0) { h1 = y1 - y0; y1 = y0; } else { h1 = y0 - y1; } } else { y1 = y0 - (y0 * pEvent->value()) / 128; h1 = y0 - y1; m_resizeMode = ResizeValue; } if (!m_bNoteDuration) w1 = 5; if (h1 < 3) h1 = 3; rectEvent.setRect(x1 - x0, y1, w1, h1); } // Set the correct target rectangle... m_rectDrag = (bEditView ? rectView : rectEvent); m_posDrag = pos; // m_rectDrag.topLeft(); // Just add this one the selection... if (!m_bEventDragEdit || m_pEventDrag == NULL) clearSelect(); m_select.selectItem(pEvent, rectEvent, rectView, true, false); // Set the proper resize-mode... if (bEditView && pEvent->type() == qtractorMidiEvent::NOTEON) { m_resizeMode = ResizeNoteRight; } else if (pEvent->type() == qtractorMidiEvent::PITCHBEND) { m_resizeMode = ResizePitchBend; } else { m_resizeMode = ResizeValue; } // Let it be a drag resize mode... return pEvent; } // Track drag-move-select cursor and mode... qtractorMidiEvent *qtractorMidiEditor::dragMoveEvent ( qtractorScrollView *pScrollView, const QPoint& pos, Qt::KeyboardModifiers modifiers ) { qtractorMidiEvent *pEvent = eventAt(pScrollView, pos, &m_rectDrag); // Make the anchor event, if any, visible yet... m_resizeMode = ResizeNone; if (pEvent) { const bool bEditView = (static_cast (m_pEditView) == pScrollView); Qt::CursorShape shape = Qt::PointingHandCursor; if (bEditView) { if (pEvent->type() == qtractorMidiEvent::NOTEON) { if (pos.x() > m_rectDrag.right() - 4) { m_resizeMode = ResizeNoteRight; shape = Qt::SplitHCursor; } else if (pos.x() < m_rectDrag.left() + 4) { m_resizeMode = ResizeNoteLeft; shape = Qt::SplitHCursor; } } } else { if (pEvent->type() == qtractorMidiEvent::NOTEON) { if (pos.y() < m_rectDrag.top() + 4) { m_resizeMode = ResizeValue; shape = Qt::SplitVCursor; } else if (m_bNoteDuration) { if (pos.x() > m_rectDrag.right() - 4) { m_resizeMode = ResizeNoteRight; shape = Qt::SplitHCursor; } else if (pos.x() < m_rectDrag.left() + 4) { m_resizeMode = ResizeNoteLeft; shape = Qt::SplitHCursor; } } } else if (pEvent->type() == qtractorMidiEvent::PITCHBEND) { const int y0 = (((m_pEditEvent->viewport())->height() & ~1) >> 1); if ((pos.y() < y0 && pos.y() < m_rectDrag.top() + 4) || (pos.y() > y0 && pos.y() > m_rectDrag.bottom() - 4)) { m_resizeMode = ResizePitchBend; shape = Qt::SplitVCursor; } } else if (pos.y() < m_rectDrag.top() + 4) { m_resizeMode = ResizeValue; shape = Qt::SplitVCursor; } if (m_resizeMode == ResizeNone && isDragEventResize(modifiers)) { shape = Qt::ArrowCursor; pEvent = NULL; } } if ((m_resizeMode == ResizeNoteRight || m_resizeMode == ResizePitchBend || m_resizeMode == ResizeValue) && (modifiers & Qt::ControlModifier)) m_dragCursor = DragRescale; else m_dragCursor = DragResize; pScrollView->setCursor(QCursor(shape)); } else if (m_dragState == DragNone) { m_dragCursor = DragNone; pScrollView->unsetCursor(); } return pEvent; } // Start drag-move-selecting... void qtractorMidiEditor::dragMoveStart ( qtractorScrollView *pScrollView, const QPoint& pos, Qt::KeyboardModifiers modifiers ) { // Are we already step-moving or pasting something? switch (m_dragState) { case DragStep: // One-click change from drag-step to drag-move... m_dragState = DragMove; m_posDrag = m_rectDrag.center(); m_posStep = QPoint(0, 0); updateDragMove(pScrollView, pos + m_posStep); // Fall thru... case DragPaste: return; default: break; } // Force null state. resetDragState(pScrollView); // Remember what and where we'll be dragging/selecting... m_dragState = DragStart; m_posDrag = pos; m_pEventDrag = dragMoveEvent(pScrollView, m_posDrag, modifiers); // Check whether we're about to create something... if (m_pEventDrag == NULL && m_bEditMode && (modifiers & (Qt::ShiftModifier | Qt::ControlModifier)) == 0) { m_dragCursor = m_dragState; m_pEventDrag = dragEditEvent(pScrollView, m_posDrag, modifiers); m_bEventDragEdit = (m_pEventDrag != NULL); pScrollView->setCursor(QCursor(QPixmap(":/images/editModeOn.png"), 5, 18)); } else if (m_resizeMode == ResizeNone) { m_dragCursor = m_dragState; if (m_pEventDrag) { pScrollView->setCursor(QCursor( static_cast (m_pEditView) == pScrollView ? Qt::SizeAllCursor : Qt::SizeHorCursor)); } else { pScrollView->setCursor(QCursor(Qt::CrossCursor)); } } // Maybe we'll have a note pending... if (m_bSendNotes && m_pEventDrag && m_pEventDrag->type() == qtractorMidiEvent::NOTEON) m_pEditList->dragNoteOn(m_pEventDrag->note(), m_pEventDrag->velocity()); } // Update drag-move-selection... void qtractorMidiEditor::dragMoveUpdate ( qtractorScrollView *pScrollView, const QPoint& pos, Qt::KeyboardModifiers modifiers ) { int flags = SelectNone; switch (m_dragState) { case DragStart: // Did we moved enough around? if ((pos - m_posDrag).manhattanLength() < QApplication::startDragDistance()) break; // Take care of selection modifier... if ((modifiers & (Qt::ShiftModifier | Qt::ControlModifier)) == 0) flags |= SelectClear; // Are we about to move something around? if (m_pEventDrag) { if (m_resizeMode == ResizeNone) { // Start moving... take care of yet initial selection... updateDragSelect(pScrollView, QRect(m_posDrag, QSize(1, 1)), flags | SelectCommit); // Start drag-moving... m_dragState = DragMove; updateDragMove(pScrollView, pos + m_posStep); } else { // Start resizing... take care of yet initial selection... if (!m_bEventDragEdit && !m_select.findItem(m_pEventDrag)) { updateDragSelect(pScrollView, QRect(m_posDrag, QSize(1, 1)), flags | SelectCommit); } // Start drag-resizing/rescaling... if ((m_resizeMode == ResizeNoteRight || m_resizeMode == ResizePitchBend || m_resizeMode == ResizeValue) && (modifiers & Qt::ControlModifier)) { m_dragState = DragRescale; updateDragRescale(pScrollView, pos); } else { m_dragState = DragResize; updateDragResize(pScrollView, pos); } } break; } // About to drag(draw) event-value reszing... if (static_cast (pScrollView) == m_pEditEvent && isDragEventResize(modifiers)) { m_dragState = DragEventResize; updateDragEventResize(pos); break; } // Just about to start rubber-banding... m_dragState = DragSelect; // Fall thru... case DragSelect: { // Set new rubber-band extents... ensureVisible(pScrollView, pos); if (modifiers & Qt::ControlModifier) flags |= SelectToggle; const QRect& rect = QRect(m_posDrag, pos).normalized(); updateDragSelect(pScrollView, rect, flags); showToolTip(pScrollView, rect); break; } case DragMove: case DragPaste: // Drag-moving... updateDragMove(pScrollView, pos + m_posStep); break; case DragRescale: // Drag-rescaling... updateDragRescale(pScrollView, pos); break; case DragResize: // Drag-resizing... updateDragResize(pScrollView, pos); // Drag-edit/drawing... if (m_bEventDragEdit && m_pEventDrag) { qtractorMidiEvent *pEvent = dragEditEvent(pScrollView, pos, modifiers); if (pEvent && pEvent != m_pEventDrag) { resizeEvent(m_pEventDrag, timeDelta(pScrollView), valueDelta(pScrollView)); m_posDelta = QPoint(0, 0); m_pEventDrag = pEvent; } } break; case DragEventResize: // Drag(draw) resizing... updateDragEventResize(pos); break; case DragStep: case DragNone: default: // Just make cursor tell something... dragMoveEvent(pScrollView, pos, modifiers); break; } // Let note hovering shine... m_pEditList->dragNoteOn(pos, -1); } // Commit drag-move-selection... void qtractorMidiEditor::dragMoveCommit ( qtractorScrollView *pScrollView, const QPoint& pos, Qt::KeyboardModifiers modifiers ) { int flags = qtractorMidiEditor::SelectCommit; switch (m_dragState) { case DragStart: // Were we about to edit-resize something? if (m_bEventDragEdit) { m_dragState = DragResize; executeDragResize(pScrollView, pos); break; } // Take care of selection modifier... if ((modifiers & (Qt::ShiftModifier | Qt::ControlModifier)) == 0) flags |= SelectClear; else // Shall we move the playhead?... if (m_pEventDrag == NULL) { // Direct snap positioning... unsigned long iFrame = m_pTimeScale->frameSnap(m_iOffset + m_pTimeScale->frameFromPixel(pos.x() > 0 ? pos.x() : 0)); // Playhead positioning... setPlayHead(iFrame); // Immediately commited... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) pSession->setPlayHead(iFrame); } // Fall thru... case DragSelect: // Terminate selection... ensureVisible(pScrollView, pos); if (modifiers & Qt::ControlModifier) flags |= SelectToggle; updateDragSelect(pScrollView, QRect(m_posDrag, pos).normalized(), flags); selectionChangeNotify(); break; case DragMove: // Move it... executeDragMove(pScrollView, pos); break; case DragPaste: // Paste it... executeDragPaste(pScrollView, pos); break; case DragRescale: // Rescale it... executeDragRescale(pScrollView, pos); break; case DragResize: // Resize it... executeDragResize(pScrollView, pos); break; case DragEventResize: // Resize(by drawing) it... executeDragEventResize(pos); break; case DragStep: case DragNone: default: break; } // Force null state. resetDragState(pScrollView); } // Trap for help/tool-tip and leave events. bool qtractorMidiEditor::dragMoveFilter ( qtractorScrollView *pScrollView, QObject *pObject, QEvent *pEvent ) { if (static_cast (pObject) == pScrollView->viewport()) { if (pEvent->type() == QEvent::ToolTip && m_bToolTips) { QHelpEvent *pHelpEvent = static_cast (pEvent); if (pHelpEvent) { const QPoint& pos = pScrollView->viewportToContents(pHelpEvent->pos()); qtractorMidiEvent *pMidiEvent = eventAt(pScrollView, pos); if (pMidiEvent) { QToolTip::showText( pHelpEvent->globalPos(), eventToolTip(pMidiEvent), pScrollView->viewport()); return true; } else { const QString sToolTip("%1 (%2)"); int note = m_last.note; if (pScrollView == static_cast (m_pEditView)) { int ch = m_pEditList->contentsHeight(); note = (ch - pos.y()) / m_pEditList->itemHeight(); } QToolTip::showText( pHelpEvent->globalPos(), sToolTip.arg(noteName(note)).arg(note), pScrollView->viewport()); return true; } } } else if (pEvent->type() == QEvent::Leave && m_dragState != DragPaste && m_dragState != DragStep) { m_dragCursor = DragNone; pScrollView->unsetCursor(); m_pEditList->dragNoteOn(-1); return true; } } // Not handled here. return false; } // Update the event selection list. void qtractorMidiEditor::updateDragSelect ( qtractorScrollView *pScrollView, const QRect& rectSelect, int flags ) { if (m_pMidiClip == NULL) return; qtractorMidiSequence *pSeq = m_pMidiClip->sequence(); if (pSeq == NULL) return; // Rubber-banding only applicable whenever // the selection rectangle is not that empty... bool bRectSelect = (rectSelect.width() > 1 || rectSelect.height() > 1); if (bRectSelect) { // Create rubber-band, if not already... if (m_pRubberBand == NULL) { m_pRubberBand = new qtractorRubberBand( QRubberBand::Rectangle, pScrollView->viewport()); m_pRubberBand->show(); } // Rubber-band selection... m_pRubberBand->setGeometry(QRect( pScrollView->contentsToViewport(rectSelect.topLeft()), rectSelect.size())); } // Do the drag-select update properly... const bool bEditView = (static_cast (m_pEditView) == pScrollView); QRect rectUpdateView(m_select.rectView()); QRect rectUpdateEvent(m_select.rectEvent()); if (flags & SelectClear) m_select.clear(); qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(m_iOffset); unsigned long t0 = pNode->tickFromFrame(m_iOffset); int x0 = m_pTimeScale->pixelFromFrame(m_iOffset); int x1, x2; if (bRectSelect) { x1 = pScrollView->contentsX(); x2 = x1 + (pScrollView->viewport())->width(); if (x1 > rectSelect.left()) x1 = rectSelect.left(); if (x2 < rectSelect.right()) x2 = rectSelect.right(); } else { x1 = x2 = rectSelect.x(); } if (--x0 < 0) x0 = 0; if (--x1 < 0) x1 = 0; ++x2; pNode = cursor.seekPixel(x0 + x1); unsigned long t1 = pNode->tickFromPixel(x0 + x1); unsigned long iTickStart = (t1 > t0 ? t1 - t0 : 0); pNode = cursor.seekPixel(x0 + x2); unsigned long t2 = pNode->tickFromPixel(x0 + x2); unsigned long iTickEnd = (t2 > t0 ? t2 - t0 : 0); // This is the edit-view spacifics... int h1 = m_pEditList->itemHeight(); int ch = m_pEditView->contentsHeight(); // + 1; // This is the edit-event zero-line... const qtractorMidiEvent::EventType etype = m_pEditEvent->eventType(); const int h0 = ((m_pEditEvent->viewport())->height() & ~1); // even. const int y0 = (etype == qtractorMidiEvent::PITCHBEND ? h0 >> 1 : h0); bool bController = (etype == qtractorMidiEvent::CONTROLLER); unsigned char controller = m_pEditEvent->controller(); qtractorMidiEvent *pEvent = m_cursorAt.seek(pSeq, iTickStart); qtractorMidiEvent *pEventAt = NULL; QRect rectViewAt; QRect rectEventAt; while (pEvent && iTickEnd >= pEvent->time()) { if (((bEditView && pEvent->type() == m_pEditView->eventType()) || (!bEditView && (pEvent->type() == m_pEditEvent->eventType() && (!bController || pEvent->controller() == controller))))) { // Assume unselected... bool bSelect = false; // Common event coords... int y; t1 = t0 + pEvent->time(); t2 = t1 + pEvent->duration(); pNode = cursor.seekTick(t1); int x = pNode->pixelFromTick(t1) - 1; int w1 = pNode->pixelFromTick(t2) - x; if (w1 < 5) w1 = 5; // View item... QRect rectView; if (pEvent->type() == m_pEditView->eventType()) { y = ch - h1 * (pEvent->note() + 1); rectView.setRect(x - x0, y, w1, h1); if (bEditView) bSelect = rectSelect.intersects(rectView); } // Event item... QRect rectEvent; if (pEvent->type() == m_pEditEvent->eventType()) { if (pEvent->type() == qtractorMidiEvent::PITCHBEND) y = y0 - (y0 * pEvent->pitchBend()) / 8192; else y = y0 - (y0 * pEvent->value()) / 128; if (!m_bNoteDuration) w1 = 5; if (y < y0) rectEvent.setRect(x - x0, y, w1, y0 - y); else if (y > y0) rectEvent.setRect(x - x0, y0, w1, y - y0); else rectEvent.setRect(x - x0, y0 - 2, w1, 4); if (!bEditView) bSelect = rectSelect.intersects(rectEvent); } // Select item... if (bRectSelect) { m_select.selectItem(pEvent, rectEvent, rectView, bSelect, flags & SelectToggle); } else if (bSelect) { pEventAt = pEvent; rectViewAt = rectView; rectEventAt = rectEvent; } } // Lookup next... pEvent = pEvent->next(); } // Most evident single selection... if (pEventAt /* && !bRectSelect*/) { m_select.selectItem(pEventAt, rectEventAt, rectViewAt, true, flags & SelectToggle); } // Commit selection... bool bCommit = (flags & SelectCommit); m_select.update(bCommit); rectUpdateView = rectUpdateView.united(m_select.rectView()); m_pEditView->viewport()->update(QRect( m_pEditView->contentsToViewport(rectUpdateView.topLeft()), rectUpdateView.size())); rectUpdateEvent = rectUpdateEvent.united(m_select.rectEvent()); m_pEditEvent->viewport()->update(QRect( m_pEditEvent->contentsToViewport(rectUpdateEvent.topLeft()), rectUpdateEvent.size())); #if 0 if (bEditView) { setEditHead(m_pTimeScale->frameSnap(m_iOffset + m_pTimeScale->frameFromPixel(rectSelect.left())), bCommit); setEditTail(m_pTimeScale->frameSnap(m_iOffset + m_pTimeScale->frameFromPixel(rectSelect.right())), bCommit); } #endif } // Compute current drag time snap (in ticks). long qtractorMidiEditor::timeSnap ( long iTime ) const { qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(m_iOffset); unsigned long t0 = pNode->tickFromFrame(m_iOffset); unsigned long t1 = t0 + iTime; pNode = cursor.seekTick(t1); iTime = long(pNode->tickSnap(t1)) - long(t0); return (iTime > 0 ? iTime : 0); } // Compute current drag time delta (in ticks). long qtractorMidiEditor::timeDelta ( qtractorScrollView *pScrollView ) const { DragTimeScale dts(m_pTimeScale, m_iOffset); int x1, x2; unsigned long t1, t2; if (m_pEventDrag) { t1 = dts.t0 + m_pEventDrag->time(); dts.node = dts.cursor.seekTick(t1); x1 = dts.node->pixelFromTick(t1); } else { x1 = dts.x0 + ( static_cast (m_pEditView) == pScrollView ? m_select.rectView().x() : m_select.rectEvent().x()); dts.node = dts.cursor.seekPixel(x1); t1 = dts.node->tickFromPixel(x1); } x2 = x1 + m_posDelta.x(); dts.node = dts.cursor.seekPixel(x2); t2 = dts.node->tickFromPixel(x2); return long(dts.node->tickSnap(t2)) - long(t1); // return long(t2) - long(t1); } // Compute current drag note delta. int qtractorMidiEditor::noteDelta ( qtractorScrollView *pScrollView ) const { int iNoteDelta = 0; if (pScrollView == static_cast (m_pEditView)) { int h1 = m_pEditList->itemHeight(); if (h1 > 0) iNoteDelta = -(m_posDelta.y() / h1); } return iNoteDelta; } // Compute current drag value delta. int qtractorMidiEditor::valueDelta ( qtractorScrollView *pScrollView ) const { int iValueDelta = 0; if (pScrollView == static_cast (m_pEditEvent)) { const int h0 = ((m_pEditEvent->viewport())->height() & ~1); // even. if (h0 > 1) { if (m_resizeMode == ResizePitchBend) iValueDelta = -(m_posDelta.y() * 8192) / (h0 >> 1); else iValueDelta = -(m_posDelta.y() * 128) / h0; } } return iValueDelta; } // Apply the event drag-resize (also editing). void qtractorMidiEditor::resizeEvent ( qtractorMidiEvent *pEvent, long iTimeDelta, int iValueDelta, qtractorMidiEditCommand *pEditCommand ) { long iTime, iDuration; int iValue; switch (m_resizeMode) { case ResizeNoteLeft: iTime = timeSnap(long(pEvent->time()) + iTimeDelta); iDuration = long(pEvent->duration()) + (long(pEvent->time()) - iTime); if (iDuration < 1) iDuration = 1; if (m_bEventDragEdit) { pEvent->setTime(iTime); pEvent->setDuration(iDuration); if (pEditCommand) pEditCommand->insertEvent(pEvent); } else if (pEditCommand) pEditCommand->resizeEventTime(pEvent, iTime, iDuration); if (pEvent == m_pEventDrag) { m_last.note = pEvent->note(); m_last.duration = iDuration; } break; case ResizeNoteRight: iTime = pEvent->time(); iDuration = timeSnap( long(pEvent->time() + pEvent->duration()) + iTimeDelta) - iTime; if (iDuration < 1) iDuration = 1; if (m_bEventDragEdit) { pEvent->setDuration(iDuration); if (pEditCommand) pEditCommand->insertEvent(pEvent); } else if (pEditCommand) pEditCommand->resizeEventTime(pEvent, iTime, iDuration); if (pEvent == m_pEventDrag) { m_last.note = pEvent->note(); m_last.duration = iDuration; } break; case ResizeValue: iValue = int(pEvent->value()) + iValueDelta; if (iValue < 0) iValue = 0; else if (iValue > 127) iValue = 127; if (m_bEventDragEdit) { pEvent->setValue(iValue); if (pEditCommand) pEditCommand->insertEvent(pEvent); } else if (pEditCommand) pEditCommand->resizeEventValue(pEvent, iValue); if (pEvent == m_pEventDrag) m_last.value = iValue; break; case ResizePitchBend: iValue = pEvent->pitchBend() + iValueDelta; if (iValue < -8191) iValue = -8191; else if (iValue > +8191) iValue = +8191; if (m_bEventDragEdit) { pEvent->setPitchBend(iValue); if (pEditCommand) pEditCommand->insertEvent(pEvent); } else if (pEditCommand) pEditCommand->resizeEventValue(pEvent, iValue); if (pEvent == m_pEventDrag) m_last.pitchBend = iValue; // Fall thru... default: break; } if (m_bEventDragEdit && pEditCommand == NULL) updateEvent(pEvent); } // Update event selection rectangle. void qtractorMidiEditor::updateEvent ( qtractorMidiEvent *pEvent ) { qtractorMidiEditSelect::Item *pItem = m_select.findItem(pEvent); if (pItem == NULL) return; // Update selection visual rectangles... updateEventRects(pEvent, pItem->rectEvent, pItem->rectView); m_select.updateItem(pItem); } // Update event visual rectangles. void qtractorMidiEditor::updateEventRects ( qtractorMidiEvent *pEvent, QRect& rectEvent, QRect& rectView ) const { qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(m_iOffset); unsigned long t0 = pNode->tickFromFrame(m_iOffset); int x0 = m_pTimeScale->pixelFromFrame(m_iOffset); // This is the edit-view spacifics... int h1 = m_pEditList->itemHeight(); int ch = m_pEditView->contentsHeight(); // + 1; // This is the edit-event zero-line... const qtractorMidiEvent::EventType etype = m_pEditEvent->eventType(); const int h0 = ((m_pEditEvent->viewport())->height() & ~1); // even. const int y0 = (etype == qtractorMidiEvent::PITCHBEND ? h0 >> 1 : h0); // Common event coords... unsigned long t1 = t0 + pEvent->time(); unsigned long t2 = t1 + pEvent->duration(); pNode = cursor.seekTick(t1); int x = pNode->pixelFromTick(t1) - 1; int w1 = pNode->pixelFromTick(t2) - x; if (w1 < 5) w1 = 5; // View item... int y; if (pEvent->type() == m_pEditView->eventType()) { y = ch - h1 * (pEvent->note() + 1); rectView.setRect(x - x0, y, w1, h1); } else rectView.setRect(0, 0, 0, 0); // Event item... if (pEvent->type() == m_pEditEvent->eventType()) { if (pEvent->type() == qtractorMidiEvent::PITCHBEND) y = y0 - (y0 * pEvent->pitchBend()) / 8192; else y = y0 - (y0 * pEvent->value()) / 128; if (!m_bNoteDuration) w1 = 5; if (y < y0) rectEvent.setRect(x - x0, y, w1, y0 - y); else if (y > y0) rectEvent.setRect(x - x0, y0, w1, y - y0); else rectEvent.setRect(x - x0, y0 - 2, w1, 4); } else rectEvent.setRect(0, 0, 0, 0); } // Drag-move current selection. void qtractorMidiEditor::updateDragMove ( qtractorScrollView *pScrollView, const QPoint& pos ) { ensureVisible(pScrollView, pos); const bool bEditView = (static_cast (m_pEditView) == pScrollView); QRect rectUpdateView(m_select.rectView().translated(m_posDelta)); QRect rectUpdateEvent(m_select.rectEvent().translated(m_posDelta.x(), 0)); QPoint delta(pos - m_posDrag); QRect rect(bEditView ? m_select.rectView() : m_select.rectEvent()); int cw = pScrollView->contentsWidth(); int dx = delta.x(); int x0 = m_rectDrag.x() + m_pTimeScale->pixelFromFrame(m_iOffset); int x1 = rect.x() + dx; if (x1 < 0) dx = -(rect.x()); if (x1 + rect.width() > cw) dx = cw - rect.right(); m_posDelta.setX(m_pTimeScale->pixelSnap(x0 + dx) - x0); int h1 = m_pEditList->itemHeight(); if (bEditView && h1 > 0) { int ch = m_pEditView->contentsHeight(); int y0 = rect.y(); int y1 = y0 + delta.y(); if (y1 < 0) y1 = 0; if (y1 + rect.height() > ch) y1 = ch - rect.height(); unsigned char note = 127 - (y1 / h1); if (m_iSnapToScaleType > 0) note = snapToScale(note, m_iSnapToScaleKey, m_iSnapToScaleType); m_posDelta.setY(h1 * (127 - note) - y0); } else { m_posDelta.setY(0); } rectUpdateView = rectUpdateView.united( m_select.rectView().translated(m_posDelta)); m_pEditView->viewport()->update(QRect( m_pEditView->contentsToViewport(rectUpdateView.topLeft()), rectUpdateView.size())); rectUpdateEvent = rectUpdateEvent.united( m_select.rectEvent().translated(m_posDelta.x(), 0)); m_pEditEvent->viewport()->update(QRect( m_pEditEvent->contentsToViewport(rectUpdateEvent.topLeft()), rectUpdateEvent.size())); // Maybe we've change some note pending... if (m_bSendNotes && m_pEventDrag && m_pEventDrag->type() == qtractorMidiEvent::NOTEON) { int iNote = int(m_pEventDrag->note()); if (h1 > 0) iNote -= (m_posDelta.y() / h1); m_pEditList->dragNoteOn(iNote, m_pEventDrag->velocity()); } // Show anchor event tooltip... if (m_bToolTips) { qtractorMidiEvent *pEvent = m_pEventDrag; if (pEvent == NULL) pEvent = m_select.anchorEvent(); if (pEvent) { QToolTip::showText( QCursor::pos(), eventToolTip(pEvent, timeDelta(pScrollView), noteDelta(pScrollView), 0), pScrollView->viewport()); } } } // Drag-rescale current selection. void qtractorMidiEditor::updateDragRescale ( qtractorScrollView *pScrollView, const QPoint& pos ) { ensureVisible(pScrollView, pos); QRect rectUpdateView(m_select.rectView()); QRect rectUpdateEvent(m_select.rectEvent()); QPoint delta(pos - m_posDrag); int x0, x1; int y0, y1; int dx = 0; int dy = 0; switch (m_resizeMode) { case ResizeNoteRight: dx = delta.x(); x0 = m_rectDrag.right() + m_pTimeScale->pixelFromFrame(m_iOffset); x1 = m_rectDrag.right() + dx; if (x1 < m_rectDrag.left()) dx = -(m_rectDrag.width()); dx = m_pTimeScale->pixelSnap(x0 + dx) - x0; break; case ResizeValue: case ResizePitchBend: dy = delta.y(); y0 = m_rectDrag.bottom(); y1 = y0 + dy; dy = y1 - y0; // Fall thru... default: break; } m_posDelta.setX(dx); m_posDelta.setY(dy); const QRect& rectView = (m_pEditView->viewport())->rect(); const QRect& rectEvent = (m_pEditEvent->viewport())->rect(); if (dx) { rectUpdateView.setLeft(rectView.left()); rectUpdateView.setRight(rectView.right()); rectUpdateEvent.setLeft(rectEvent.left()); rectUpdateEvent.setRight(rectEvent.right()); } if (dy) { rectUpdateEvent.setTop(rectEvent.top()); rectUpdateEvent.setBottom(rectEvent.bottom()); } m_pEditView->viewport()->update(QRect( m_pEditView->contentsToViewport(rectUpdateView.topLeft()), rectUpdateView.size())); m_pEditEvent->viewport()->update(QRect( m_pEditEvent->contentsToViewport(rectUpdateEvent.topLeft()), rectUpdateEvent.size())); // Show anchor event tooltip... if (m_bToolTips) { qtractorMidiEvent *pEvent = m_pEventDrag; if (pEvent == NULL) pEvent = m_select.anchorEvent(); if (pEvent) { QToolTip::showText( QCursor::pos(), eventToolTip(pEvent, timeDelta(pScrollView), 0, valueDelta(pScrollView)), pScrollView->viewport()); } } } // Drag-resize current selection (also editing). void qtractorMidiEditor::updateDragResize ( qtractorScrollView *pScrollView, const QPoint& pos ) { ensureVisible(pScrollView, pos); QRect rectUpdateView(m_select.rectView().translated(m_posDelta.x(), 0)); QRect rectUpdateEvent(m_select.rectEvent().translated(m_posDelta)); QPoint delta(pos - m_posDrag); int x0, x1; int y0, y1; int dx = 0; int dy = 0; // TODO: Plenty of... switch (m_resizeMode) { case ResizeNoteLeft: dx = delta.x(); x0 = m_rectDrag.left() + m_pTimeScale->pixelFromFrame(m_iOffset); x1 = m_rectDrag.left() + dx; if (x1 < 0) dx = -(m_rectDrag.left()); if (x1 > m_rectDrag.right()) dx = +(m_rectDrag.width()); dx = m_pTimeScale->pixelSnap(x0 + dx) - x0; break; case ResizeNoteRight: dx = delta.x(); x0 = m_rectDrag.right() + m_pTimeScale->pixelFromFrame(m_iOffset); x1 = m_rectDrag.right() + dx; if (x1 < m_rectDrag.left()) dx = -(m_rectDrag.width()); dx = m_pTimeScale->pixelSnap(x0 + dx) - x0; break; case ResizeValue: case ResizePitchBend: dy = delta.y(); y0 = m_rectDrag.bottom(); y1 = y0 + dy; dy = y1 - y0; // Fall thru... default: break; } m_posDelta.setX(dx); m_posDelta.setY(dy); rectUpdateView = rectUpdateView.united( m_select.rectView().translated(dx, 0)); m_pEditView->viewport()->update(QRect( m_pEditView->contentsToViewport(rectUpdateView.topLeft()), rectUpdateView.size())); rectUpdateEvent = rectUpdateEvent.united( m_select.rectEvent().translated(dx, dy)); m_pEditEvent->viewport()->update(QRect( m_pEditEvent->contentsToViewport(rectUpdateEvent.topLeft()), rectUpdateEvent.size())); // Show anchor event tooltip... if (m_bToolTips) { qtractorMidiEvent *pEvent = m_pEventDrag; if (pEvent == NULL) pEvent = m_select.anchorEvent(); if (pEvent) { QToolTip::showText( QCursor::pos(), eventToolTip(pEvent, timeDelta(pScrollView), 0, valueDelta(pScrollView)), pScrollView->viewport()); } } } // Drag(draw) event value-resize check. bool qtractorMidiEditor::isDragEventResize ( Qt::KeyboardModifiers modifiers ) const { if (!m_bEditMode || !m_bEditModeDraw) return false; if (modifiers & (Qt::ShiftModifier | Qt::ControlModifier)) return false; const qtractorMidiEvent::EventType etype = m_pEditEvent->eventType(); const qtractorMidiEditSelect::ItemList& items = m_select.items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorMidiEvent *pEvent = iter.key(); qtractorMidiEditSelect::Item *pItem = iter.value(); if ((pItem->flags & 1) == 0) continue; if (pEvent->type() == etype) return true; } return false; } // Drag(draw) event value-resize to current selection... void qtractorMidiEditor::updateDragEventResize ( const QPoint& pos ) { m_pEditEvent->ensureVisible(pos.x(), 0, 16, 0); const QPoint delta(pos - m_posDrag); if (delta.manhattanLength() < 4) return; const qtractorMidiEvent::EventType etype = m_pEditEvent->eventType(); const int h0 = ((m_pEditEvent->viewport())->height() & ~1); // even. const int y0 = (etype == qtractorMidiEvent::PITCHBEND ? h0 >> 1 : h0); if (y0 < 1) return; const QRect& rectDrag = QRect(m_posDrag, m_posDragEventResize).normalized(); QRect rectUpdateEvent(m_select.rectEvent().united(rectDrag)); const int xmin = (delta.x() < 0 ? pos.x() : m_posDrag.x()); const int xmax = (delta.x() > 0 ? pos.x() : m_posDrag.x()); const int ymin = 1; const int ymax = h0; const float m = float(delta.y()) / float(delta.x()); const float b = float(pos.y()) - m * float(pos.x()); const qtractorMidiEditSelect::ItemList& items = m_select.items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorMidiEvent *pEvent = iter.key(); qtractorMidiEditSelect::Item *pItem = iter.value(); if ((pItem->flags & 1) == 0) continue; if (pEvent->type() != etype) continue; const QRect& rectEvent = pItem->rectEvent; if (rectEvent.right() < xmin || rectEvent.left() > xmax) continue; int y = int(m * float(rectEvent.x()) + b); if (pEvent->type() == qtractorMidiEvent::PITCHBEND) { if (y < ymin) y = ymin; else if (y > ymax) y = ymax; if (y > y0) { pItem->rectEvent.setBottom(y); y = y0; } else { pItem->rectEvent.setBottom(y0); } } pItem->rectEvent.setTop(y); pItem->flags |= 4; m_select.updateItem(pItem); } rectUpdateEvent = rectUpdateEvent.united(m_select.rectEvent()); m_pEditEvent->viewport()->update(QRect( m_pEditEvent->contentsToViewport(rectUpdateEvent.topLeft()), rectUpdateEvent.size())); m_posDragEventResize = pos; } // Finalize the event drag-move. void qtractorMidiEditor::executeDragMove ( qtractorScrollView *pScrollView, const QPoint& pos ) { if (m_pMidiClip == NULL) return; updateDragMove(pScrollView, pos + m_posStep); long iTimeDelta = timeDelta(pScrollView); int iNoteDelta = noteDelta(pScrollView); qtractorMidiEditCommand *pEditCommand = new qtractorMidiEditCommand(m_pMidiClip, tr("move")); const qtractorMidiEditSelect::ItemList& items = m_select.items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorMidiEvent *pEvent = iter.key(); qtractorMidiEditSelect::Item *pItem = iter.value(); if ((pItem->flags & 1) == 0) continue; int iNote = int(pEvent->note()) + iNoteDelta; if (iNote < 0) iNote = 0; if (iNote > 127) iNote = 127; long iTime = long(pEvent->time() + pItem->delta) + iTimeDelta; // if (pEvent == m_pEventDrag) // iTime = timeSnap(iTime); pEditCommand->moveEvent(pEvent, iNote, iTime); } // Make it as an undoable command... m_pCommands->exec(pEditCommand); } // Finalize the event drag-resize (also editing). void qtractorMidiEditor::executeDragResize ( qtractorScrollView *pScrollView, const QPoint& pos ) { if (m_pMidiClip == NULL) return; updateDragResize(pScrollView, pos); long iTimeDelta = timeDelta(pScrollView); int iValueDelta = valueDelta(pScrollView); qtractorMidiEditCommand *pEditCommand = new qtractorMidiEditCommand(m_pMidiClip, m_bEventDragEdit ? tr("edit") : tr("resize")); const qtractorMidiEditSelect::ItemList& items = m_select.items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorMidiEvent *pEvent = iter.key(); qtractorMidiEditSelect::Item *pItem = iter.value(); if ((pItem->flags & 1) == 0) continue; if (!m_bEventDragEdit || m_pEventDrag == pEvent) resizeEvent(pEvent, iTimeDelta, iValueDelta, pEditCommand); else resizeEvent(pEvent, 0, 0, pEditCommand); } // On edit mode we own the new events... if (m_bEventDragEdit) { m_bEventDragEdit = false; m_pEventDrag = NULL; m_select.clear(); } // Make it as an undoable command... m_pCommands->exec(pEditCommand); } // Finalize the event drag-rescale. void qtractorMidiEditor::executeDragRescale ( qtractorScrollView *pScrollView, const QPoint& pos ) { if (m_pMidiClip == NULL) return; if (m_pEventDrag == NULL) return; updateDragRescale(pScrollView, pos); DragTimeScale *pDts = NULL; int x1; unsigned long t1 = 0, t2; unsigned long d1 = 0, d2; int v1 = 0, v2; long iTimeDelta = 0; int iValueDelta = 0; switch (m_resizeMode) { case ResizeNoteRight: pDts = new DragTimeScale(m_pTimeScale, m_iOffset); t1 = pDts->t0 + m_pEventDrag->time(); pDts->node = pDts->cursor.seekTick(t1); x1 = pDts->node->pixelFromTick(t1); d1 = m_pEventDrag->duration(); x1 += m_posDelta.x(); pDts->node = pDts->cursor.seekPixel(x1); t2 = pDts->node->tickFromPixel(x1); iTimeDelta = long(pDts->node->tickSnap(t2)) - long(t1); break; case ResizeValue: v1 = m_pEventDrag->value(); iValueDelta = valueDelta(pScrollView); break; case ResizePitchBend: v1 = m_pEventDrag->pitchBend(); iValueDelta = valueDelta(pScrollView); // Fall thru... default: break; } qtractorMidiEditCommand *pEditCommand = new qtractorMidiEditCommand(m_pMidiClip, tr("rescale")); const qtractorMidiEditSelect::ItemList& items = m_select.items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorMidiEvent *pEvent = iter.key(); qtractorMidiEditSelect::Item *pItem = iter.value(); if ((pItem->flags & 1) == 0) continue; switch (m_resizeMode) { case ResizeNoteRight: if (pDts && d1 > 0) { d2 = pEvent->duration() * (d1 + iTimeDelta) / d1; if (d2 < 1) d2 = 1; t2 = pDts->t0 + pEvent->time(); if (t2 > t1) t2 = t1 + (t2 - t1) * (d1 + iTimeDelta) / d1; if (t2 < pDts->t0) t2 = pDts->t0; pEditCommand->resizeEventTime(pEvent, t2 - pDts->t0, d2); if (pEvent == m_pEventDrag) { m_last.note = pEvent->note(); m_last.duration = d2; } } break; case ResizeValue: if (v1) { v2 = pEvent->value() * (v1 + iValueDelta) / v1; if (v2 < 0) v2 = 0; else if (v2 > 127) v2 = 127; pEditCommand->resizeEventValue(pEvent, v2); if (pEvent == m_pEventDrag) m_last.value = v2; } break; case ResizePitchBend: if (v1) { v2 = pEvent->pitchBend() * (v1 + iValueDelta) / v1; if (v2 < -8191) v2 = -8191; else if (v2 > +8191) v2 = +8191; pEditCommand->resizeEventValue(pEvent, v2); if (pEvent == m_pEventDrag) m_last.pitchBend = v2; } // Fall thru... default: break; } } // Local cleanup. if (pDts) delete pDts; // Make it as an undoable command... m_pCommands->exec(pEditCommand); } // Finalize the event drag-paste. void qtractorMidiEditor::executeDragPaste ( qtractorScrollView *pScrollView, const QPoint& pos ) { if (m_pMidiClip == NULL) return; updateDragMove(pScrollView, pos + m_posStep); const bool bEditView = (static_cast (m_pEditView) == pScrollView); long iTimeDelta = timeDelta(pScrollView); int iNoteDelta = (bEditView ? noteDelta(pScrollView) : 0); qtractorMidiEditCommand *pEditCommand = new qtractorMidiEditCommand(m_pMidiClip, tr("paste")); QList events; const qtractorMidiEditSelect::ItemList& items = m_select.items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorMidiEvent *pEvent = new qtractorMidiEvent(*iter.key()); qtractorMidiEditSelect::Item *pItem = iter.value(); if ((pItem->flags & 1) == 0) continue; long iTime = long(pEvent->time() + pItem->delta) + iTimeDelta; // if (pEvent == m_pEventDrag) // iTime = timeSnap(iTime); pEvent->setTime(iTime); if (bEditView) { int iNote = int(pEvent->note()) + iNoteDelta; if (iNote < 0) iNote = 0; if (iNote > 127) iNote = 127; pEvent->setNote(iNote); } else if (m_pEditEvent->eventType() == qtractorMidiEvent::CONTROLLER) pEvent->setController(m_pEditEvent->controller()); pEditCommand->insertEvent(pEvent); events.append(pEvent); } // Make it as an undoable command... m_pCommands->exec(pEditCommand); // Remake current selection alright... if (!events.isEmpty()) { m_select.clear(); QListIterator event_iter(events); while (event_iter.hasNext()) { qtractorMidiEvent *pEvent = event_iter.next(); if (pEvent) { QRect rectEvent, rectView; updateEventRects(pEvent, rectEvent, rectView); m_select.addItem(pEvent, rectEvent, rectView); } } } } // Apply drag(draw) event value-resize to current selection. void qtractorMidiEditor::executeDragEventResize ( const QPoint& pos ) { if (m_pMidiClip == NULL) return; updateDragEventResize(pos); const qtractorMidiEvent::EventType etype = m_pEditEvent->eventType(); const int h0 = ((m_pEditEvent->viewport())->height() & ~1); // even. const int y0 = (etype == qtractorMidiEvent::PITCHBEND ? h0 >> 1 : h0); if (y0 < 1) return; qtractorMidiEditCommand *pEditCommand = new qtractorMidiEditCommand(m_pMidiClip, tr("resize")); const qtractorMidiEditSelect::ItemList& items = m_select.items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorMidiEvent *pEvent = iter.key(); qtractorMidiEditSelect::Item *pItem = iter.value(); if ((pItem->flags & 1) == 0) continue; if ((pItem->flags & 4) == 0) continue; if (pEvent->type() != etype) continue; int iValue = 0; int y = pItem->rectEvent.top(); if (pEvent->type() == qtractorMidiEvent::PITCHBEND) { if (y >= y0) y = pItem->rectEvent.bottom(); iValue = (8192 * (y0 - y)) / y0; pEditCommand->resizeEventValue(pEvent, iValue); if (pEvent == m_pEventDrag) m_last.pitchBend = iValue; } else { iValue = (128 * (y0 - y)) / y0; pEditCommand->resizeEventValue(pEvent, iValue); if (pEvent == m_pEventDrag) m_last.value = iValue; } pItem->flags &= ~4; } // Make it as an undoable command... m_pCommands->exec(pEditCommand); } // Visualize the event selection drag-move. void qtractorMidiEditor::paintDragState ( qtractorScrollView *pScrollView, QPainter *pPainter ) { #ifdef CONFIG_DEBUG_0 const QRect& rectSelect = (bEditView ? m_select.rectView() : m_select.rectEvent()); if (!rectSelect.isEmpty()) { pPainter->fillRect(QRect( pScrollView->contentsToViewport(rectSelect.topLeft()), rectSelect.size()), QColor(0, 0, 255, 40)); } #endif const bool bEditView = (static_cast (m_pEditView) == pScrollView); int x1, y1; DragTimeScale *pDts = NULL; unsigned long t1 = 0, t2; unsigned long d1 = 0, d2; int v1 = 0; long iTimeDelta = 0; int iValueDelta = 0; if (m_dragState == DragRescale && m_pEventDrag) { switch (m_resizeMode) { case ResizeNoteRight: pDts = new DragTimeScale(m_pTimeScale, m_iOffset); t1 = pDts->t0 + m_pEventDrag->time(); pDts->node = pDts->cursor.seekTick(t1); x1 = pDts->node->pixelFromTick(t1); d1 = m_pEventDrag->duration(); x1 += m_posDelta.x(); pDts->node = pDts->cursor.seekPixel(x1); t2 = pDts->node->tickFromPixel(x1); iTimeDelta = long(pDts->node->tickSnap(t2)) - long(t1); break; case ResizeValue: v1 = m_pEventDrag->value(); iValueDelta = valueDelta(pScrollView); break; case ResizePitchBend: v1 = m_pEventDrag->pitchBend(); iValueDelta = valueDelta(pScrollView); // Fall thru... default: break; } } const qtractorMidiEditSelect::ItemList& items = m_select.items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorMidiEvent *pEvent = iter.key(); qtractorMidiEditSelect::Item *pItem = iter.value(); if ((pItem->flags & 1) == 0) continue; int c = (pEvent == m_pEventDrag ? 64 : 0); QRect rect = (bEditView ? pItem->rectView : pItem->rectEvent); if (!m_bEventDragEdit || pEvent == m_pEventDrag) { if (m_dragState == DragRescale) { switch (m_resizeMode) { case ResizeNoteRight: if (pDts && d1 > 0) { t2 = pDts->t0 + pEvent->time(); if (t2 > t1) t2 = t1 + (t2 - t1) * (d1 + iTimeDelta) / d1; if (t2 < pDts->t0) t2 = pDts->t0; pDts->node = pDts->cursor.seekTick(t2); rect.setLeft( pDts->node->pixelFromTick(t2) - pDts->x0); if (bEditView || m_bNoteDuration) { d2 = pEvent->duration() * (d1 + iTimeDelta) / d1; if (d2 < 1) d2 = 1; rect.setRight( pDts->node->pixelFromTick(t2 + d2) - pDts->x0); } else rect.setWidth(5); } break; case ResizeValue: if (v1) { y1 = rect.height() * (v1 + iValueDelta) / v1; y1 = rect.bottom() - y1; if (y1 < 0) y1 = 0; rect.setTop(y1); } break; case ResizePitchBend: if (v1) { const int y0 = ((m_pEditEvent->viewport())->height() & ~1) >> 1; y1 = rect.height() * (v1 + iValueDelta) / v1; if (y0 > rect.top()) { y1 = rect.bottom() - y1; if (y1 < 0) y1 = 0; if (y1 > rect.bottom()) { rect.setTop(rect.bottom()); rect.setBottom(y1); } else { rect.setTop(y1); } } else if (y0 < rect.bottom()) { y1 = rect.top() + y1; if (y1 < 0) y1 = 0; if (y1 < rect.top()) { rect.setBottom(rect.top()); rect.setTop(y1); } else { rect.setBottom(y1); } } } // Fall thru... default: break; } } else if (m_dragState == DragResize) { switch (m_resizeMode) { case ResizeNoteLeft: x1 = rect.left() + m_posDelta.x(); if (x1 < 0) x1 = 0; if (x1 > rect.right()) x1 = rect.right(); rect.setLeft(x1); if (!bEditView && !m_bNoteDuration) rect.setWidth(5); break; case ResizeNoteRight: if (bEditView || m_bNoteDuration) { x1 = rect.right() + m_posDelta.x(); if (x1 < rect.left()) x1 = rect.left(); rect.setRight(x1); } break; case ResizeValue: if (!bEditView) { y1 = rect.top() + m_posDelta.y(); if (y1 < 0) y1 = 0; if (y1 > rect.bottom()) y1 = rect.bottom(); rect.setTop(y1); } break; case ResizePitchBend: if (!bEditView) { const int y0 = ((m_pEditEvent->viewport())->height() & ~1) >> 1; if (y0 > rect.top()) { y1 = rect.top() + m_posDelta.y(); if (y1 < 0) y1 = 0; if (y1 > rect.bottom()) { rect.setTop(rect.bottom()); rect.setBottom(y1); } else { rect.setTop(y1); } } else if (y0 < rect.bottom()) { y1 = rect.bottom() + m_posDelta.y(); if (y1 < 0) y1 = 0; if (y1 < rect.top()) { rect.setBottom(rect.top()); rect.setTop(y1); } else { rect.setBottom(y1); } } } // Fall thru... default: break; } } // Draw for selection/move... else if (bEditView) rect.translate(m_posDelta); else rect.translate(m_posDelta.x(), 0); } // Paint the damn bastard... pPainter->fillRect(QRect( pScrollView->contentsToViewport(rect.topLeft()), rect.size()), QColor(c, 0, 255 - c, 120)); } // Local cleanup. if (pDts) delete pDts; // Paint drag(draw) event-value line... if (!bEditView && m_dragState == DragEventResize) { QPen pen(Qt::DotLine); pen.setColor(Qt::blue); pPainter->setPen(pen); pPainter->drawLine( pScrollView->contentsToViewport(m_posDrag), pScrollView->contentsToViewport(m_posDragEventResize)); } } // Reset drag/select/move state. void qtractorMidiEditor::resetDragState ( qtractorScrollView *pScrollView ) { if (m_bEventDragEdit) { const qtractorMidiEditSelect::ItemList& items = m_select.items(); qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin(); const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd(); for ( ; iter != iter_end; ++iter) delete iter.key(); m_select.clear(); } m_pEventDrag = NULL; m_bEventDragEdit = false; m_posDelta = QPoint(0, 0); m_posStep = QPoint(0, 0); m_posDragEventResize = QPoint(0, 0); m_pEditPaste = NULL; if (m_pRubberBand) { m_pRubberBand->hide(); delete m_pRubberBand; m_pRubberBand = NULL; } if (pScrollView) { if (m_dragState != DragNone) { m_dragCursor = DragNone; pScrollView->unsetCursor(); } if (m_dragState == DragMove || m_dragState == DragResize || m_dragState == DragRescale || m_dragState == DragPaste || m_dragState == DragStep) { // m_select.clear(); updateContents(); } } else if (m_pEditList) m_pEditList->dragNoteOn(-1); m_dragState = DragNone; m_resizeMode = ResizeNone; } // Edit tools form page selector. void qtractorMidiEditor::executeTool ( int iToolIndex ) { if (m_pMidiClip == NULL) return; qtractorMidiToolsForm toolsForm(this); toolsForm.setToolIndex(iToolIndex); if (toolsForm.exec()) { qtractorMidiEditCommand *pEditCommand = toolsForm.editCommand(m_pMidiClip, &m_select, m_pTimeScale->tickFromFrame(m_iOffset)); m_pCommands->exec(pEditCommand); } QWidget::activateWindow(); m_pEditView->setFocus(); } // Command list accessor. qtractorCommandList *qtractorMidiEditor::commands (void) const { return m_pCommands; } // Update instrument default note names (nb. drum key names). void qtractorMidiEditor::updateDefaultDrumNoteNames (void) { for (int i = 13; g_aNoteNames[i].name; ++i) { m_noteNames.insert(g_aNoteNames[i].note, tr(g_aNoteNames[i].name, "noteName")); } } // Update instrument defined names for current clip/track. void qtractorMidiEditor::updateInstrumentNames (void) { m_noteNames.clear(); m_controllerNames.clear(); if (m_pMidiClip == NULL) return; qtractorTrack *pTrack = m_pMidiClip->track(); if (pTrack == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorInstrumentList *pInstruments = pSession->instruments(); if (pInstruments == NULL) return; // Get instrument name from patch descriptor... QString sInstrument; qtractorMidiBus *pMidiBus = static_cast (pTrack->outputBus()); if (pMidiBus) sInstrument = pMidiBus->patch(pTrack->midiChannel()).instrumentName; // Do we have any?... if (sInstrument.isEmpty() || !pInstruments->contains(sInstrument)) { // Default drumk-key note names: // at least have a GM Drums (Channel 10) help... if (pTrack->midiChannel() == 9) updateDefaultDrumNoteNames(); // No instrument definition... return; } // Finally, got instrument descriptor... const qtractorInstrument& instr = (*pInstruments)[sInstrument]; const int iBank = pTrack->midiBank(); const int iProg = pTrack->midiProg(); // Key note names... const qtractorInstrumentData& notes = instr.notes(iBank, iProg); qtractorInstrumentData::ConstIterator nit = notes.constBegin(); const qtractorInstrumentData::ConstIterator& nit_end = notes.constEnd(); for ( ; nit != nit_end; ++nit) m_noteNames.insert(nit.key(), nit.value()); // Default drumk-key note names: // at least have a GM Drums (Channel 10) help... if (m_noteNames.isEmpty() && (pTrack->midiChannel() == 9 || instr.isDrum(iBank, iProg))) updateDefaultDrumNoteNames(); // Controller names... const qtractorInstrumentData& controllers = instr.control(); qtractorInstrumentData::ConstIterator cit = controllers.constBegin(); const qtractorInstrumentData::ConstIterator& cit_end = controllers.constEnd(); for ( ; cit != cit_end; ++cit) m_controllerNames.insert(cit.key(), cit.value()); } // Note name map accessor. const QString qtractorMidiEditor::noteName ( unsigned char note ) const { QHash::ConstIterator iter = m_noteNames.constFind(note); if (iter == m_noteNames.constEnd()) return defaultNoteName(note); else return iter.value(); } // Controller name map accessor. const QString& qtractorMidiEditor::controllerName ( unsigned char controller ) const { QHash::ConstIterator iter = m_controllerNames.constFind(controller); if (iter == m_controllerNames.constEnd()) return defaultControllerName(controller); else return iter.value(); } // Command execution notification slot. void qtractorMidiEditor::updateNotifySlot ( unsigned int flags ) { if (flags & qtractorCommand::Refresh) updateContents(); contentsChangeNotify(); } // Emit selection/changes. void qtractorMidiEditor::selectionChangeNotify (void) { emit selectNotifySignal(this); } void qtractorMidiEditor::contentsChangeNotify (void) { emit changeNotifySignal(this); } // Emit note on/off. void qtractorMidiEditor::sendNote ( int iNote, int iVelocity ) { if (iVelocity == 1) iVelocity = m_last.value; emit sendNoteSignal(iNote, iVelocity); } // MIDI event tool tip helper. QString qtractorMidiEditor::eventToolTip ( qtractorMidiEvent *pEvent, long iTimeDelta, int iNoteDelta, int iValueDelta ) const { long d0 = 0; if (m_resizeMode == ResizeNoteRight) { d0 = iTimeDelta; iTimeDelta = 0; } else if (m_resizeMode == ResizeNoteLeft) d0 = -iTimeDelta; unsigned long t0 = m_pTimeScale->tickFromFrame(m_iOffset) + pEvent->time(); t0 = (long(t0) + iTimeDelta < 0 ? 0 : t0 + iTimeDelta); QString sToolTip = tr("Time:\t%1\nType:\t") .arg(m_pTimeScale->textFromTick(t0)); switch (pEvent->type()) { // case qtractorMidiEvent::NOTEOFF: // sToolTip += tr("Note Off (%1)").arg(int(pEvent->note())); // break; case qtractorMidiEvent::NOTEON: d0 = (long(pEvent->duration()) + d0 < 0 ? 0 : pEvent->duration() + d0); sToolTip += tr("Note On (%1) %2\nVelocity:\t%3\nDuration:\t%4") .arg(int(pEvent->note() + iNoteDelta)) .arg(noteName(pEvent->note() + iNoteDelta)) .arg(int(pEvent->velocity() + iValueDelta)) .arg(m_pTimeScale->textFromTick(t0, true, d0)); break; case qtractorMidiEvent::KEYPRESS: sToolTip += tr("Key Press (%1) %2\nValue:\t%3") .arg(int(pEvent->note() + iNoteDelta)) .arg(noteName(pEvent->note() + iNoteDelta)) .arg(int(pEvent->velocity() + iValueDelta)); break; case qtractorMidiEvent::CONTROLLER: sToolTip += tr("Controller (%1)\nName:\t%2\nValue:\t%3") .arg(int(pEvent->controller())) .arg(controllerName(int(pEvent->controller()))) .arg(int(pEvent->value() + iValueDelta)); break; case qtractorMidiEvent::PGMCHANGE: sToolTip += tr("Pgm Change (%1)") .arg(int(pEvent->value() + iValueDelta)); break; case qtractorMidiEvent::CHANPRESS: sToolTip += tr("Chan Press (%1)") .arg(int(pEvent->value() + iValueDelta)); break; case qtractorMidiEvent::PITCHBEND: sToolTip += tr("Pitch Bend (%1)") .arg(int(pEvent->pitchBend() + iValueDelta)); break; case qtractorMidiEvent::SYSEX: { unsigned char *data = pEvent->sysex(); unsigned short len = pEvent->sysex_len(); sToolTip += tr("SysEx (%1 bytes)\nData: ").arg(int(len)); sToolTip += '{'; sToolTip += ' '; for (unsigned short i = 0; i < len; ++i) sToolTip += QString().sprintf("%02x ", data[i]); sToolTip += '}'; break; } // case qtractorMidiEvent::META: // sToolTip += tr("Meta"); // break; default: sToolTip += tr("Unknown (%1)").arg(int(pEvent->type())); break; } // That's it return sToolTip; } // Keyboard event handler (common). bool qtractorMidiEditor::keyPress ( qtractorScrollView *pScrollView, int iKey, Qt::KeyboardModifiers modifiers ) { switch (iKey) { case Qt::Key_Insert: // Aha, joking :) case Qt::Key_Return: if (m_dragState == DragStep) { executeDragMove(m_pEditView, m_posDrag); } else { const QPoint& pos = pScrollView->viewportToContents( pScrollView->viewport()->mapFromGlobal(QCursor::pos())); if (m_dragState == DragMove) executeDragMove(pScrollView, pos); else if (m_dragState == DragPaste) executeDragPaste(pScrollView, pos); } resetDragState(pScrollView); break; case Qt::Key_Escape: m_dragState = DragStep; // HACK: Force selection clearance! m_select.clear(); resetDragState(pScrollView); break; case Qt::Key_Home: if (modifiers & Qt::ControlModifier) { pScrollView->setContentsPos(0, 0); } else { pScrollView->setContentsPos(0, pScrollView->contentsY()); } break; case Qt::Key_End: if (modifiers & Qt::ControlModifier) { pScrollView->setContentsPos( pScrollView->contentsWidth() - pScrollView->width(), pScrollView->contentsHeight() - pScrollView->height()); } else { pScrollView->setContentsPos( pScrollView->contentsWidth() - pScrollView->width(), pScrollView->contentsY()); } break; case Qt::Key_Left: if (modifiers & Qt::ControlModifier) { pScrollView->setContentsPos( pScrollView->contentsX() - pScrollView->width(), pScrollView->contentsY()); } else if (!keyStep(iKey)) { pScrollView->setContentsPos( pScrollView->contentsX() - 16, pScrollView->contentsY()); } break; case Qt::Key_Right: if (modifiers & Qt::ControlModifier) { pScrollView->setContentsPos( pScrollView->contentsX() + pScrollView->width(), pScrollView->contentsY()); } else if (!keyStep(iKey)) { pScrollView->setContentsPos( pScrollView->contentsX() + 16, pScrollView->contentsY()); } break; case Qt::Key_Up: if (modifiers & Qt::ControlModifier) { pScrollView->setContentsPos( pScrollView->contentsX(), pScrollView->contentsY() - pScrollView->height()); } else if (!keyStep(iKey)) { pScrollView->setContentsPos( pScrollView->contentsX(), pScrollView->contentsY() - 16); } break; case Qt::Key_Down: if (modifiers & Qt::ControlModifier) { pScrollView->setContentsPos( pScrollView->contentsX(), pScrollView->contentsY() + pScrollView->height()); } else if (!keyStep(iKey)) { pScrollView->setContentsPos( pScrollView->contentsX(), pScrollView->contentsY() + 16); } break; case Qt::Key_PageUp: if (modifiers & Qt::ControlModifier) { pScrollView->setContentsPos( pScrollView->contentsX(), 16); } else { pScrollView->setContentsPos( pScrollView->contentsX(), pScrollView->contentsY() - pScrollView->height()); } break; case Qt::Key_PageDown: if (modifiers & Qt::ControlModifier) { pScrollView->setContentsPos( pScrollView->contentsX(), pScrollView->contentsHeight() - pScrollView->height()); } else { pScrollView->setContentsPos( pScrollView->contentsX(), pScrollView->contentsY() + pScrollView->height()); } break; default: // Not handled here. return false; } // Done. return true; } // Keyboard step handler. bool qtractorMidiEditor::keyStep ( int iKey ) { // Only applicable if something is selected... if (m_select.items().isEmpty()) return false; // Set initial bound conditions... if (m_dragState == DragNone) { m_dragState = m_dragCursor = DragStep; m_rectDrag = m_select.rectView(); m_posDrag = m_rectDrag.topLeft(); m_posStep = QPoint(0, 0); m_pEditView->setCursor(Qt::SizeAllCursor); m_pEditEvent->setCursor(Qt::SizeAllCursor); } // Now to say the truth... if (m_dragState != DragMove && m_dragState != DragStep && m_dragState != DragPaste) return false; // Make sure we've a anchor... if (m_pEventDrag == NULL) m_pEventDrag = m_select.anchorEvent(); // Determine vertical step... if (iKey == Qt::Key_Up || iKey == Qt::Key_Down) { int iVerticalStep = m_pEditList->itemHeight(); int y0 = m_posDrag.y(); int y1 = y0 + m_posStep.y(); if (iKey == Qt::Key_Up) y1 -= iVerticalStep; else y1 += iVerticalStep; m_posStep.setY((y1 < 0 ? 0 : y1) - y0); } else // Determine horizontal step... if (iKey == Qt::Key_Left || iKey == Qt::Key_Right) { int iHorizontalStep = 0; int x0 = m_posDrag.x() + m_pTimeScale->pixelFromFrame(m_iOffset); int x1 = x0 + m_posStep.x(); qtractorTimeScale::Cursor cursor(m_pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekPixel(x1); unsigned short iSnapPerBeat = m_pTimeScale->snapPerBeat(); if (iSnapPerBeat > 0) iHorizontalStep = pNode->pixelsPerBeat() / iSnapPerBeat; if (iHorizontalStep < 1) iHorizontalStep = 1; if (iKey == Qt::Key_Left) x1 -= iHorizontalStep; else x1 += iHorizontalStep; m_posStep.setX(m_pTimeScale->pixelSnap(x1 < 0 ? 0 : x1) - x0); } // Early sanity check... const QRect& rect = m_select.rectView(); QPoint pos = m_posDrag; if (m_dragState == DragMove || m_dragState == DragPaste) { pos = m_pEditView->viewportToContents( m_pEditView->viewport()->mapFromGlobal(QCursor::pos())); } int x2 = - pos.x(); int y2 = - pos.y(); if (m_dragState == DragMove || m_dragState == DragPaste) { x2 += (m_posDrag.x() - rect.x()); y2 += (m_posDrag.y() - rect.y()); } if (m_posStep.x() < x2) { m_posStep.setX (x2); } else { x2 += m_pEditView->contentsWidth() - rect.width(); if (m_posStep.x() > x2) m_posStep.setX (x2); } if (m_posStep.y() < y2) { m_posStep.setY (y2); } else { y2 += m_pEditView->contentsHeight() - rect.height(); if (m_posStep.y() > y2) m_posStep.setY (y2); } // Do our deeds... updateDragMove(m_pEditView, pos + m_posStep); return true; } // Focus lost event. void qtractorMidiEditor::focusOut ( qtractorScrollView *pScrollView ) { if (m_dragState == DragStep && m_pEditPaste == pScrollView) resetDragState(pScrollView); } // Show selection tooltip... void qtractorMidiEditor::showToolTip ( qtractorScrollView *pScrollView, const QRect& rect ) const { if (pScrollView == NULL) return; if (!m_bToolTips) return; if (m_pTimeScale == NULL) return; unsigned long iFrameStart = m_pTimeScale->frameSnap( m_iOffset + m_pTimeScale->frameFromPixel(rect.left())); unsigned long iFrameEnd = m_pTimeScale->frameSnap( iFrameStart + m_pTimeScale->frameFromPixel(rect.width())); QToolTip::showText( QCursor::pos(), tr("Start:\t%1\nEnd:\t%2\nLength:\t%3") .arg(m_pTimeScale->textFromFrame(iFrameStart)) .arg(m_pTimeScale->textFromFrame(iFrameEnd)) .arg(m_pTimeScale->textFromFrame(iFrameStart, true, iFrameEnd - iFrameStart)), pScrollView->viewport()); } // end of qtractorMidiEditor.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorBusForm.ui0000644000175000001440000000012212067456742020753 xustar000000000000000026 mtime=1356750306.99751 26 atime=1381134667.00008 30 ctime=1381134667.000080049 qtractor-0.5.11/src/qtractorBusForm.ui0000644000175000001440000006114212067456742020247 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorBusForm 0 0 658 317 Qt::StrongFocus Buses - Qtractor :/images/qtractorTracks.png Qt::Horizontal 4 120 120 Bus list false true true Buses Ch Mode 4 0 10 75 true Bus 2 6 0 Properties Bus 8 4 &Name: BusNameLineEdit Bus name &Mode: BusModeComboBox Qt::Horizontal 20 20 Bus mode 2 Input Output Duplex Bus monitor (pass-through) M&onitor (pass-through) Alt+O Audio 8 4 Cha&nnels: AudioChannelsSpinBox Audio channels 1 2 Qt::Horizontal 20 20 Audio auto-connect &Auto connect Alt+A MIDI MIDI Instrument name MIDI SysEx setup SysE&x... Qt::AlignCenter Qt::Horizontal 20 20 Input Plugins Qt::WheelFocus Input bus plugins 90 28 Add input plugin &Add... :/images/formCreate.png Alt+A Qt::ToolButtonTextBesideIcon 90 28 Remove input plugin &Remove :/images/formRemove.png Alt+R Qt::ToolButtonTextBesideIcon Qt::Vertical 8 8 90 28 Move input plugin up &Up :/images/formMoveUp.png Alt+U Qt::ToolButtonTextBesideIcon 90 28 Move input plugin down &Down :/images/formMoveDown.png Alt+D Qt::ToolButtonTextBesideIcon Output Plugins Qt::WheelFocus Output bus plugins 90 28 Add output plugin &Add... :/images/formCreate.png Alt+A Qt::ToolButtonTextBesideIcon 90 28 Remove output plugin &Remove :/images/formRemove.png Alt+R Qt::ToolButtonTextBesideIcon Qt::Vertical 8 8 90 28 Move output plugin up &Up :/images/formMoveUp.png Alt+U Qt::ToolButtonTextBesideIcon 90 28 Move output plugin down &Down :/images/formMoveDown.png Alt+D Qt::ToolButtonTextBesideIcon 4 0 Refresh bus list view &Refresh :/images/formRefresh.png Alt+R Qt::Horizontal 20 20 Create bus &Create :/images/formCreate.png Alt+C Update bus &Update :/images/formAccept.png Alt+U Delete bus &Delete :/images/formRemove.png Alt+D Close this dialog Close qtractorPluginListView QListWidget
qtractorPluginListView.h
BusListView BusTabWidget BusNameLineEdit BusModeComboBox MonitorCheckBox AudioChannelsSpinBox AudioAutoConnectCheckBox InputPluginListView AddInputPluginToolButton RemoveInputPluginToolButton MoveUpInputPluginToolButton MoveDownInputPluginToolButton OutputPluginListView AddOutputPluginToolButton RemoveOutputPluginToolButton MoveUpOutputPluginToolButton MoveDownOutputPluginToolButton RefreshPushButton CreatePushButton UpdatePushButton DeletePushButton ClosePushButton
qtractor-0.5.11/src/PaxHeaders.10084/qtractorLv2Plugin.h0000644000175000001440000000012212205157155021020 xustar000000000000000027 mtime=1377099373.764437 26 atime=1381134667.73208 29 ctime=1381134667.73208006 qtractor-0.5.11/src/qtractorLv2Plugin.h0000644000175000001440000003011312205157155020306 0ustar00rncbcusers00000000000000// qtractorLv2Plugin.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorLv2Plugin_h #define __qtractorLv2Plugin_h #include "qtractorPlugin.h" #include #ifdef CONFIG_LV2_EVENT // LV2 Event/MIDI support. #include "lv2/lv2plug.in/ns/ext/event/event.h" #include "lv2/lv2plug.in/ns/ext/event/event-helpers.h" #ifndef QTRACTOR_LV2_MIDI_EVENT_ID #define QTRACTOR_LV2_MIDI_EVENT_ID 1 #endif #endif #ifdef CONFIG_LV2_ATOM // LV2 Atom/MIDI support. #include "lv2_atom_helpers.h" #ifndef QTRACTOR_LV2_MIDI_EVENT_ID #define QTRACTOR_LV2_MIDI_EVENT_ID 1 #endif #endif #ifdef CONFIG_LV2_WORKER // LV2 Worker/Schedule support. #include "lv2/lv2plug.in/ns/ext/worker/worker.h" // Forward declarations. class qtractorLv2Worker; #endif #ifdef CONFIG_LV2_UI // LV2 UI support. #include #include "lv2/lv2plug.in/ns/extensions/ui/ui.h" // LV2 UI data/instance access support. #include "lv2/lv2plug.in/ns/ext/data-access/data-access.h" #include "lv2/lv2plug.in/ns/ext/instance-access/instance-access.h" #ifdef CONFIG_LV2_ATOM #include #endif #ifdef CONFIG_LV2_EXTERNAL_UI // LV2 External UI support. #include "lv2_external_ui.h" #endif #endif #ifdef CONFIG_LV2_STATE // LV2 State support. #include "lv2/lv2plug.in/ns/ext/atom/atom.h" #include "lv2/lv2plug.in/ns/ext/state/state.h" #endif #ifdef CONFIG_LV2_PROGRAMS // LV2 Programs support. #include "lv2_programs.h" #endif #ifdef CONFIG_LV2_PRESETS // LV2 Presets support. #include "lv2/lv2plug.in/ns/ext/presets/presets.h" #endif #ifdef CONFIG_LV2_TIME // LV2 Time support. #include "lv2/lv2plug.in/ns/ext/time/time.h" // JACK Transport position support. #include #endif #ifdef CONFIG_LV2_OPTIONS // LV2 Options support. #include "lv2/lv2plug.in/ns/ext/options/options.h" #endif // CONFIG_LV2_OPTIONS //---------------------------------------------------------------------------- // qtractorLv2PluginType -- LV2 plugin type instance. // class qtractorLv2PluginType : public qtractorPluginType { public: // Constructor. qtractorLv2PluginType(const QString& sUri, LilvPlugin *plugin = NULL) : qtractorPluginType(NULL, 0, qtractorPluginType::Lv2), m_sUri(sUri), m_lv2_plugin(plugin) {} // Destructor. ~qtractorLv2PluginType() { close(); } // Derived methods. bool open(); void close(); // Factory method (static) static qtractorLv2PluginType *createType( const QString& sUri, LilvPlugin *plugin = NULL); // LV2 plugin URI (virtual override). QString filename() const { return m_sUri; } // LV2 descriptor method (static) static LilvPlugin *lv2_plugin(const QString& sUri); // Specific accessors. LilvPlugin *lv2_plugin() const { return m_lv2_plugin; } // LV2 World stuff (ref. counted). static void lv2_open(); static void lv2_close(); // Plugin type listing (static). static bool getTypes(qtractorPluginPath& path); #ifdef CONFIG_LV2_EVENT unsigned short midiEventIns() const { return m_iMidiEventIns; } unsigned short midiEventOuts() const { return m_iMidiEventOuts; } #endif #ifdef CONFIG_LV2_ATOM unsigned short midiAtomIns() const { return m_iMidiAtomIns; } unsigned short midiAtomOuts() const { return m_iMidiAtomOuts; } #endif protected: // LV2 plgin URI. QString m_sUri; // LV2 descriptor itself. LilvPlugin *m_lv2_plugin; #ifdef CONFIG_LV2_EVENT unsigned short m_iMidiEventIns; unsigned short m_iMidiEventOuts; #endif #ifdef CONFIG_LV2_ATOM unsigned short m_iMidiAtomIns; unsigned short m_iMidiAtomOuts; #endif }; //---------------------------------------------------------------------------- // qtractorLv2Plugin -- LV2 plugin instance. // class qtractorLv2Plugin : public qtractorPlugin { public: // Constructors. qtractorLv2Plugin(qtractorPluginList *pList, qtractorLv2PluginType *pLv2Type); // Destructor. ~qtractorLv2Plugin(); // Channel/intsance number accessors. void setChannels(unsigned short iChannels); // Do the actual (de)activation. void activate(); void deactivate(); // The main plugin processing procedure. void process(float **ppIBuffer, float **ppOBuffer, unsigned int nframes); // Specific accessors. LilvPlugin *lv2_plugin() const; LilvInstance *lv2_instance(unsigned short iInstance) const; LV2_Handle lv2_handle(unsigned short iInstance) const; // Audio port numbers. unsigned long audioIn(unsigned short i) { return m_piAudioIns[i]; } unsigned long audioOut(unsigned short i) { return m_piAudioOuts[i]; } #ifdef CONFIG_LV2_UI // GUI Editor stuff. void openEditor(QWidget *pParent); void closeEditor(); void idleEditor(); // GUI editor visibility state. void setEditorVisible(bool bVisible); bool isEditorVisible() const; void setEditorTitle(const QString& sTitle); // Parameter update method. void updateParam(qtractorPluginParam *pParam, float fValue, bool bUpdate); // Idle editor (static). static void idleEditorAll(); // LV2 UI control change method. void lv2_ui_write(uint32_t port_index, uint32_t buffer_size, uint32_t protocol, const void *buffer); // LV2 UI resize control (host->ui). void resizeEditor(const QSize& size) const; // GUI editor closed state. void setEditorClosed(bool bClosed) { m_bEditorClosed = bClosed; } bool isEditorClosed() const { return m_bEditorClosed; } void closeEditorEx(); #endif // Plugin configuration/state (save) snapshot. void freezeConfigs(); // Plugin configuration/state (load) realization. void realizeConfigs(); // Plugin configuration/state release. void releaseConfigs(); #ifdef CONFIG_LV2_WORKER // LV2 Worker/Schedule extension data interface accessor. const LV2_Worker_Interface *lv2_worker_interface(unsigned short iInstance) const; #endif #ifdef CONFIG_LV2_STATE // LV2 State extension data interface accessor. const LV2_State_Interface *lv2_state_interface(unsigned short iInstance) const; LV2_State_Status lv2_state_store( uint32_t key, const void *value, size_t size, uint32_t type, uint32_t flags); const void *lv2_state_retrieve( uint32_t key, size_t *size, uint32_t *type, uint32_t *flags); #endif // URID map/unmap helpers. static uint32_t lv2_urid_map(const char *uri); static const char *lv2_urid_unmap(uint32_t id); #ifdef CONFIG_LV2_PROGRAMS // LV2 Programs extension data descriptor accessor. const LV2_Programs_Interface *lv2_programs_descriptor(unsigned short iInstance) const; // Bank/program selector override. void selectProgram(int iBank, int iProg); // Provisional program/patch accessor. bool getProgram(int iIndex, Program& program) const; // Program/patch notification. void lv2_program_changed(int iIndex); #endif #ifdef CONFIG_LV2_PRESETS // Refresh and load preset labels listing. QStringList presetList() const; // Load/Save plugin state from/into a named preset. bool loadPreset(const QString& sPreset); bool savePreset(const QString& sPreset); // Delete plugin state preset (from file-system). bool deletePreset(const QString& sPreset); // Whether given preset is internal/read-only. bool isReadOnlyPreset(const QString& sPreset) const; #endif #ifdef CONFIG_LV2_TIME // Update LV2 Time from JACK transport position. static void updateTime( const jack_transport_state_t state, const jack_position_t *pPos); #endif private: // Instance variables. LilvInstance **m_ppInstances; // List of output control port indexes and data. unsigned long *m_piControlOuts; float *m_pfControlOuts; float *m_pfControlOutsLast; // List of audio port indexes. unsigned long *m_piAudioIns; unsigned long *m_piAudioOuts; #ifdef CONFIG_LV2_EVENT // List of LV2 Event/MIDI port indexes. unsigned long *m_piMidiEventIns; unsigned long *m_piMidiEventOuts; #endif #ifdef CONFIG_LV2_ATOM // List of LV2 Atom/MIDI port indexes and buffers. unsigned long *m_piMidiAtomIns; unsigned long *m_piMidiAtomOuts; LV2_Atom_Buffer *m_lv2_atom_buffer_in; LV2_Atom_Buffer **m_lv2_atom_buffer_ins; LV2_Atom_Buffer *m_lv2_atom_buffer_out; LV2_Atom_Buffer **m_lv2_atom_buffer_outs; #endif // Local copy of features array. LV2_Feature **m_lv2_features; #ifdef CONFIG_LV2_WORKER // LV2 Worker/Schedule support. qtractorLv2Worker *m_lv2_worker; #endif #ifdef CONFIG_LV2_UI int m_lv2_ui_type; QByteArray m_aEditorTitle; bool m_bEditorVisible; volatile bool m_bEditorClosed; LilvUIs *m_lv2_uis; LilvUI *m_lv2_ui; LV2_Extension_Data_Feature m_lv2_data_access; LV2_Feature m_lv2_data_access_feature; LV2_Feature m_lv2_instance_access_feature; LV2_Feature **m_lv2_ui_features; SuilHost *m_suil_host; SuilInstance *m_suil_instance; SuilWidget m_lv2_ui_widget; #ifdef CONFIG_LV2_ATOM // LV2 Atom control (ring)buffers for UI updates. struct ControlEvent { uint32_t index; uint32_t protocol; uint32_t size; uint8_t body[]; }; jack_ringbuffer_t *m_ui_events; jack_ringbuffer_t *m_plugin_events; #endif #ifdef CONFIG_LV2_EXTERNAL_UI LV2_Feature m_lv2_ui_external_feature; LV2_External_UI_Host m_lv2_ui_external_host; #ifdef LV2_EXTERNAL_UI_DEPRECATED_URI LV2_Feature m_lv2_ui_external_deprecated_feature; #endif #endif #if QT_VERSION < 0x050000 // Our own Qt UI widget (native). class EventFilter; EventFilter *m_pQt4Filter; QWidget *m_pQt4Widget; #endif // Changed UI params hash-queue. QHash m_ui_params; #endif // CONFIG_LV2_UI #ifdef CONFIG_LV2_STATE QHash m_lv2_state_configs; QHash m_lv2_state_ctypes; #endif #ifdef CONFIG_LV2_STATE_FILES LV2_Feature m_lv2_state_map_path_feature; LV2_State_Map_Path m_lv2_state_map_path; #ifdef CONFIG_LV2_STATE_MAKE_PATH LV2_Feature m_lv2_state_make_path_feature; LV2_State_Make_Path m_lv2_state_make_path; #endif #endif #ifdef CONFIG_LV2_PROGRAMS LV2_Feature m_lv2_programs_host_feature; LV2_Programs_Host m_lv2_programs_host; #endif #ifdef CONFIG_LV2_PRESETS // LV2 Presets label-to-uri map. QHash m_lv2_presets; #endif #ifdef CONFIG_LV2_TIME // LV2 Time designated ports map. QHash m_lv2_time_ports; #endif #ifdef CONFIG_LV2_OPTIONS #ifdef CONFIG_LV2_BUF_SIZE LV2_Feature m_lv2_options_feature; LV2_Options_Option m_lv2_options[4]; uint32_t m_iMinBlockLength; uint32_t m_iMaxBlockLength; uint32_t m_iSequenceSize; #endif #endif }; //---------------------------------------------------------------------------- // qtractorLv2PluginParam -- LV2 plugin control input port instance. // class qtractorLv2PluginParam : public qtractorPluginParam { public: // Constructors. qtractorLv2PluginParam(qtractorLv2Plugin *pLv2Plugin, unsigned long iIndex); // Destructor. ~qtractorLv2PluginParam(); // Port range hints predicate methods. bool isBoundedBelow() const; bool isBoundedAbove() const; bool isDefaultValue() const; bool isLogarithmic() const; bool isSampleRate() const; bool isInteger() const; bool isToggled() const; bool isDisplay() const; // Current display value. QString display() const; private: // Port bit-wise hints. enum { None = 0, Toggled = 1, Integer = 2, SampleRate = 4, Logarithmic = 8, }; // Instance variables. unsigned int m_iPortHints; QHash m_display; }; #endif // __qtractorLv2Plugin_h // end of qtractorLv2Plugin.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorCommand.h0000644000175000001440000000012312156176530020560 xustar000000000000000027 mtime=1371077976.416182 26 atime=1381134667.50408 30 ctime=1381134667.504080057 qtractor-0.5.11/src/qtractorCommand.h0000644000175000001440000000737712156176530020065 0ustar00rncbcusers00000000000000// qtractorCommand.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorCommand_h #define __qtractorCommand_h #include "qtractorList.h" #include #include // Forward declarations. class QAction; //---------------------------------------------------------------------- // class qtractorCommand - declaration. // class qtractorCommand : public qtractorList::Link { public: // Constructor. qtractorCommand(const QString& sName) : m_sName(sName), m_flags(Refresh) {} // Virtual destructor. virtual ~qtractorCommand() {} // Descriptive command name accessors. void setName(const QString& sName) { m_sName = sName; } const QString& name() const { return m_sName; } // Command flags. enum Flag { None = 0, AutoDelete = 1, Refresh = 2, ClearSelect = 4 }; // Command flags accessor. unsigned int flags() const { return m_flags; } // Auto-removal/deletion flag accessors. void setAutoDelete(bool bAutoDelete) { setFlag(AutoDelete, bAutoDelete); } bool isAutoDelete() const { return isFlag(AutoDelete); } // Contents-refresh accessors. void setRefresh(bool bRefresh) { setFlag(Refresh, bRefresh); } bool isRefresh() const { return isFlag(Refresh); } // Selection-reset accessors. void setClearSelect(bool bClearSelect) { setFlag(ClearSelect, bClearSelect); } bool isClearSelect() const { return isFlag(ClearSelect); } // Cannonical command methods. virtual bool redo() = 0; virtual bool undo() = 0; protected: // Discrete flag accessors. void setFlag(Flag flag, bool bOn = true) { if (bOn) m_flags |= (unsigned int) (flag); else m_flags &= ~(unsigned int) (flag); } bool isFlag(Flag flag) const { return (m_flags & (unsigned int) (flag)); } private: // Instance variables. QString m_sName; unsigned int m_flags; }; //---------------------------------------------------------------------- // class qtractorCommandList - declaration. // class qtractorCommandList : public QObject { Q_OBJECT public: // Constructor. qtractorCommandList(); // Destructor. virtual ~qtractorCommandList(); // Command stack cleaner. void clear(); // Command cursor accessors. qtractorCommand *lastCommand() const; qtractorCommand *nextCommand() const; // Remove last command from command chain. void removeLastCommand(); // Special backout method (EXPERIMENTAL). void backout(qtractorCommand *pCommand); // Cannonical command methods. bool push(qtractorCommand *pCommand); bool exec(qtractorCommand *pCommand); bool undo(); bool redo(); // Command action update helper. void updateAction(QAction *pAction, qtractorCommand *pCommand) const; signals: // Command update notification. void updateNotifySignal(unsigned int); private: // Instance variables. qtractorList m_commands; qtractorCommand *m_pLastCommand; }; #endif // __qtractorCommand_h // end of qtractorCommand.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditCommand.cpp0000644000175000001440000000012312075634407022526 xustar000000000000000027 mtime=1358379271.965668 26 atime=1381134666.64408 30 ctime=1381134666.644080043 qtractor-0.5.11/src/qtractorMidiEditCommand.cpp0000644000175000001440000002702312075634407022021 0ustar00rncbcusers00000000000000// qtractorMidiEditCommand.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorMidiEditCommand.h" #include "qtractorMidiClip.h" #include "qtractorMidiEngine.h" #include "qtractorSession.h" //---------------------------------------------------------------------- // class qtractorMidiEditCommand - implementation. // // Constructor. qtractorMidiEditCommand::qtractorMidiEditCommand ( qtractorMidiClip *pMidiClip, const QString& sName ) : qtractorCommand(sName), m_pMidiClip(pMidiClip), m_bAdjusted(false), m_iDuration((pMidiClip->sequence())->duration()) { } // Destructor. qtractorMidiEditCommand::~qtractorMidiEditCommand (void) { QListIterator iter(m_items); while (iter.hasNext()) { Item *pItem = iter.next(); if (pItem->autoDelete) delete pItem->event; } qDeleteAll(m_items); m_items.clear(); } // Primitive command methods. void qtractorMidiEditCommand::insertEvent ( qtractorMidiEvent *pEvent ) { m_items.append(new Item(InsertEvent, pEvent)); } void qtractorMidiEditCommand::moveEvent ( qtractorMidiEvent *pEvent, int iNote, unsigned long iTime ) { m_items.append(new Item(MoveEvent, pEvent, iNote, iTime)); } void qtractorMidiEditCommand::resizeEventTime ( qtractorMidiEvent *pEvent, unsigned long iTime, unsigned long iDuration ) { m_items.append(new Item(ResizeEventTime, pEvent, 0, iTime, iDuration)); } void qtractorMidiEditCommand::resizeEventValue ( qtractorMidiEvent *pEvent, int iValue ) { if (pEvent->type() == qtractorMidiEvent::NOTEON && iValue < 1) iValue = 1; // Avoid zero velocity (aka. NOTEOFF) m_items.append(new Item(ResizeEventValue, pEvent, 0, 0, 0, iValue)); } void qtractorMidiEditCommand::removeEvent ( qtractorMidiEvent *pEvent ) { m_items.append(new Item(RemoveEvent, pEvent)); } // Check whether the event is already in chain. bool qtractorMidiEditCommand::findEvent ( qtractorMidiEvent *pEvent, qtractorMidiEditCommand::CommandType cmd ) const { QListIterator iter(m_items); while (iter.hasNext()) { Item *pItem = iter.next(); if (pItem->event == pEvent && (pItem->command == InsertEvent || pItem->command == cmd)) return true; } return false; } // Common executive method. bool qtractorMidiEditCommand::execute ( bool bRedo ) { if (m_pMidiClip == NULL) return false; qtractorMidiSequence *pSeq = m_pMidiClip->sequence(); if (pSeq == NULL) return false; // Dropped enqueued events... qtractorSession *pSession = NULL; qtractorTrack *pTrack = m_pMidiClip->track(); if (pTrack) pSession = pTrack->session(); #if 0 if (pSession && pSession->isPlaying()) pSession->midiEngine()->trackMute(pTrack, true); #endif // Track sequence duration changes... unsigned long iOldDuration = pSeq->duration(); int iSelectClear = 0; // Changes are due... QListIterator iter(m_items); if (!bRedo) iter.toBack(); while (bRedo ? iter.hasNext() : iter.hasPrevious()) { Item *pItem = (bRedo ? iter.next() : iter.previous()); qtractorMidiEvent *pEvent = pItem->event; // Execute the command item... switch (pItem->command) { case InsertEvent: { if (bRedo) pSeq->insertEvent(pEvent); else pSeq->unlinkEvent(pEvent); pItem->autoDelete = !bRedo; ++iSelectClear; break; } case MoveEvent: { int iOldNote = int(pEvent->note()); unsigned long iOldTime = pEvent->time(); pSeq->unlinkEvent(pEvent); pEvent->setNote(pItem->note); pEvent->setTime(pItem->time); pSeq->insertEvent(pEvent); pItem->note = iOldNote; pItem->time = iOldTime; break; } case ResizeEventTime: { unsigned long iOldTime = pEvent->time(); unsigned long iOldDuration = pEvent->duration(); pSeq->unlinkEvent(pEvent); pEvent->setTime(pItem->time); if (pEvent->type() == qtractorMidiEvent::NOTEON) pEvent->setDuration(pItem->duration); pSeq->insertEvent(pEvent); pItem->time = iOldTime; pItem->duration = iOldDuration; break; } case ResizeEventValue: { int iOldValue; if (pEvent->type() == qtractorMidiEvent::PITCHBEND) { iOldValue = pEvent->pitchBend(); pEvent->setPitchBend(pItem->value); } else { iOldValue = pEvent->value(); pEvent->setValue(pItem->value); } pItem->value = iOldValue; break; } case RemoveEvent: { if (bRedo) pSeq->unlinkEvent(pEvent); else pSeq->insertEvent(pEvent); pItem->autoDelete = bRedo; ++iSelectClear; break; } default: break; } } // It's dirty, definitly... m_pMidiClip->setDirtyEx(true); // Have we changed on something less durable? if (m_iDuration != iOldDuration) { pSeq->setDuration(m_iDuration); m_iDuration = iOldDuration; } // Adjust edit-command result to prevent event overlapping. if (bRedo && !m_bAdjusted) m_bAdjusted = adjust(); // Or are we changing something more durable? if (pSeq->duration() != iOldDuration) { pSeq->setTimeLength(pSeq->duration()); if (pSession) { m_pMidiClip->setClipLengthEx( pSession->frameFromTick(pSession->tickFromFrame( m_pMidiClip->clipStart()) + pSeq->duration()) - m_pMidiClip->clipStart()); } m_pMidiClip->updateEditorEx(iSelectClear > 0); } // Just reset editor internals... else m_pMidiClip->resetEditorEx(iSelectClear > 0); // Re-enqueue dropped events... if (pSession && pSession->isPlaying()) { // Reset all current running event cursors, // make them play it right and sound again... m_pMidiClip->reset(pSession->isLooping()); // Re-enqueueing in proper sense... pSession->midiEngine()->trackMute(pTrack, false); } return true; } // Adjust edit-command result to prevent event overlapping. bool qtractorMidiEditCommand::adjust (void) { if (m_pMidiClip == NULL) return false; qtractorMidiSequence *pSeq = m_pMidiClip->sequence(); if (pSeq == NULL) return false; // HACK: What we're going to do here is about checking the // whole sequence, fixing any overlapping (note) events and // adjusting the issued command for proper undo/redo... QHash events; // For each event, do rescan... qtractorMidiEvent *pEvent = pSeq->events().first(); while (pEvent) { qtractorMidiEvent *pNextEvent = pEvent->next(); // Whether event is (time) adjustable... int key = int(pEvent->type()) << 7; switch (pEvent->type()) { case qtractorMidiEvent::NOTEON: case qtractorMidiEvent::NOTEOFF: case qtractorMidiEvent::KEYPRESS: key += int(pEvent->note()); break; case qtractorMidiEvent::CONTROLLER: key += int(pEvent->controller()); break; case qtractorMidiEvent::CHANPRESS: case qtractorMidiEvent::PITCHBEND: break; default: key = 0; // Non adjustable! break; } // Adjustable? if (key) { // Already there? qtractorMidiEvent *pPrevEvent = events.value(key, NULL); if (pPrevEvent) { unsigned long iTime = pEvent->time(); unsigned long iPrevTime = pPrevEvent->time(); // NOTEON: Find previous note event and check overlaps... if (pEvent->type() == qtractorMidiEvent::NOTEON) { unsigned long iTimeEnd = iTime + pEvent->duration(); unsigned long iPrevTimeEnd = iPrevTime + pPrevEvent->duration(); // Inner operlap... if (iTime > iPrevTime && iTime < iPrevTimeEnd) { // Left-side outer event... unsigned long iDuration = pPrevEvent->duration(); pPrevEvent->setDuration(iTime - iPrevTime); if (!findEvent(pPrevEvent, ResizeEventTime)) resizeEventTime(pPrevEvent, iPrevTime, iDuration); // Right-side outer event... if (iTimeEnd < iPrevTimeEnd) { qtractorMidiEvent *pNewEvent = new qtractorMidiEvent(*pPrevEvent); pNewEvent->setTime(iTimeEnd); pNewEvent->setDuration(iPrevTimeEnd - iTimeEnd); insertEvent(pNewEvent); pSeq->insertEvent(pNewEvent); pNextEvent = pNewEvent->next(); // Keep or set as last note... pEvent = pNewEvent; } } else // Loose overlap?... if (iTime == iPrevTime) { // Exact overlap... if (iTimeEnd == iPrevTimeEnd) { pSeq->unlinkEvent(pPrevEvent); if (!findEvent(pPrevEvent, RemoveEvent)) removeEvent(pPrevEvent); } else { // Partial overlap... if (iTimeEnd < iPrevTimeEnd) { // Short over large... unsigned long iDuration = pPrevEvent->duration(); pPrevEvent->setDuration(pEvent->duration()); if (!findEvent(pPrevEvent, ResizeEventTime)) resizeEventTime(pPrevEvent, iPrevTime, iDuration); iDuration = pEvent->duration(); pSeq->unlinkEvent(pEvent); pEvent->setTime(iTimeEnd); pEvent->setDuration(iPrevTimeEnd - iTimeEnd); pSeq->insertEvent(pEvent); if (!findEvent(pEvent, ResizeEventTime)) { resizeEventTime(pEvent, iTime, iDuration); } } else { // Large over short... unsigned long iDuration = pEvent->duration(); pSeq->unlinkEvent(pEvent); pEvent->setTime(iPrevTimeEnd); pEvent->setDuration(iTimeEnd - iPrevTimeEnd); pSeq->insertEvent(pEvent); if (!findEvent(pEvent, ResizeEventTime)) { resizeEventTime(pEvent, iTime, iDuration); } } // We've move it ahead... pEvent = pPrevEvent; } } } else // All other channel events... if (iTime == iPrevTime) { pSeq->unlinkEvent(pPrevEvent); if (!findEvent(pPrevEvent, RemoveEvent)) removeEvent(pPrevEvent); } } // Remember last one... events.insert(key, pEvent); } // Iterate next... pEvent = pNextEvent; } return true; } // Virtual command methods. bool qtractorMidiEditCommand::redo (void) { return execute(true); } bool qtractorMidiEditCommand::undo (void) { return execute(false); } //---------------------------------------------------------------------- // class qtractorMidiClipCommand - declaration. // // Constructor. qtractorMidiClipCommand::qtractorMidiClipCommand ( const QString& sName ) : qtractorCommand(sName) { } // Destructor. qtractorMidiClipCommand::~qtractorMidiClipCommand (void) { qDeleteAll(m_editCommands); m_editCommands.clear(); } // Composite command methods. void qtractorMidiClipCommand::addEditCommand ( qtractorMidiEditCommand *pEditCommand ) { m_editCommands.append(pEditCommand); } // Composite predicate. bool qtractorMidiClipCommand::isEmpty (void) const { return m_editCommands.isEmpty(); } // Virtual command methods. bool qtractorMidiClipCommand::redo (void) { QListIterator iter(m_editCommands); while (iter.hasNext()) { if (!iter.next()->redo()) return false; } return true; } bool qtractorMidiClipCommand::undo (void) { QListIterator iter(m_editCommands); iter.toBack(); while (iter.hasPrevious()) { if (!iter.previous()->undo()) return false; } return true; } // end of qtractorMidiEditCommand.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorCurve.h0000644000175000001440000000012312161335204020255 xustar000000000000000027 mtime=1371912836.382031 26 atime=1381134668.17408 30 ctime=1381134668.174080067 qtractor-0.5.11/src/qtractorCurve.h0000644000175000001440000003377112161335204017557 0ustar00rncbcusers00000000000000// qtractorCurve.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorCurve_h #define __qtractorCurve_h #include "qtractorObserver.h" #include "qtractorMidiSequence.h" #include // Forward declarations. class qtractorTimeScale; class qtractorCurveList; class qtractorCurveEditList; //---------------------------------------------------------------------- // class qtractorCurve -- The generic curve declaration. // class qtractorCurve : public qtractorList::Link { public: // Curve modes. enum Mode { Hold = 0, Linear = 1, Spline = 2 }; // Constructor. qtractorCurve(qtractorCurveList *pList, qtractorSubject *pSubject, Mode mode, unsigned int iMinFrameDist = 3200); // Destructor. ~qtractorCurve(); // Curve list owner accessor. qtractorCurveList *list() const { return m_pList; } // Curve subject accessors. void setSubject(qtractorSubject *pSubject) { m_observer.setSubject(pSubject); } qtractorSubject *subject() const { return m_observer.subject(); } // Curve mode accessor. void setMode(Mode mode) { m_mode = (m_observer.isToggled() ? Hold : mode); } Mode mode() const { return (m_observer.isToggled() ? Hold : m_mode); } // Minimum distance between adjacent nodes accessors. void setMinFrameDist(unsigned int iMinFrameDist) { m_iMinFrameDist = iMinFrameDist; } unsigned int minFrameDist() const { return m_iMinFrameDist; } // The curve node declaration. struct Node : public qtractorList::Link { // Constructor. Node(unsigned long iFrame = 0, float fValue = 0.0f) : frame(iFrame), value(fValue), a(0.0f), b(0.0f), c(0.0f), d(0.0f) {} // Node members. unsigned long frame; float value; float a, b, c, d; }; // Node list accessor. const qtractorList& nodes() const { return m_nodes; } // Curve list reset method. void clear(); // Node list management methods. Node *addNode(unsigned long iFrame, float fValue, qtractorCurveEditList *pEditList = NULL); void insertNode(Node *pNode); void unlinkNode(Node *pNode); void removeNode(Node *pNode); // Master seeker method. Node *seek(unsigned long iFrame) { return m_cursor.seek(iFrame); } // Common interpolate methods. float value(const Node *pNode, unsigned long iFrame) const; float value(unsigned long iFrame); // Normalized scale converters. float valueFromScale(float fScale) const; float scaleFromValue(float fValue) const; // Common normalized methods. float scale(const Node *pNode, unsigned long iFrame) const { return scaleFromValue(value(pNode, iFrame)); } float scale(unsigned long iFrame) { return scaleFromValue(value(iFrame)); } // Default value accessors. void setDefaultValue(float fDefaultValue); float defaultValue() const { return m_tail.value; } // Default length accessors. void setLength(unsigned long iLength); unsigned long length() const { return m_tail.frame; } // Refresh all coefficients. void update(); // To optimize and keep track of current frame // position, mostly like a sequence cursor/iterator. class Cursor { public: // Constructor. Cursor(qtractorCurve *pCurve) : m_pCurve(pCurve), m_pNode(NULL), m_iFrame(0) {} // Accessors. qtractorCurve *curve() const { return m_pCurve; } unsigned long frame() const { return m_iFrame; } // Specific methods. Node *seek(unsigned long iFrame); void reset(Node *pNode = NULL); // Interpolate methods. float value(const Node *pNode, unsigned long iFrame) const { return m_pCurve->value(pNode, iFrame); } float value(unsigned long iFrame) { return value(seek(iFrame), iFrame); } // Normalized methods. float scale(const Node *pNode, unsigned long iFrame) const { return m_pCurve->scale(pNode, iFrame); } float scale(unsigned long iFrame) { return scale(seek(iFrame), iFrame); } float scale(const Node *pNode) const { return m_pCurve->scaleFromValue(pNode->value); } private: // Member variables. qtractorCurve *m_pCurve; Node *m_pNode; unsigned long m_iFrame; }; // Internal cursor accessor. const Cursor& cursor() const { return m_cursor; } // Curve state flags. enum State { Idle = 0, Process = 1, Capture = 2, Locked = 4 }; bool isIdle() const { return (m_state == Idle); } bool isProcess() const { return (m_state & Process); } bool isCapture() const { return (m_state & Capture); } bool isLocked() const { return (m_state & Locked); } // Ccapture/process state settlers. void setCapture(bool bCapture); void setProcess(bool bProcess); void setLocked(bool bLocked); // The meta-processing automation procedure. void process(unsigned long iFrame) { if (isProcess()) { Node *pNode = seek(iFrame); if (!isCapture()) m_observer.setValue(value(pNode, iFrame)); } } void process() { process(m_cursor.frame()); } // Record automation procedure. void capture(unsigned long iFrame) { if (isCapture()) addNode(iFrame, m_observer.value(), m_pEditList); } void capture() { capture(m_cursor.frame()); } qtractorCurveEditList *editList() const { return m_pEditList; } // Convert MIDI sequence events to curve nodes. void readMidiSequence(qtractorMidiSequence *pSeq, qtractorMidiEvent::EventType ctype, unsigned short iChannel, unsigned short iParam, qtractorTimeScale *pTimeScale); // Convert curve nodes to MIDI sequence. void writeMidiSequence(qtractorMidiSequence *pSeq, qtractorMidiEvent::EventType ctype, unsigned short iChannel, unsigned short iParam, qtractorTimeScale *pTimeScale) const; // Logarithmic scale mode accessors. void setLogarithmic(bool bLogarithmic) { m_bLogarithmic = bLogarithmic; } bool isLogarithmic() const { return m_bLogarithmic; } // Curve mode accessor. void setColor(const QColor& color) { m_color = color; } const QColor& color() const { return m_color; } // Emptyness status. bool isEmpty() const { return (m_nodes.count() < 1); } protected: // Snap to minimum distance frame. unsigned long frameDist(unsigned long iFrame) const; // Node interpolation coefficients updater. void updateNode(Node *pNode); void updateNodeEx(Node *pNode); // Observer for capture. class Observer : public qtractorObserver { public: // Constructor. Observer(qtractorSubject *pSubject, qtractorCurve *pCurve) : qtractorObserver(pSubject), m_pCurve(pCurve) {} // Capture updater. void update(bool) { m_pCurve->capture(); } private: // Own curve reference. qtractorCurve *m_pCurve; }; private: // Curve list owner. qtractorCurveList *m_pList; // Curve mode. Mode m_mode; // Minimum distance between adjacent nodes. unsigned int m_iMinFrameDist; // Capture observer. Observer m_observer; // The curve node list. qtractorList m_nodes; // Default (initial/final) node. Node m_tail; // Curve state. State m_state; // Optimizing cursor. Cursor m_cursor; // Logarithmic scale mode accessors. bool m_bLogarithmic; // Curve color. QColor m_color; // Capture (record) edit list. qtractorCurveEditList *m_pEditList; }; //---------------------------------------------------------------------------- // qtractorCurveListProxy -- Automation signal/slot notifier. // class qtractorCurveListProxy : public QObject { Q_OBJECT public: qtractorCurveListProxy(QObject *pParent = NULL) : QObject(pParent) {} void notify() { emit update(); } signals: void update(); }; //---------------------------------------------------------------------- // qtractorCurveEditList -- Curve node edit (command) list. class qtractorCurveEditList { public: // Constructor. qtractorCurveEditList(qtractorCurve *pCurve) : m_pCurve(pCurve) {} // Copy cnstructor. qtractorCurveEditList(const qtractorCurveEditList& list) : m_pCurve(list.curve()) { append(list); } // Destructor ~qtractorCurveEditList() { clear(); } // Curve accessor. qtractorCurve *curve() const { return m_pCurve; } // List predicate accessor. bool isEmpty() const { return m_items.isEmpty(); } // List methods. void addNode(qtractorCurve::Node *pNode) { m_items.append(new Item(AddNode, pNode, pNode->frame)); } void moveNode(qtractorCurve::Node *pNode, unsigned long iFrame) { m_items.append(new Item(MoveNode, pNode, iFrame)); } void removeNode(qtractorCurve::Node *pNode) { m_items.append(new Item(RemoveNode, pNode)); } // List appender. void append(const qtractorCurveEditList& list) { QListIterator iter(list.m_items); while (iter.hasNext()) m_items.append(new Item(*iter.next())); } // List cleanup. void clear() { QListIterator iter(m_items); while (iter.hasNext()) { Item *pItem = iter.next(); if (pItem->autoDelete) delete pItem->node; } qDeleteAll(m_items); m_items.clear(); } // Curve edit list command executive. bool execute(bool bRedo = true); protected: // Primitive command types. enum Command { AddNode, MoveNode, RemoveNode }; // Curve item struct. struct Item { // Item constructor. Item(Command cmd, qtractorCurve::Node *pNode, unsigned long iFrame = 0) : command(cmd), node(pNode), frame(iFrame), value(pNode->value), autoDelete(false) {} // Item copy constructor. Item(const Item& item) : command(item.command), node(item.node), frame(item.frame), value(item.value), autoDelete(item.autoDelete) {} // Item members. Command command; qtractorCurve::Node *node; unsigned long frame; float value; bool autoDelete; }; private: // Instance variables. qtractorCurve *m_pCurve; QList m_items; }; //---------------------------------------------------------------------------- // qtractorCurveList -- Automation item list // class qtractorCurveList : public qtractorList { public: // Constructor. qtractorCurveList() : m_iProcess(0), m_iCapture(0), m_iLocked(0), m_pCurrentCurve(NULL) { setAutoDelete(true); } // ~Destructor. ~qtractorCurveList() { clearAll(); } // Simple list methods. void addCurve(qtractorCurve *pCurve) { append(pCurve); } void removeCurve(qtractorCurve *pCurve) { if (m_pCurrentCurve == pCurve) m_pCurrentCurve = NULL; if (pCurve->isProcess()) updateProcess(false); if (pCurve->isCapture()) updateCapture(false); if (pCurve->isLocked()) updateLocked(false); // remove(pCurve); } // Set common curve length procedure. void setLength(unsigned long iLength) { qtractorCurve *pCurve = first(); while (pCurve) { pCurve->setLength(iLength); pCurve = pCurve->next(); } } unsigned long length() const { return (first() ? first()->length() : 0); } // Record automation procedure. void capture(unsigned long iFrame) { qtractorCurve *pCurve = first(); while (pCurve) { pCurve->capture(iFrame); pCurve = pCurve->next(); } } // The meta-processing automation procedure. void process(unsigned long iFrame) { qtractorCurve *pCurve = first(); while (pCurve) { pCurve->process(iFrame); pCurve = pCurve->next(); } } // Process management. void updateProcess(bool bProcess) { if (bProcess) ++m_iProcess; else if (!bProcess) --m_iProcess; } void setProcessAll(bool bProcess) { qtractorCurve *pCurve = first(); while (pCurve) { pCurve->setProcess(bProcess); pCurve = pCurve->next(); } } bool isProcessAll() const { return isProcess() && m_iProcess >= count(); } bool isProcess() const { return m_iProcess > 0; } // Capture management. void updateCapture(bool bCapture) { if (bCapture) ++m_iCapture; else --m_iCapture; } void setCaptureAll(bool bCapture) { qtractorCurve *pCurve = first(); while (pCurve) { pCurve->setCapture(bCapture); pCurve = pCurve->next(); } } bool isCaptureAll() const { return isCapture() && m_iCapture >= count(); } bool isCapture() const { return m_iCapture > 0; } // Locked management. void updateLocked(bool bLocked) { if (bLocked) ++m_iLocked; else --m_iLocked; } void setLockedAll(bool bLocked) { qtractorCurve *pCurve = first(); while (pCurve) { pCurve->setLocked(bLocked); pCurve = pCurve->next(); } } bool isLockedAll() const { return isLocked() && m_iLocked >= count(); } bool isLocked() const { return m_iLocked > 0; } // Check whether there's any captured material. bool isEditListEmpty() const { qtractorCurve *pCurve = first(); while (pCurve) { qtractorCurveEditList *pEditList = pCurve->editList(); if (pEditList && !pEditList->isEmpty()) return false; pCurve = pCurve->next(); } return true; } // Emptyness status. bool isEmpty() const { return (count() < 1); } // Whole list cleaner. void clearAll() { m_pCurrentCurve = NULL; clear(); m_iCapture = 0; m_iProcess = 0; m_iLocked = 0; } // Signal/slot notifier accessor. qtractorCurveListProxy *proxy() { return &m_proxy; } // Signal/slot notification. void notify() { m_proxy.notify(); } // Current curve accessors. void setCurrentCurve(qtractorCurve *pCurve) { m_pCurrentCurve = pCurve; } qtractorCurve *currentCurve() const { return m_pCurrentCurve; } private: // Mass capture/process state counters. int m_iProcess; int m_iCapture; int m_iLocked; // Signal/slot notifier. qtractorCurveListProxy m_proxy; // Current selected curve. qtractorCurve *m_pCurrentCurve; }; #endif // __qtractorCurve_h // end of qtractorCurve.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorTimeStretcher.cpp0000644000175000001440000000012311504365622022315 xustar000000000000000027 mtime=1293020050.654157 26 atime=1381134666.76208 30 ctime=1381134666.762080045 qtractor-0.5.11/src/qtractorTimeStretcher.cpp0000644000175000001440000001512011504365622021603 0ustar00rncbcusers00000000000000// qtractorTimeStretcher.cpp // /**************************************************************************** Copyright (C) 2005-2010, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorTimeStretcher.h" #include #include #include // Constructor. qtractorTimeStretcher::qtractorTimeStretcher ( unsigned short iChannels, unsigned int iSampleRate, float fTimeStretch, float fPitchShift, unsigned int iFlags, unsigned int iBufferSize ) : m_pTimeStretch(NULL) #ifdef CONFIG_LIBRUBBERBAND , m_pRubberBandStretcher(NULL) , m_iRubberBandChannels(iChannels) , m_iRubberBandLatency(0) , m_iRubberBandFrames(0) , m_ppRubberBandFrames(NULL) , m_ppRubberBandBuffer(NULL) , m_bRubberBandFlush(false) #endif { if ((fTimeStretch > 0.1f && fTimeStretch < 1.0f - 1e-3f) || (fTimeStretch > 1.0f + 1e-3f && fTimeStretch < 4.0f)) { if (iFlags & WsolaTimeStretch) { m_pTimeStretch = new qtractorTimeStretch(iChannels, iSampleRate); m_pTimeStretch->setTempo(1.0f / fTimeStretch); m_pTimeStretch->setQuickSeek(iFlags & WsolaQuickSeek); fTimeStretch = 0.0f; } } else fTimeStretch = 0.0f; #ifdef CONFIG_LIBRUBBERBAND if (fTimeStretch > 0.0f || (fPitchShift > 0.1f && fPitchShift < 1.0f - 1e-3f) || (fPitchShift > 1.0f + 1e-3f && fPitchShift < 4.0f)) { if (fTimeStretch < 0.1f) fTimeStretch = 1.0f; m_pRubberBandStretcher = new RubberBand::RubberBandStretcher( iSampleRate, iChannels, RubberBand::RubberBandStretcher::OptionProcessRealTime, fTimeStretch, fPitchShift); m_pRubberBandStretcher->setMaxProcessSize(iBufferSize); m_ppRubberBandBuffer = new float * [m_iRubberBandChannels]; m_iRubberBandLatency = m_pRubberBandStretcher->getLatency(); m_iRubberBandFrames = m_iRubberBandLatency; if (m_iRubberBandFrames > 0) { m_ppRubberBandFrames = new float * [m_iRubberBandChannels]; m_ppRubberBandFrames[0] = new float [m_iRubberBandFrames]; ::memset(m_ppRubberBandFrames[0], 0, m_iRubberBandFrames * sizeof(float)); for (unsigned short i = 1; i < m_iRubberBandChannels; ++i) m_ppRubberBandFrames[i] = m_ppRubberBandFrames[0]; } } #endif } // Destructor. qtractorTimeStretcher::~qtractorTimeStretcher() { if (m_pTimeStretch) delete m_pTimeStretch; #ifdef CONFIG_LIBRUBBERBAND if (m_ppRubberBandBuffer) delete [] m_ppRubberBandBuffer; if (m_ppRubberBandFrames) { delete [] m_ppRubberBandFrames[0]; delete [] m_ppRubberBandFrames; } if (m_pRubberBandStretcher) delete m_pRubberBandStretcher; #endif } // Adds frames of samples into the input buffer. void qtractorTimeStretcher::process ( float **ppFrames, unsigned int iFrames ) { if (m_pTimeStretch) { m_pTimeStretch->putFrames(ppFrames, iFrames); #ifdef CONFIG_LIBRUBBERBAND if (m_pRubberBandStretcher) { unsigned int noffs = 0; unsigned int nread = iFrames; while (nread > 0 && noffs < iFrames) { for (unsigned short i = 0; i < m_iRubberBandChannels; ++i) m_ppRubberBandBuffer[i] = ppFrames[i] + noffs; nread = m_pTimeStretch->receiveFrames( m_ppRubberBandBuffer, iFrames - noffs); noffs += nread; } iFrames = noffs; } } if (m_pRubberBandStretcher) { m_pRubberBandStretcher->process(ppFrames, iFrames, false); #endif } } // Copies requested frames output buffer and removes them // from the sample buffer. If there are less than available() // samples in the buffer, returns all that available. duh? unsigned int qtractorTimeStretcher::retrieve ( float **ppFrames, unsigned int iFrames ) { #ifdef CONFIG_LIBRUBBERBAND if (m_pRubberBandStretcher) { unsigned int nread = m_pRubberBandStretcher->retrieve(ppFrames, iFrames); if (nread > 0 && m_iRubberBandLatency > 0) { if (m_iRubberBandLatency > nread) { m_iRubberBandLatency -= nread; nread = 0; } else { unsigned int noffs = m_iRubberBandLatency; nread -= m_iRubberBandLatency; m_iRubberBandLatency = 0; for (unsigned int i = 0; i < m_iRubberBandChannels; ++i) { float *pFrames = ppFrames[i]; ::memmove(pFrames, pFrames + noffs, nread * sizeof(float)); } } } return nread; } #endif return (m_pTimeStretch ? m_pTimeStretch->receiveFrames(ppFrames, iFrames) : 0); } // Returns number of frames currently available. unsigned int qtractorTimeStretcher::available (void) const { int iAvailable = 0; #ifdef CONFIG_LIBRUBBERBAND if (m_pRubberBandStretcher) iAvailable = m_pRubberBandStretcher->available(); else #endif if (m_pTimeStretch) iAvailable = m_pTimeStretch->frames(); return (iAvailable > 0 ? iAvailable : 0); } // Flush any last samples that are hiding // in the internal processing pipeline. void qtractorTimeStretcher::flush (void) { if (m_pTimeStretch) m_pTimeStretch->flushInput(); #ifdef CONFIG_LIBRUBBERBAND if (m_pRubberBandStretcher && !m_bRubberBandFlush) { // Process a last dummy empty buffer... if (m_iRubberBandFrames > 0) { m_pRubberBandStretcher->process( m_ppRubberBandFrames, m_iRubberBandFrames, true); } m_iRubberBandLatency = 0; m_bRubberBandFlush = true; } #endif } // Clears all buffers. void qtractorTimeStretcher::reset (void) { if (m_pTimeStretch) m_pTimeStretch->clear(); #ifdef CONFIG_LIBRUBBERBAND if (m_pRubberBandStretcher) { m_pRubberBandStretcher->reset(); m_iRubberBandLatency = m_pRubberBandStretcher->getLatency(); m_iRubberBandFrames = m_iRubberBandLatency; if (m_iRubberBandFrames > 0) { if (m_ppRubberBandFrames) { delete [] m_ppRubberBandFrames[0]; // delete [] m_ppRubberBandFrames; } // m_ppRubberBandFrames = new float * [m_iRubberBandChannels]; m_ppRubberBandFrames[0] = new float [m_iRubberBandFrames]; ::memset(m_ppRubberBandFrames[0], 0, m_iRubberBandFrames * sizeof(float)); for (unsigned short i = 1; i < m_iRubberBandChannels; ++i) m_ppRubberBandFrames[i] = m_ppRubberBandFrames[0]; } m_bRubberBandFlush = false; } #endif } // end of qtractorTimeStretcher.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorObserverWidget.cpp0000644000175000001440000000012312161335204022457 xustar000000000000000027 mtime=1371912836.382031 26 atime=1381134667.36708 30 ctime=1381134667.367080055 qtractor-0.5.11/src/qtractorObserverWidget.cpp0000644000175000001440000001121312161335204021744 0ustar00rncbcusers00000000000000// qtractorObserverWidget.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorObserverWidget.h" #include #include //---------------------------------------------------------------------- // class qtractorObserverCheckBox -- Concrete widget observer. // // Constructor. qtractorObserverCheckBox::qtractorObserverCheckBox ( QWidget *pParent ) : qtractorObserverWidget (pParent) { QObject::connect(this, SIGNAL(toggled(bool)), SLOT(checkBoxChanged(bool))); } // Visitors overload. void qtractorObserverCheckBox::updateValue ( float fValue ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorObserverCheckBox[%p]::updateValue(%g)", this, fValue); #endif bool bBlockSignals = QCheckBox::blockSignals(true); QCheckBox::setChecked(bool(scaleFromValue(fValue))); QCheckBox::blockSignals(bBlockSignals); } // Protected slot. void qtractorObserverCheckBox::checkBoxChanged ( bool bValue ) { float fValue = valueFromScale(bValue ? 1.0f : 0.0f); #ifdef CONFIG_DEBUG_0 qDebug("qtractorObserverCheckBox[%p]::checkBoxChanged(%g)", this, fValue); #endif observer()->setValue(fValue); emit valueChanged(fValue); } //---------------------------------------------------------------------- // class qtractorObserverSpinBox -- Concrete widget observer. // // Constructor. qtractorObserverSpinBox::qtractorObserverSpinBox ( QWidget *pParent ) : qtractorObserverWidget (pParent) { QObject::connect(this, SIGNAL(valueChanged(double)), SLOT(spinBoxChanged(double))); } // Visitors overload. void qtractorObserverSpinBox::updateValue ( float fValue ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorObserverSpinBox[%p]::updateValue(%g)", this, fValue); #endif bool bBlockSignals = QDoubleSpinBox::blockSignals(true); QDoubleSpinBox::setValue(scaleFromValue(fValue)); QDoubleSpinBox::blockSignals(bBlockSignals); } // Protected slot. void qtractorObserverSpinBox::spinBoxChanged ( double value ) { float fValue = valueFromScale(float(value)); #ifdef CONFIG_DEBUG_0 qDebug("qtractorObserverSpinBox[%p]::spinBoxChanged(%g)", this, fValue); #endif observer()->setValue(fValue); emit valueChanged(fValue); } //---------------------------------------------------------------------- // class qtractorObserverSlider -- Concrete widget observer. // // Constructor. qtractorObserverSlider::qtractorObserverSlider ( QWidget *pParent ) : qtractorObserverWidget (pParent) { QObject::connect(this, SIGNAL(valueChanged(int)), SLOT(sliderChanged(int))); } // Alternate mouse behavior event handlers. void qtractorObserverSlider::mousePressEvent ( QMouseEvent *pMouseEvent ) { // Reset to default value... if (pMouseEvent->button() == Qt::MidButton) setValue(scaleFromValue(observer()->defaultValue())); else qtractorObserverWidget::mousePressEvent(pMouseEvent); } void qtractorObserverSlider::wheelEvent ( QWheelEvent *pWheelEvent ) { int iValue = value(); if (pWheelEvent->delta() < 0) iValue -= pageStep(); else iValue += pageStep(); if (iValue > maximum()) iValue = maximum(); else if (iValue < minimum()) iValue = minimum(); setValue(iValue); } // Visitors overload. void qtractorObserverSlider::updateValue ( float fValue ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorObserverSlider[%p]::updateValue(%g)", this, fValue); #endif bool bBlockSignals = QSlider::blockSignals(true); QSlider::setValue(int(scaleFromValue(fValue))); QSlider::blockSignals(bBlockSignals); } // Protected slot. void qtractorObserverSlider::sliderChanged ( int iValue ) { float fValue = valueFromScale(float(iValue)); #ifdef CONFIG_DEBUG_0 qDebug("qtractorObserverSlider[%p]::sliderChanged(%g)", this, fValue); #endif observer()->setValue(fValue); emit valueChanged(fValue); }; // end of qtractorObserverWidget.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorFileListView.h0000644000175000001440000000012312141747305021546 xustar000000000000000027 mtime=1367854789.991712 26 atime=1381134666.48808 30 ctime=1381134666.488080041 qtractor-0.5.11/src/qtractorFileListView.h0000644000175000001440000002154712141747305021046 0ustar00rncbcusers00000000000000// qtractorFileListView.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorFileListView_h #define __qtractorFileListView_h #include "qtractorFileList.h" #include // Forward declarations. class qtractorFileListView; class qtractorFileListItem; class qtractorFileGroupItem; class qtractorRubberBand; class qtractorDocument; class QDomElement; //---------------------------------------------------------------------------- // qtractorFileListView -- Group/File list view, supporting drag-n-drop. // class qtractorFileListView : public QTreeWidget { Q_OBJECT public: // Constructor. qtractorFileListView(qtractorFileList::Type iFileType, QWidget *pParent = 0); // Default destructor. virtual ~qtractorFileListView(); // File list type property. void setFileType(qtractorFileList::Type iFileType); qtractorFileList::Type fileType() const; // QListViewItem::type() return values. enum ItemType { GroupItem = 1001, FileItem = 1002, ChannelItem = 1003 }; // Prompt for proper file list open. QStringList openFileNames(); // Add a new group/file item, optionally under a given group. qtractorFileGroupItem *addGroupItem(const QString& sName, qtractorFileGroupItem *pParentItem = NULL); qtractorFileListItem *addFileItem(const QString& sPath, bool bAutoRemove, qtractorFileGroupItem *pParentItem = NULL); // Current group/file item accessors... qtractorFileGroupItem *currentGroupItem() const; qtractorFileListItem *currentFileItem() const; // Find a group/file item, given its name. qtractorFileGroupItem *findGroupItem(const QString& sName) const; qtractorFileListItem *findFileItem(const QString& sPath) const; // Make as current selection an existing file item. qtractorFileListItem *selectFileItem(const QString& sPath, int iChannel = -1); // Add a new group item below the current one. void newGroup(); // Add a new file item below the current group one. void openFile(); // Copy/cut current file item(s) to clipboard. void copyItem(bool bCut = false); // Paste file item(s) from clipboard. void pasteItem(); // Rename current group/file item. void renameItem(); // Remove current group/file item(s). void removeItem(); // Clean-up unused file items. void cleanupItem(QTreeWidgetItem *pItem); void cleanup(); // Emit actiovation signal for given item... void activateItem(QTreeWidgetItem *pItem = NULL); // Master clean-up. void clear(); // Auto-open timer methods. void setAutoOpenTimeout(int iAutoOpenTimeout); int autoOpenTimeout() const; // Recently used directory, if any. void setRecentDir(const QString& sRecentDir); const QString& recentDir() const; // Elemental loader/saver... bool loadElement(qtractorDocument *pDocument, QDomElement *pElement); bool saveElement(qtractorDocument *pDocument, QDomElement *pElement); signals: // File entry activated. void selected(const QString& sFilename, int iTrackChannel, bool bSelect); // File entry activated. void activated(const QString& sFilename, int iTrackChannel); // Contents change signal; void contentsChanged(); protected slots: // In-place toggle slot. void itemClickedSlot(QTreeWidgetItem *pItem); // In-place activate slot. void itemActivatedSlot(QTreeWidgetItem *pItem); // In-place open/close slot. void itemExpandedSlot(QTreeWidgetItem *pItem); void itemCollapsedSlot(QTreeWidgetItem *pItem); // Tracking of item changes (e.g in-place edits). void itemRenamedSlot(); // Auto-open timeout slot. void timeoutSlot(); protected: // Find and return the nearest group item... qtractorFileGroupItem *groupItem(QTreeWidgetItem *pItem) const; // Find a list view item, given its type and name. QTreeWidgetItem *findItem(const QString& sText, int iType) const; // Which column is the complete file path? virtual int pathColumn() const = 0; // Pure virtual file item creation; // must be implemented in derived classes. virtual qtractorFileListItem *createFileItem(const QString& sPath) = 0; // Prompt for proper file list open (pure virtual). virtual QStringList getOpenFileNames() = 0; // Trap for help/tool-tip events. bool eventFilter(QObject *pObject, QEvent *pEvent); // Drag-n-drop stuff -- reimplemented virtual methods. void mousePressEvent(QMouseEvent *pMouseEvent); void mouseMoveEvent(QMouseEvent *pMouseEvent); void mouseReleaseEvent(QMouseEvent *pMouseEvent); void dragEnterEvent(QDragEnterEvent *pDragEnterEvent); void dragMoveEvent(QDragMoveEvent *pDragMoveEvent); void dragLeaveEvent(QDragLeaveEvent *pDragLeaveEvent); void dropEvent(QDropEvent *pDropEvent); // Drag-n-drop stuff. bool canDecodeEvent(QDropEvent *pDropEvent); bool canDropItem(QTreeWidgetItem *pDropItem) const; QTreeWidgetItem *dragDropItem(const QPoint& pos); // Ensure given item is brought to viewport visibility... void ensureVisibleItem(QTreeWidgetItem *pItem); // Show and move rubber-band item. void moveRubberBand(QTreeWidgetItem *pDropItem, bool bOutdent = false); // Drag-and-drop target method... QTreeWidgetItem *dropItem(QTreeWidgetItem *pDropItem, QTreeWidgetItem *pDragItem, bool bOutdent = false); // Internal recursive loaders/savers... bool loadListElement(qtractorDocument *pDocument, QDomElement *pElement, QTreeWidgetItem *pItem); bool saveListElement(qtractorDocument *pDocument, QDomElement *pElement, QTreeWidgetItem *pItem); private: // Major file type property. qtractorFileList::Type m_iFileType; // Auto-open timer. int m_iAutoOpenTimeout; QTimer *m_pAutoOpenTimer; // The point from where drag started. QPoint m_posDrag; // Item we'll eventually drag around. QTreeWidgetItem *m_pDragItem; // Item we'll eventually drop something. QTreeWidgetItem *m_pDropItem; // To show the point where drop will go. qtractorRubberBand *m_pRubberBand; // Last recently used directory. QString m_sRecentDir; }; //---------------------------------------------------------------------- // class qtractorFileGroupItem -- custom group list view item. // class qtractorFileGroupItem : public QTreeWidgetItem { public: // Constructors. qtractorFileGroupItem(const QString& sName, int iType = qtractorFileListView::GroupItem); // Default destructor. virtual ~qtractorFileGroupItem(); // Instance accessors. void setName(const QString& sName); QString name() const; qtractorFileListView *listView() const; qtractorFileGroupItem *groupItem() const; // To show up whether its open or not. void setOpen(bool bOpen); bool isOpen() const; // Virtual tooltip renderer. virtual QString toolTip() const; }; //---------------------------------------------------------------------- // class qtractorFileListItem -- custom file list view item. // class qtractorFileListItem : public qtractorFileGroupItem { public: // Constructors. qtractorFileListItem(const QString& sPath); // Default destructor. ~qtractorFileListItem(); // Full path accessor. const QString& path() const; private: // File item full path. QString m_sPath; }; //---------------------------------------------------------------------- // class qtractorFileChannelItem -- custom channel list view item. // class qtractorFileChannelItem : public qtractorFileGroupItem { public: // Constructors. qtractorFileChannelItem(qtractorFileListItem *pFileItem, const QString& sName, unsigned short iChannel); // Default destructor. ~qtractorFileChannelItem(); // File chhannel accessor. unsigned short channel() const; // Full path accessor. const QString path() const; private: // File channel identifier. unsigned short m_iChannel; }; //---------------------------------------------------------------------- // class qtractorFileChannelDrag -- custom file channel drag object. // class qtractorFileChannelDrag { public: struct Item { QString path; unsigned short channel; }; typedef QList List; // Encode method. static void encode(QMimeData *pMimeData, const List& items); // Decode methods. static bool canDecode(const QMimeData *pMimeData); static List decode(const QMimeData *pMimeData); }; #endif // __qtractorFileListView_h // end of qtractorFileListView.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorVstPlugin.h0000644000175000001440000000012312161335204021124 xustar000000000000000027 mtime=1371912836.382031 26 atime=1381134666.81708 30 ctime=1381134666.817080046 qtractor-0.5.11/src/qtractorVstPlugin.h0000644000175000001440000001255212161335204020420 0ustar00rncbcusers00000000000000// qtractorVstPlugin.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorVstPlugin_h #define __qtractorVstPlugin_h #include "qtractorPlugin.h" // Allow VST 2.3 compability mode. // #define VST_2_4_EXTENSIONS 0 // #define VST_FORCE_DEPRECATED 1 #include #if !defined(__WIN32__) && !defined(_WIN32) && !defined(WIN32) #define __cdecl #endif #include //---------------------------------------------------------------------------- // qtractorVstPluginType -- VST plugin type instance. // class qtractorVstPluginType : public qtractorPluginType { public: // Forward declarations. class Effect; // Constructor. qtractorVstPluginType(qtractorPluginFile *pFile, Effect *pEffect = NULL) : qtractorPluginType(pFile, 0, qtractorPluginType::Vst), m_pEffect(pEffect), m_iFlagsEx(0) {} // Destructor. ~qtractorVstPluginType() { close(); } // Derived methods. bool open(); void close(); // Specific accessors. Effect *effect() const { return m_pEffect; } // Factory method (static) static qtractorVstPluginType *createType(qtractorPluginFile *pFile); // Effect instance method (static) static AEffect *vst_effect(qtractorPluginFile *pFile); // VST host dispatcher. int vst_dispatch( long opcode, long index, long value, void *ptr, float opt) const; protected: // VST flag inquirer. bool vst_canDo(const char *pszCanDo) const; private: // VST descriptor reference. Effect *m_pEffect; unsigned int m_iFlagsEx; }; //---------------------------------------------------------------------------- // qtractorVstPlugin -- VST plugin instance. // class qtractorVstPlugin : public qtractorPlugin { public: // Constructor. qtractorVstPlugin(qtractorPluginList *pList, qtractorVstPluginType *pVstType); // Destructor. ~qtractorVstPlugin(); // Channel/intsance number accessors. void setChannels(unsigned short iChannels); // Do the actual (de)activation. void activate(); void deactivate(); // The main plugin processing procedure. void process(float **ppIBuffer, float **ppOBuffer, unsigned int nframes); // Parameter update method. void updateParam(qtractorPluginParam *pParam, float fValue, bool bUpdate); // Bank/program selector override. void selectProgram(int iBank, int iProg); // Provisional program/patch accessor. bool getProgram(int iIndex, Program& program) const; // Configuration (CLOB) stuff. void configure(const QString& sKey, const QString& sValue); // Plugin configuration/state snapshot. void freezeConfigs(); void releaseConfigs(); // GUI Editor stuff. void openEditor(QWidget *pParent); void closeEditor(); void idleEditor(); // GUI editor visibility state. void setEditorVisible(bool bVisible); bool isEditorVisible() const; void setEditorTitle(const QString& sTitle); // Specific accessors. AEffect *vst_effect(unsigned short iInstance) const; // VST host dispatcher. int vst_dispatch(unsigned short iInstance, long opcode, long index, long value, void *ptr, float opt) const; // Our own editor widget accessor. QWidget *editorWidget() const; // Our own editor widget size accessor. void resizeEditor(int w, int h); // Global VST plugin lookup. static qtractorVstPlugin *findPlugin(AEffect *pVstEffect); // Idle editor (static). static void idleEditorAll(); // Editor widget forward decls. class EditorWidget; #if defined(Q_WS_X11) // Global X11 event filter. static bool x11EventFilter(void *pvEvent); #endif // Parameter update method. void updateParamValues(bool bUpdate); private: // Instance variables. qtractorVstPluginType::Effect **m_ppEffects; // Audio I/O buffer pointers. float **m_ppIBuffer; float **m_ppOBuffer; // Our own editor widget (parent frame). EditorWidget *m_pEditorWidget; }; //---------------------------------------------------------------------------- // qtractorVstPluginParam -- VST plugin control input port instance. // class qtractorVstPluginParam : public qtractorPluginParam { public: // Constructors. qtractorVstPluginParam(qtractorVstPlugin *pVstPlugin, unsigned long iIndex); // Destructor. ~qtractorVstPluginParam(); // Port range hints predicate methods. bool isBoundedBelow() const; bool isBoundedAbove() const; bool isDefaultValue() const; bool isLogarithmic() const; bool isSampleRate() const; bool isInteger() const; bool isToggled() const; bool isDisplay() const; // Current display value. QString display() const; private: VstParameterProperties m_props; }; #endif // __qtractorVstPlugin_h // end of qtractorVstPlugin.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMixer.h0000644000175000001440000000012312073012112020245 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134668.01608 30 ctime=1381134668.016080065 qtractor-0.5.11/src/qtractorMixer.h0000644000175000001440000002055512073012112017543 0ustar00rncbcusers00000000000000// qtractorMixer.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMixer_h #define __qtractorMixer_h #include "qtractorEngine.h" #include "qtractorTrackButton.h" #include #include #include // Forward declarations. class qtractorMixerStrip; class qtractorMixerRack; class qtractorMixer; class qtractorMeter; class qtractorPluginListView; class QHBoxLayout; class QVBoxLayout; class QLabel; class QSplitter; class QPushButton; //---------------------------------------------------------------------------- // qtractorMonitorButton -- Monitor observer tool button. class qtractorMonitorButton : public qtractorMidiControlButton { Q_OBJECT public: // Constructors. qtractorMonitorButton(qtractorTrack *pTrack, QWidget *pParent = 0); qtractorMonitorButton(qtractorBus *pBus, QWidget *pParent = 0); // Specific track accessors. void setTrack(qtractorTrack *pTrack); qtractorTrack *track() const; // Specific bus accessors. void setBus(qtractorBus *pBus); qtractorBus *bus() const; protected slots: // Special toggle slot. void toggledSlot(bool bOn); protected: // Common initializer. void initMonitorButton(); // Visitor setup. void updateMonitor(); // Visitors overload. void updateValue(float fValue); private: // Instance variables. qtractorTrack *m_pTrack; qtractorBus *m_pBus; }; //---------------------------------------------------------------------------- // qtractorMixerStrip -- Mixer strip widget. class qtractorMixerStrip : public QFrame { Q_OBJECT public: // Constructors. qtractorMixerStrip(qtractorMixerRack *pRack, qtractorBus *pBus, qtractorBus::BusMode busMode); qtractorMixerStrip(qtractorMixerRack *pRack, qtractorTrack *pTrack); // Default destructor. ~qtractorMixerStrip(); // Clear/suspend delegates. void clear(); // Delegated properties accessors. void setMonitor(qtractorMonitor *pMonitor); qtractorMonitor *monitor() const; // Child accessors. qtractorPluginListView *pluginListView() const; qtractorMeter *meter() const; // Bus property accessors. void setBus(qtractorBus *pBus); qtractorBus *bus() const; // Track property accessors. void setTrack(qtractorTrack *pTrack); qtractorTrack *track() const; // Selection methods. void setSelected(bool bSelected); bool isSelected() const; // Strip refreshment. void refresh(); // Hacko-list-management marking... void setMark(int iMark); int mark() const; // Special bus dispatchers. void busConnections(qtractorBus::BusMode busMode); void busMonitor(bool bMonitor); // Track monitor dispatcher. void trackMonitor(bool bMonitor); protected slots: // Bus connections button notification. void busButtonSlot(); // Meter slider change slots. void panningChangedSlot(float); void gainChangedSlot(float); protected: // Common mixer-strip initializer. void initMixerStrip(); void updateMidiLabel(); void updateName(); // Mouse selection event handlers. void mousePressEvent(QMouseEvent *); // Mouse selection event handlers. void mouseDoubleClickEvent(QMouseEvent *); private: // Local instance variables. qtractorMixerRack *m_pRack; qtractorBus *m_pBus; qtractorBus::BusMode m_busMode; qtractorTrack *m_pTrack; // Local widgets. class IconLabel; QVBoxLayout *m_pLayout; IconLabel *m_pLabel; qtractorPluginListView *m_pPluginListView; QHBoxLayout *m_pButtonLayout; qtractorMonitorButton *m_pMonitorButton; qtractorTrackButton *m_pRecordButton; qtractorTrackButton *m_pMuteButton; qtractorTrackButton *m_pSoloButton; qtractorMeter *m_pMeter; QPushButton *m_pBusButton; QLabel *m_pMidiLabel; // Selection stuff. bool m_bSelected; // Hacko-list-management mark... int m_iMark; }; //---------------------------------------------------------------------------- // qtractorMixerRack -- Mixer strip rack. class qtractorMixerRack : public QScrollArea { Q_OBJECT public: // Constructor. qtractorMixerRack(qtractorMixer *pMixer, const QString& sName); // Default destructor. ~qtractorMixerRack(); // The main mixer widget accessor. qtractorMixer *mixer() const; // Rack name accessor. void setName(const QString& sName); const QString& name() const; // The mixer strip workspace. QWidget *workspace() const; // Strip list primitive methods. void addStrip(qtractorMixerStrip *pStrip); void removeStrip(qtractorMixerStrip *pStrip); // Find a mixer strip, given its monitor handle. qtractorMixerStrip *findStrip(qtractorMonitor *pMonitor); // Update a mixer strip on rack list. void updateStrip(qtractorMixerStrip *pStrip, qtractorMonitor *pMonitor); // Current Strip count. int stripCount() const; // Complete rack refreshment. void refresh(); // Complete rack recycle. void clear(); // Selection stuff. void setSelectEnabled(bool bSelectEnabled); bool isSelectEnabled() const; void setSelectedStrip(qtractorMixerStrip *pStrip); qtractorMixerStrip *selectedStrip() const; // Hacko-list-management marking... void markStrips(int iMark); void cleanStrips(int iMark); public slots: // Bus context menu slots. void busInputsSlot(); void busOutputsSlot(); void busMonitorSlot(); void busPropertiesSlot(); signals: // Selection changed signal. void selectionChanged(); protected: // Resize event handler. void resizeEvent(QResizeEvent *pResizeEvent); // Context menu request event handler. void contextMenuEvent(QContextMenuEvent *); // Mouse click event handler. void mousePressEvent(QMouseEvent *); private: // Instance properties. qtractorMixer *m_pMixer; // Rack title. QString m_sName; // Layout widgets. QWidget *m_pWorkspace; QHBoxLayout *m_pWorkspaceLayout; // The Strips list. typedef QHash Strips; Strips m_strips; // Selection stuff. bool m_bSelectEnabled; qtractorMixerStrip *m_pSelectedStrip; }; //---------------------------------------------------------------------------- // qtractorMixer -- Mixer widget. class qtractorMixer : public QWidget { Q_OBJECT public: // Constructor. qtractorMixer(QWidget *pParent, Qt::WindowFlags wflags = 0); // Default destructor. ~qtractorMixer(); // The splitter layout widget accessor. QSplitter *splitter() const; // The mixer strips rack accessors. qtractorMixerRack *inputRack() const; qtractorMixerRack *trackRack() const; qtractorMixerRack *outputRack() const; // Update buses and tracks'racks. void updateBuses(bool bReset = false); void updateTracks(bool bReset = false); // Update mixer rack, checking whether the monitor actually exists. void updateBusStrip(qtractorMixerRack *pRack, qtractorBus *pBus, qtractorBus::BusMode busMode, bool bReset = false); void updateTrackStrip(qtractorTrack *pTrack, bool bReset = false); // Complete mixer refreshment. void refresh(); // Complete mixer recycle. void clear(); protected: // Notify the main application widget that we're closing. void showEvent(QShowEvent *); void hideEvent(QHideEvent *); // Just about to notify main-window that we're closing. void closeEvent(QCloseEvent *); // Keyboard event handler. void keyPressEvent(QKeyEvent *); // Special splitter-size persistence methods. void loadSplitterSizes(); void saveSplitterSizes(); // Initial minimum widget extents. QSize sizeHint() const; private: // Child controls. QSplitter *m_pSplitter; qtractorMixerRack *m_pInputRack; qtractorMixerRack *m_pTrackRack; qtractorMixerRack *m_pOutputRack; }; #endif // __qtractorMixer_h // end of qtractorMixer.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorCurveCommand.cpp0000644000175000001440000000012312214700751022111 xustar000000000000000027 mtime=1379107305.445084 26 atime=1381134668.06908 30 ctime=1381134668.085080066 qtractor-0.5.11/src/qtractorCurveCommand.cpp0000644000175000001440000003252412214700751021406 0ustar00rncbcusers00000000000000// qtractorCurveCommand.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorCurveCommand.h" #include "qtractorSession.h" #include "qtractorMainForm.h" #include "qtractorTracks.h" //---------------------------------------------------------------------- // class qtractorCurveBaseCommand - declaration. // // Constructor. qtractorCurveBaseCommand::qtractorCurveBaseCommand ( const QString& sName ) : qtractorCommand(sName) { } // Virtual command methods. bool qtractorCurveBaseCommand::redo (void) { return execute(true); } bool qtractorCurveBaseCommand::undo (void) { return execute(false); } // Virtual command methods. bool qtractorCurveBaseCommand::execute ( bool /*bRedo*/ ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession && !pSession->isPlaying()) pSession->process_curve(pSession->playHead()); qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) { qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks) { pTracks->clearSelect(); pTracks->updateTrackList(); } } return true; } //---------------------------------------------------------------------- // class qtractorCurveCommand - declaration. // // Constructor. qtractorCurveCommand::qtractorCurveCommand ( const QString& sName, qtractorCurve *pCurve ) : qtractorCurveBaseCommand(sName), m_pCurve(pCurve) { } //---------------------------------------------------------------------- // class qtractorCurveListCommand - declaration. // // Constructor. qtractorCurveListCommand::qtractorCurveListCommand ( const QString& sName, qtractorCurveList *pCurveList ) : qtractorCurveBaseCommand(sName), m_pCurveList(pCurveList) { } //---------------------------------------------------------------------- // class qtractorCurveSelectCommand - declaration. // // Constructor. qtractorCurveSelectCommand::qtractorCurveSelectCommand ( qtractorCurveList *pCurveList, qtractorCurve *pCurrentCurve ) : qtractorCurveListCommand(QObject::tr("automation select"), pCurveList), m_pCurrentCurve(pCurrentCurve) { } // Virtual command methods. bool qtractorCurveSelectCommand::execute ( bool bRedo ) { if (m_pCurveList == NULL) return false; qtractorCurve *pCurrentCurve = m_pCurveList->currentCurve(); m_pCurveList->setCurrentCurve(m_pCurrentCurve); m_pCurrentCurve = pCurrentCurve; return qtractorCurveBaseCommand::execute(bRedo); } //---------------------------------------------------------------------- // class qtractorCurveModeCommand - declaration. // // Constructor. qtractorCurveModeCommand::qtractorCurveModeCommand ( qtractorCurve *pCurve, qtractorCurve::Mode mode ) : qtractorCurveCommand(QObject::tr("automation mode"), pCurve), m_mode(mode) { } // Virtual command methods. bool qtractorCurveModeCommand::execute ( bool bRedo ) { if (m_pCurve == NULL) return false; qtractorCurve::Mode mode = m_pCurve->mode(); m_pCurve->setMode(m_mode); m_pCurve->update(); m_mode = mode; return qtractorCurveBaseCommand::execute(bRedo); } //---------------------------------------------------------------------- // class qtractorCurveProcessCommand - declaration. // // Constructor. qtractorCurveProcessCommand::qtractorCurveProcessCommand ( qtractorCurve *pCurve, bool bProcess ) : qtractorCurveCommand(QObject::tr("automation play"), pCurve), m_bProcess(bProcess) { } // Virtual command methods. bool qtractorCurveProcessCommand::execute ( bool bRedo ) { if (m_pCurve == NULL) return false; bool bProcess = m_pCurve->isProcess(); if (!m_bProcess) m_pCurve->setCapture(false); m_pCurve->setProcess(m_bProcess); m_bProcess = bProcess; return qtractorCurveBaseCommand::execute(bRedo); } //---------------------------------------------------------------------- // class qtractorCurveCaptureCommand - declaration. // // Constructor. qtractorCurveCaptureCommand::qtractorCurveCaptureCommand ( qtractorCurve *pCurve, bool bCapture ) : qtractorCurveCommand(QObject::tr("automation record"), pCurve), m_bCapture(bCapture) { } // Virtual command methods. bool qtractorCurveCaptureCommand::execute ( bool bRedo ) { if (m_pCurve == NULL) return false; bool bCapture = m_pCurve->isCapture(); if (m_bCapture) m_pCurve->setProcess(true); m_pCurve->setCapture(m_bCapture); m_bCapture = bCapture; return qtractorCurveBaseCommand::execute(bRedo); } //---------------------------------------------------------------------- // class qtractorCurveLogarithmicCommand - declaration. // // Constructor. qtractorCurveLogarithmicCommand::qtractorCurveLogarithmicCommand ( qtractorCurve *pCurve, bool bLogarithmic ) : qtractorCurveCommand(QObject::tr("automation logarithmic"), pCurve), m_bLogarithmic(bLogarithmic) { } // Virtual command methods. bool qtractorCurveLogarithmicCommand::execute ( bool /*bRedo*/ ) { if (m_pCurve == NULL) return false; bool bLogarithmic = m_pCurve->isLogarithmic(); m_pCurve->setLogarithmic(m_bLogarithmic); m_bLogarithmic = bLogarithmic; return true; } //---------------------------------------------------------------------- // class qtractorCurveCaptureCommand - declaration. // // Constructor. qtractorCurveColorCommand::qtractorCurveColorCommand ( qtractorCurve *pCurve, const QColor& color ) : qtractorCurveCommand(QObject::tr("automation color"), pCurve), m_color(color) { } // Virtual command methods. bool qtractorCurveColorCommand::execute ( bool /*bRedo*/ ) { if (m_pCurve == NULL) return false; QColor color = m_pCurve->color(); m_pCurve->setColor(m_color); m_color = color; return true; } //---------------------------------------------------------------------- // class qtractorCurveProcessAllCommand - declaration. // // Constructor. qtractorCurveProcessAllCommand::qtractorCurveProcessAllCommand ( qtractorCurveList *pCurveList, bool bProcessAll ) : qtractorCurveListCommand(QObject::tr("automation play all"), pCurveList), m_bProcessAll(bProcessAll) { } // Virtual command methods. bool qtractorCurveProcessAllCommand::execute ( bool bRedo ) { if (m_pCurveList == NULL) return false; bool bProcessAll = m_pCurveList->isProcessAll(); if (!m_bProcessAll) m_pCurveList->setCaptureAll(false); m_pCurveList->setProcessAll(m_bProcessAll); m_bProcessAll = bProcessAll; return qtractorCurveBaseCommand::execute(bRedo); } //---------------------------------------------------------------------- // class qtractorCurveCaptureAllCommand - declaration. // // Constructor. qtractorCurveCaptureAllCommand::qtractorCurveCaptureAllCommand ( qtractorCurveList *pCurveList, bool bCaptureAll ) : qtractorCurveListCommand(QObject::tr("automation record all"), pCurveList), m_bCaptureAll(bCaptureAll) { } // Virtual command methods. bool qtractorCurveCaptureAllCommand::execute ( bool bRedo ) { if (m_pCurveList == NULL) return false; bool bCaptureAll = m_pCurveList->isCaptureAll(); if (m_bCaptureAll) m_pCurveList->setProcessAll(true); m_pCurveList->setCaptureAll(m_bCaptureAll); m_bCaptureAll = bCaptureAll; return qtractorCurveBaseCommand::execute(bRedo); } //---------------------------------------------------------------------- // class qtractorCurveEditCommand - declaration. // // Constructors. qtractorCurveEditCommand::qtractorCurveEditCommand ( const QString& sName, qtractorCurve *pCurve ) : qtractorCurveCommand(sName, pCurve), m_edits(pCurve) { } qtractorCurveEditCommand::qtractorCurveEditCommand ( qtractorCurve *pCurve ) : qtractorCurveCommand(QObject::tr("automation edit"), pCurve), m_edits(pCurve) { } // Destructor. qtractorCurveEditCommand::~qtractorCurveEditCommand (void) { m_edits.clear(); } // Primitive command methods. void qtractorCurveEditCommand::addNode ( qtractorCurve::Node *pNode ) { m_edits.addNode(pNode); } void qtractorCurveEditCommand::moveNode ( qtractorCurve::Node *pNode, unsigned long iFrame ) { m_edits.moveNode(pNode, iFrame); } void qtractorCurveEditCommand::removeNode ( qtractorCurve::Node *pNode ) { m_edits.removeNode(pNode); } void qtractorCurveEditCommand::addEditList ( qtractorCurveEditList *pEditList ) { if (pEditList) m_edits.append(*pEditList); } // Composite predicate. bool qtractorCurveEditCommand::isEmpty (void) const { return m_edits.isEmpty(); } // Common executive method. bool qtractorCurveEditCommand::execute ( bool bRedo ) { if (!m_edits.execute(bRedo)) return false; return qtractorCurveBaseCommand::execute(bRedo); } //---------------------------------------------------------------------- // class qtractorCurveClearCommand - declaration. // // Constructor. qtractorCurveClearCommand::qtractorCurveClearCommand ( qtractorCurve *pCurve ) : qtractorCurveEditCommand(QObject::tr("automation clear"), pCurve) { qtractorCurve::Node *pNode = m_pCurve->nodes().first(); while (pNode) { qtractorCurveEditCommand::removeNode(pNode); pNode = pNode->next(); } } //---------------------------------------------------------------------- // class qtractorCurveClearAllCommand - declaration. // // Constructor. qtractorCurveClearAllCommand::qtractorCurveClearAllCommand ( qtractorCurveList *pCurveList ) : qtractorCurveListCommand(QObject::tr("automation clear all"), pCurveList) { if (m_pCurveList) { qtractorCurve *pCurve = m_pCurveList->first(); while (pCurve) { m_commands.append(new qtractorCurveClearCommand(pCurve)); pCurve = pCurve->next(); } } } // Destructor. qtractorCurveClearAllCommand::~qtractorCurveClearAllCommand (void) { qDeleteAll(m_commands); m_commands.clear(); } // Composite predicate. bool qtractorCurveClearAllCommand::isEmpty (void) const { return m_commands.isEmpty(); } // Virtual executive method. bool qtractorCurveClearAllCommand::execute ( bool bRedo ) { if (m_pCurveList == NULL) return false; QListIterator iter(m_commands); while (iter.hasNext()) { qtractorCurveClearCommand *pCommand = iter.next(); if (bRedo) pCommand->redo(); else pCommand->undo(); } return true; } //---------------------------------------------------------------------- // class qtractorCurveEditListCommand - declaration. // // Constructor. qtractorCurveEditListCommand::qtractorCurveEditListCommand ( qtractorCurveList *pCurveList ) : qtractorCurveListCommand(QObject::tr("automation edit list"), pCurveList) { if (m_pCurveList) { qtractorCurve *pCurve = m_pCurveList->first(); while (pCurve) { qtractorCurveEditList *pCurveEditList = pCurve->editList(); if (pCurveEditList && !pCurveEditList->isEmpty()) { qtractorCurveEditCommand *pCurveEditCommand = new qtractorCurveEditCommand(pCurve); pCurveEditCommand->addEditList(pCurveEditList); m_curveEditCommands.append(pCurveEditCommand); pCurveEditList->clear(); } pCurve = pCurve->next(); } } } // Destructor. qtractorCurveEditListCommand::~qtractorCurveEditListCommand (void) { qDeleteAll(m_curveEditCommands); m_curveEditCommands.clear(); } // Composite predicate. bool qtractorCurveEditListCommand::isEmpty (void) const { return m_curveEditCommands.isEmpty(); } // Virtual executive method. bool qtractorCurveEditListCommand::execute ( bool bRedo ) { if (m_pCurveList == NULL) return false; QListIterator iter(m_curveEditCommands); while (iter.hasNext()) { qtractorCurveEditCommand *pCurveEditCommand = iter.next(); if (bRedo) pCurveEditCommand->redo(); else pCurveEditCommand->undo(); } return true; } //---------------------------------------------------------------------- // class qtractorCurveCaptureListCommand - declaration. // // Constructor. qtractorCurveCaptureListCommand::qtractorCurveCaptureListCommand (void) : qtractorCommand(QObject::tr("automation record")) { } // Destructor. qtractorCurveCaptureListCommand::~qtractorCurveCaptureListCommand (void) { qDeleteAll(m_commands); m_commands.clear(); } // Curve list adder. void qtractorCurveCaptureListCommand::addCurveList ( qtractorCurveList *pCurveList ) { qtractorCurveEditListCommand *pCommand = new qtractorCurveEditListCommand(pCurveList); if (pCommand->isEmpty()) delete pCommand; else m_commands.append(pCommand); } // Composite predicate. bool qtractorCurveCaptureListCommand::isEmpty (void) const { return m_commands.isEmpty(); } // Virtual command methods. bool qtractorCurveCaptureListCommand::redo (void) { QListIterator iter(m_commands); while (iter.hasNext()) iter.next()->redo(); return true; } bool qtractorCurveCaptureListCommand::undo (void) { QListIterator iter(m_commands); while (iter.hasNext()) iter.next()->undo(); return true; } // end of qtractorCurveCommand.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorExportForm.cpp0000644000175000001440000000012312166526620021642 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134671.20108 30 ctime=1381134671.201080115 qtractor-0.5.11/src/qtractorExportForm.cpp0000644000175000001440000003453612166526620021144 0ustar00rncbcusers00000000000000// qtractorExportForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorExportForm.h" #include "qtractorAbout.h" #include "qtractorAudioEngine.h" #include "qtractorMidiEngine.h" #include "qtractorAudioFile.h" #include "qtractorMainForm.h" #include "qtractorSession.h" #include "qtractorOptions.h" #include #include #include #include #include //---------------------------------------------------------------------------- // qtractorExportForm -- UI wrapper form. // Constructor. qtractorExportForm::qtractorExportForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::ApplicationModal); // Initialize dirty control state. m_exportType = qtractorTrack::None; m_pTimeScale = NULL; // Try to restore old window positioning. adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.ExportPathComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(stabilizeForm())); QObject::connect(m_ui.ExportPathToolButton, SIGNAL(clicked()), SLOT(browseExportPath())); QObject::connect(m_ui.SessionRangeRadioButton, SIGNAL(toggled(bool)), SLOT(rangeChanged())); QObject::connect(m_ui.LoopRangeRadioButton, SIGNAL(toggled(bool)), SLOT(rangeChanged())); QObject::connect(m_ui.PunchRangeRadioButton, SIGNAL(toggled(bool)), SLOT(rangeChanged())); QObject::connect(m_ui.EditRangeRadioButton, SIGNAL(toggled(bool)), SLOT(rangeChanged())); QObject::connect(m_ui.CustomRangeRadioButton, SIGNAL(toggled(bool)), SLOT(rangeChanged())); QObject::connect(m_ui.ExportBusNameListBox, SIGNAL(currentRowChanged(int)), SLOT(stabilizeForm())); QObject::connect(m_ui.ExportStartSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(valueChanged())); QObject::connect(m_ui.ExportStartSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.ExportEndSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(valueChanged())); QObject::connect(m_ui.ExportEndSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.FormatComboBox, SIGNAL(activated(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); } // Destructor. qtractorExportForm::~qtractorExportForm (void) { // Don't forget to get rid of local time-scale instance... if (m_pTimeScale) delete m_pTimeScale; } // Populate (setup) dialog controls from settings descriptors. void qtractorExportForm::setExportType ( qtractorTrack::TrackType exportType ) { // Export type... m_exportType = exportType; QIcon icon; qtractorEngine *pEngine = NULL; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { // Copy from global time-scale instance... if (m_pTimeScale) delete m_pTimeScale; m_pTimeScale = new qtractorTimeScale(*pSession->timeScale()); m_ui.ExportStartSpinBox->setTimeScale(m_pTimeScale); m_ui.ExportEndSpinBox->setTimeScale(m_pTimeScale); switch (m_exportType) { case qtractorTrack::Audio: pEngine = pSession->audioEngine(); icon = QIcon(":/images/trackAudio.png"); m_sExportType = tr("Audio"); m_sExportExt = qtractorAudioFileFactory::defaultExt(); break; case qtractorTrack::Midi: pEngine = pSession->midiEngine(); icon = QIcon(":/images/trackMidi.png"); m_sExportType = tr("MIDI"); m_sExportExt = "mid"; break; case qtractorTrack::None: default: m_sExportType.clear(); m_sExportExt.clear(); break; } } // Grab export file history, one that might me useful... m_ui.ExportPathComboBox->setObjectName( m_sExportType + m_ui.ExportPathComboBox->objectName()); qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) pOptions->loadComboBoxHistory(m_ui.ExportPathComboBox); // Suggest a brand new export filename... if (pSession) { m_ui.ExportPathComboBox->setEditText( pSession->createFilePath("export", m_sExportExt)); } // Fill in the output bus names list... m_ui.ExportBusNameListBox->clear(); if (pEngine) { QDialog::setWindowIcon(icon); QDialog::setWindowTitle( tr("Export %1").arg(m_sExportType) + " - " QTRACTOR_TITLE); for (qtractorBus *pBus = pEngine->buses().first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Output) m_ui.ExportBusNameListBox->addItem( new QListWidgetItem(icon, pBus->busName())); } } // Set proper time scales display format... if (m_pTimeScale) { m_ui.FormatComboBox->setCurrentIndex( int(m_pTimeScale->displayFormat())); } // Populate range values... m_ui.SessionRangeRadioButton->setChecked(true); // rangeChanged(); // Done. stabilizeForm(); } // Retrieve the current export type, if the case arises. qtractorTrack::TrackType qtractorExportForm::exportType (void) const { return m_exportType; } // Accept settings (OK button slot). void qtractorExportForm::accept (void) { // Must always be a export bus target... QListWidgetItem *pExportBusNameItem = m_ui.ExportBusNameListBox->currentItem(); if (pExportBusNameItem == NULL) return; // Enforce (again) default file extension... QString sExportPath = m_ui.ExportPathComboBox->currentText(); if (QFileInfo(sExportPath).suffix().isEmpty()) sExportPath += '.' + m_sExportExt; // Check (again) wether the file already exists... if (QFileInfo(sExportPath).exists()) { if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("The file already exists:\n\n" "\"%1\"\n\n" "Do you want to replace it?") .arg(sExportPath), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) { m_ui.ExportPathComboBox->setFocus(); return; } } qtractorSession *pSession = qtractorSession::getInstance(); qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pSession && pMainForm) { // It can take a minute... m_ui.ExportPathTextLabel->setEnabled(false); m_ui.ExportPathComboBox->setEnabled(false); m_ui.ExportPathToolButton->setEnabled(false); m_ui.ExportBusGroupBox->setEnabled(false); m_ui.ExportRangeGroupBox->setEnabled(false); m_ui.FormatGroupBox->setEnabled(false); m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false); // Carry on... if (m_exportType == qtractorTrack::Audio) { // Audio file export... qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine) { // Get the export bus by name... qtractorAudioBus *pExportBus = static_cast ( pAudioEngine->findOutputBus( pExportBusNameItem->text())); // Log this event... pMainForm->appendMessages( tr("Audio file export: \"%1\" started...") .arg(sExportPath)); // Do the export as commanded... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); bool bResult = pAudioEngine->fileExport( sExportPath, m_ui.ExportStartSpinBox->value(), m_ui.ExportEndSpinBox->value(), pExportBus); QApplication::restoreOverrideCursor(); if (bResult) { // Log the success... pMainForm->addAudioFile(sExportPath); pMainForm->appendMessages( tr("Audio file export: \"%1\" complete.") .arg(sExportPath)); } else { // Log the failure... pMainForm->appendMessagesError( tr("Audio file export:\n\n\"%1\"\n\nfailed.") .arg(sExportPath)); } } } else if (m_exportType == qtractorTrack::Midi) { // MIDI file export... qtractorMidiEngine *pMidiEngine = pSession->midiEngine(); if (pMidiEngine) { // Get the export bus by name... qtractorMidiBus *pExportBus = static_cast ( pMidiEngine->findOutputBus( pExportBusNameItem->text())); // Log this event... pMainForm->appendMessages( tr("MIDI file export: \"%1\" started...") .arg(sExportPath)); // Do the export as commanded... QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); bool bResult = pMidiEngine->fileExport( sExportPath, m_ui.ExportStartSpinBox->value(), m_ui.ExportEndSpinBox->value(), pExportBus); QApplication::restoreOverrideCursor(); if (bResult) { // Log the success... pMainForm->addMidiFile(sExportPath); pMainForm->appendMessages( tr("MIDI file export: \"%1\" complete.") .arg(sExportPath)); } else { // Log the failure... pMainForm->appendMessagesError( tr("MIDI file export:\n\n\"%1\"\n\nfailed.") .arg(sExportPath)); } } } // Save other conveniency options... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) pOptions->saveComboBoxHistory(m_ui.ExportPathComboBox); } // Just go with dialog acceptance. QDialog::accept(); } // Reject settings (Cancel button slot). void qtractorExportForm::reject (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { // It can take a minute... m_ui.DialogButtonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); switch (m_exportType) { case qtractorTrack::Audio: { // Audio file export... qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine) pAudioEngine->setExporting(false); break; } case qtractorTrack::Midi: default: break; } } // Bail out... QDialog::reject(); } // Choose the target filename of export. void qtractorExportForm::browseExportPath (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; QString sExportPath = m_ui.ExportPathComboBox->currentText(); if (sExportPath.isEmpty()) sExportPath = pSession->sessionDir(); // Actual browse for the file... const QString& sTitle = tr("Export %1 File").arg(m_sExportType) + " - " QTRACTOR_TITLE; const QString& sFilter = tr("%1 files (*.%1)").arg(m_sExportExt); #if 0//QT_VERSION < 0x040400 sExportPath = QFileDialog::getSaveFileName(this, sTitle, sExportPath, sFilter); #else QFileDialog fileDialog(this, sTitle, sExportPath, sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptSave); fileDialog.setFileMode(QFileDialog::AnyFile); fileDialog.setDefaultSuffix(m_sExportExt); // Stuff sidebar... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); switch (m_exportType) { case qtractorTrack::Audio: urls.append(QUrl::fromLocalFile(pOptions->sAudioDir)); break; case qtractorTrack::Midi: urls.append(QUrl::fromLocalFile(pOptions->sMidiDir)); break; case qtractorTrack::None: default: break; } fileDialog.setSidebarUrls(urls); } // Show dialog... if (fileDialog.exec()) sExportPath = fileDialog.selectedFiles().first(); else sExportPath.clear(); #endif // Have we cancelled it? if (sExportPath.isEmpty()) return; // Enforce default file extension... if (QFileInfo(sExportPath).suffix().isEmpty()) sExportPath += '.' + m_sExportExt; // Finallly set as wanted... m_ui.ExportPathComboBox->setEditText(sExportPath); m_ui.ExportPathComboBox->setFocus(); stabilizeForm(); } // Display format has changed. void qtractorExportForm::rangeChanged (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; if (m_ui.SessionRangeRadioButton->isChecked()) { m_ui.ExportStartSpinBox->setValue(pSession->sessionStart(), false); m_ui.ExportEndSpinBox->setValue(pSession->sessionEnd(), false); } else if (m_ui.LoopRangeRadioButton->isChecked()) { m_ui.ExportStartSpinBox->setValue(pSession->loopStart(), false); m_ui.ExportEndSpinBox->setValue(pSession->loopEnd(), false); } else if (m_ui.PunchRangeRadioButton->isChecked()) { m_ui.ExportStartSpinBox->setValue(pSession->punchIn(), false); m_ui.ExportEndSpinBox->setValue(pSession->punchOut(), false); } else if (m_ui.EditRangeRadioButton->isChecked()) { m_ui.ExportStartSpinBox->setValue(pSession->editHead(), false); m_ui.ExportEndSpinBox->setValue(pSession->editTail(), false); } stabilizeForm(); } // Range values have changed. void qtractorExportForm::valueChanged (void) { m_ui.CustomRangeRadioButton->setChecked(true); stabilizeForm(); } // Display format has changed. void qtractorExportForm::formatChanged ( int iDisplayFormat ) { bool bBlockSignals = m_ui.FormatComboBox->blockSignals(true); m_ui.FormatComboBox->setCurrentIndex(iDisplayFormat); qtractorTimeScale::DisplayFormat displayFormat = qtractorTimeScale::DisplayFormat(iDisplayFormat); m_ui.ExportStartSpinBox->setDisplayFormat(displayFormat); m_ui.ExportEndSpinBox->setDisplayFormat(displayFormat); if (m_pTimeScale) m_pTimeScale->setDisplayFormat(displayFormat); m_ui.FormatComboBox->blockSignals(bBlockSignals); stabilizeForm(); } // Stabilize current form state. void qtractorExportForm::stabilizeForm (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; m_ui.LoopRangeRadioButton->setEnabled(pSession->isLooping()); m_ui.PunchRangeRadioButton->setEnabled(pSession->isPunching()); m_ui.EditRangeRadioButton->setEnabled( pSession->editHead() < pSession->editTail()); m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled( !m_ui.ExportPathComboBox->currentText().isEmpty() && m_ui.ExportBusNameListBox->currentItem() != NULL && m_ui.ExportStartSpinBox->value() < m_ui.ExportEndSpinBox->value()); } // end of qtractorExportForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/src.pri.in0000644000175000001440000000012211447471305017160 xustar000000000000000026 mtime=1285452485.06239 26 atime=1381134668.12208 30 ctime=1381134668.122080067 qtractor-0.5.11/src/src.pri.in0000644000175000001440000000024411447471305016450 0ustar00rncbcusers00000000000000# qtractor.pri # PREFIX = @ac_prefix@ CONFIG += @ac_debug@ INCLUDEPATH += @ac_incpath@ LIBS += @ac_libs@ # Extra optimization flags QMAKE_CXXFLAGS += @ac_cflags@ qtractor-0.5.11/src/PaxHeaders.10084/qtractorExportForm.ui0000644000175000001440000000012312165325675021503 xustar000000000000000027 mtime=1372957629.743777 26 atime=1381134667.59108 30 ctime=1381134667.591080058 qtractor-0.5.11/src/qtractorExportForm.ui0000644000175000001440000002401212165325675020771 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorExportForm 0 0 360 300 Qt::StrongFocus Export - Qtractor :/images/qtractor.png:/images/qtractor.png 8 4 &File: ExportPathComboBox 4 0 320 0 Export file name true 22 22 24 24 Qt::TabFocus Browse export file name :/images/fileOpen.png:/images/fileOpen.png Range 8 4 Session range &Session false Loop range &Loop false Punch range &Punch false Edit range &Edit false Custom range &Custom true Qt::Horizontal QSizePolicy::Fixed 16 16 St&art: ExportStartSpinBox 120 0 Clip start En&d: ExportEndSpinBox 120 0 Clip offset Output 4 8 130 100 Output bus name Format Time display format Frames Time BBT Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qtractorTimeSpinBox QSpinBox
qtractorSpinBox.h
ExportPathComboBox ExportPathToolButton SessionRangeRadioButton LoopRangeRadioButton PunchRangeRadioButton EditRangeRadioButton CustomRangeRadioButton ExportStartSpinBox ExportEndSpinBox ExportBusNameListBox FormatComboBox
qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiFileTempo.h0000644000175000001440000000012312050711552021661 xustar000000000000000027 mtime=1352897386.067527 26 atime=1381134666.95008 30 ctime=1381134666.950080048 qtractor-0.5.11/src/qtractorMidiFileTempo.h0000644000175000001440000001303312050711552021150 0ustar00rncbcusers00000000000000// qtractorMidiFileTempo.h // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiFileTempo_h #define __qtractorMidiFileTempo_h #include "qtractorList.h" #include // Forward decls. class qtractorMidiFile; class qtractorTimeScale; //---------------------------------------------------------------------- // class qtractorMidiFileTempo -- MIDI tempo/time-signature map class. // class qtractorMidiFileTempo { public: // Constructor. qtractorMidiFileTempo(qtractorMidiFile *pMidiFile) : m_pMidiFile(pMidiFile) { clear(); } // Destructor. ~qtractorMidiFileTempo() { m_nodes.clear(); m_markers.clear(); } // (Re)nitializer method. void clear(); // Tempo-map node declaration. class Node : public qtractorList::Link { public: // Constructor. Node(unsigned long iTick = 0, float fTempo = 120.0f, unsigned short iBeatsPerBar = 4, unsigned short iBeatDivisor = 2) : tick(iTick), bar(0), tempo(fTempo), beatsPerBar(iBeatsPerBar), beatDivisor(iBeatDivisor), ticksPerBeat(0) {} // Update node coefficients. void update(qtractorMidiFile *pMidiFile); // Update node position metrics. void reset(Node *pNode); // Tick/bar convertors. unsigned short barFromTick(unsigned long iTick) const { return bar + ((iTick - tick) / (ticksPerBeat * beatsPerBar)); } unsigned long tickFromBar(unsigned short iBar) const { return tick + (ticksPerBeat * beatsPerBar * (iBar - bar)) ; } // Tick/bar quantizer. unsigned long tickSnapToBar(unsigned long iTick) const { return tickFromBar(barFromTick(iTick)); } // Node keys. unsigned long tick; unsigned short bar; // Node payload. float tempo; unsigned short beatsPerBar; unsigned short beatDivisor; // Node coefficients. unsigned short ticksPerBeat; }; // Node list accessors. const qtractorList& nodes() const { return m_nodes; } // Node list seeker. Node *seekNode(unsigned long iTick) const; // Node list specifics. Node *addNode( unsigned long iTick = 0, float fTempo = 120.0f, unsigned short iBeatsPerBar = 4, unsigned short iBeatDivisor = 2); void updateNode(Node *pNode); void removeNode(Node *pNode); // More node list specifics (fit to corresp.META events). Node *addNodeTempo(unsigned long iTick, float fTempo) { Node *pNode = seekNode(iTick); return addNode(iTick, fTempo, (pNode ? pNode->beatsPerBar : 4), (pNode ? pNode->beatDivisor : 2)); } Node *addNodeTime(unsigned long iTick, unsigned short iBeatsPerBar, unsigned short iBeatDivisor) { Node *pNode = seekNode(iTick); return addNode(iTick, (pNode ? pNode->tempo : 120.0f), iBeatsPerBar, iBeatDivisor); } // Tempo convertors (default's quarter notes per minute) void setTempo(float fTempo) { Node *pNode = m_nodes.first(); if (pNode) pNode->tempo = fTempo; } float tempo() const { Node *pNode = m_nodes.first(); return (pNode ? pNode->tempo : 120.0f); } // Time signature (numerator) void setBeatsPerBar(unsigned short iBeatsPerBar) { Node *pNode = m_nodes.first(); if (pNode) pNode->beatsPerBar = iBeatsPerBar; } unsigned short beatsPerBar() const { Node *pNode = m_nodes.first(); return (pNode ? pNode->beatsPerBar : 4); } // Time signature (denominator) void setBeatDivisor(unsigned short iBeatDivisor) { Node *pNode = m_nodes.first(); if (pNode) pNode->beatDivisor = iBeatDivisor; } unsigned short beatDivisor() const { Node *pNode = m_nodes.first(); return (pNode ? pNode->beatDivisor : 2); } // Resolution (ticks per beat) unsigned short ticksPerBeat() const { Node *pNode = m_nodes.first(); return (pNode ? pNode->ticksPerBeat : 960); } // Location marker declaration. class Marker : public qtractorList::Link { public: // Constructor. Marker(unsigned long iTick, const QString& sText) : tick(iTick), text(sText) {} // Marker key. unsigned long tick; // Marker payload. QString text; }; // Marker list accessors. const qtractorList& markers() const { return m_markers; } // Location marker seeker (by tick). Marker *seekMarker(unsigned long iTick) const; // Marker list specifics. Marker *addMarker( unsigned long iTick, const QString& sText); void removeMarker(Marker *pMarker); // Time-scale sync methods. void fromTimeScale( qtractorTimeScale *pTimeScale, unsigned long iTimeOffset = 0); void intoTimeScale( qtractorTimeScale *pTimeScale, unsigned long iTimeOffset = 0); private: // Tempo-map owner. qtractorMidiFile *m_pMidiFile; // Tempo-map node list. qtractorList m_nodes; // Location markers list. qtractorList m_markers; }; #endif // __qtractorMidiFileTempo_h // end of qtractorMidiFileTempo.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiCursor.h0000644000175000001440000000012312026024607021253 xustar000000000000000027 mtime=1347955079.929716 26 atime=1381134668.12308 30 ctime=1381134668.123080067 qtractor-0.5.11/src/qtractorMidiCursor.h0000644000175000001440000000336012026024607020544 0ustar00rncbcusers00000000000000// qtractorMidiCursor.h // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiCursor_h #define __qtractorMidiCursor_h // Forward declarations. class qtractorMidiEvent; class qtractorMidiSequence; //------------------------------------------------------------------------- // qtractorMidiCursor -- MIDI event cursor capsule. class qtractorMidiCursor { public: // Constructor. qtractorMidiCursor(); // Intra-sequence tick/time positioning seek. qtractorMidiEvent *seek( qtractorMidiSequence *pSeq, unsigned long iTime); // Intra-sequence tick/time positioning reset (seek forward). qtractorMidiEvent *reset( qtractorMidiSequence *pSeq, unsigned long iTime = 0); private: // Current event cursor variables. qtractorMidiEvent *m_pEvent; unsigned long m_iTime; }; #endif // __qtractorMidiCursor_h // end of qtractorMidiCursor.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorConnect.cpp0000644000175000001440000000012312166526620021126 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134671.09108 30 ctime=1381134671.091080114 qtractor-0.5.11/src/qtractorConnect.cpp0000644000175000001440000013617212166526620020427 0ustar00rncbcusers00000000000000// qtractorConnect.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorConnect.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #include #endif //---------------------------------------------------------------------- // qtractorPortListItem -- Port list item. // // Constructor. qtractorPortListItem::qtractorPortListItem ( qtractorClientListItem *pClientItem, const QString& sPortName ) : QTreeWidgetItem(pClientItem, qtractorConnect::PortItem) { m_pClientItem = pClientItem; m_sPortName = sPortName; m_iPortMark = 0; m_bHilite = false; QTreeWidgetItem::setText(0, m_sPortName); } // Default destructor. qtractorPortListItem::~qtractorPortListItem (void) { m_connects.clear(); } // Instance accessors. void qtractorPortListItem::setPortName ( const QString& sPortName ) { QTreeWidgetItem::setText(0, sPortName); m_sPortName = sPortName; } const QString& qtractorPortListItem::clientName (void) const { return m_pClientItem->clientName(); } const QString& qtractorPortListItem::portName (void) const { return m_sPortName; } // Complete client:port name helper. QString qtractorPortListItem::clientPortName (void) { return m_pClientItem->clientName() + ':' + m_sPortName; } // Connect client item accessor. qtractorClientListItem *qtractorPortListItem::clientItem (void) const { return m_pClientItem; } // Client:port set housekeeping marker. void qtractorPortListItem::markPort ( int iMark ) { setHilite(false); m_iPortMark = iMark; if (iMark > 0) m_connects.clear(); } void qtractorPortListItem::markClientPort ( int iMark ) { markPort(iMark); m_pClientItem->markClient(iMark); } int qtractorPortListItem::portMark (void) { return m_iPortMark; } // Connected port list primitives. void qtractorPortListItem::addConnect ( qtractorPortListItem *pPortItem ) { m_connects.append(pPortItem); } void qtractorPortListItem::removeConnect ( qtractorPortListItem *pPortItem ) { QMutableListIterator iter(m_connects); while (iter.hasNext()) { qtractorPortListItem *pPortItemPtr = iter.next(); if (pPortItemPtr == pPortItem) { pPortItem->setHilite(false); iter.remove(); break; } } } // Clear the connection list, taking care of hilighting... void qtractorPortListItem::cleanConnects (void) { QMutableListIterator iter(m_connects); while (iter.hasNext()) { qtractorPortListItem *pPortItem = iter.next(); pPortItem->setHilite(false); iter.remove(); } } // Connected port finder. qtractorPortListItem *qtractorPortListItem::findConnect ( qtractorPortListItem *pPortItem ) { QListIterator iter(m_connects); while (iter.hasNext()) { qtractorPortListItem *pPortItemPtr = iter.next(); if (pPortItemPtr == pPortItem) return pPortItem; } return NULL; } // Connection cache list accessor. const QList& qtractorPortListItem::connects (void) const { return m_connects; } // Connectiopn highlight methods. void qtractorPortListItem::setHilite ( bool bHilite ) { // Update the port highlightning if changed... if ((m_bHilite && !bHilite) || (!m_bHilite && bHilite)) { m_bHilite = bHilite; // Propagate this to the parent... m_pClientItem->setHilite(bHilite); } // Set the new color. const QPalette& pal = QTreeWidgetItem::treeWidget()->palette(); QTreeWidgetItem::setForeground(0, m_bHilite ? (pal.base().color().value() < 0x7f ? Qt::cyan : Qt::blue) : pal.text().color()); } bool qtractorPortListItem::isHilite (void) const { return m_bHilite; } // Proxy sort override method. // - Natural decimal sorting comparator. bool qtractorPortListItem::operator< ( const QTreeWidgetItem& other ) const { return qtractorClientListView::lessThan(*this, other); #if 0 const QString& s1 = text(0); const QString& s2 = other.text(0); int ich1, ich2; int cch1 = s1.length(); int cch2 = s2.length(); for (ich1 = ich2 = 0; ich1 < cch1 && ich2 < cch2; ++ich1, ++ich2) { // Skip (white)spaces... while (s1.at(ich1).isSpace()) ++ich1; while (s2.at(ich2).isSpace()) ++ich2; // Normalize (to uppercase) the next characters... QChar ch1 = s1.at(ich1).toUpper(); QChar ch2 = s2.at(ich2).toUpper(); if (ch1.isDigit() && ch2.isDigit()) { // Find the whole length numbers... int iDigits1 = ich1++; while (ich1 < cch1 && s1.at(ich1).isDigit()) ++ich1; int iDigits2 = ich2++; while (ich2 < cch2 && s2.at(ich2).isDigit()) ++ich2; // Compare as natural decimal-numbers... int n1 = s1.mid(iDigits1, ich1 - iDigits1).toInt(); int n2 = s2.mid(iDigits2, ich2 - iDigits2).toInt(); if (n1 != n2) return (n1 < n2); // Never go out of bounds... if (ich1 >= cch1 || ich1 >= cch2) break; // Go on with this next char... ch1 = s1.at(ich1).toUpper(); ch2 = s2.at(ich2).toUpper(); } // Compare this char... if (ch1 != ch2) return (ch1 < ch2); } // Probable exact match. return false; #endif } //---------------------------------------------------------------------------- // qtractorClientListItem -- Client list item. // // Constructor. qtractorClientListItem::qtractorClientListItem ( qtractorClientListView *pClientListView, const QString& sClientName ) : QTreeWidgetItem(pClientListView, qtractorConnect::ClientItem) { m_sClientName = sClientName; m_iClientMark = 0; m_iHilite = 0; QTreeWidgetItem::setText(0, m_sClientName); } // Default destructor. qtractorClientListItem::~qtractorClientListItem (void) { } // Port finder. qtractorPortListItem *qtractorClientListItem::findPortItem ( const QString& sPortName ) { int iChildCount = QTreeWidgetItem::childCount(); for (int iChild = 0; iChild < iChildCount; ++iChild) { QTreeWidgetItem *pChild = QTreeWidgetItem::child(iChild); if (pChild->type() != qtractorConnect::PortItem) continue; qtractorPortListItem *pPortItem = static_cast (pChild); if (pPortItem && pPortItem->portName() == sPortName) return pPortItem; } return NULL; } // Instance accessors. void qtractorClientListItem::setClientName ( const QString& sClientName ) { QTreeWidgetItem::setText(0, sClientName); m_sClientName = sClientName; } const QString& qtractorClientListItem::clientName (void) const { return m_sClientName; } // Readable flag client accessor. bool qtractorClientListItem::isReadable (void) { qtractorClientListView *pClientListView = static_cast (QTreeWidgetItem::treeWidget()); return (pClientListView ? pClientListView->isReadable() : false); } // Client:port set housekeeping marker. void qtractorClientListItem::markClient ( int iMark ) { setHilite(false); m_iClientMark = iMark; } void qtractorClientListItem::markClientPorts ( int iMark ) { markClient(iMark); int iChildCount = QTreeWidgetItem::childCount(); for (int iChild = 0; iChild < iChildCount; ++iChild) { QTreeWidgetItem *pChild = QTreeWidgetItem::child(iChild); if (pChild->type() != qtractorConnect::PortItem) continue; qtractorPortListItem *pPortItem = static_cast (pChild); if (pPortItem) pPortItem->markPort(iMark); } } void qtractorClientListItem::cleanClientPorts ( int iMark ) { int iChildCount = QTreeWidgetItem::childCount(); for (int iChild = 0; iChild < iChildCount; ++iChild) { QTreeWidgetItem *pChild = QTreeWidgetItem::child(iChild); if (pChild->type() != qtractorConnect::PortItem) continue; qtractorPortListItem *pPortItem = static_cast (pChild); if (pPortItem && pPortItem->portMark() == iMark) { pPortItem->cleanConnects(); delete pPortItem; --iChildCount; --iChild; } } } int qtractorClientListItem::clientMark (void) const { return m_iClientMark; } // Connectiopn highlight methods. void qtractorClientListItem::setHilite ( bool bHilite ) { // Update the client highlightning if changed... if (bHilite) ++m_iHilite; else if (m_iHilite > 0) --m_iHilite; // Set the new color. const QPalette& pal = QTreeWidgetItem::treeWidget()->palette(); QTreeWidgetItem::setForeground(0, m_iHilite > 0 ? (pal.base().color().value() < 0x7f ? Qt::darkCyan : Qt::darkBlue) : pal.text().color()); } bool qtractorClientListItem::isHilite (void) const { return (m_iHilite > 0); } // Client item openness status. void qtractorClientListItem::setOpen ( bool bOpen ) { QTreeWidgetItem::setExpanded(bOpen); } bool qtractorClientListItem::isOpen (void) const { return QTreeWidgetItem::isExpanded(); } // Proxy sort override method. // - Natural decimal sorting comparator. bool qtractorClientListItem::operator< ( const QTreeWidgetItem& other ) const { return qtractorClientListView::lessThan(*this, other); } //---------------------------------------------------------------------------- // qtractorClientListView -- Client list view, supporting drag-n-drop. // // Constructor. qtractorClientListView::qtractorClientListView ( QWidget *pParent ) : QTreeWidget(pParent) { m_pConnect = NULL; m_bReadable = false; m_pAutoOpenTimer = NULL; m_iAutoOpenTimeout = 0; m_pDragItem = NULL; m_pDropItem = NULL; m_pHiliteItem = NULL; QHeaderView *pHeader = QTreeWidget::header(); pHeader->setDefaultAlignment(Qt::AlignLeft); // pHeader->setDefaultSectionSize(120); #if QT_VERSION >= 0x050000 // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionsMovable(false); pHeader->setSectionsClickable(true); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setMovable(false); pHeader->setClickable(true); #endif pHeader->setSortIndicatorShown(true); pHeader->setStretchLastSection(true); QTreeWidget::setRootIsDecorated(true); QTreeWidget::setUniformRowHeights(true); // QTreeWidget::setDragEnabled(true); QTreeWidget::setAcceptDrops(true); QTreeWidget::setDropIndicatorShown(true); QTreeWidget::setAutoScroll(true); QTreeWidget::setSelectionMode(QAbstractItemView::SingleSelection); QTreeWidget::setSizePolicy( QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); QTreeWidget::setSortingEnabled(true); QTreeWidget::setMinimumWidth(120); QTreeWidget::setColumnCount(1); // Trap for help/tool-tips events. QTreeWidget::viewport()->installEventFilter(this); setAutoOpenTimeout(800); } // Default destructor. qtractorClientListView::~qtractorClientListView (void) { setAutoOpenTimeout(0); } // Client item finder. qtractorClientListItem *qtractorClientListView::findClientItem ( const QString& sClientName ) { int iItemCount = QTreeWidget::topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = QTreeWidget::topLevelItem(iItem); if (pItem->type() != qtractorConnect::ClientItem) continue; qtractorClientListItem *pClientItem = static_cast (pItem); if (pClientItem && pClientItem->clientName() == sClientName) return pClientItem; } return NULL; } // Client:port finder. qtractorPortListItem *qtractorClientListView::findClientPortItem ( const QString& sClientPort ) { qtractorPortListItem *pPortItem = NULL; int iColon = sClientPort.indexOf(':'); if (iColon >= 0) { qtractorClientListItem *pClientItem = findClientItem(sClientPort.left(iColon)); if (pClientItem) { pPortItem = pClientItem->findPortItem( sClientPort.right(sClientPort.length() - iColon - 1)); } } return pPortItem; } // Main controller accessors. void qtractorClientListView::setBinding ( qtractorConnect *pConnect ) { m_pConnect = pConnect; } qtractorConnect *qtractorClientListView::binding (void) const { return m_pConnect; } // Readable flag client accessors. void qtractorClientListView::setReadable ( bool bReadable ) { m_bReadable = bReadable; QString sText; if (m_bReadable) sText = tr("Readable Clients / Output Ports"); else sText = tr("Writable Clients / Input Ports"); QTreeWidget::headerItem()->setText(0, sText); QTreeWidget::sortItems(0, Qt::AscendingOrder); QTreeWidget::setToolTip(sText); } bool qtractorClientListView::isReadable (void) const { return m_bReadable; } // Client name filter helpers. void qtractorClientListView::setClientName ( const QString& sClientName ) { m_rxClientName.setPattern(sClientName); if (sClientName.isEmpty()) m_rxPortName.setPattern(QString::null); } QString qtractorClientListView::clientName (void) const { return m_rxClientName.pattern(); } // Client name filter helpers. void qtractorClientListView::setPortName ( const QString& sPortName ) { m_rxPortName.setPattern(sPortName); } QString qtractorClientListView::portName (void) const { return m_rxPortName.pattern(); } // Maintained current client name list. const QStringList& qtractorClientListView::clientNames (void) const { return m_clientNames; } // Override clear method. void qtractorClientListView::clear (void) { m_pHiliteItem = NULL; m_clientNames.clear(); QTreeWidget::clear(); } // Client filter regular expression; // take the chance to add to maintained client name list. bool qtractorClientListView::isClientName ( const QString& sClientName ) { if (m_clientNames.indexOf(sClientName) < 0) m_clientNames.append(sClientName); return (m_rxClientName.isEmpty() || m_rxClientName.exactMatch(sClientName)); } // Port filter regular expression; bool qtractorClientListView::isPortName ( const QString& sPortName ) { return (m_rxClientName.isEmpty() || m_rxPortName.isEmpty() || m_rxPortName.exactMatch(sPortName)); } // Whether items are all open (expanded) or closed (collapsed). void qtractorClientListView::setOpenAll ( bool bOpen ) { // For each client item... int iItemCount = QTreeWidget::topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = QTreeWidget::topLevelItem(iItem); if (pItem->type() != qtractorConnect::ClientItem) continue; qtractorClientListItem *pClientItem = static_cast (pItem); if (pClientItem == NULL) continue; // For each port item... int iChildCount = pClientItem->childCount(); for (int iChild = 0; iChild < iChildCount; ++iChild) { QTreeWidgetItem *pChildItem = pClientItem->child(iChild); if (pChildItem->type() != qtractorConnect::PortItem) continue; qtractorPortListItem *pPortItem = static_cast (pChildItem); if (pPortItem) { pClientItem->setOpen(bOpen); QListIterator iter(pPortItem->connects()); while (iter.hasNext()) { qtractorPortListItem *pConnectItem = iter.next(); pConnectItem->clientItem()->setOpen(bOpen); } } } } } // Client:port set housekeeping marker. void qtractorClientListView::markClientPorts ( int iMark ) { m_clientNames.clear(); m_pHiliteItem = NULL; int iItemCount = QTreeWidget::topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = QTreeWidget::topLevelItem(iItem); if (pItem->type() != qtractorConnect::ClientItem) continue; qtractorClientListItem *pClientItem = static_cast (pItem); if (pClientItem) pClientItem->markClientPorts(iMark); } } void qtractorClientListView::cleanClientPorts ( int iMark ) { int iItemCount = QTreeWidget::topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = QTreeWidget::topLevelItem(iItem); if (pItem->type() != qtractorConnect::ClientItem) continue; qtractorClientListItem *pClientItem = static_cast (pItem); if (pClientItem) { if (pClientItem->clientMark() == iMark) { delete pClientItem; --iItemCount; --iItem; } else { pClientItem->cleanClientPorts(iMark); } } } } // Client:port hilite update stabilization. void qtractorClientListView::hiliteClientPorts (void) { QTreeWidgetItem *pCurrentItem = QTreeWidget::currentItem(); // Dehilite the previous selected items. if (m_pHiliteItem && pCurrentItem != m_pHiliteItem) { if (m_pHiliteItem->type() == qtractorConnect::ClientItem) { int iChildCount = m_pHiliteItem->childCount(); for (int iChild = 0; iChild < iChildCount; ++iChild) { QTreeWidgetItem *pChild = m_pHiliteItem->child(iChild); if (pChild->type() != qtractorConnect::PortItem) continue; qtractorPortListItem *pPortItem = static_cast (pChild); if (pPortItem) { QListIterator iter(pPortItem->connects()); while (iter.hasNext()) iter.next()->setHilite(false); } } } else { qtractorPortListItem *pPortItem = static_cast (m_pHiliteItem); if (pPortItem) { QListIterator iter(pPortItem->connects()); while (iter.hasNext()) iter.next()->setHilite(false); } } } // Hilite the now current selected items. if (pCurrentItem && pCurrentItem->type() == qtractorConnect::ClientItem) { int iChildCount = pCurrentItem->childCount(); for (int iChild = 0; iChild < iChildCount; ++iChild) { QTreeWidgetItem *pChild = pCurrentItem->child(iChild); if (pChild->type() != qtractorConnect::PortItem) continue; qtractorPortListItem *pPortItem = static_cast (pChild); if (pPortItem) { QListIterator iter(pPortItem->connects()); while (iter.hasNext()) iter.next()->setHilite(true); } } } else { qtractorPortListItem *pPortItem = static_cast (pCurrentItem); if (pPortItem) { QListIterator iter(pPortItem->connects()); while (iter.hasNext()) iter.next()->setHilite(true); } } // Do remember this one, ever. m_pHiliteItem = pCurrentItem; } // Auto-open timeout method. void qtractorClientListView::setAutoOpenTimeout ( int iAutoOpenTimeout ) { m_iAutoOpenTimeout = iAutoOpenTimeout; if (m_pAutoOpenTimer) delete m_pAutoOpenTimer; m_pAutoOpenTimer = NULL; if (m_iAutoOpenTimeout > 0) { m_pAutoOpenTimer = new QTimer(this); QObject::connect(m_pAutoOpenTimer, SIGNAL(timeout()), SLOT(timeoutSlot())); } } // Auto-open timeout accessor. int qtractorClientListView::autoOpenTimeout (void) { return m_iAutoOpenTimeout; } // Auto-open timer slot. void qtractorClientListView::timeoutSlot (void) { if (m_pAutoOpenTimer) { m_pAutoOpenTimer->stop(); if (m_pDropItem && m_pDropItem->type() == qtractorConnect::ClientItem) { qtractorClientListItem *pClientItem = static_cast (m_pDropItem); if (pClientItem && !pClientItem->isOpen()) pClientItem->setOpen(true); } } } // Trap for help/tool-tip events. bool qtractorClientListView::eventFilter ( QObject *pObject, QEvent *pEvent ) { QWidget *pViewport = QTreeWidget::viewport(); if (static_cast (pObject) == pViewport && pEvent->type() == QEvent::ToolTip) { QHelpEvent *pHelpEvent = static_cast (pEvent); if (pHelpEvent) { QTreeWidgetItem *pItem = QTreeWidget::itemAt(pHelpEvent->pos()); if (pItem && pItem->type() == qtractorConnect::ClientItem) { qtractorClientListItem *pClientItem = static_cast (pItem); if (pClientItem) { QToolTip::showText(pHelpEvent->globalPos(), pClientItem->clientName(), pViewport); return true; } } else if (pItem && pItem->type() == qtractorConnect::PortItem) { qtractorPortListItem *pPortItem = static_cast (pItem); if (pPortItem) { QToolTip::showText(pHelpEvent->globalPos(), pPortItem->portName(), pViewport); return true; } } } } // Not handled here. return QTreeWidget::eventFilter(pObject, pEvent); } // Drag-n-drop stuff. QTreeWidgetItem *qtractorClientListView::dragDropItem ( const QPoint& pos ) { QTreeWidgetItem *pItem = QTreeWidget::itemAt(pos); if (pItem) { if (m_pDropItem != pItem) { QTreeWidget::setCurrentItem(pItem); m_pDropItem = pItem; if (m_pAutoOpenTimer) m_pAutoOpenTimer->start(m_iAutoOpenTimeout); qtractorConnect *pConnect = binding(); if (pConnect == NULL || !pConnect->canConnectSelected()) pItem = NULL; } } else { m_pDropItem = NULL; if (m_pAutoOpenTimer) m_pAutoOpenTimer->stop(); } return pItem; } void qtractorClientListView::dragEnterEvent ( QDragEnterEvent *pDragEnterEvent ) { if (pDragEnterEvent->source() != this && pDragEnterEvent->mimeData()->hasText() && dragDropItem(pDragEnterEvent->pos())) { pDragEnterEvent->accept(); } else { pDragEnterEvent->ignore(); } } void qtractorClientListView::dragMoveEvent ( QDragMoveEvent *pDragMoveEvent ) { if (pDragMoveEvent->source() != this && pDragMoveEvent->mimeData()->hasText() && dragDropItem(pDragMoveEvent->pos())) { pDragMoveEvent->accept(); } else { pDragMoveEvent->ignore(); } } void qtractorClientListView::dragLeaveEvent ( QDragLeaveEvent * ) { m_pDropItem = NULL; if (m_pAutoOpenTimer) m_pAutoOpenTimer->stop(); } void qtractorClientListView::dropEvent( QDropEvent *pDropEvent ) { if (pDropEvent->source() != this && pDropEvent->mimeData()->hasText() && dragDropItem(pDropEvent->pos())) { const QString sText = pDropEvent->mimeData()->text(); if (!sText.isEmpty() && m_pConnect) m_pConnect->connectSelected(); } dragLeaveEvent(0); } // Handle mouse events for drag-and-drop stuff. void qtractorClientListView::mousePressEvent ( QMouseEvent *pMouseEvent ) { QTreeWidget::mousePressEvent(pMouseEvent); if (pMouseEvent->button() == Qt::LeftButton) { m_posDrag = pMouseEvent->pos(); m_pDragItem = QTreeWidget::itemAt(m_posDrag); } } void qtractorClientListView::mouseMoveEvent ( QMouseEvent *pMouseEvent ) { QTreeWidget::mouseMoveEvent(pMouseEvent); if ((pMouseEvent->buttons() & Qt::LeftButton) && m_pDragItem && ((pMouseEvent->pos() - m_posDrag).manhattanLength() >= QApplication::startDragDistance())) { // We'll start dragging something alright... QMimeData *pMimeData = new QMimeData(); pMimeData->setText(m_pDragItem->text(0)); QDrag *pDrag = new QDrag(this); pDrag->setMimeData(pMimeData); pDrag->setPixmap(m_pDragItem->icon(0).pixmap(16)); pDrag->setHotSpot(QPoint(-4, -12)); pDrag->start(Qt::LinkAction); // We've dragged and maybe dropped it by now... m_pDragItem = NULL; } } // Context menu request event handler. void qtractorClientListView::contextMenuEvent ( QContextMenuEvent *pContextMenuEvent ) { if (m_pConnect) m_pConnect->contextMenu(pContextMenuEvent->globalPos()); } // Natural decimal sorting comparator. bool qtractorClientListView::lessThan ( const QTreeWidgetItem& i1, const QTreeWidgetItem& i2 ) { const QString& s1 = i1.text(0); const QString& s2 = i2.text(0); int ich1, ich2; int cch1 = s1.length(); int cch2 = s2.length(); for (ich1 = ich2 = 0; ich1 < cch1 && ich2 < cch2; ++ich1, ++ich2) { // Skip (white)spaces... while (s1.at(ich1).isSpace()) ++ich1; while (s2.at(ich2).isSpace()) ++ich2; // Normalize (to uppercase) the next characters... QChar ch1 = s1.at(ich1).toUpper(); QChar ch2 = s2.at(ich2).toUpper(); if (ch1.isDigit() && ch2.isDigit()) { // Find the whole length numbers... int iDigits1 = ich1++; while (ich1 < cch1 && s1.at(ich1).isDigit()) ++ich1; int iDigits2 = ich2++; while (ich2 < cch2 && s2.at(ich2).isDigit()) ++ich2; // Compare as natural decimal-numbers... int n1 = s1.mid(iDigits1, ich1 - iDigits1).toInt(); int n2 = s2.mid(iDigits2, ich2 - iDigits2).toInt(); if (n1 != n2) return (n1 < n2); // Never go out of bounds... if (ich1 >= cch1 || ich1 >= cch2) break; // Go on with this next char... ch1 = s1.at(ich1).toUpper(); ch2 = s2.at(ich2).toUpper(); } // Compare this char... if (ch1 != ch2) return (ch1 < ch2); } // Probable exact match. return false; } // Do proper contents refresh/update. void qtractorClientListView::refresh (void) { QHeaderView *pHeader = QTreeWidget::header(); QTreeWidget::sortItems( pHeader->sortIndicatorSection(), pHeader->sortIndicatorOrder()); } //---------------------------------------------------------------------- // qtractorConnectorView -- Connector view widget. // // Constructor. qtractorConnectorView::qtractorConnectorView ( QWidget *pParent ) : QWidget(pParent) { m_pConnect = NULL; QWidget::setMinimumWidth(20); // QWidget::setMaximumWidth(120); QWidget::setSizePolicy( QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); } // Default destructor. qtractorConnectorView::~qtractorConnectorView (void) { } // Main controller accessors. void qtractorConnectorView::setBinding ( qtractorConnect *pConnect ) { m_pConnect = pConnect; } qtractorConnect *qtractorConnectorView::binding (void) const { return m_pConnect; } // Legal client/port item position helper. int qtractorConnectorView::itemY ( QTreeWidgetItem *pItem ) const { QRect rect; QTreeWidget *pList = pItem->treeWidget(); QTreeWidgetItem *pParent = pItem->parent(); qtractorClientListItem *pClientItem = NULL; if (pParent && pParent->type() == qtractorConnect::ClientItem) pClientItem = static_cast (pParent); if (pClientItem && !pClientItem->isOpen()) { rect = pList->visualItemRect(pClientItem); } else { rect = pList->visualItemRect(pItem); } return rect.top() + rect.height() / 2; } // Draw visible port connection relation lines void qtractorConnectorView::drawConnectionLine ( QPainter *pPainter, int x1, int y1, int x2, int y2, int h1, int h2 ) { // Account for list view headers. y1 += h1; y2 += h2; // Invisible output ports don't get a connecting dot. if (y1 > h1) pPainter->drawLine(x1, y1, x1 + 4, y1); // How do we'll draw it? if (m_pConnect->isBezierLines()) { // Setup control points QPolygon spline(4); int cp = int(float(x2 - x1 - 8) * 0.4f); spline.putPoints(0, 4, x1 + 4, y1, x1 + 4 + cp, y1, x2 - 4 - cp, y2, x2 - 4, y2); // The connection line, it self. QPainterPath path; path.moveTo(spline.at(0)); path.cubicTo(spline.at(1), spline.at(2), spline.at(3)); pPainter->strokePath(path, pPainter->pen()); } else pPainter->drawLine(x1 + 4, y1, x2 - 4, y2); // Invisible input ports don't get a connecting dot. if (y2 > h2) pPainter->drawLine(x2 - 4, y2, x2, y2); } // Draw visible port connection relation arrows. void qtractorConnectorView::paintEvent ( QPaintEvent * ) { if (m_pConnect == NULL) return; if (m_pConnect->OListView() == NULL || m_pConnect->IListView() == NULL) return; qtractorClientListView *pOListView = m_pConnect->OListView(); qtractorClientListView *pIListView = m_pConnect->IListView(); int yc = QWidget::pos().y(); int yo = pOListView->pos().y(); int yi = pIListView->pos().y(); QPainter painter(this); int x1, y1, h1; int x2, y2, h2; int i, rgb[3] = { 0x33, 0x66, 0x99 }; // Inline adaptive to darker background themes... if (QWidget::palette().window().color().value() < 0x7f) for (i = 0; i < 3; ++i) rgb[i] += 0x33; // Initialize color changer. i = 0; // Almost constants. x1 = 0; x2 = QWidget::width(); h1 = (pOListView->header())->sizeHint().height(); h2 = (pIListView->header())->sizeHint().height(); // For each output client item... int iItemCount = pOListView->topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = pOListView->topLevelItem(iItem); if (pItem->type() != qtractorConnect::ClientItem) continue; qtractorClientListItem *pOClient = static_cast (pItem); if (pOClient == NULL) continue; // Set new connector color. ++i; painter.setPen(QColor(rgb[i % 3], rgb[(i / 3) % 3], rgb[(i / 9) % 3])); // For each port item int iChildCount = pOClient->childCount(); for (int iChild = 0; iChild < iChildCount; ++iChild) { QTreeWidgetItem *pChild = pOClient->child(iChild); if (pChild->type() != qtractorConnect::PortItem) continue; qtractorPortListItem *pOPort = static_cast (pChild); if (pOPort) { // Get starting connector arrow coordinates. y1 = itemY(pOPort) + (yo - yc); // Get port connections... QListIterator iter(pOPort->connects()); while (iter.hasNext()) { qtractorPortListItem *pIPort = iter.next(); // Obviously, should be a connection // from pOPort to pIPort items: y2 = itemY(pIPort) + (yi - yc); drawConnectionLine(&painter, x1, y1, x2, y2, h1, h2); } } } } } // Context menu request event handler. void qtractorConnectorView::contextMenuEvent ( QContextMenuEvent *pContextMenuEvent ) { if (m_pConnect) m_pConnect->contextMenu(pContextMenuEvent->globalPos()); } // Widget event slots... void qtractorConnectorView::contentsChanged (void) { QWidget::update(); } //---------------------------------------------------------------------------- // qtractorConnect -- Connections controller. // // Constructor. qtractorConnect::qtractorConnect ( qtractorClientListView *pOListView, qtractorClientListView *pIListView, qtractorConnectorView *pConnectorView ) { m_pOListView = pOListView; m_pIListView = pIListView; m_pConnectorView = pConnectorView; m_bBezierLines = false; m_pOListView->setBinding(this); m_pOListView->setReadable(true); m_pIListView->setBinding(this); m_pIListView->setReadable(false); m_pConnectorView->setBinding(this); QObject::connect(m_pOListView, SIGNAL(itemExpanded(QTreeWidgetItem *)), m_pConnectorView, SLOT(contentsChanged())); QObject::connect(m_pOListView, SIGNAL(itemCollapsed(QTreeWidgetItem *)), m_pConnectorView, SLOT(contentsChanged())); QObject::connect(m_pOListView->verticalScrollBar(), SIGNAL(valueChanged(int)), m_pConnectorView, SLOT(contentsChanged())); QObject::connect(m_pOListView->header(), SIGNAL(sectionClicked(int)), m_pConnectorView, SLOT(contentsChanged())); QObject::connect(m_pIListView, SIGNAL(itemExpanded(QTreeWidgetItem *)), m_pConnectorView, SLOT(contentsChanged())); QObject::connect(m_pIListView, SIGNAL(itemCollapsed(QTreeWidgetItem *)), m_pConnectorView, SLOT(contentsChanged())); QObject::connect(m_pIListView->verticalScrollBar(), SIGNAL(valueChanged(int)), m_pConnectorView, SLOT(contentsChanged())); QObject::connect(m_pIListView->header(), SIGNAL(sectionClicked(int)), m_pConnectorView, SLOT(contentsChanged())); } // Default destructor. qtractorConnect::~qtractorConnect (void) { // Force end of works here. m_pOListView->setBinding(0); m_pIListView->setBinding(0); m_pConnectorView->setBinding(0); } // Connector line style accessors. void qtractorConnect::setBezierLines ( bool bBezierLines ) { m_bBezierLines = bBezierLines; } bool qtractorConnect::isBezierLines (void) { return m_bBezierLines; } // Connection primitive. bool qtractorConnect::connectPortsEx ( qtractorPortListItem *pOPort, qtractorPortListItem *pIPort ) { if (pOPort->findConnect(pIPort)) return false; if (!connectPorts(pOPort, pIPort)) return false; pOPort->addConnect(pIPort); pIPort->addConnect(pOPort); return true; } // Disconnection primitive. bool qtractorConnect::disconnectPortsEx ( qtractorPortListItem *pOPort, qtractorPortListItem *pIPort ) { if (pOPort->findConnect(pIPort) == NULL) return false; if (!disconnectPorts(pOPort, pIPort)) return false; pOPort->removeConnect(pIPort); pIPort->removeConnect(pOPort); return true; } // Test if selected ports are connectable. bool qtractorConnect::canConnectSelected (void) { // Take this opportunity to highlight any current selections. m_pOListView->hiliteClientPorts(); m_pIListView->hiliteClientPorts(); // Now with our predicate work... QTreeWidgetItem *pOItem = m_pOListView->currentItem(); if (pOItem == NULL) return false; QTreeWidgetItem *pIItem = m_pIListView->currentItem(); if (pIItem == NULL) return false; if (pOItem->type() == qtractorConnect::ClientItem) { qtractorClientListItem *pOClient = static_cast (pOItem); if (pOClient == NULL) return false; if (pIItem->type() == qtractorConnect::ClientItem) { // Each-to-each connections... qtractorClientListItem *pIClient = static_cast (pIItem); if (pIClient == NULL) return false; int iOItem = 0; int iOCount = pOClient->childCount(); int iIItem = 0; int iICount = pIClient->childCount(); while (iIItem < iICount && iOItem < iOCount) { pOItem = pOClient->child(iOItem); pIItem = pIClient->child(iIItem); if (pOItem && pOItem->type() == qtractorConnect::PortItem && pIItem && pIItem->type() == qtractorConnect::PortItem) { qtractorPortListItem *pOPort = static_cast (pOItem); qtractorPortListItem *pIPort = static_cast (pIItem); if (pOPort && pIPort && pOPort->findConnect(pIPort) == NULL) return true; } ++iOItem; ++iIItem; } } else { // Many(all)-to-one connection... qtractorPortListItem *pIPort = static_cast (pIItem); if (pIPort == NULL) return false; int iOItem = 0; int iOCount = pOClient->childCount(); while (iOItem < iOCount) { pOItem = pOClient->child(iOItem); if (pOItem && pOItem->type() == qtractorConnect::PortItem) { qtractorPortListItem *pOPort = static_cast (pOItem); if (pOPort && pOPort->findConnect(pIPort) == NULL) return true; } ++iOItem; } } } else { qtractorPortListItem *pOPort = static_cast (pOItem); if (pOPort == NULL) return false; if (pIItem->type() == qtractorConnect::ClientItem) { // One-to-many(all) connection... qtractorClientListItem *pIClient = static_cast (pIItem); if (pIClient == NULL) return false; int iIItem = 0; int iICount = pIClient->childCount(); while (iIItem < iICount) { pIItem = pIClient->child(iIItem); if (pIItem && pIItem->type() == qtractorConnect::PortItem) { qtractorPortListItem *pIPort = static_cast (pIItem); if (pIPort && pOPort->findConnect(pIPort) == NULL) return true; } ++iIItem; } } else { // One-to-one connection... qtractorPortListItem *pIPort = static_cast (pIItem); if (pIPort && pOPort->findConnect(pIPort) == NULL) return true; } } return false; } // Connect current selected ports. bool qtractorConnect::connectSelected (void) { bool bResult = connectSelectedEx(); m_pConnectorView->update(); if (bResult) emit connectChanged(); return bResult; } bool qtractorConnect::connectSelectedEx (void) { // Now with our predicate work... QTreeWidgetItem *pOItem = m_pOListView->currentItem(); if (pOItem == NULL) return false; QTreeWidgetItem *pIItem = m_pIListView->currentItem(); if (pIItem == NULL) return false; if (pOItem->type() == qtractorConnect::ClientItem) { qtractorClientListItem *pOClient = static_cast (pOItem); if (pOClient == NULL) return false; if (pIItem->type() == qtractorConnect::ClientItem) { // Each-to-each connections... qtractorClientListItem *pIClient = static_cast (pIItem); if (pIClient == NULL) return false; int iOItem = 0; int iOCount = pOClient->childCount(); int iIItem = 0; int iICount = pIClient->childCount(); while (iIItem < iICount && iOItem < iOCount) { pOItem = pOClient->child(iOItem); pIItem = pIClient->child(iIItem); if (pOItem && pOItem->type() == qtractorConnect::PortItem && pIItem && pIItem->type() == qtractorConnect::PortItem) { qtractorPortListItem *pOPort = static_cast (pOItem); qtractorPortListItem *pIPort = static_cast (pIItem); connectPortsEx(pOPort, pIPort); } ++iOItem; ++iIItem; } } else { // Many(all)-to-one connection... qtractorPortListItem *pIPort = static_cast (pIItem); if (pIPort == NULL) return false; int iOItem = 0; int iOCount = pOClient->childCount(); while (iOItem < iOCount) { pOItem = pOClient->child(iOItem); if (pOItem && pOItem->type() == qtractorConnect::PortItem) { qtractorPortListItem *pOPort = static_cast (pOItem); connectPortsEx(pOPort, pIPort); } ++iOItem; } } } else { qtractorPortListItem *pOPort = static_cast (pOItem); if (pOPort == NULL) return false; if (pIItem->type() == qtractorConnect::ClientItem) { // One-to-many(all) connection... qtractorClientListItem *pIClient = static_cast (pIItem); if (pIClient == NULL) return false; int iIItem = 0; int iICount = pIClient->childCount(); while (iIItem < iICount) { pIItem = pIClient->child(iIItem); if (pIItem && pIItem->type() == qtractorConnect::PortItem) { qtractorPortListItem *pIPort = static_cast (pIItem); connectPortsEx(pOPort, pIPort); } ++iIItem; } } else { // One-to-one connection... qtractorPortListItem *pIPort = static_cast (pIItem); connectPortsEx(pOPort, pIPort); } } return true; } // Test if selected ports are disconnectable. bool qtractorConnect::canDisconnectSelected (void) { // Now with our predicate work... QTreeWidgetItem *pOItem = m_pOListView->currentItem(); if (pOItem == NULL) return false; QTreeWidgetItem *pIItem = m_pIListView->currentItem(); if (pIItem == NULL) return false; if (pOItem->type() == qtractorConnect::ClientItem) { qtractorClientListItem *pOClient = static_cast (pOItem); if (pOClient == NULL) return false; if (pIItem->type() == qtractorConnect::ClientItem) { // Each-to-each connections... qtractorClientListItem *pIClient = static_cast (pIItem); if (pIClient == NULL) return false; int iOItem = 0; int iOCount = pOClient->childCount(); int iIItem = 0; int iICount = pIClient->childCount(); while (iIItem < iICount && iOItem < iOCount) { pOItem = pOClient->child(iOItem); pIItem = pIClient->child(iIItem); if (pOItem && pOItem->type() == qtractorConnect::PortItem && pIItem && pIItem->type() == qtractorConnect::PortItem) { qtractorPortListItem *pOPort = static_cast (pOItem); qtractorPortListItem *pIPort = static_cast (pIItem); if (pOPort && pIPort && pOPort->findConnect(pIPort)) return true; } ++iOItem; ++iIItem; } } else { // Many(all)-to-one connection... qtractorPortListItem *pIPort = static_cast (pIItem); if (pIPort == NULL) return false; int iOItem = 0; int iOCount = pOClient->childCount(); while (iOItem < iOCount) { pOItem = pOClient->child(iOItem); if (pOItem && pOItem->type() == qtractorConnect::PortItem) { qtractorPortListItem *pOPort = static_cast (pOItem); if (pOPort && pOPort->findConnect(pIPort)) return true; } ++iOItem; } } } else { qtractorPortListItem *pOPort = static_cast (pOItem); if (pOPort == NULL) return false; if (pIItem->type() == qtractorConnect::ClientItem) { // One-to-many(all) connection... qtractorClientListItem *pIClient = static_cast (pIItem); if (pIClient == NULL) return false; int iIItem = 0; int iICount = pIClient->childCount(); while (iIItem < iICount) { pIItem = pIClient->child(iIItem); if (pIItem && pIItem->type() == qtractorConnect::PortItem) { qtractorPortListItem *pIPort = static_cast (pIItem); if (pIPort && pOPort->findConnect(pIPort)) return true; } ++iIItem; } } else { // One-to-one connection... qtractorPortListItem *pIPort = static_cast (pIItem); if (pIPort && pOPort->findConnect(pIPort)) return true; } } return false; } // Disconnect current selected ports. bool qtractorConnect::disconnectSelected (void) { bool bResult = disconnectSelectedEx(); m_pConnectorView->update(); if (bResult) emit connectChanged(); return bResult; } bool qtractorConnect::disconnectSelectedEx (void) { // Now with our predicate work... QTreeWidgetItem *pOItem = m_pOListView->currentItem(); if (pOItem == NULL) return false; QTreeWidgetItem *pIItem = m_pIListView->currentItem(); if (pIItem == NULL) return false; if (pOItem->type() == qtractorConnect::ClientItem) { qtractorClientListItem *pOClient = static_cast (pOItem); if (pOClient == NULL) return false; if (pIItem->type() == qtractorConnect::ClientItem) { // Each-to-each connections... qtractorClientListItem *pIClient = static_cast (pIItem); if (pIClient == NULL) return false; int iOItem = 0; int iOCount = pOClient->childCount(); int iIItem = 0; int iICount = pIClient->childCount(); while (iIItem < iICount && iOItem < iOCount) { pOItem = pOClient->child(iOItem); pIItem = pIClient->child(iIItem); if (pOItem && pOItem->type() == qtractorConnect::PortItem && pIItem && pIItem->type() == qtractorConnect::PortItem) { qtractorPortListItem *pOPort = static_cast (pOItem); qtractorPortListItem *pIPort = static_cast (pIItem); disconnectPortsEx(pOPort, pIPort); } ++iOItem; ++iIItem; } } else { // Many(all)-to-one connection... qtractorPortListItem *pIPort = static_cast (pIItem); if (pIPort == NULL) return false; int iOItem = 0; int iOCount = pOClient->childCount(); while (iOItem < iOCount) { pOItem = pOClient->child(iOItem); if (pOItem && pOItem->type() == qtractorConnect::PortItem) { qtractorPortListItem *pOPort = static_cast (pOItem); disconnectPortsEx(pOPort, pIPort); } ++iOItem; } } } else { qtractorPortListItem *pOPort = static_cast (pOItem); if (pOPort == NULL) return false; if (pIItem->type() == qtractorConnect::ClientItem) { // One-to-many(all) connection... qtractorClientListItem *pIClient = static_cast (pIItem); if (pIClient == NULL) return false; int iIItem = 0; int iICount = pIClient->childCount(); while (iIItem < iICount) { pIItem = pIClient->child(iIItem); if (pIItem && pIItem->type() == qtractorConnect::PortItem) { qtractorPortListItem *pIPort = static_cast (pIItem); disconnectPortsEx(pOPort, pIPort); } ++iIItem; } } else { // One-to-one connection... qtractorPortListItem *pIPort = static_cast (pIItem); disconnectPortsEx(pOPort, pIPort); } } return true; } // Test if any port is disconnectable. bool qtractorConnect::canDisconnectAll (void) { // For each output client item... int iItemCount = m_pOListView->topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = m_pOListView->topLevelItem(iItem); if (pItem->type() != qtractorConnect::ClientItem) continue; qtractorClientListItem *pOClient = static_cast (pItem); if (pOClient == NULL) continue; // For each output port item... int iChildCount = pOClient->childCount(); for (int iChild = 0; iChild < iChildCount; ++iChild) { QTreeWidgetItem *pChild = pOClient->child(iChild); if (pChild->type() != qtractorConnect::PortItem) continue; qtractorPortListItem *pOPort = static_cast (pChild); if (pOPort && pOPort->connects().count() > 0) return true; } } return false; } // Disconnect all ports. bool qtractorConnect::disconnectAll (void) { bool bResult = disconnectAllEx(); m_pConnectorView->update(); if (bResult) emit connectChanged(); return bResult; } bool qtractorConnect::disconnectAllEx (void) { // For each output client item... int iItemCount = m_pOListView->topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = m_pOListView->topLevelItem(iItem); if (pItem->type() != qtractorConnect::ClientItem) continue; qtractorClientListItem *pOClient = static_cast (pItem); if (pOClient == NULL) continue; // For each output port item... int iChildCount = pOClient->childCount(); for (int iChild = 0; iChild < iChildCount; ++iChild) { QTreeWidgetItem *pChild = pOClient->child(iChild); if (pChild->type() != qtractorConnect::PortItem) continue; qtractorPortListItem *pOPort = static_cast (pChild); if (pOPort) { QList connects = pOPort->connects(); QListIterator iter(connects); while (iter.hasNext()) { qtractorPortListItem *pIPort = iter.next(); disconnectPortsEx(pOPort, pIPort); } } } } return true; } // Complete/incremental contents rebuilder; // check dirty status if incremental. void qtractorConnect::updateContents ( bool bClear ) { int iDirtyCount = 0; // Do we do a complete rebuild? if (bClear) { m_pOListView->clear(); m_pIListView->clear(); } // Add (newer) client:ports and respective connections... if (m_pOListView->updateClientPorts() > 0) { m_pOListView->refresh(); ++iDirtyCount; } if (m_pIListView->updateClientPorts() > 0) { m_pIListView->refresh(); ++iDirtyCount; } updateConnections(); m_pConnectorView->update(); if (!bClear && iDirtyCount > 0) emit contentsChanged(); } // Incremental contents rebuilder; // check dirty status. void qtractorConnect::refresh (void) { updateContents(false); } // Context menu helper. void qtractorConnect::contextMenu ( const QPoint& gpos ) { QMenu menu(m_pConnectorView); QAction *pAction; pAction = menu.addAction( QIcon(":/images/formConnect.png"), tr("Connect"), this, SLOT(connectSelected())); pAction->setEnabled(canConnectSelected()); pAction = menu.addAction( QIcon(":/images/formDisconnect.png"), tr("Disconnect"), this, SLOT(disconnectSelected())); pAction->setEnabled(canDisconnectSelected()); pAction = menu.addAction( QIcon(":/images/formDisconnectAll.png"), tr("Disconnect All"), this, SLOT(disconnectAll())); pAction->setEnabled(canDisconnectAll()); menu.addSeparator(); pAction = menu.addAction( QIcon(":/images/formRefresh.png"), tr("Refresh"), this, SLOT(refresh())); menu.exec(gpos); } // end of qtractorConnect.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiMeter.h0000644000175000001440000000012311514173274021060 xustar000000000000000027 mtime=1295054524.563054 26 atime=1381134666.77208 30 ctime=1381134666.772080045 qtractor-0.5.11/src/qtractorMidiMeter.h0000644000175000001440000001031011514173274020342 0ustar00rncbcusers00000000000000// qtractorMidiMeter.h // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiMeter_h #define __qtractorMidiMeter_h #include "qtractorMeter.h" // Forward declarations. class qtractorMidiMeter; class qtractorMidiMeterValue; class qtractorMidiMonitor; class QLabel; class QResizeEvent; class QPaintEvent; //---------------------------------------------------------------------------- // qtractorMidiMeterScale -- MIDI meter bridge scale widget. class qtractorMidiMeterScale : public qtractorMeterScale { Q_OBJECT public: // Constructor. qtractorMidiMeterScale(qtractorMidiMeter *pMidiMeter, QWidget *pParent = 0); protected: // Actual scale drawing method. void paintScale(QPainter *p); }; //---------------------------------------------------------------------------- // qtractorMidiMeterValue -- MIDI meter bridge value widget. class qtractorMidiMeterValue : public QWidget { Q_OBJECT public: // Constructor. qtractorMidiMeterValue(qtractorMidiMeter *pMidiMeter, QWidget *pParent = 0); // Default destructor. ~qtractorMidiMeterValue(); // Reset peak holder. void peakReset(); // Value refreshment. void refresh(); protected: // Specific event handlers. void paintEvent(QPaintEvent *); void resizeEvent(QResizeEvent *); private: // Local instance variables. qtractorMidiMeter *m_pMidiMeter; // Running variables. int m_iValue; float m_fValueDecay; int m_iPeak; int m_iPeakHold; float m_fPeakDecay; }; //---------------------------------------------------------------------------- // qtractorMidiMeter -- MIDI meter bridge slot widget. class qtractorMidiMeter : public qtractorMeter { Q_OBJECT public: // Constructor. qtractorMidiMeter(qtractorMidiMonitor *pMidiMonitor, QWidget *pParent = 0); // Default destructor. ~qtractorMidiMeter(); // Virtual monitor accessor. void setMonitor(qtractorMonitor *pMonitor); qtractorMonitor *monitor() const; // MIDI monitor accessor. void setMidiMonitor(qtractorMidiMonitor *pMidiMonitor); qtractorMidiMonitor *midiMonitor() const; // Local slider update methods. void updatePanning(); void updateGain(); // Monitor reset. void reset(); // Slot refreshment. void refresh(); // Reset peak holder. void peakReset(); #ifdef CONFIG_GRADIENT const QPixmap& pixmap() const; void updatePixmap(); #endif // Color/level indexes. enum { ColorPeak = 0, ColorOver = 1, ColorBack = 2, ColorFore = 3, ColorCount = 4 }; // Common resource accessors. static void setColor(int iIndex, const QColor& color); static const QColor& color(int iIndex); static const QColor& defaultColor(int iIndex); protected: // Specific event handlers. void resizeEvent(QResizeEvent *); private: // Local forward declarations. class GainSliderInterface; class GainSpinBoxInterface; // Local instance variables. qtractorMidiMonitor *m_pMidiMonitor; qtractorMidiMeterScale *m_pMidiScale; qtractorMidiMeterValue *m_pMidiValue; QLabel *m_pMidiLabel; unsigned int m_iMidiCount; #ifdef CONFIG_GRADIENT QPixmap *m_pPixmap; #endif // MIDI I/O LED pixmap stuff. enum { LedOff = 0, LedOn = 1, LedCount = 2 }; static int g_iLedRefCount; static QPixmap *g_pLedPixmap[LedCount]; static QColor g_defaultColors[ColorCount]; static QColor g_currentColors[ColorCount]; }; #endif // __qtractorMidiMeter_h // end of qtractorMidiMeter.h qtractor-0.5.11/src/PaxHeaders.10084/qtractor.cpp0000644000175000001440000000012312166526620017614 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134666.88208 30 ctime=1381134666.883080047 qtractor-0.5.11/src/qtractor.cpp0000644000175000001440000002453112166526620017110 0ustar00rncbcusers00000000000000// qtractor.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorOptions.h" #include "qtractorMainForm.h" #include #include #include #include #define CONFIG_QUOTE1(x) #x #define CONFIG_QUOTED(x) CONFIG_QUOTE1(x) #if defined(DATADIR) #define CONFIG_DATADIR CONFIG_QUOTED(DATADIR) #else #define CONFIG_DATADIR CONFIG_PREFIX "/share" #endif #if defined(LOCALEDIR) #define CONFIG_LOCALEDIR CONFIG_QUOTED(LOCALEDIR) #else #define CONFIG_LOCALEDIR CONFIG_DATADIR "/locale" #endif //------------------------------------------------------------------------- // Singleton application instance stuff (Qt/X11 only atm.) // #if defined(Q_WS_X11) #ifdef CONFIG_VST #include "qtractorVstPlugin.h" #endif #ifdef CONFIG_XUNIQUE #include #include #include #define QTRACTOR_XUNIQUE "qtractorApplication" #endif // CONFIG_XUNIQUE #endif // Q_WS_X11 class qtractorApplication : public QApplication { public: // Constructor. qtractorApplication(int& argc, char **argv) : QApplication(argc, argv), m_pQtTranslator(0), m_pMyTranslator(0), m_pWidget(0) { // Load translation support. QLocale loc; if (loc.language() != QLocale::C) { // Try own Qt translation... m_pQtTranslator = new QTranslator(this); QString sLocName = "qt_" + loc.name(); QString sLocPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); if (m_pQtTranslator->load(sLocName, sLocPath)) { QApplication::installTranslator(m_pQtTranslator); } else { delete m_pQtTranslator; m_pQtTranslator = 0; #ifdef CONFIG_DEBUG qWarning("Warning: no translation found for '%s' locale: %s/%s.qm", loc.name().toUtf8().constData(), sLocPath.toUtf8().constData(), sLocName.toUtf8().constData()); #endif } // Try own application translation... m_pMyTranslator = new QTranslator(this); sLocName = "qtractor_" + loc.name(); if (m_pMyTranslator->load(sLocName, sLocPath)) { QApplication::installTranslator(m_pMyTranslator); } else { sLocPath = CONFIG_LOCALEDIR; if (m_pMyTranslator->load(sLocName, sLocPath)) { QApplication::installTranslator(m_pMyTranslator); } else { delete m_pMyTranslator; m_pMyTranslator = 0; #ifdef CONFIG_DEBUG qWarning("Warning: no translation found for '%s' locale: %s/%s.qm", loc.name().toUtf8().constData(), sLocPath.toUtf8().constData(), sLocName.toUtf8().constData()); #endif } } } #if defined(Q_WS_X11) #ifdef CONFIG_XUNIQUE m_pDisplay = QX11Info::display(); m_aUnique = XInternAtom(m_pDisplay, QTRACTOR_XUNIQUE, false); XGrabServer(m_pDisplay); m_wOwner = XGetSelectionOwner(m_pDisplay, m_aUnique); XUngrabServer(m_pDisplay); #endif #endif } // Destructor. ~qtractorApplication() { if (m_pMyTranslator) delete m_pMyTranslator; if (m_pQtTranslator) delete m_pQtTranslator; } // Main application widget accessors. void setMainWidget(QWidget *pWidget) { m_pWidget = pWidget; #if defined(Q_WS_X11) #ifdef CONFIG_XUNIQUE XGrabServer(m_pDisplay); m_wOwner = m_pWidget->winId(); XSetSelectionOwner(m_pDisplay, m_aUnique, m_wOwner, CurrentTime); XUngrabServer(m_pDisplay); #endif #endif } QWidget *mainWidget() const { return m_pWidget; } // Check if another instance is running, // and raise its proper main widget... bool setup() { #if defined(Q_WS_X11) #ifdef CONFIG_XUNIQUE if (m_wOwner != None) { // First, notify any freedesktop.org WM // that we're about to show the main widget... Screen *pScreen = XDefaultScreenOfDisplay(m_pDisplay); int iScreen = XScreenNumberOfScreen(pScreen); XEvent ev; memset(&ev, 0, sizeof(ev)); ev.xclient.type = ClientMessage; ev.xclient.display = m_pDisplay; ev.xclient.window = m_wOwner; ev.xclient.message_type = XInternAtom(m_pDisplay, "_NET_ACTIVE_WINDOW", false); ev.xclient.format = 32; ev.xclient.data.l[0] = 0; // Source indication. ev.xclient.data.l[1] = 0; // Timestamp. ev.xclient.data.l[2] = 0; // Requestor's currently active window (none) ev.xclient.data.l[3] = 0; ev.xclient.data.l[4] = 0; XSelectInput(m_pDisplay, m_wOwner, StructureNotifyMask); XSendEvent(m_pDisplay, RootWindow(m_pDisplay, iScreen), false, (SubstructureNotifyMask | SubstructureRedirectMask), &ev); XSync(m_pDisplay, false); XRaiseWindow(m_pDisplay, m_wOwner); // And then, let it get caught on destination // by QApplication::x11EventFilter... QByteArray value = QTRACTOR_XUNIQUE; XChangeProperty( m_pDisplay, m_wOwner, m_aUnique, m_aUnique, 8, PropModeReplace, (unsigned char *) value.data(), value.length()); // Done. return true; } #endif #endif return false; } #if defined(Q_WS_X11) bool x11EventFilter(XEvent *pEv) { #ifdef CONFIG_XUNIQUE if (m_pWidget && m_wOwner != None && pEv->type == PropertyNotify && pEv->xproperty.window == m_wOwner && pEv->xproperty.state == PropertyNewValue) { // Always check whether our property-flag is still around... Atom aType; int iFormat = 0; unsigned long iItems = 0; unsigned long iAfter = 0; unsigned char *pData = 0; if (XGetWindowProperty( m_pDisplay, m_wOwner, m_aUnique, 0, 1024, false, m_aUnique, &aType, &iFormat, &iItems, &iAfter, &pData) == Success && aType == m_aUnique && iItems > 0 && iAfter == 0) { // Avoid repeating it-self... XDeleteProperty(m_pDisplay, m_wOwner, m_aUnique); // Just make it always shows up fine... m_pWidget->show(); m_pWidget->raise(); m_pWidget->activateWindow(); } // Free any left-overs... if (iItems > 0 && pData) XFree(pData); } #endif #ifdef CONFIG_VST // Let xevents be processed by VST plugin editors... if (qtractorVstPlugin::x11EventFilter(pEv)) return true; #endif return QApplication::x11EventFilter(pEv); } #endif private: // Translation support. QTranslator *m_pQtTranslator; QTranslator *m_pMyTranslator; // Instance variables. QWidget *m_pWidget; #if defined(Q_WS_X11) #ifdef CONFIG_XUNIQUE Display *m_pDisplay; Atom m_aUnique; Window m_wOwner; #endif #endif }; //------------------------------------------------------------------------- // stacktrace - Signal crash handler. // #ifdef CONFIG_STACKTRACE #if defined(__GNUC__) && defined(Q_OS_LINUX) #include #include #include #include #include void stacktrace ( int signo ) { pid_t pid; int rc; int status = 0; char cmd[80]; // Reinstall default handler; prevent race conditions... signal(signo, SIG_DFL); static const char *shell = "/bin/sh"; static const char *format = "gdb -q --batch --pid=%d" " --eval-command='thread apply all bt'"; snprintf(cmd, sizeof(cmd), format, (int) getpid()); pid = fork(); // Fork failure! if (pid < 0) return; // Fork child... if (pid == 0) { execl(shell, shell, "-c", cmd, NULL); _exit(1); return; } // Parent here: wait for child to terminate... do { rc = waitpid(pid, &status, 0); } while ((rc < 0) && (errno == EINTR)); // Dispatch any logging, if any... QApplication::processEvents(QEventLoop::AllEvents, 3000); // Make sure everyone terminates... kill(pid, SIGTERM); _exit(1); } #endif #endif //------------------------------------------------------------------------- // main - The main program trunk. // int main ( int argc, char **argv ) { Q_INIT_RESOURCE(qtractor); #ifdef CONFIG_STACKTRACE #if defined(__GNUC__) && defined(Q_OS_LINUX) signal(SIGILL, stacktrace); signal(SIGFPE, stacktrace); signal(SIGSEGV, stacktrace); signal(SIGABRT, stacktrace); signal(SIGBUS, stacktrace); #endif #endif qtractorApplication app(argc, argv); // Construct default settings; override with command line arguments. qtractorOptions options; if (!options.parse_args(app.arguments())) { app.quit(); return 1; } // Have another instance running? if (app.setup()) { app.quit(); return 2; } // Dark themes grayed/disabled color group fix... QPalette pal(app.palette()); if (pal.base().color().value() < 0x7f) { const QColor& color = pal.window().color(); const int iGroups = int(QPalette::Active | QPalette::Inactive) + 1; for (int i = 0; i < iGroups; ++i) { const QPalette::ColorGroup group = QPalette::ColorGroup(i); pal.setBrush(group, QPalette::Light, color.lighter(140)); pal.setBrush(group, QPalette::Midlight, color.lighter(100)); pal.setBrush(group, QPalette::Mid, color.lighter(90)); pal.setBrush(group, QPalette::Dark, color.darker(160)); pal.setBrush(group, QPalette::Shadow, color.darker(180)); } pal.setColorGroup(QPalette::Disabled, pal.windowText().color().darker(), pal.button(), pal.light(), pal.dark(), pal.mid(), pal.text().color().darker(), pal.text().color().lighter(), pal.base(), pal.window()); #if QT_VERSION >= 0x050000 pal.setColor(QPalette::Disabled, QPalette::Highlight, pal.mid().color()); pal.setColor(QPalette::Disabled, QPalette::ButtonText, pal.mid().color()); #endif app.setPalette(pal); } // Set default base font... int iBaseFontSize = app.font().pointSize(); if (options.iBaseFontSize > 0) iBaseFontSize = options.iBaseFontSize; app.setFont(QFont(app.font().family(), iBaseFontSize)); // Construct, setup and show the main form (a pseudo-singleton). qtractorMainForm w; w.setup(&options); w.show(); // Settle this one as application main widget... app.setMainWidget(&w); return app.exec(); } // end of qtractor.cpp qtractor-0.5.11/src/PaxHeaders.10084/lv20000644000175000001440000000013212224470513015671 xustar000000000000000030 mtime=1381134667.407080055 30 atime=1381134667.368080055 30 ctime=1381134667.407080055 qtractor-0.5.11/src/lv2/0000755000175000001440000000000012224470513015235 5ustar00rncbcusers00000000000000qtractor-0.5.11/src/lv2/PaxHeaders.10084/lv2_atom_helpers.h0000644000175000001440000000012312020417260021356 xustar000000000000000027 mtime=1346510512.481834 26 atime=1381134667.40708 30 ctime=1381134667.407080055 qtractor-0.5.11/src/lv2/lv2_atom_helpers.h0000644000175000001440000001351612020417260020653 0ustar00rncbcusers00000000000000// lv2_atom_helpers.h // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ /* Helper functions for LV2 atom:Sequence event buffer. * * tentatively adapted from: * * - lv2_evbuf.h,c - An abstract/opaque LV2 event buffer implementation. * * - event-helpers.h - Helper functions for the LV2 Event extension. * * * Copyright 2008-2012 David Robillard */ #ifndef LV2_ATOM_HELPERS_H #define LV2_ATOM_HELPERS_H #include #include #include #include #include #include "lv2/lv2plug.in/ns/ext/atom/atom.h" // An abstract/opaque LV2 atom:Sequence buffer. // typedef struct _LV2_Atom_Buffer { uint32_t capacity; uint32_t chunk_type; uint32_t sequence_type; LV2_Atom_Sequence atoms; } LV2_Atom_Buffer; // Pad a size to 64 bits (for LV2 atom:Sequence event sizes). // static inline uint32_t lv2_atom_buffer_pad_size ( uint32_t size ) { return (size + 7) & (~7); } // Clear and initialize an existing LV2 atom:Sequenece buffer. // static inline void lv2_atom_buffer_reset ( LV2_Atom_Buffer *buf, bool input ) { if (input) buf->atoms.atom.size = sizeof(LV2_Atom_Sequence_Body); else buf->atoms.atom.size = buf->capacity; buf->atoms.atom.type = buf->sequence_type; } // Allocate a new, empty LV2 atom:Sequence buffer. // static inline LV2_Atom_Buffer *lv2_atom_buffer_new ( uint32_t capacity, uint32_t sequence_type, bool input ) { LV2_Atom_Buffer *buf = (LV2_Atom_Buffer *) malloc(sizeof(LV2_Atom_Buffer) + sizeof(LV2_Atom_Sequence) + capacity); buf->capacity = capacity; buf->sequence_type = sequence_type; lv2_atom_buffer_reset(buf, input); return buf; } // Free an LV2 atom:Sequenece buffer allocated with lv2_atome_buffer_new. // static inline void lv2_atom_buffer_free ( LV2_Atom_Buffer *buf ) { free(buf); } // Return the total padded size of events stored in a LV2 atom:Sequence buffer. // static inline uint32_t lv2_atom_buffer_get_size ( LV2_Atom_Buffer *buf ) { return buf->atoms.atom.size - sizeof(LV2_Atom_Sequence_Body); } // Return the actual LV2 atom:Sequence implementation. // static inline LV2_Atom_Sequence *lv2_atom_buffer_get_sequence ( LV2_Atom_Buffer *buf ) { return &buf->atoms; } // An iterator over an atom:Sequence buffer. // typedef struct _LV2_Atom_Buffer_Iterator { LV2_Atom_Buffer *buf; uint32_t offset; } LV2_Atom_Buffer_Iterator; // Reset an iterator to point to the start of an LV2 atom:Sequence buffer. // static inline bool lv2_atom_buffer_begin ( LV2_Atom_Buffer_Iterator *iter, LV2_Atom_Buffer *buf ) { iter->buf = buf; iter->offset = 0; return (buf->atoms.atom.size > 0); } // Reset an iterator to point to the end of an LV2 atom:Sequence buffer. // static inline bool lv2_atom_buffer_end ( LV2_Atom_Buffer_Iterator *iter, LV2_Atom_Buffer *buf ) { iter->buf = buf; iter->offset = lv2_atom_buffer_pad_size(lv2_atom_buffer_get_size(buf)); return (iter->offset < buf->capacity - sizeof(LV2_Atom_Event)); } // Check if a LV2 atom:Sequenece buffer iterator is valid. // static inline bool lv2_atom_buffer_is_valid ( LV2_Atom_Buffer_Iterator *iter ) { return iter->offset < lv2_atom_buffer_get_size(iter->buf); } // Advance a LV2 atom:Sequenece buffer iterator forward one event. // static inline bool lv2_atom_buffer_increment ( LV2_Atom_Buffer_Iterator *iter ) { if (!lv2_atom_buffer_is_valid(iter)) return false; LV2_Atom_Buffer *buf = iter->buf; LV2_Atom_Sequence *atoms = &buf->atoms; uint32_t size = ((LV2_Atom_Event *) ((char *) LV2_ATOM_CONTENTS(LV2_Atom_Sequence, atoms) + iter->offset))->body.size; iter->offset += lv2_atom_buffer_pad_size(sizeof(LV2_Atom_Event) + size); return true; } // Get the event currently pointed at a LV2 atom:Sequence buffer iterator. // static inline LV2_Atom_Event *lv2_atom_buffer_get ( LV2_Atom_Buffer_Iterator *iter, uint8_t **data ) { if (!lv2_atom_buffer_is_valid(iter)) return NULL; LV2_Atom_Buffer *buf = iter->buf; LV2_Atom_Sequence *atoms = &buf->atoms; LV2_Atom_Event *ev = (LV2_Atom_Event *) ((char *) LV2_ATOM_CONTENTS(LV2_Atom_Sequence, atoms) + iter->offset); *data = (uint8_t *) LV2_ATOM_BODY(&ev->body); return ev; } // Write an event at a LV2 atom:Sequence buffer iterator. static inline bool lv2_atom_buffer_write ( LV2_Atom_Buffer_Iterator *iter, uint32_t frames, uint32_t /*subframes*/, uint32_t type, uint32_t size, const uint8_t *data ) { LV2_Atom_Buffer *buf = iter->buf; LV2_Atom_Sequence *atoms = &buf->atoms; if (buf->capacity - sizeof(LV2_Atom) - atoms->atom.size < sizeof(LV2_Atom_Event) + size) return false; LV2_Atom_Event *ev = (LV2_Atom_Event*) ((char *) LV2_ATOM_CONTENTS(LV2_Atom_Sequence, atoms) + iter->offset); ev->time.frames = frames; ev->body.type = type; ev->body.size = size; memcpy(LV2_ATOM_BODY(&ev->body), data, size); size = lv2_atom_buffer_pad_size(sizeof(LV2_Atom_Event) + size); atoms->atom.size += size; iter->offset += size; return true; } #endif // LV2_ATOM_HELPERS_H // end of lv2_atom_helpers.h qtractor-0.5.11/src/lv2/PaxHeaders.10084/lv2_programs.h0000644000175000001440000000012312020417260020526 xustar000000000000000027 mtime=1346510512.481834 26 atime=1381134667.36808 30 ctime=1381134667.407080055 qtractor-0.5.11/src/lv2/lv2_programs.h0000644000175000001440000001401212020417260020013 0ustar00rncbcusers00000000000000/* LV2 Programs Extension Copyright 2012 Filipe Coelho Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /** @file programs.h C header for the LV2 programs extension . */ #ifndef LV2_PROGRAMS_H #define LV2_PROGRAMS_H #include "lv2.h" #include "lv2/lv2plug.in/ns/extensions/ui/ui.h" #define LV2_PROGRAMS_URI "http://kxstudio.sf.net/ns/lv2ext/programs" #define LV2_PROGRAMS_PREFIX LV2_PROGRAMS_URI "#" #define LV2_PROGRAMS__Host LV2_PROGRAMS_PREFIX "Host" #define LV2_PROGRAMS__Interface LV2_PROGRAMS_PREFIX "Interface" #define LV2_PROGRAMS__UIInterface LV2_PROGRAMS_PREFIX "UIInterface" #ifdef __cplusplus extern "C" { #endif typedef void* LV2_Programs_Handle; typedef struct _LV2_Program_Descriptor { /** Bank number for this program. Note that this extension does not support MIDI-style separation of bank LSB and MSB values. There is no restriction on the set of available banks: the numbers do not need to be contiguous, there does not need to be a bank 0, etc. */ uint32_t bank; /** Program number (unique within its bank) for this program. There is no restriction on the set of available programs: the numbers do not need to be contiguous, there does not need to be a program 0, etc. */ uint32_t program; /** Name of the program. */ const char * name; } LV2_Program_Descriptor; /** Programs extension, plugin data. When the plugin's extension_data is called with argument LV2_PROGRAMS__Interface, the plugin MUST return an LV2_Programs_Instance structure, which remains valid for the lifetime of the plugin. */ typedef struct _LV2_Programs_Interface { /** * get_program() * * This member is a function pointer that provides a description * of a program (named preset sound) available on this plugin. * * The index argument is an index into the plugin's list of * programs, not a program number as represented by the Program * field of the LV2_Program_Descriptor. (This distinction is * needed to support plugins that use non-contiguous program or * bank numbers.) * * This function returns a LV2_Program_Descriptor pointer that is * guaranteed to be valid only until the next call to get_program * or deactivate, on the same plugin instance. This function must * return NULL if passed an index argument out of range, so that * the host can use it to query the number of programs as well as * their properties. */ const LV2_Program_Descriptor *(*get_program)(LV2_Handle handle, uint32_t index); /** * select_program() * * This member is a function pointer that selects a new program * for this plugin. The program change should take effect * immediately at the start of the next run() call. (This * means that a host providing the capability of changing programs * between any two notes on a track must vary the block size so as * to place the program change at the right place. A host that * wanted to avoid this would probably just instantiate a plugin * for each program.) * * Plugins should ignore a select_program() call with an invalid * bank or program. * * A plugin is not required to select any particular default * program on activate(): it's the host's duty to set a program * explicitly. * * A plugin is permitted to re-write the values of its input * control ports when select_program is called. The host should * re-read the input control port values and update its own * records appropriately. (This is the only circumstance in which * a LV2 plugin is allowed to modify its own control-input ports.) */ void (*select_program)(LV2_Handle handle, uint32_t bank, uint32_t program); } LV2_Programs_Interface; /** Programs extension, UI data. When the UI's extension_data is called with argument LV2_PROGRAMS__UIInterface, the UI MUST return an LV2_Programs_UI_Interface structure, which remains valid for the lifetime of the UI. */ typedef struct _LV2_Programs_UI_Interface { /** * select_program() * * This is exactly the same as select_program in LV2_Programs_Instance, * but this struct relates to the UI instead of the plugin. * * When called, UIs should update their state to match the selected program. */ void (*select_program)(LV2UI_Handle handle, uint32_t bank, uint32_t program); } LV2_Programs_UI_Interface; /** Feature data for LV2_PROGRAMS__Host. */ typedef struct _LV2_Programs_Host { /** * Opaque host data. */ LV2_Programs_Handle handle; /** * program_changed() * * Tell the host to reload a plugin's program. * Parameter handle MUST be the 'handle' member of this struct. * Parameter index is program index to change. * When index is -1, host should reload all the programs. * * NOTE: The plugin MUST NEVER call this function on a RT context or during run(). */ void (*program_changed)(LV2_Programs_Handle handle, int32_t index); } LV2_Programs_Host; #ifdef __cplusplus } /* extern "C" */ #endif #endif /* LV2_PROGRAMS_H */ qtractor-0.5.11/src/lv2/PaxHeaders.10084/lv2_external_ui.h0000644000175000001440000000012312121172107021213 xustar000000000000000027 mtime=1363473479.448133 26 atime=1381134667.40708 30 ctime=1381134667.407080055 qtractor-0.5.11/src/lv2/lv2_external_ui.h0000644000175000001440000000634512121172107020512 0ustar00rncbcusers00000000000000/* LV2 External UI extension This work is in public domain. This file 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. If you have questions, contact Filipe Coelho (aka falkTX) or ask in #lad channel, FreeNode IRC network. */ /** @file lv2_external_ui.h C header for the LV2 External UI extension . */ #ifndef LV2_EXTERNAL_UI_H #define LV2_EXTERNAL_UI_H #include "lv2/lv2plug.in/ns/extensions/ui/ui.h" #define LV2_EXTERNAL_UI_URI "http://kxstudio.sf.net/ns/lv2ext/external-ui" #define LV2_EXTERNAL_UI_PREFIX LV2_EXTERNAL_UI_URI "#" #define LV2_EXTERNAL_UI__Host LV2_EXTERNAL_UI_PREFIX "Host" #define LV2_EXTERNAL_UI__Widget LV2_EXTERNAL_UI_PREFIX "Widget" /** This extension used to be defined by a lv2plug.in URI */ #define LV2_EXTERNAL_UI_DEPRECATED_URI "http://lv2plug.in/ns/extensions/ui#external" #ifdef __cplusplus extern "C" { #endif /** * When LV2_EXTERNAL_UI__Widget UI is instantiated, the returned * LV2UI_Widget handle must be cast to pointer to LV2_External_UI_Widget. * UI is created in invisible state. */ typedef struct _LV2_External_UI_Widget { /** * Host calls this function regulary. UI library implementing the * callback may do IPC or redraw the UI. * * @param _this_ the UI context */ void (*run)(struct _LV2_External_UI_Widget * _this_); /** * Host calls this function to make the plugin UI visible. * * @param _this_ the UI context */ void (*show)(struct _LV2_External_UI_Widget * _this_); /** * Host calls this function to make the plugin UI invisible again. * * @param _this_ the UI context */ void (*hide)(struct _LV2_External_UI_Widget * _this_); } LV2_External_UI_Widget; #define LV2_EXTERNAL_UI_RUN(ptr) (ptr)->run(ptr) #define LV2_EXTERNAL_UI_SHOW(ptr) (ptr)->show(ptr) #define LV2_EXTERNAL_UI_HIDE(ptr) (ptr)->hide(ptr) /** * On UI instantiation, host must supply LV2_EXTERNAL_UI__Host feature. * LV2_Feature::data must be pointer to LV2_External_UI_Host. */ typedef struct _LV2_External_UI_Host { /** * Callback that plugin UI will call * when UI (GUI window) is closed by user. * This callback will be called during execution of LV2_External_UI_Widget::run() * (i.e. not from background thread). * * After this callback is called, UI is defunct. Host must call * LV2UI_Descriptor::cleanup(). If host wants to make the UI visible * again UI must be reinstantiated. * * @param controller Host context associated with plugin UI, as * supplied to LV2UI_Descriptor::instantiate() */ void (*ui_closed)(LV2UI_Controller controller); /** * Optional (may be NULL) "user friendly" identifier which the UI * may display to allow a user to easily associate this particular * UI instance with the correct plugin instance as it is represented * by the host (e.g. "track 1" or "channel 4"). * * If supplied by host, the string will be referenced only during * LV2UI_Descriptor::instantiate() */ const char * plugin_human_id; } LV2_External_UI_Host; #ifdef __cplusplus } /* extern "C" */ #endif #endif /* LV2_EXTERNAL_UI_H */ qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioBuffer.cpp0000644000175000001440000000012312221533310021712 xustar000000000000000027 mtime=1380366024.715787 26 atime=1381134667.59008 30 ctime=1381134667.590080058 qtractor-0.5.11/src/qtractorAudioBuffer.cpp0000644000175000001440000011100412221533310021176 0ustar00rncbcusers00000000000000// qtractorAudioBuffer.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorAudioBuffer.h" #include "qtractorAudioPeak.h" #include "qtractorTimeStretcher.h" #include "qtractorSession.h" // Glitch, click, pop-free ramp length (in frames). #define QTRACTOR_RAMP_LENGTH 32 //---------------------------------------------------------------------- // class qtractorAudioBufferThread -- Ring-cache manager thread. // // Constructor. qtractorAudioBufferThread::qtractorAudioBufferThread ( unsigned int iSyncSize ) : QThread() { m_iSyncSize = (4 << 1); while (m_iSyncSize < iSyncSize) m_iSyncSize <<= 1; m_iSyncMask = (m_iSyncSize - 1); m_ppSyncItems = new qtractorAudioBuffer * [m_iSyncSize]; m_iSyncRead = 0; m_iSyncWrite = 0; m_bRunState = false; } // Destructor. qtractorAudioBufferThread::~qtractorAudioBufferThread (void) { delete [] m_ppSyncItems; } // Run state accessor. void qtractorAudioBufferThread::setRunState ( bool bRunState ) { QMutexLocker locker(&m_mutex); m_bRunState = bRunState; } bool qtractorAudioBufferThread::runState (void) const { return m_bRunState; } // Wake from executive wait condition (RT-safe). void qtractorAudioBufferThread::sync ( qtractorAudioBuffer *pAudioBuffer ) { if (pAudioBuffer == NULL) { unsigned int r = m_iSyncRead; unsigned int w = m_iSyncWrite; while (r != w) { m_ppSyncItems[r]->setSyncFlag(qtractorAudioBuffer::WaitSync, false); ++r &= m_iSyncMask; w = m_iSyncWrite; } m_iSyncRead = r; } else { // !pAudioBuffer->isSyncFlag(qtractorAudioBuffer::WaitSync) unsigned int n; unsigned int r = m_iSyncRead; unsigned int w = m_iSyncWrite; if (w > r) { n = ((r - w + m_iSyncSize) & m_iSyncMask) - 1; } else if (r > w) { n = (r - w) - 1; } else { n = m_iSyncSize - 1; } if (n > 0) { pAudioBuffer->setSyncFlag(qtractorAudioBuffer::WaitSync); m_ppSyncItems[w] = pAudioBuffer; m_iSyncWrite = (w + 1) & m_iSyncMask; } } if (m_mutex.tryLock()) { m_cond.wakeAll(); m_mutex.unlock(); } #ifdef CONFIG_DEBUG_0 else qDebug("qtractorAudioBufferThread[%p]::sync(): tryLock() failed.", this); #endif } // Bypass executive wait condition (non RT-safe). void qtractorAudioBufferThread::syncExport (void) { QMutexLocker locker(&m_mutex); process(); } // Thread run executive. void qtractorAudioBufferThread::run (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioBufferThread[%p]::run(): started.", this); #endif m_mutex.lock(); m_bRunState = true; while (m_bRunState) { // Do whatever we must, then wait for more... process(); // Wait for sync... m_cond.wait(&m_mutex); } m_mutex.unlock(); #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioBufferThread[%p]::run(): stopped.", this); #endif } // Thread run executive. void qtractorAudioBufferThread::process (void) { unsigned int r = m_iSyncRead; unsigned int w = m_iSyncWrite; while (r != w) { m_ppSyncItems[r]->sync(); ++r &= m_iSyncMask; w = m_iSyncWrite; } m_iSyncRead = r; } // Conditional resize check. void qtractorAudioBufferThread::checkSyncSize ( unsigned int iSyncSize ) { if (iSyncSize > (m_iSyncSize - 4)) { QMutexLocker locker(&m_mutex); unsigned int iNewSyncSize = (m_iSyncSize << 1); while (iNewSyncSize < iSyncSize) iNewSyncSize <<= 1; qtractorAudioBuffer **ppNewSyncItems = new qtractorAudioBuffer * [iNewSyncSize]; qtractorAudioBuffer **ppOldSyncItems = m_ppSyncItems; ::memcpy(ppNewSyncItems, ppOldSyncItems, m_iSyncSize * sizeof(qtractorAudioBuffer *)); m_iSyncSize = iNewSyncSize; m_iSyncMask = (iNewSyncSize - 1); m_ppSyncItems = ppNewSyncItems; delete [] ppOldSyncItems; } } //---------------------------------------------------------------------- // class qtractorAudioBuffer -- Ring buffer/cache method implementation. // // Constructors. qtractorAudioBuffer::qtractorAudioBuffer ( qtractorAudioBufferThread *pSyncThread, unsigned short iChannels, unsigned int iSampleRate ) { m_pSyncThread = pSyncThread; m_iChannels = iChannels; m_iSampleRate = iSampleRate; m_pFile = NULL; m_pRingBuffer = NULL; m_iThreshold = 0; m_iBufferSize = 0; m_syncFlags = 0; m_iReadOffset = 0; m_iWriteOffset = 0; m_iFileLength = 0; m_bIntegral = false; m_iOffset = 0; m_iLength = 0; m_iLoopStart = 0; m_iLoopEnd = 0; m_iSeekOffset = 0; ATOMIC_SET(&m_seekPending, 0); m_ppFrames = NULL; m_bTimeStretch = false; m_fTimeStretch = 1.0f; m_bPitchShift = false; m_fPitchShift = 1.0f; m_pTimeStretcher = NULL; m_fNextGain = 1.0f; m_iRampGain = 1; #ifdef CONFIG_LIBSAMPLERATE m_bResample = false; m_fResampleRatio = 1.0f; m_iInputPending = 0; m_ppInBuffer = NULL; m_ppOutBuffer = NULL; m_ppSrcState = NULL; #endif m_pPeak = NULL; } // Default destructor. qtractorAudioBuffer::~qtractorAudioBuffer (void) { close(); } // Return the internal file descriptor. qtractorAudioFile *qtractorAudioBuffer::file (void) const { return m_pFile; } // Buffer channels. unsigned short qtractorAudioBuffer::channels (void) const { return (m_pFile ? m_pFile->channels() : 0); } // Estimated file size in frames. unsigned long qtractorAudioBuffer::frames (void) const { return (m_pFile ? framesIn(m_pFile->frames()) : 0); } // Working sample rate. unsigned int qtractorAudioBuffer::sampleRate (void) const { return m_iSampleRate; } // Operational properties. unsigned int qtractorAudioBuffer::bufferSize (void) const { return m_iBufferSize; } // Working resample ratio. float qtractorAudioBuffer::resampleRatio (void) const { #ifdef CONFIG_LIBSAMPLERATE return m_fResampleRatio; #else return 1.0f; #endif } // Operational buffer initializer/terminator. bool qtractorAudioBuffer::open ( const QString& sFilename, int iMode ) { // Make sure everything starts closed. close(); // Get proper file type class... m_pFile = qtractorAudioFileFactory::createAudioFile( sFilename, m_iChannels, m_iSampleRate); if (m_pFile == NULL) return false; // Go open it... if (!m_pFile->open(sFilename, iMode)) { delete m_pFile; m_pFile = NULL; return false; } // Check samplerate and how many channels there really are. unsigned short iChannels = m_pFile->channels(); // Just one more sanity check... if (iChannels < 1 || m_pFile->sampleRate() < 1) { m_pFile->close(); delete m_pFile; m_pFile = NULL; return false; } #ifdef CONFIG_LIBSAMPLERATE // Compute sample rate converter stuff. m_iInputPending = 0; m_fResampleRatio = 1.0f; m_bResample = (m_iSampleRate != m_pFile->sampleRate()); if (m_bResample) { m_fResampleRatio = float(m_iSampleRate) / float(m_pFile->sampleRate()); m_ppInBuffer = new float * [iChannels]; m_ppOutBuffer = new float * [iChannels]; m_ppSrcState = new SRC_STATE * [iChannels]; } #endif // FIXME: default logical length gets it total... if (m_iLength == 0) { m_iLength = frames(); if (m_iOffset < m_iLength) m_iLength -= m_iOffset; else m_iOffset = 0; } // Allocate ring-buffer now. unsigned int iBufferSize = m_iLength; if (iBufferSize == 0) iBufferSize = (m_iSampleRate >> 1); else if (iBufferSize > (m_iSampleRate << 2)) iBufferSize = (m_iSampleRate << 2); m_pRingBuffer = new qtractorRingBuffer (iChannels, iBufferSize); m_iThreshold = (m_pRingBuffer->bufferSize() >> 2); m_iBufferSize = (m_iThreshold >> 2); #ifdef CONFIG_LIBSAMPLERATE if (m_bResample && m_fResampleRatio < 1.0f) { iBufferSize = (unsigned int) framesOut(m_iBufferSize); while (m_iBufferSize < iBufferSize) m_iBufferSize <<= 1; } #endif // Allocate actual buffer stuff... m_ppFrames = new float * [iChannels]; for (unsigned short i = 0; i < iChannels; ++i) m_ppFrames[i] = new float [m_iBufferSize]; // Allocate time-stretch engine whether needed... if (m_bTimeStretch || m_bPitchShift) { unsigned int iFlags = qtractorTimeStretcher::None; if (g_bWsolaTimeStretch) iFlags |= qtractorTimeStretcher::WsolaTimeStretch; if (g_bWsolaQuickSeek) iFlags |= qtractorTimeStretcher::WsolaQuickSeek; m_pTimeStretcher = new qtractorTimeStretcher(iChannels, m_iSampleRate, m_fTimeStretch, m_fPitchShift, iFlags, m_iBufferSize); } #ifdef CONFIG_LIBSAMPLERATE // Sample rate converter stuff, whether needed... if (m_bResample) { int err = 0; for (unsigned short i = 0; i < iChannels; ++i) { m_ppInBuffer[i] = m_ppFrames[i]; m_ppOutBuffer[i] = new float [m_iBufferSize]; m_ppSrcState[i] = src_new(g_iResampleType, 1, &err); } } #endif // Consider it done when recording... if (m_pFile->mode() & qtractorAudioFile::Write) setSyncFlag(InitSync); // Make it sync-managed... if (m_pSyncThread) m_pSyncThread->sync(this); return true; } // Operational buffer terminator. void qtractorAudioBuffer::close (void) { if (m_pFile == NULL) return; // Wait for regular file close... if (m_pSyncThread) { setSyncFlag(CloseSync); m_pSyncThread->sync(this); do QThread::yieldCurrentThread(); // qtractorSession::stabilize(); while (isSyncFlag(CloseSync)); } // Take careof remains, if applicable... if (m_pFile->mode() & qtractorAudioFile::Write) { // Close on-the-fly peak file, if applicable... if (m_pPeak) { m_pPeak->closeWrite(); m_pPeak = NULL; } } // Deallocate any buffer stuff... if (m_pTimeStretcher) { delete m_pTimeStretcher; m_pTimeStretcher = NULL; } // Release internal I/O buffers. if (m_pRingBuffer) { deleteIOBuffers(); delete m_pRingBuffer; m_pRingBuffer = NULL; } // Finally delete what we still own. if (m_pFile) { delete m_pFile; m_pFile = NULL; } // Reset all relevant state variables. m_iThreshold = 0; m_iBufferSize = 0; m_syncFlags = 0; m_iReadOffset = 0; m_iWriteOffset = 0; m_iFileLength = 0; m_bIntegral = false; m_iSeekOffset = 0; ATOMIC_SET(&m_seekPending, 0); m_fNextGain = 1.0f; m_iRampGain = 1; m_pPeak = NULL; } // Buffer data read. int qtractorAudioBuffer::read ( float **ppFrames, unsigned int iFrames, unsigned int iOffset ) { if (m_pRingBuffer == NULL) return -1; int nread; unsigned long ro = m_iReadOffset; unsigned long ls = m_iLoopStart; unsigned long le = m_iLoopEnd; // Are we off decoded file limits (EoS)? if (ro >= m_iFileLength) { nread = iFrames; if (ls < le) { if (m_bIntegral) { unsigned int ri = m_pRingBuffer->readIndex(); while (ri < le && ri + nread >= le) { nread -= le - ri; ro = m_iOffset + ls; m_pRingBuffer->setReadIndex(ls); } } else { ls += m_iOffset; le += m_iOffset; while (ro < le && ro + nread >= le) { nread -= le - ro; ro = ls; } } } m_iReadOffset = (ro + nread); // Force out-of-sync... setSyncFlag(ReadSync, false); return nread; } // Are we in the middle of the loop range ? if (ls < le) { if (m_bIntegral) { unsigned int ri = m_pRingBuffer->readIndex(); while (ri < le && ri + iFrames >= le) { nread = m_pRingBuffer->read(ppFrames, le - ri, iOffset); iFrames -= nread; iOffset += nread; ro = m_iOffset + ls; m_pRingBuffer->setReadIndex(ls); } } else { ls += m_iOffset; le += m_iOffset; while (ro < le && ro + iFrames >= le) { nread = m_pRingBuffer->read(ppFrames, le - ro, iOffset); iFrames -= nread; iOffset += nread; ro = ls; } } } // Move the (remaining) data around... nread = m_pRingBuffer->read(ppFrames, iFrames, iOffset); m_iReadOffset = (ro + nread); if (m_iReadOffset >= m_iOffset + m_iLength) { // Force out-of-sync... setSyncFlag(ReadSync, false); } // Time to sync()? if (!m_bIntegral && m_pSyncThread && m_pRingBuffer->writable() > m_iThreshold) m_pSyncThread->sync(this); return nread; } // Buffer data write. int qtractorAudioBuffer::write ( float **ppFrames, unsigned int iFrames, unsigned short iChannels, unsigned int iOffset ) { if (m_pRingBuffer == NULL) return -1; unsigned short iBuffers = m_pRingBuffer->channels(); if (iChannels < 1) iChannels = iBuffers; unsigned int nwrite = iFrames; if (iChannels == iBuffers) { // Direct write... nwrite = m_pRingBuffer->write(ppFrames, nwrite, iOffset); } else { // Multiplexed write... unsigned int ws = m_pRingBuffer->writable(); if (nwrite > ws) nwrite = ws; if (nwrite > 0) { unsigned int w = m_pRingBuffer->writeIndex(); unsigned int n, n1, n2; unsigned int bs = m_pRingBuffer->bufferSize(); if (w + nwrite > bs) { n1 = (bs - w); n2 = (w + nwrite) & m_pRingBuffer->bufferMask(); } else { n1 = nwrite; n2 = 0; } unsigned short i, j; float **ppBuffer = m_pRingBuffer->buffer(); if (iChannels > iBuffers) { for (i = 0, j = 0; i < iBuffers; ++i, ++j) { for (n = 0; n < n1; ++n) ppBuffer[j][n + w] = ppFrames[i][n] + iOffset; for (n = 0; n < n2; ++n) ppBuffer[j][n] = ppFrames[i][n + n1] + iOffset; } for (j = 0; i < iChannels; ++i) { for (n = 0; n < n1; ++n) ppBuffer[j][n + w] += ppFrames[i][n] + iOffset; for (n = 0; n < n2; ++n) ppBuffer[j][n] += ppFrames[i][n + n1] + iOffset; if (++j >= iBuffers) j = 0; } } else { // (iChannels < iBuffers) i = 0; for (j = 0; j < iBuffers; ++j) { for (n = 0; n < n1; ++n) ppBuffer[j][n + w] = ppFrames[i][n] + iOffset; for (n = 0; n < n2; ++n) ppBuffer[j][n] = ppFrames[i][n + n1] + iOffset; if (++i >= iChannels) i = 0; } } m_pRingBuffer->setWriteIndex(w + nwrite); } } // Make it statiscally correct... m_iWriteOffset += nwrite; // Time to sync()? if (m_pSyncThread && m_pRingBuffer->readable() > m_iThreshold) m_pSyncThread->sync(this); return nwrite; } // Special kind of super-read/channel-mix. int qtractorAudioBuffer::readMix ( float **ppFrames, unsigned int iFrames, unsigned short iChannels, unsigned int iOffset, float fGain ) { if (m_pRingBuffer == NULL) return -1; int nread; unsigned long ro = m_iReadOffset; unsigned long ls = m_iLoopStart; unsigned long le = m_iLoopEnd; // Are we off decoded file limits (EoS)? if (ro >= m_iFileLength) { nread = iFrames; if (ls < le) { if (m_bIntegral) { unsigned int ri = m_pRingBuffer->readIndex(); while (ri < le && ri + nread >= le) { nread -= le - ri; ro = m_iOffset + ls; m_pRingBuffer->setReadIndex(ls); } } else { ls += m_iOffset; le += m_iOffset; while (ro < le && ro + nread >= le) { nread -= le - ro; ro = ls; } } } m_iReadOffset = (ro + nread); // Force out-of-sync... setSyncFlag(ReadSync, false); return nread; } // Take care of end-of-stream... if (ro + iFrames >= m_iFileLength) fGain = 0.0f; // Are we in the middle of the loop range ? if (ls < le) { if (m_bIntegral) { unsigned int ri = m_pRingBuffer->readIndex(); while (ri < le && ri + iFrames >= le) { m_iRampGain = -1; nread = readMixFrames(ppFrames, le - ri, iChannels, iOffset, fGain); iFrames -= nread; iOffset += nread; ro = m_iOffset + ls; m_pRingBuffer->setReadIndex(ls); } } else { ls += m_iOffset; le += m_iOffset; while (le >= ro && ro + iFrames >= le) { m_iRampGain = -1; nread = readMixFrames(ppFrames, le - ro, iChannels, iOffset, fGain); iFrames -= nread; iOffset += nread; ro = ls; } } } // Mix the (remaining) data around... nread = readMixFrames(ppFrames, iFrames, iChannels, iOffset, fGain); m_iReadOffset = (ro + nread); if (m_iReadOffset >= m_iOffset + m_iLength) { // Force out-of-sync... setSyncFlag(ReadSync, false); } // Time to sync()? if (!m_bIntegral && m_pSyncThread && m_pRingBuffer->writable() > m_iThreshold) m_pSyncThread->sync(this); return nread; } // Buffer data seek. bool qtractorAudioBuffer::seek ( unsigned long iFrame ) { if (m_pRingBuffer == NULL) return false; // Seek is only valid on read-only mode. if (m_pFile == NULL) return false; if (m_pFile->mode() & qtractorAudioFile::Write) return false; // Must not break while on initial sync... if (!isSyncFlag(InitSync)) return false; // Reset running gain... m_fNextGain = 1.0f; m_iRampGain = 1; // Are we off-limits? if (iFrame >= m_iLength) return false; // Force (premature) out-of-sync... setSyncFlag(ReadSync, false); setSyncFlag(WaitSync, false); // Special case on integral cached files... if (m_bIntegral) { m_pRingBuffer->setReadIndex(iFrame); // m_iWriteOffset = m_iOffset + iFrame; m_iReadOffset = m_iOffset + iFrame; // Maybe (always) in-sync... //setSyncFlag(ReadSync); return true; } // Adjust to logical offset... iFrame += m_iOffset; // Check if target is already cached... unsigned int rs = m_pRingBuffer->readable(); unsigned int ri = m_pRingBuffer->readIndex(); unsigned long ro = m_iReadOffset; if (iFrame >= ro && iFrame < ro + rs) { m_pRingBuffer->setReadIndex(ri + iFrame - ro); // m_iWriteOffset += iFrame - ro; m_iReadOffset += iFrame - ro; // Maybe (late) in-sync... //setSyncFlag(ReadSync); return true; } #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioBuffer[%p]::seek(%lu) pending(%d, %lu) wo=%lu ro=%lu", this, iFrame, ATOMIC_GET(&m_seekPending), m_iSeekOffset, m_iWriteOffset, m_iReadOffset); #endif // Bad luck, gotta go straight down to disk... // if (!seekSync(iFrame)) // return false; // Force (late) out-of-sync... m_iReadOffset = m_iOffset + m_iLength + 1; // An unlikely offset! m_iSeekOffset = iFrame; ATOMIC_INC(&m_seekPending); // readSync(); if (m_pSyncThread) m_pSyncThread->sync(this); return true; } // Sync thread state flags accessors (ought to be inline?). void qtractorAudioBuffer::setSyncFlag ( SyncFlag flag, bool bOn ) { if (bOn) m_syncFlags |= (unsigned char) (flag); else m_syncFlags &= ~(unsigned char) (flag); } bool qtractorAudioBuffer::isSyncFlag ( SyncFlag flag ) const { return (m_syncFlags & (unsigned char) (flag)); } // Initial thread-sync executive (if file is on read mode, // check whether it can be cache-loaded integrally). void qtractorAudioBuffer::initSync (void) { if (m_pRingBuffer == NULL) return; // Initialization is only valid on read-only mode. if (m_pFile == NULL) return; if (m_pFile->mode() & qtractorAudioFile::Write) return; #if 0 if (isSyncFlag(CloseSync)) return; #endif // Reset all relevant state variables. setSyncFlag(ReadSync, false); m_iReadOffset = 0; m_iWriteOffset = 0; m_iFileLength = 0; m_bIntegral = false; m_iSeekOffset = 0; ATOMIC_SET(&m_seekPending, 0); // Reset running gain... m_fNextGain = 1.0f; m_iRampGain = 1; // Set to initial offset... m_iSeekOffset = m_iOffset; ATOMIC_INC(&m_seekPending); // Initial buffer read in... readSync(); // We're mostly done with initialization... // m_bInitSync = true; setSyncFlag(InitSync); // Check if fitted integrally... if (m_iFileLength < m_iOffset + m_pRingBuffer->bufferSize() - 1) { m_bIntegral = true; deleteIOBuffers(); } else // Re-sync if loop falls short in initial area... if (m_iLoopStart < m_iLoopEnd && m_iWriteOffset >= m_iOffset + m_iLoopEnd) { // Will do it again, but now we're // sure we aren't fit integral... m_iSeekOffset = m_iOffset; ATOMIC_INC(&m_seekPending); // Initial buffer re-read in... readSync(); } // Make sure we're not closing anymore, // of course, don't be ridiculous... setSyncFlag(CloseSync, false); } // Base-mode sync executive. void qtractorAudioBuffer::sync (void) { if (m_pFile == NULL) return; if (!isSyncFlag(WaitSync)) return; if (!isSyncFlag(InitSync)) { initSync(); setSyncFlag(WaitSync, false); } else { setSyncFlag(WaitSync, false); const int mode = m_pFile->mode(); if (mode & qtractorAudioFile::Read) readSync(); else if (mode & qtractorAudioFile::Write) writeSync(); if (isSyncFlag(CloseSync)) { m_pFile->close(); setSyncFlag(CloseSync, false); } } } // Audio frame process synchronization predicate method. bool qtractorAudioBuffer::inSync ( unsigned long iFrameStart, unsigned long iFrameEnd ) { if (!isSyncFlag(InitSync)) return false; if (isSyncFlag(ReadSync)) return true; #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioBuffer[%p]::inSync(%lu, %lu) (%ld)", this, iFrameStart, iFrameEnd, (long) m_iReadOffset - (iFrameStart + m_iOffset)); #endif if (m_iReadOffset == iFrameStart + m_iOffset) { setSyncFlag(ReadSync); return true; } seek(iFrameEnd); return false; } // Export-mode sync executive. void qtractorAudioBuffer::syncExport (void) { if (m_pSyncThread) m_pSyncThread->syncExport(); } // Read-mode sync executive. void qtractorAudioBuffer::readSync (void) { if (m_pRingBuffer == NULL) return; if (isSyncFlag(CloseSync)) return; // Check whether we have some hard-seek pending... if (ATOMIC_TAZ(&m_seekPending)) { // Do it... if (!seekSync(m_iSeekOffset)) return; // Refill the whole buffer.... m_pRingBuffer->reset(); // Override with new intended offset... m_iWriteOffset = m_iSeekOffset; m_iReadOffset = m_iSeekOffset; } unsigned int ws = m_pRingBuffer->writable(); if (ws == 0) return; unsigned int nahead = ws; unsigned int ntotal = 0; while (nahead > 0 && !ATOMIC_GET(&m_seekPending)) { // Take looping into account, if any... unsigned long ls = m_iOffset + m_iLoopStart; unsigned long le = m_iOffset + m_iLoopEnd; bool bLooping = (ls < le && m_iWriteOffset < le && isSyncFlag(InitSync)); // Adjust request for sane size... if (nahead > m_iBufferSize) nahead = m_iBufferSize; // Check whether behind the loop-end point... if (bLooping && m_iWriteOffset + nahead > le) nahead = le - m_iWriteOffset; // Check whether behind the logical end-of-file... if (m_iWriteOffset + nahead > m_iOffset + m_iLength) { if (m_iWriteOffset < m_iOffset + m_iLength) { nahead = (m_iOffset + m_iLength) - m_iWriteOffset; } else { nahead = 0; } } // Read the block in... // (assume end-of-file) int nread = -1; if (nahead > 0) nread = readBuffer(nahead); if (nread > 0) { // Another block was read in... m_iWriteOffset += nread; if (m_iFileLength < m_iWriteOffset) m_iFileLength = m_iWriteOffset; if (bLooping && m_iWriteOffset >= le && seekSync(ls)) m_iWriteOffset = ls; ntotal += nread; nahead = (ws > ntotal ? ws - ntotal : 0); } else if (nread < 0) { // Think of end-of-file... nahead = 0; // But we can re-cache, if not an integral fit... if (m_iFileLength >= m_iOffset + m_pRingBuffer->bufferSize() - 1) { unsigned long offset = (bLooping ? ls : m_iOffset); if (seekSync(offset)) m_iWriteOffset = offset; } } } } // Write-mode sync executive. void qtractorAudioBuffer::writeSync (void) { if (m_pRingBuffer == NULL) return; unsigned int rs = m_pRingBuffer->readable(); if (rs == 0) return; unsigned int nwrite; unsigned int nbehind = rs; unsigned int ntotal = 0; while (nbehind > 0) { // Adjust request for sane size... if (nbehind > m_iBufferSize) nbehind = m_iBufferSize; // Read the block out... nwrite = writeBuffer(nbehind); if (nwrite > 0) { // Another block was written out... m_iReadOffset += nwrite; if (m_iFileLength < m_iReadOffset) m_iFileLength = m_iReadOffset; ntotal += nwrite; } // Think of end-of-turn... if (nwrite < nbehind) { nbehind = 0; } else { nbehind = rs - ntotal; } } } // Internal-seek sync executive. bool qtractorAudioBuffer::seekSync ( unsigned long iFrame ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorAudioBuffer[%p]::seekSync(%lu) pending(%d, %lu) wo=%lu ro=%lu", this, iFrame, ATOMIC_GET(&m_seekPending), m_iSeekOffset, m_iWriteOffset, m_iReadOffset); #endif #ifdef CONFIG_LIBSAMPLERATE if (m_bResample) { m_iInputPending = 0; for (unsigned short i = 0; i < m_pRingBuffer->channels(); ++i) { if (m_ppSrcState && m_ppSrcState[i]) src_reset(m_ppSrcState[i]); m_ppInBuffer[i] = m_ppFrames[i]; } } #endif if (m_pTimeStretcher) m_pTimeStretcher->reset(); return m_pFile->seek(framesOut(iFrame)); } // Last-mile frame buffer-helper processor. int qtractorAudioBuffer::writeFrames ( float **ppFrames, unsigned int iFrames ) { // Time-stretch processing... if (m_pTimeStretcher) { int nread = 0; m_pTimeStretcher->process(ppFrames, iFrames); unsigned int nwrite = m_pRingBuffer->writable(); unsigned int nahead = m_pTimeStretcher->available(); while (nahead > 0) { if (nahead > m_iBufferSize) nahead = m_iBufferSize; if (nahead > nwrite) nahead = nwrite; if (nahead > 0) nahead = m_pTimeStretcher->retrieve(ppFrames, nahead); if (nahead > 0) { nread += m_pRingBuffer->write(ppFrames, nahead); nwrite = m_pRingBuffer->writable(); nahead = m_pTimeStretcher->available(); } } // Done with time-stretching... return nread; } // Normal straight processing... return m_pRingBuffer->write(ppFrames, iFrames); } // Flush buffer-helper processor. int qtractorAudioBuffer::flushFrames ( unsigned int iFrames ) { int nread = 0; // Flush time-stretch processing... if (m_pTimeStretcher) { m_pTimeStretcher->flush(); unsigned int nwrite = m_pRingBuffer->writable(); unsigned int nahead = m_pTimeStretcher->available(); while (nahead > 0) { if (nahead > m_iBufferSize) nahead = m_iBufferSize; if (nahead > nwrite) nahead = nwrite; if (nahead > 0) nahead = m_pTimeStretcher->retrieve(m_ppFrames, nahead); if (nahead > 0) { nread += m_pRingBuffer->write(m_ppFrames, nahead); nwrite = m_pRingBuffer->writable(); nahead = m_pTimeStretcher->available(); } } } // Zero-flush till known end-of-clip (avoid sure drifting)... if ((nread < 1) && (m_iWriteOffset + iFrames > m_iOffset + m_iLength)) { unsigned int nahead = (m_iOffset + m_iLength) - m_iWriteOffset; for (unsigned int i = 0; i < m_pRingBuffer->channels(); ++i) ::memset(m_ppFrames[i], 0, nahead * sizeof(float)); nread += m_pRingBuffer->write(m_ppFrames, nahead); } return (nread > 0 ? nread : -1); } // I/O buffer read process; return -1 on end-of-file. int qtractorAudioBuffer::readBuffer ( unsigned int iFrames ) { #ifdef CONFIG_DEBUG_0 qDebug("+readBuffer(%u)", iFrames); #endif int nread = 0; #ifdef CONFIG_LIBSAMPLERATE if (m_bResample) { if (iFrames > m_iInputPending) nread = m_pFile->read(m_ppInBuffer, iFrames - m_iInputPending); nread += m_iInputPending; int ngen = 0; SRC_DATA src_data; for (unsigned short i = 0; i < m_pRingBuffer->channels(); ++i) { // Fill all resampler parameter data... src_data.data_in = m_ppFrames[i]; src_data.data_out = m_ppOutBuffer[i]; src_data.input_frames = nread; src_data.output_frames = iFrames; src_data.end_of_input = (nread < 1); src_data.src_ratio = m_fResampleRatio; src_data.input_frames_used = 0; src_data.output_frames_gen = 0; // Do the resample work... if (src_process(m_ppSrcState[i], &src_data) == 0) { if (i == 0) { m_iInputPending = nread - src_data.input_frames_used; ngen = src_data.output_frames_gen; } if (m_iInputPending > 0 && src_data.input_frames_used > 0) { ::memcpy(m_ppFrames[i], m_ppFrames[i] + src_data.input_frames_used, m_iInputPending * sizeof(float)); } m_ppInBuffer[i] = m_ppFrames[i] + m_iInputPending; } } if (ngen > 0) nread = writeFrames(m_ppOutBuffer, ngen); else if (nread < 1) nread = flushFrames(iFrames); // Maybe EoF! } else { #endif // CONFIG_LIBSAMPLERATE nread = m_pFile->read(m_ppFrames, iFrames); if (nread > 0) nread = writeFrames(m_ppFrames, nread); else nread = flushFrames(iFrames); // Maybe EoF! #ifdef CONFIG_LIBSAMPLERATE } #endif // CONFIG_LIBSAMPLERATE #ifdef CONFIG_DEBUG_0 qDebug("-readBuffer(%u) --> nread=%d", iFrames, nread); #endif return nread; } // I/O buffer write process. int qtractorAudioBuffer::writeBuffer ( unsigned int iFrames ) { int nwrite = m_pRingBuffer->read(m_ppFrames, iFrames, 0); if (nwrite > 0) { nwrite = m_pFile->write(m_ppFrames, nwrite); if (m_pPeak) m_pPeak->write(m_ppFrames, nwrite); } return nwrite; } // Special kind of super-read/channel-mix buffer helper. int qtractorAudioBuffer::readMixFrames ( float **ppFrames, unsigned int iFrames, unsigned short iChannels, unsigned int iOffset, float fGain ) { if (iFrames == 0) return 0; unsigned int rs = m_pRingBuffer->readable(); if (rs == 0) return 0; // Reset running gain... float fPrevGain = m_fNextGain; m_fNextGain = fGain; // HACK: Case of clip ramp out-set... if (m_fNextGain < 1e-9f && fPrevGain > (1.0f - 1e-9f)) { // Final micro fade-out... // (anti-glitch out-set ramp) m_fNextGain = 1.0f; m_iRampGain = -1; } if (m_iRampGain) fPrevGain = m_fNextGain; float fGainStep = (m_fNextGain - fPrevGain) / float(iFrames); if (iFrames > rs) iFrames = rs; unsigned int r = m_pRingBuffer->readIndex(); unsigned int n, n1, n2; unsigned int bs = m_pRingBuffer->bufferSize(); if (r + iFrames > bs) { n1 = (bs - r); n2 = (r + iFrames) & m_pRingBuffer->bufferMask(); } else { n1 = iFrames; n2 = 0; } float fGainIter; unsigned short i, j; unsigned short iBuffers = m_pRingBuffer->channels(); float **ppBuffer = m_pRingBuffer->buffer(); float *pFrames, *pBuffer; if (iChannels == iBuffers) { for (i = 0; i < iBuffers; ++i) { pFrames = ppFrames[i] + iOffset; pBuffer = ppBuffer[i]; fGainIter = fPrevGain; for (n = 0; n < n1; ++n, fGainIter += fGainStep) *pFrames++ += fGainIter * pBuffer[n + r]; for (n = 0; n < n2; ++n, fGainIter += fGainStep) *pFrames++ += fGainIter * pBuffer[n]; } } else if (iChannels > iBuffers) { j = 0; for (i = 0; i < iChannels; ++i) { pFrames = ppFrames[i] + iOffset; pBuffer = ppBuffer[j]; fGainIter = fPrevGain; for (n = 0; n < n1; ++n, fGainIter += fGainStep) *pFrames++ += fGainIter * pBuffer[n + r]; for (n = 0; n < n2; ++n, fGainIter += fGainStep) *pFrames++ += fGainIter * pBuffer[n]; if (++j >= iBuffers) j = 0; } } else { // (iChannels < iBuffers) i = 0; for (j = 0; j < iBuffers; ++j) { pFrames = ppFrames[i] + iOffset; pBuffer = ppBuffer[j]; fGainIter = fPrevGain; for (n = 0; n < n1; ++n, fGainIter += fGainStep) *pFrames++ += fGainIter * pBuffer[n + r]; for (n = 0; n < n2; ++n, fGainIter += fGainStep) *pFrames++ += fGainIter * pBuffer[n]; if (++i >= iChannels) i = 0; } } m_pRingBuffer->setReadIndex(r + iFrames); // HACK: Case of clip ramp outset in this run... if (m_iRampGain) { unsigned int iLength = QTRACTOR_RAMP_LENGTH; if (iLength > iFrames) iLength = iFrames; iOffset += (m_iRampGain < 0 ? iFrames - iLength : 0); fGainStep = float(m_iRampGain) / float(iLength); for (i = 0; i < iChannels; ++i) { pFrames = ppFrames[i] + iOffset; fGainIter = (m_iRampGain < 0 ? 1.0f : 0.0f); for (n = 0; n < iLength; ++n, fGainIter += fGainStep) *pFrames++ *= fGainIter; } m_iRampGain = (m_iRampGain < 0 ? 1 : 0); } return iFrames; } // I/O buffer release. void qtractorAudioBuffer::deleteIOBuffers (void) { #ifdef CONFIG_LIBSAMPLERATE // Release internal and resampler buffers. for (unsigned short i = 0; i < m_pRingBuffer->channels(); ++i) { if (m_ppSrcState && m_ppSrcState[i]) m_ppSrcState[i] = src_delete(m_ppSrcState[i]); if (m_ppOutBuffer && m_ppOutBuffer[i]) { delete [] m_ppOutBuffer[i]; m_ppOutBuffer[i] = NULL; } } if (m_ppSrcState) { delete [] m_ppSrcState; m_ppSrcState = NULL; } if (m_ppOutBuffer) { delete [] m_ppOutBuffer; m_ppOutBuffer = NULL; } if (m_ppInBuffer) { delete [] m_ppInBuffer; m_ppInBuffer = NULL; } m_iInputPending = 0; #endif if (m_ppFrames) { for (unsigned short i = 0; i < m_pRingBuffer->channels(); ++i) { if (m_ppFrames[i]) { delete [] m_ppFrames[i]; m_ppFrames[i] = NULL; } } delete [] m_ppFrames; m_ppFrames = NULL; } } // Reset this buffers state. void qtractorAudioBuffer::reset ( bool bLooping ) { if (m_pRingBuffer == NULL) return; unsigned long iFrame = 0; // If looping, we'll reset to loop-start point, // otherwise it's a buffer full-reset... if (bLooping && m_iLoopStart < m_iLoopEnd) { iFrame = m_iLoopStart; // Make sure we're not already there... // (force out-of-sync with an unlikely offset!) if (!m_bIntegral) m_iReadOffset = m_iOffset + m_iLength + 1; } seek(iFrame); } // Frame position converters. unsigned long qtractorAudioBuffer::framesIn ( unsigned long iFrames ) const { #ifdef CONFIG_LIBSAMPLERATE if (m_bResample) iFrames = (unsigned long) (float(iFrames) * m_fResampleRatio); #endif if (m_bTimeStretch) iFrames = (unsigned long) (float(iFrames) * m_fTimeStretch); return iFrames; } unsigned long qtractorAudioBuffer::framesOut ( unsigned long iFrames ) const { #ifdef CONFIG_LIBSAMPLERATE if (m_bResample) iFrames = (unsigned long) (float(iFrames) / m_fResampleRatio); #endif if (m_bTimeStretch) iFrames = (unsigned long) (float(iFrames) / m_fTimeStretch); return iFrames; } // Logical clip-offset (in frames from beginning-of-file). void qtractorAudioBuffer::setOffset ( unsigned long iOffset ) { m_iOffset = iOffset; } unsigned long qtractorAudioBuffer::offset() const { return m_iOffset; } // Logical clip-length (in frames from clip-start/offset). void qtractorAudioBuffer::setLength ( unsigned long iLength ) { m_iLength = iLength; } unsigned long qtractorAudioBuffer::length (void) const { return m_iLength; } // Current (last known) file length accessor. unsigned long qtractorAudioBuffer::fileLength (void) const { return m_iFileLength; } // Loop points accessors. void qtractorAudioBuffer::setLoop ( unsigned long iLoopStart, unsigned long iLoopEnd ) { // Buffer-looping magic check! if (iLoopStart < iLoopEnd) { m_iLoopStart = iLoopStart; m_iLoopEnd = iLoopEnd; } else { m_iLoopStart = 0; m_iLoopEnd = 0; } // Force out-of-sync... setSyncFlag(ReadSync, false); m_iReadOffset = m_iOffset + m_iLength + 1; // An unlikely offset! // seek(m_iReadOffset - m_iOffset); } unsigned long qtractorAudioBuffer::loopStart (void) const { return m_iLoopStart; } unsigned long qtractorAudioBuffer::loopEnd (void) const { return m_iLoopEnd; } // Time-stretch factor. void qtractorAudioBuffer::setTimeStretch ( float fTimeStretch ) { m_bTimeStretch = (fTimeStretch > 0.1f && fTimeStretch < 1.0f - 1e-3f) || (fTimeStretch > 1.0f + 1e-3f && fTimeStretch < 4.0f); m_fTimeStretch = (m_bTimeStretch ? fTimeStretch : 1.0f); } float qtractorAudioBuffer::timeStretch (void) const { return m_fTimeStretch; } bool qtractorAudioBuffer::isTimeStretch (void) const { return m_bTimeStretch; } // Pitch-shift factor. void qtractorAudioBuffer::setPitchShift ( float fPitchShift ) { m_bPitchShift = (fPitchShift > 0.1f && fPitchShift < 1.0f - 1e-3f) || (fPitchShift > 1.0f + 1e-3f && fPitchShift < 4.0f); m_fPitchShift = (m_bPitchShift ? fPitchShift : 1.0f); } float qtractorAudioBuffer::pitchShift (void) const { return m_fPitchShift; } bool qtractorAudioBuffer::isPitchShift (void) const { return m_bPitchShift; } // Internal peak descriptor accessors. void qtractorAudioBuffer::setPeak ( qtractorAudioPeak *pPeak ) { m_pPeak = pPeak; // Reset for building the peak file on-the-fly... if (!m_pPeak->openWrite(m_iChannels, m_iSampleRate)) m_pPeak = NULL; } qtractorAudioPeak *qtractorAudioBuffer::peak (void) const { return m_pPeak; } // Sample-rate converter type (global option). int qtractorAudioBuffer::g_iResampleType = 2; // SRC_SINC_FASTEST; void qtractorAudioBuffer::setResampleType ( int iResampleType ) { g_iResampleType = iResampleType; } int qtractorAudioBuffer::resampleType (void) { return g_iResampleType; } // WSOLA time-stretch modes (global options). bool qtractorAudioBuffer::g_bWsolaTimeStretch = true; bool qtractorAudioBuffer::g_bWsolaQuickSeek = false; void qtractorAudioBuffer::setWsolaTimeStretch ( bool bWsolaTimeStretch ) { g_bWsolaTimeStretch = bWsolaTimeStretch; } bool qtractorAudioBuffer::isWsolaTimeStretch (void) { return g_bWsolaTimeStretch; } void qtractorAudioBuffer::setWsolaQuickSeek ( bool bWsolaQuickSeek ) { g_bWsolaQuickSeek = bWsolaQuickSeek; } bool qtractorAudioBuffer::isWsolaQuickSeek (void) { return g_bWsolaQuickSeek; } // end of qtractorAudioBuffer.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorSessionForm.ui0000644000175000001440000000012211710266757021644 xustar000000000000000026 mtime=1327590895.47101 26 atime=1381134666.35808 30 ctime=1381134666.358080039 qtractor-0.5.11/src/qtractorSessionForm.ui0000644000175000001440000003640511710266757021144 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorSessionForm 0 0 469 311 Qt::StrongFocus Session - Qtractor :/images/qtractor.png 0 Session &Name: SessionNameLineEdit 320 0 Session name &Directory: SessionDirComboBox 0 320 0 Session directory true 22 22 24 24 :/images/fileOpen.png Qt::TabFocus Browse for session directory ... &Description: DescriptionTextEdit 32767 72 Session description Properties Time Sample &Rate: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter SampleRateComboBox Sample rate (Hz) true 44100 48000 96000 192000 &Tempo: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter TempoSpinBox 100 0 Tempo (BPM) / Signature T&icks/Beat: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter TicksPerBeatSpinBox Resolution (ticks/beat; tpqn) 24 3840 24 960 Qt::Vertical 20 40 View &Snap/Beat: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter SnapPerBeatComboBox Snap/beat false &Pixels/Beat: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter PixelsPerBeatSpinBox Pixels/beat 4 240 4 32 &Horizontal Zoom: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter HorizontalZoomSpinBox Horizontal Zoom (%) % 10 1000 10 100 &Vertical Zoom: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter VerticalZoomSpinBox Vertical Zoom (%) % 10 1000 10 100 Qt::Vertical 20 40 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qtractorTempoSpinBox QSpinBox
qtractorSpinBox.h
SessionNameLineEdit SessionDirComboBox SessionDirToolButton DescriptionTextEdit SampleRateComboBox TempoSpinBox TicksPerBeatSpinBox SnapPerBeatComboBox PixelsPerBeatSpinBox HorizontalZoomSpinBox VerticalZoomSpinBox SessionTabWidget DialogButtonBox
qtractor-0.5.11/src/PaxHeaders.10084/qtractorClip.cpp0000644000175000001440000000012312166526620020424 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134668.17308 30 ctime=1381134668.173080067 qtractor-0.5.11/src/qtractorClip.cpp0000644000175000001440000006370512166526620017726 0ustar00rncbcusers00000000000000// qtractorClip.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorClip.h" #include "qtractorSession.h" #include "qtractorDocument.h" #include "qtractorClipCommand.h" #include "qtractorClipForm.h" #include #include #include #include #include #ifdef CONFIG_GRADIENT #include #endif //------------------------------------------------------------------------- // qtractorClip -- Track clip capsule. // Constructorz. qtractorClip::qtractorClip ( qtractorTrack *pTrack ) { m_pTrack = pTrack; m_pTakeInfo = NULL; m_pFadeInFunctor = NULL; m_pFadeOutFunctor = NULL; clear(); } // Default constructor. qtractorClip::~qtractorClip (void) { if (m_pTakeInfo) m_pTakeInfo->releaseRef(); if (m_pFadeInFunctor) delete m_pFadeInFunctor; if (m_pFadeOutFunctor) delete m_pFadeOutFunctor; } // Reset clip. void qtractorClip::clear (void) { m_sClipName.clear(); m_iClipStart = 0; m_iClipLength = 0; m_iClipOffset = 0; m_iClipStartTime = 0; m_iClipOffsetTime = 0; m_iClipLengthTime = 0; m_iSelectStart = 0; m_iSelectEnd = 0; m_fGain = 1.0f; // Gain fractionalizer(tm)... m_fractGain.num = 1; m_fractGain.den = 8; m_iFadeInLength = 0; m_iFadeOutLength = 0; m_iFadeInTime = 0; m_iFadeOutTime = 0; setFadeInType(InQuad); setFadeOutType(OutQuad); m_bDirty = false; } // Clip filename properties accessors. void qtractorClip::setFilename ( const QString& sFilename ) { QDir dir; if (m_pTrack && m_pTrack->session()) dir.setPath(m_pTrack->session()->sessionDir()); m_sFilename = QDir::cleanPath(dir.absoluteFilePath(sFilename)); } const QString& qtractorClip::filename (void) const { return m_sFilename; } QString qtractorClip::relativeFilename ( qtractorDocument *pDocument ) const { if (pDocument && pDocument->isArchive()) return pDocument->addFile(m_sFilename); QDir dir; if (m_pTrack && m_pTrack->session()) dir.setPath(m_pTrack->session()->sessionDir()); return dir.relativeFilePath(m_sFilename); } QString qtractorClip::shortClipName ( const QString& sClipName ) const { QString sShortClipName(sClipName); if (m_pTrack && m_pTrack->session()) { const QString& sSessionName = m_pTrack->session()->sessionName(); if (!sSessionName.isEmpty()) { const QString sRegExp("^%1[\\-|_|\\s]+"); sShortClipName.remove(QRegExp(sRegExp.arg(sSessionName))); } } return sShortClipName; } QString qtractorClip::clipTitle (void) const { QString sClipTitle(m_sClipName); if (m_pTakeInfo && m_pTakeInfo->currentTake() >= 0) { sClipTitle += QObject::tr(" (take %1)") .arg(m_pTakeInfo->currentTake() + 1); } return sClipTitle; } // Clip start frame accessor. void qtractorClip::setClipStart ( unsigned long iClipStart ) { m_iClipStart = iClipStart; if (m_pTrack && m_pTrack->session()) m_iClipStartTime = m_pTrack->session()->tickFromFrame(iClipStart); } // Clip frame length accessor. void qtractorClip::setClipLength ( unsigned long iClipLength ) { m_iClipLength = iClipLength; if (m_pTrack && m_pTrack->session()) m_iClipLengthTime = m_pTrack->session()->tickFromFrameRange( m_iClipStart, m_iClipStart + m_iClipLength); } // Clip frame offset accessor. void qtractorClip::setClipOffset ( unsigned long iClipOffset ) { m_iClipOffset = iClipOffset; if (m_pTrack && m_pTrack->session()) m_iClipOffsetTime = m_pTrack->session()->tickFromFrameRange( m_iClipStart, m_iClipStart + m_iClipOffset); } // Clip selection accessors. void qtractorClip::setClipSelected ( bool bClipSelected ) { if (bClipSelected) { setClipSelect(m_iClipStart, m_iClipStart + m_iClipLength); } else { setClipSelect(0, 0); } } bool qtractorClip::isClipSelected (void) const { return (m_iSelectStart < m_iSelectEnd); } // Clip-selection points accessors. void qtractorClip::setClipSelect ( unsigned long iSelectStart, unsigned long iSelectEnd ) { if (iSelectStart < m_iClipStart) iSelectStart = m_iClipStart; if (iSelectEnd > m_iClipStart + m_iClipLength) iSelectEnd = m_iClipStart + m_iClipLength; if (iSelectStart < iSelectEnd) { m_iSelectStart = iSelectStart; m_iSelectEnd = iSelectEnd; } else { m_iSelectStart = 0; m_iSelectEnd = 0; } } // Clip-loop points accessors. void qtractorClip::setClipGain ( float fGain ) { m_fGain = fGain; // Gain fractionalizer(tm)... m_fractGain.den = 8; while(fGain != int(fGain) && m_fractGain.den < 20) { m_fractGain.den += 2; fGain *= 4.0f; } m_fractGain.num = int(fGain); } // Clip fade-in accessors void qtractorClip::setFadeInType ( qtractorClip::FadeType fadeType ) { if (m_pFadeInFunctor) delete m_pFadeInFunctor; m_fadeInType = fadeType; m_pFadeInFunctor = createFadeFunctor(FadeIn, fadeType); } void qtractorClip::setFadeInLength ( unsigned long iFadeInLength ) { if (iFadeInLength > m_iClipLength) iFadeInLength = m_iClipLength; m_iFadeInLength = iFadeInLength; if (m_pTrack && m_pTrack->session()) m_iFadeInTime = m_pTrack->session()->tickFromFrameRange( m_iClipStart, m_iClipStart + m_iFadeInLength); } // Clip fade-out accessors void qtractorClip::setFadeOutType ( qtractorClip::FadeType fadeType ) { if (m_pFadeOutFunctor) delete m_pFadeOutFunctor; m_fadeOutType = fadeType; m_pFadeOutFunctor = createFadeFunctor(FadeOut, fadeType); } void qtractorClip::setFadeOutLength ( unsigned long iFadeOutLength ) { if (iFadeOutLength > m_iClipLength) iFadeOutLength = m_iClipLength; m_iFadeOutLength = iFadeOutLength; if (m_pTrack && m_pTrack->session()) m_iFadeOutTime = m_pTrack->session()->tickFromFrameRange( m_iClipStart + m_iClipLength - m_iFadeOutLength, m_iClipStart + m_iClipLength); } // Compute clip gain, given current fade-in/out slopes. float qtractorClip::gain ( unsigned long iOffset ) const { if (iOffset >= m_iClipLength) return 0.0f; float fGain = m_fGain; if (m_iFadeInLength > 0 && iOffset < m_iFadeInLength) { fGain *= (*m_pFadeInFunctor)( float(iOffset) / float(m_iFadeInLength)); } if (m_iFadeOutLength > 0 && iOffset > m_iClipLength - m_iFadeOutLength) { fGain *= (*m_pFadeOutFunctor)( float(iOffset - (m_iClipLength - m_iFadeOutLength)) / float(m_iFadeOutLength)); } return fGain; } // Clip time reference settler method. void qtractorClip::updateClipTime (void) { if (m_pTrack == NULL) return; qtractorSession *pSession = m_pTrack->session(); if (pSession == NULL) return; m_iClipStart = pSession->frameFromTick(m_iClipStartTime); m_iClipOffset = pSession->frameFromTickRange( m_iClipStartTime, m_iClipStartTime + m_iClipOffsetTime); m_iClipLength = pSession->frameFromTickRange( m_iClipStartTime, m_iClipStartTime + m_iClipLengthTime); m_iFadeInLength = pSession->frameFromTickRange( m_iClipStartTime, m_iClipStartTime + m_iFadeInTime); m_iFadeOutLength = pSession->frameFromTickRange( m_iClipStartTime + m_iClipLengthTime - m_iFadeOutTime, m_iClipStartTime + m_iClipLengthTime); } // Base clip drawing method. void qtractorClip::drawClip ( QPainter *pPainter, const QRect& clipRect, unsigned long iClipOffset ) { // Fill clip background... pPainter->setPen(m_pTrack->background().darker()); #ifdef CONFIG_GRADIENT QLinearGradient grad(0, clipRect.top(), 0, clipRect.bottom()); grad.setColorAt(0.4, m_pTrack->background()); grad.setColorAt(1.0, m_pTrack->background().darker(130)); pPainter->setBrush(grad); #else pPainter->setBrush(m_pTrack->background()); #endif pPainter->drawRect(clipRect); qtractorSession *pSession = m_pTrack->session(); if (pSession == NULL) return; // Adjust the clip rectangle left origin... QRect rect(clipRect); if (iClipOffset > 0) rect.setLeft(rect.left() - pSession->pixelFromFrame(iClipOffset) + 1); // Draw clip name label... pPainter->drawText(rect, Qt::AlignLeft | Qt::AlignBottom | Qt::TextSingleLine, clipTitle()); // Draw clip contents (virtual) draw(pPainter, clipRect, iClipOffset); // Avoid drawing fade in/out handles // on still empty clips (eg. while recording) if (m_iClipLength < 1) return; // Fade in/out handle color... QColor rgbFade(m_pTrack->foreground()); rgbFade.setAlpha(120); pPainter->setPen(rgbFade); pPainter->setBrush(rgbFade); // Fade-in slope... int y = rect.top(); int x = rect.left(); int w = pSession->pixelFromFrame(m_iFadeInLength); int h = rect.bottom(); const QRect rectFadeIn(x + w, y, 8, 8); if (w > 0 && x + w > clipRect.left()) { #if 0 QPolygon polyg(3); polyg.setPoint(0, x, y); polyg.setPoint(1, x, h); polyg.setPoint(2, x + w, y); pPainter->drawPolygon(polyg); #else const int w2 = (w >> 1); const int w4 = (w >> 2); QPolygon polyg(5); polyg.setPoint(0, x, y); polyg.setPoint(1, x, h); switch (m_fadeInType) { case Linear: polyg.setPoint(2, x, h); polyg.setPoint(3, x, h); break; case InQuad: polyg.setPoint(2, x + w2, h); polyg.setPoint(3, x + w, y); break; case OutQuad: polyg.setPoint(2, x + w2, y); polyg.setPoint(3, x + w, y); break; case InOutQuad: polyg.setPoint(2, x + w2, h); polyg.setPoint(3, x + w2, y); break; case InCubic: polyg.setPoint(2, x + w - w4, h); polyg.setPoint(3, x + w, y); break; case OutCubic: polyg.setPoint(2, x + w2, y); polyg.setPoint(3, x + w - w4, y); break; case InOutCubic: polyg.setPoint(2, x + w - w4, h); polyg.setPoint(3, x + w4, y); break; } polyg.setPoint(4, x + w, y); QPainterPath path; path.moveTo(polyg.at(0)); path.lineTo(polyg.at(1)); path.cubicTo(polyg.at(2), polyg.at(3), polyg.at(4)); path.lineTo(polyg.at(0)); pPainter->drawPath(path); #endif } // Fade-out slope... x = rect.left() + pSession->pixelFromFrame(m_iClipLength); w = pSession->pixelFromFrame(m_iFadeOutLength); const QRect rectFadeOut(x - w - 8, y, 8, 8); if (w > 0 && x - w < clipRect.right()) { #if 0 QPolygon polyg(3); polyg.setPoint(0, x, y); polyg.setPoint(1, x, h); polyg.setPoint(2, x - w, y); pPainter->drawPolygon(polyg); #else const int w2 = (w >> 1); const int w4 = (w >> 2); QPolygon polyg(5); polyg.setPoint(0, x, y); polyg.setPoint(1, x, h); switch (m_fadeOutType) { case Linear: polyg.setPoint(2, x, h); polyg.setPoint(3, x, h); break; case InQuad: polyg.setPoint(2, x - w2, y); polyg.setPoint(3, x - w, y); break; case OutQuad: polyg.setPoint(2, x - w2, h); polyg.setPoint(3, x - w, y); break; case InOutQuad: polyg.setPoint(2, x - w2, h); polyg.setPoint(3, x - w2, y); break; case InCubic: polyg.setPoint(2, x - w2, y); polyg.setPoint(3, x - w + w4, y); break; case OutCubic: polyg.setPoint(2, x - w + w4, h); polyg.setPoint(3, x - w, y); break; case InOutCubic: polyg.setPoint(2, x - w + w4, h); polyg.setPoint(3, x - w4, y); break; } polyg.setPoint(4, x - w, y); QPainterPath path; path.moveTo(polyg.at(0)); path.lineTo(polyg.at(1)); path.cubicTo(polyg.at(2), polyg.at(3), polyg.at(4)); path.lineTo(polyg.at(0)); pPainter->drawPath(path); #endif } // Fade in/out handles... if (rectFadeIn.intersects(clipRect)) pPainter->fillRect(rectFadeIn, rgbFade.darker(120)); if (rectFadeOut.intersects(clipRect)) pPainter->fillRect(rectFadeOut, rgbFade.darker(120)); } // Clip editor method. bool qtractorClip::startEditor ( QWidget *pParent ) { // Make sure the regular clip-form is started modal... qtractorClipForm clipForm(pParent); clipForm.setClip(this); return clipForm.exec(); } // Clip editor reset. void qtractorClip::resetEditor ( bool /*bSelectClear*/ ) { // Do nothing here. } // Clip editor update. void qtractorClip::updateEditor ( bool /*bSelectClear*/ ) { // Do nothing here. } // Clip query-close method (return true if editing is done). bool qtractorClip::queryEditor (void) { return !isDirty(); } // Clip tool-tip. QString qtractorClip::toolTip (void) const { QString sToolTip = QObject::tr("Name:\t%1").arg(clipTitle()); qtractorSession *pSession = NULL; if (m_pTrack) pSession = m_pTrack->session(); if (pSession) { sToolTip += '\n'; qtractorTimeScale *pTimeScale = pSession->timeScale(); sToolTip += QObject::tr("Start / End:\t%1 / %2\nOffset / Length:\t%3 / %4") .arg(pTimeScale->textFromFrame(m_iClipStart)) .arg(pTimeScale->textFromFrame(m_iClipStart + m_iClipLength)) .arg(pTimeScale->textFromFrame(m_iClipStart, true, m_iClipOffset)) .arg(pTimeScale->textFromFrame(m_iClipStart, true, m_iClipLength)); } sToolTip += '\n'; sToolTip += QObject::tr("File:\t%1").arg(QFileInfo(m_sFilename).fileName()); return sToolTip; } // Document element methods. bool qtractorClip::loadElement ( qtractorDocument *pDocument, QDomElement *pElement ) { qtractorClip::setClipName(pElement->attribute("name")); // Load clip children... for (QDomNode nChild = pElement->firstChild(); !nChild.isNull(); nChild = nChild.nextSibling()) { // Convert node to element... QDomElement eChild = nChild.toElement(); if (eChild.isNull()) continue; // Load clip properties... if (eChild.tagName() == "properties") { for (QDomNode nProp = eChild.firstChild(); !nProp.isNull(); nProp = nProp.nextSibling()) { // Convert property node to element... QDomElement eProp = nProp.toElement(); if (eProp.isNull()) continue; if (eProp.tagName() == "name") qtractorClip::setClipName(eProp.text()); else if (eProp.tagName() == "start") qtractorClip::setClipStart(eProp.text().toULong()); else if (eProp.tagName() == "offset") qtractorClip::setClipOffset(eProp.text().toULong()); else if (eProp.tagName() == "length") qtractorClip::setClipLength(eProp.text().toULong()); else if (eProp.tagName() == "gain") qtractorClip::setClipGain(eProp.text().toFloat()); else if (eProp.tagName() == "fade-in") { qtractorClip::setFadeInType( qtractorClip::fadeInTypeFromText(eProp.attribute("type"))); qtractorClip::setFadeInLength(eProp.text().toULong()); } else if (eProp.tagName() == "fade-out") { qtractorClip::setFadeOutType( qtractorClip::fadeOutTypeFromText(eProp.attribute("type"))); qtractorClip::setFadeOutLength(eProp.text().toULong()); } } } else // Load clip derivative properties... if (eChild.tagName() == "audio-clip" || eChild.tagName() == "midi-clip") { if (!loadClipElement(pDocument, &eChild)) return false; } else if (eChild.tagName() == "take-info") { int iTakeID = eChild.attribute("id").toInt(); qtractorClip::TakeInfo::ClipPart cpart = qtractorClip::TakeInfo::ClipPart( eChild.attribute("part").toInt()); // Load take(record) descriptor children, if any... unsigned long iClipStart = 0; unsigned long iClipOffset = 0; unsigned long iClipLength = 0; unsigned long iTakeStart = 0; unsigned long iTakeEnd = 0; int iCurrentTake = -1; for (QDomNode nProp = eChild.firstChild(); !nProp.isNull(); nProp = nProp.nextSibling()) { // Convert node to element... QDomElement eProp = nProp.toElement(); if (eProp.isNull()) continue; // Load take-info properties... if (eProp.tagName() == "clip-start") iClipStart = eProp.text().toULong(); else if (eProp.tagName() == "clip-offset") iClipOffset = eProp.text().toULong(); else if (eProp.tagName() == "clip-length") iClipLength = eProp.text().toULong(); else if (eProp.tagName() == "take-start") iTakeStart = eProp.text().toULong(); else if (eProp.tagName() == "take-end") iTakeEnd = eProp.text().toULong(); else if (eProp.tagName() == "current-take") iCurrentTake = eProp.text().toInt(); } qtractorTrack::TakeInfo *pTakeInfo = NULL; qtractorTrack *pTrack = qtractorClip::track(); if (pTrack && iTakeID >= 0) pTakeInfo = pTrack->takeInfo(iTakeID); if (pTakeInfo == NULL && iTakeStart < iTakeEnd) { pTakeInfo = static_cast ( new qtractorClip::TakeInfo( iClipStart, iClipOffset, iClipLength, iTakeStart, iTakeEnd)); if (pTrack && iTakeID >= 0) pTrack->takeInfoAdd(iTakeID, pTakeInfo); } if (pTakeInfo) { qtractorClip::setTakeInfo(pTakeInfo); pTakeInfo->setClipPart(cpart, this); if (iCurrentTake >= 0) pTakeInfo->setCurrentTake(iCurrentTake); } } } return true; } bool qtractorClip::saveElement ( qtractorDocument *pDocument, QDomElement *pElement ) const { pElement->setAttribute("name", qtractorClip::clipName()); // Save clip properties... QDomElement eProps = pDocument->document()->createElement("properties"); pDocument->saveTextElement("name", qtractorClip::clipName(), &eProps); pDocument->saveTextElement("start", QString::number(qtractorClip::clipStart()), &eProps); pDocument->saveTextElement("offset", QString::number(qtractorClip::clipOffset()), &eProps); pDocument->saveTextElement("length", QString::number(qtractorClip::clipLength()), &eProps); pDocument->saveTextElement("gain", QString::number(qtractorClip::clipGain()), &eProps); QDomElement eFadeIn = pDocument->document()->createElement("fade-in"); eFadeIn.setAttribute("type", qtractorClip::textFromFadeType(qtractorClip::fadeInType())); eFadeIn.appendChild(pDocument->document()->createTextNode( QString::number(qtractorClip::fadeInLength()))); eProps.appendChild(eFadeIn); QDomElement eFadeOut = pDocument->document()->createElement("fade-out"); eFadeOut.setAttribute("type", qtractorClip::textFromFadeType(qtractorClip::fadeOutType())); eFadeOut.appendChild(pDocument->document()->createTextNode( QString::number(qtractorClip::fadeOutLength()))); eProps.appendChild(eFadeOut); pElement->appendChild(eProps); // Save clip derivative properties... if (!saveClipElement(pDocument, pElement)) return false; // At last, save clip take(record) properties, if any... qtractorTrack::TakeInfo *pTakeInfo = static_cast (qtractorClip::takeInfo()); if (pTakeInfo) { qtractorTrack *pTrack = qtractorClip::track(); if (pTrack) { QDomElement eTakeInfo = pDocument->document()->createElement("take-info"); int iTakeID = pTrack->takeInfoId(pTakeInfo); if (iTakeID < 0) { iTakeID = pTrack->takeInfoNew(pTakeInfo); pDocument->saveTextElement("clip-start", QString::number(pTakeInfo->clipStart()), &eTakeInfo); pDocument->saveTextElement("clip-offset", QString::number(pTakeInfo->clipOffset()), &eTakeInfo); pDocument->saveTextElement("clip-length", QString::number(pTakeInfo->clipLength()), &eTakeInfo); pDocument->saveTextElement("take-start", QString::number(pTakeInfo->takeStart()), &eTakeInfo); pDocument->saveTextElement("take-end", QString::number(pTakeInfo->takeEnd()), &eTakeInfo); pDocument->saveTextElement("current-take", QString::number(pTakeInfo->currentTake()), &eTakeInfo); } eTakeInfo.setAttribute("id", QString::number(iTakeID)); eTakeInfo.setAttribute("part", QString::number(int(pTakeInfo->partClip(this)))); pElement->appendChild(eTakeInfo); } } // Successs. return true; } // Clip fade type textual helper methods. qtractorClip::FadeType qtractorClip::fadeInTypeFromText ( const QString& sText ) { FadeType fadeType = InQuad; if (sText == "Linear" || sText == "linear") fadeType = Linear; else if (sText == "InCubic" || sText == "cubic") fadeType = InCubic; else if (sText == "OutQuad") fadeType = OutQuad; else if (sText == "InOutQuad") fadeType = InOutQuad; else if (sText == "OutCubic") fadeType = OutCubic; else if (sText == "InOutCubic") fadeType = InOutCubic; return fadeType; } qtractorClip::FadeType qtractorClip::fadeOutTypeFromText ( const QString& sText ) { FadeType fadeType = OutQuad; if (sText == "Linear" || sText == "linear") fadeType = Linear; else if (sText == "OutCubic" || sText == "cubic") fadeType = OutCubic; else if (sText == "InQuad") fadeType = InQuad; else if (sText == "InOutQuad") fadeType = InOutQuad; else if (sText == "InCubic") fadeType = InCubic; else if (sText == "InOutCubic") fadeType = InOutCubic; return fadeType; } QString qtractorClip::textFromFadeType ( FadeType fadeType ) { QString sText; switch (fadeType) { case Linear: sText = "Linear"; break; case InQuad: sText = "InQuad"; break; case OutQuad: sText = "OutQuad"; break; case InOutQuad: sText = "InOutQuad"; break; case InCubic: sText = "InCubic"; break; case OutCubic: sText = "OutCubic"; break; case InOutCubic: sText = "InOutCubic"; break; } return sText; } // Estimate total number of takes. int qtractorClip::TakeInfo::takeCount (void) const { int iTakeCount = -1; unsigned long iClipEnd = m_iClipStart + m_iClipLength; unsigned long iTakeLength = m_iTakeEnd - m_iTakeStart; if (iTakeLength > 0) { if (m_iClipStart < m_iTakeStart) iTakeCount = (iClipEnd - m_iTakeStart) / iTakeLength; else if (m_iClipStart < m_iTakeEnd && iClipEnd > m_iTakeEnd) iTakeCount = (iClipEnd - m_iTakeEnd) / iTakeLength + 1; } return iTakeCount + 1; } // Select current take set. int qtractorClip::TakeInfo::select ( qtractorClipCommand *pClipCommand, qtractorTrack *pTrack, int iTake ) { unsigned long iClipStart = m_iClipStart; unsigned long iClipOffset = m_iClipOffset; unsigned long iClipLength = m_iClipLength; unsigned long iClipEnd = iClipStart + iClipLength; unsigned long iTakeStart = m_iTakeStart; unsigned long iTakeEnd = m_iTakeEnd; unsigned long iTakeLength = m_iTakeEnd - m_iTakeStart; #ifdef CONFIG_DEBUG qDebug("qtractorClip::TakeInfo[%p]::select(%d, %lu, %lu, %lu, %lu, %lu)", this, iTake, iClipStart, iClipOffset, iClipLength, iTakeStart, iTakeEnd); #endif if (iClipStart < iTakeStart) { int iTakeCount = (iClipEnd - iTakeStart) / iTakeLength; if (iTake < 0 || iTake > iTakeCount) iTake = iTakeCount; // Clip-head for sure... iClipLength = iTakeStart - iClipStart; selectClipPart(pClipCommand, pTrack, ClipHead, iClipStart, iClipOffset, iClipLength); // Clip-take from now on... iClipOffset += iClipLength; if (iTake > 0) iClipOffset += iTake * iTakeLength; if (iTake < iTakeCount) iClipLength = iTakeLength; else iClipLength = (iClipEnd - iTakeStart) % iTakeLength; iClipStart = iTakeStart; } else if (iClipStart < iTakeEnd && iClipEnd > iTakeEnd) { int iTakeCount = (iClipEnd - iTakeEnd) / iTakeLength + 1; if (iTake < 0 || iTake > iTakeCount) iTake = iTakeCount; // Clip-take for sure... if (iTake > 0 || iTakeCount < 1) { iClipOffset += (iTakeEnd - iClipStart); if (iTake > 0) iClipOffset += (iTake - 1) * iTakeLength; if (iTake < iTakeCount) iClipLength = iTakeLength; else iClipLength = (iClipEnd - iTakeStart) % iTakeLength; iClipStart = iTakeStart; } else iClipLength = iTakeEnd - iClipStart; } else iTake = -1; selectClipPart(pClipCommand, pTrack, ClipTake, iClipStart, iClipOffset, iClipLength); // m_iCurrentTake = iTake; return iTake; } // Select current take sub-clip part. void qtractorClip::TakeInfo::selectClipPart ( qtractorClipCommand *pClipCommand, qtractorTrack *pTrack, ClipPart cpart, unsigned long iClipStart, unsigned long iClipOffset, unsigned long iClipLength ) { #ifdef CONFIG_DEBUG qDebug("qtractorClip::TakeInfo[%p]::selectClipPart(%d, %lu, %lu, %lu)", this, int(cpart), iClipStart, iClipOffset, iClipLength); #endif // Priority to recording clip... qtractorClip *pClip = (pTrack ? pTrack->clipRecord() : NULL); // Clip already taken?... if (pClip == NULL) { pClip = clipPart(cpart); if (pClip) { // Don't change what hasn't change... if (iClipStart != pClip->clipStart() || iClipOffset != pClip->clipOffset() || iClipLength != pClip->clipLength()) { pClipCommand->resizeClip(pClip, iClipStart, iClipOffset, iClipLength); } return; // Done. } // Take clip-take clone... if (cpart == ClipHead) pClip = clipPart(ClipTake); } // Clip about to be taken (as new)?... if (pClip) { TakePart part(this, cpart); pClipCommand->addClipRecordTake(pTrack, pClip, iClipStart, iClipOffset, iClipLength, &part); } } // Reset(unfold) whole take set. void qtractorClip::TakeInfo::reset ( qtractorClipCommand *pClipCommand, bool bClear ) { unsigned long iClipStart = m_iClipStart; unsigned long iClipOffset = m_iClipOffset; unsigned long iClipLength = m_iClipLength; #ifdef CONFIG_DEBUG qDebug("qtractorClip::TakeInfo[%p]::reset(%lu, %lu, %lu, %d)", this, iClipStart, iClipOffset, iClipLength, int(bClear)); #endif qtractorClip *pClip = clipPart(ClipHead); if (pClip) { pClipCommand->removeClip(pClip); pClipCommand->takeInfoClip(pClip, NULL); setClipPart(ClipHead, NULL); } pClip = clipPart(ClipTake); if (pClip) { pClipCommand->resizeClip(pClip, iClipStart, iClipOffset, iClipLength); if (bClear) { pClipCommand->takeInfoClip(pClip, NULL); // setClipPart(ClipTake, NULL); } } // m_iCurrentTake = -1; } // Take(record) descriptor accessors. void qtractorClip::setTakeInfo ( qtractorClip::TakeInfo *pTakeInfo ) { #ifdef CONFIG_DEBUG qDebug("qtractorClip[%p]::setTakeInfo(%p)", this, pTakeInfo); #endif if (m_pTakeInfo) m_pTakeInfo->releaseRef(); m_pTakeInfo = pTakeInfo; if (m_pTakeInfo) m_pTakeInfo->addRef(); } qtractorClip::TakeInfo *qtractorClip::takeInfo (void) const { return m_pTakeInfo; } // end of qtractorClip.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTrackTime.cpp0000644000175000001440000000012312223025330021402 xustar000000000000000027 mtime=1380723416.183262 26 atime=1381134668.12208 30 ctime=1381134668.122080067 qtractor-0.5.11/src/qtractorTrackTime.cpp0000644000175000001440000006055112223025330020700 0ustar00rncbcusers00000000000000// qtractorTrackTime.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorTrackTime.h" #include "qtractorTrackView.h" #include "qtractorSession.h" #include "qtractorTracks.h" #include "qtractorOptions.h" #include "qtractorSessionCommand.h" #include "qtractorTimeScaleCommand.h" #include "qtractorMainForm.h" #include "qtractorTimeScaleForm.h" #include #include #include #include #include #include #include #include //---------------------------------------------------------------------------- // qtractorTrackTime -- Track time scale widget. // Constructor. qtractorTrackTime::qtractorTrackTime ( qtractorTracks *pTracks, QWidget *pParent ) : qtractorScrollView(pParent) { m_pTracks = pTracks; m_dragState = DragNone; m_dragCursor = DragNone; m_pDragMarker = NULL; qtractorScrollView::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); qtractorScrollView::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); qtractorScrollView::setFrameStyle(QFrame::Panel | QFrame::Raised); qtractorScrollView::setFocusPolicy(Qt::NoFocus); // qtractorScrollView::viewport()->setFocusPolicy(Qt::ClickFocus); // qtractorScrollView::viewport()->setFocusProxy(this); // qtractorScrollView::viewport()->setAcceptDrops(true); // qtractorScrollView::setDragAutoScroll(false); qtractorScrollView::setMouseTracking(true); const QFont& font = qtractorScrollView::font(); qtractorScrollView::setFont(QFont(font.family(), font.pointSize() - 2)); // QObject::connect(this, SIGNAL(contentsMoving(int,int)), // this, SLOT(updatePixmap(int,int))); // Trap for help/tool-tips events. qtractorScrollView::viewport()->installEventFilter(this); } // (Re)create the complete track view pixmap. void qtractorTrackTime::updatePixmap ( int cx, int /* cy */) { QWidget *pViewport = qtractorScrollView::viewport(); const int w = pViewport->width(); const int h = pViewport->height(); if (w < 1 || h < 1) return; const QPalette& pal = qtractorScrollView::palette(); m_pixmap = QPixmap(w, h); m_pixmap.fill(pal.window().color()); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorTimeScale *pTimeScale = pSession->timeScale(); if (pTimeScale == NULL) return; QPainter painter(&m_pixmap); painter.initFrom(this); // Draw the time scale... // const QFontMetrics& fm = painter.fontMetrics(); int x, y1, y2 = h - 1; qtractorTimeScale::Cursor cursor(pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekPixel(cx); unsigned short iPixelsPerBeat = pNode->pixelsPerBeat(); unsigned int iBeat = pNode->beatFromPixel(cx); if (iBeat > 0) pNode = cursor.seekBeat(--iBeat); x = pNode->pixelFromBeat(iBeat) - cx; while (x < w) { const bool bBeatIsBar = pNode->beatIsBar(iBeat); if (bBeatIsBar) { y1 = 0; painter.setPen(pal.windowText().color()); painter.drawText(x + 2, fm.ascent(), QString::number(pNode->barFromBeat(iBeat) + 1)); if (iBeat == pNode->beat) { iPixelsPerBeat = pNode->pixelsPerBeat(); painter.setPen(pal.base().color().value() < 0x7f ? pal.light().color() : pal.dark().color()); painter.drawText(x + 16, fm.ascent(), QString("%1 %2/%3") .arg(pNode->tempo, 0, 'g', 3) .arg(pNode->beatsPerBar) .arg(1 << pNode->beatDivisor)); } } else { y1 = (y2 >> 1); } if (bBeatIsBar || iPixelsPerBeat > 16) { painter.setPen(pal.mid().color()); painter.drawLine(x, y1, x, y2); painter.setPen(pal.light().color()); painter.drawLine(x + 1, y1, x + 1, y2); } pNode = cursor.seekBeat(++iBeat); x = pNode->pixelFromBeat(iBeat) - cx; } // Draw location markers, if any... qtractorTimeScale::Marker *pMarker = pTimeScale->markers().seekPixel(cx); while (pMarker) { x = pTimeScale->pixelFromFrame(pMarker->frame) - cx + 4; if (x > w) break; painter.setPen(pMarker->color); painter.drawText(x, y2, pMarker->text); pMarker = pMarker->next(); } // Draw loop boundaries, if applicable... if (pSession->isLooping()) { QPolygon polyg(3); // h -= 4; const int d = (h >> 2); painter.setPen(Qt::darkCyan); painter.setBrush(Qt::cyan); x = pTimeScale->pixelFromFrame(pSession->loopStart()) - cx; if (x >= 0 && x < w) { polyg.putPoints(0, 3, x + d, h - d, x, h, x, h - d); painter.drawPolygon(polyg); } x = pTimeScale->pixelFromFrame(pSession->loopEnd()) - cx; if (x >= 0 && x < w) { polyg.putPoints(0, 3, x, h - d, x, h, x - d, h - d); painter.drawPolygon(polyg); } } // Draw punch in/out boundaries, if applicable... if (pSession->isPunching()) { QPolygon polyg(3); // h -= 4; const int d = (h >> 2); painter.setPen(Qt::darkMagenta); painter.setBrush(Qt::magenta); x = pTimeScale->pixelFromFrame(pSession->punchIn()) - cx; if (x >= 0 && x < w) { polyg.putPoints(0, 3, x + d, h - d, x, h, x, h - d); painter.drawPolygon(polyg); } x = pTimeScale->pixelFromFrame(pSession->punchOut()) - cx; if (x >= 0 && x < w) { polyg.putPoints(0, 3, x, h - d, x, h, x - d, h - d); painter.drawPolygon(polyg); } } } // Rectangular contents update. void qtractorTrackTime::updateContents ( const QRect& rect ) { updatePixmap( qtractorScrollView::contentsX(), qtractorScrollView::contentsY()); qtractorScrollView::updateContents(rect); } // Overall contents update. void qtractorTrackTime::updateContents (void) { updatePixmap( qtractorScrollView::contentsX(), qtractorScrollView::contentsY()); qtractorScrollView::updateContents(); } // Resize event handler. void qtractorTrackTime::resizeEvent ( QResizeEvent *pResizeEvent ) { qtractorScrollView::resizeEvent(pResizeEvent); updateContents(); } // Draw the time scale. void qtractorTrackTime::drawContents ( QPainter *pPainter, const QRect& rect ) { // Render the famous pixmap region... pPainter->drawPixmap(rect, m_pixmap, rect); // Headers a-head... const int cx = qtractorScrollView::contentsX(); const int h = qtractorScrollView::height() - 4; const int d = (h >> 2); qtractorTrackView *pTrackView = m_pTracks->trackView(); // Draw edit-head line... int x = pTrackView->editHeadX() - cx; if (x >= rect.left() - d && x <= rect.right() + d) { QPolygon polyg(3); polyg.putPoints(0, 3, x + d, h - d, x, h, x, h - d); pPainter->setPen(Qt::blue); pPainter->setBrush(Qt::blue); pPainter->drawPolygon(polyg); } // Draw edit-tail line... x = pTrackView->editTailX() - cx; if (x >= rect.left() - d && x <= rect.right() + d) { QPolygon polyg(3); polyg.putPoints(0, 3, x, h - d, x, h, x - d, h - d); pPainter->setPen(Qt::blue); pPainter->setBrush(Qt::blue); pPainter->drawPolygon(polyg); } // Draw special play-head header... x = pTrackView->playHeadX() - cx; if (x >= rect.left() - d && x <= rect.right() + d) { QPolygon polyg(3); polyg.putPoints(0, 3, x - d, h - d, x, h, x + d, h - d); pPainter->setPen(Qt::red); pPainter->setBrush(Qt::red); pPainter->drawPolygon(polyg); } } // To have timeline in h-sync with main track view. void qtractorTrackTime::contentsXMovingSlot ( int cx, int /*cy*/ ) { if (qtractorScrollView::contentsX() != cx) qtractorScrollView::setContentsPos(cx, qtractorScrollView::contentsY()); } // Check if some position header is to be dragged... bool qtractorTrackTime::dragHeadStart ( const QPoint& pos ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; qtractorTimeScale *pTimeScale = pSession->timeScale(); if (pTimeScale == NULL) return false; // Try to catch mouse clicks over the // play/edit-head/tail cursors... const int h = qtractorScrollView::height(); // - 4; const int d = (h >> 1); QRect rect(0, h - d, d << 1, d); qtractorTrackView *pTrackView = m_pTracks->trackView(); // Check play-head header... rect.moveLeft(pTrackView->playHeadX() - d); if (rect.contains(pos)) { m_dragCursor = DragPlayHead; return true; } // Check loop-point headers... if (pSession->isLooping()) { // Check loop-start header... rect.moveLeft(pTimeScale->pixelFromFrame(pSession->loopStart()) - d); if (rect.contains(pos)) { m_dragCursor = DragLoopStart; return true; } // Check loop-end header... rect.moveLeft(pTimeScale->pixelFromFrame(pSession->loopEnd()) - d); if (rect.contains(pos)) { m_dragCursor = DragLoopEnd; return true; } } // Check punch-point headers... if (pSession->isPunching()) { // Check punch-in header... rect.moveLeft(pTimeScale->pixelFromFrame(pSession->punchIn()) - d); if (rect.contains(pos)) { m_dragCursor = DragPunchIn; return true; } // Check punch-out header... rect.moveLeft(pTimeScale->pixelFromFrame(pSession->punchOut()) - d); if (rect.contains(pos)) { m_dragCursor = DragPunchOut; return true; } } // Check location marker headers... qtractorTimeScale::Marker *pMarker = pTimeScale->markers().seekPixel(pos.x()); if (pMarker) { rect.moveLeft(pTimeScale->pixelFromFrame(pMarker->frame) - d); if (rect.contains(pos)) { m_dragCursor = DragMarker; m_pDragMarker = pMarker; return true; } } // Check edit-head header... rect.moveLeft(pTrackView->editHeadX() - d); if (rect.contains(pos)) { m_dragCursor = DragEditHead; return true; } // Check edit-tail header... rect.moveLeft(pTrackView->editTailX() - d); if (rect.contains(pos)) { m_dragCursor = DragEditTail; return true; } // Reset cursor if any persist around. if (m_dragCursor != DragNone) { qtractorScrollView::unsetCursor(); m_dragCursor = DragNone; } // Nothing. return false; } // Handle selection/dragging -- mouse button press. void qtractorTrackTime::mousePressEvent ( QMouseEvent *pMouseEvent ) { // Force null state. m_dragState = DragNone; qtractorTrackView *pTrackView = m_pTracks->trackView(); // We'll need options somehow... qtractorOptions *pOptions = qtractorOptions::getInstance(); // We need a session and a location... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { // Direct snap positioning... const QPoint& pos = viewportToContents(pMouseEvent->pos()); unsigned long iFrame = pSession->frameSnap( pSession->frameFromPixel(pos.x() > 0 ? pos.x() : 0)); // Which mouse state? const Qt::KeyboardModifiers& modifiers = pMouseEvent->modifiers(); bool bModifier = (modifiers & (Qt::ShiftModifier | Qt::ControlModifier)); switch (pMouseEvent->button()) { case Qt::LeftButton: // Remember what and where we'll be dragging/selecting... m_dragState = DragStart; m_posDrag = pos; // Try to catch mouse clicks over the cursor heads... if (dragHeadStart(m_posDrag)) { qtractorScrollView::setCursor(QCursor(Qt::SizeHorCursor)); m_dragState = m_dragCursor; } break; case Qt::MidButton: // Mid-button direct positioning... m_pTracks->selectNone(); if (pOptions && pOptions->bMidButtonModifier) bModifier = !bModifier; // Reverse mid-button role... if (bModifier) { // Play-head positioning commit... pTrackView->setPlayHead(iFrame); pSession->setPlayHead(pTrackView->playHead()); } else { // Edit cursor (merge) positioning... pTrackView->setEditHead(iFrame); pTrackView->setEditTail(iFrame); } // Logical contents changed, just for visual feedback... m_pTracks->selectionChangeNotify(); break; case Qt::RightButton: // Right-button direct positioning... pTrackView->setEditTail(iFrame); // Logical contents changed, just for visual feedback... m_pTracks->selectionChangeNotify(); // Fall thru... default: break; } } // qtractorScrollView::mousePressEvent(pMouseEvent); } // Handle selection/dragging -- mouse pointer move. void qtractorTrackTime::mouseMoveEvent ( QMouseEvent *pMouseEvent ) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { qtractorTrackView *pTrackView = m_pTracks->trackView(); // Which mouse state? const Qt::KeyboardModifiers& modifiers = pMouseEvent->modifiers(); // Are we already moving/dragging something? const QPoint& pos = viewportToContents(pMouseEvent->pos()); const unsigned long iFrame = pSession->frameSnap( pSession->frameFromPixel(pos.x() > 0 ? pos.x() : 0)); const int y = pTrackView->contentsY(); qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); switch (m_dragState) { case DragNone: // Try to catch mouse over the cursor heads... if (dragHeadStart(pos)) qtractorScrollView::setCursor(QCursor(Qt::PointingHandCursor)); break; case DragSelect: // Rubber-band selection... m_rectDrag.setRight(pos.x()); pTrackView->ensureVisible(pos.x(), y, 16, 0); if (pTrackView->isCurveEdit()) { // Select all current track curve/automation // nodes that fall inside range... pTrackView->selectCurveRect(m_rectDrag, qtractorTrackView::SelectRange, qtractorTrackView::selectFlags(modifiers), qtractorTrackView::EditBoth); } else { // Here we're mainly supposed to select a few // bunch of clips that fall inside range... pTrackView->selectClipRect(m_rectDrag, qtractorTrackView::SelectRange, qtractorTrackView::selectFlags(modifiers), qtractorTrackView::EditBoth); } showToolTip(m_rectDrag.normalized()); break; case DragPlayHead: // Play-head positioning... pTrackView->ensureVisible(pos.x(), y, 16, 0); pTrackView->setPlayHead(iFrame); // Let the change get some immediate visual feedback... if (pMainForm) pMainForm->updateTransportTime(iFrame); showToolTip(iFrame); break; case DragLoopStart: case DragPunchIn: case DragEditHead: // Edit-head positioning... pTrackView->ensureVisible(pos.x(), y, 16, 0); pTrackView->setEditHead(iFrame); showToolTip(iFrame); break; case DragLoopEnd: case DragPunchOut: case DragEditTail: // Edit-tail positioning... pTrackView->ensureVisible(pos.x(), y, 16, 0); pTrackView->setEditTail(iFrame); showToolTip(iFrame); break; case DragMarker: // Marker positioning... pTrackView->ensureVisible(pos.x(), y, 16, 0); showToolTip(iFrame); break; case DragStart: // Rubber-band starting... if ((m_posDrag - pos).manhattanLength() > QApplication::startDragDistance()) { // We'll start dragging alright... int h = qtractorScrollView::height(); // - 4; m_rectDrag.setTop(0); // h - (h >> 2) m_rectDrag.setLeft(m_posDrag.x()); m_rectDrag.setRight(pos.x()); m_rectDrag.setBottom(h); m_dragState = m_dragCursor = DragSelect; qtractorScrollView::setCursor(QCursor(Qt::SizeHorCursor)); } // Fall thru... default: break; } } // qtractorScrollView::mouseMoveEvent(pMouseEvent); } // Handle selection/dragging -- mouse button release. void qtractorTrackTime::mouseReleaseEvent ( QMouseEvent *pMouseEvent ) { // qtractorScrollView::mouseReleaseEvent(pMouseEvent); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { qtractorTrackView *pTrackView = m_pTracks->trackView(); // Which mouse state? const Qt::KeyboardModifiers& modifiers = pMouseEvent->modifiers(); const bool bModifier = (modifiers & (Qt::ShiftModifier | Qt::ControlModifier)); // Direct snap positioning... const QPoint& pos = viewportToContents(pMouseEvent->pos()); const unsigned long iFrame = pSession->frameSnap( pSession->frameFromPixel(pos.x() > 0 ? pos.x() : 0)); switch (m_dragState) { case DragSelect: // Do the final range selection... if (pTrackView->isCurveEdit()) { // Select all current track curve/automation // nodes that fall inside range... pTrackView->selectCurveRect(m_rectDrag, qtractorTrackView::SelectRange, qtractorTrackView::selectFlags(modifiers) | qtractorTrackView::SelectCommit, qtractorTrackView::EditBoth); } else { // Here we're mainly supposed to select a few // bunch of clips that fall inside range... pTrackView->selectClipRect(m_rectDrag, qtractorTrackView::SelectRange, qtractorTrackView::selectFlags(modifiers) | qtractorTrackView::SelectCommit, qtractorTrackView::EditBoth); } // For immediate visual feedback... m_pTracks->selectionChangeNotify(); break; case DragPlayHead: // Play-head positioning commit... pTrackView->setPlayHead(iFrame); pSession->setPlayHead(pTrackView->playHead()); // Not quite a selection, rather just // for immediate visual feedback... m_pTracks->selectionChangeNotify(); break; case DragLoopStart: // New loop-start boundary... if (pSession->editHead() < pSession->loopEnd()) { // Yep, new loop-start point... pSession->execute( new qtractorSessionLoopCommand(pSession, pSession->editHead(), pSession->loopEnd())); } break; case DragPunchIn: // New punch-in boundary... if (pSession->editHead() < pSession->punchOut()) { // Yep, new punch-in point... pSession->setPunch( pSession->editHead(), pSession->punchOut()); // For visual feedback... m_pTracks->contentsChangeNotify(); } break; case DragEditHead: // Not quite a contents change, but for visual feedback... m_pTracks->selectionChangeNotify(); break; case DragLoopEnd: // New loop-end boundary... if (pSession->loopStart() < pSession->editTail()) { // Yep, new loop-end point... pSession->execute( new qtractorSessionLoopCommand(pSession, pSession->loopStart(), pSession->editTail())); } break; case DragPunchOut: // New punch-out boundary... if (pSession->punchIn() < pSession->editTail()) { // Yep, new punch-out point... pSession->setPunch( pSession->punchIn(), pSession->editTail()); // For visual feedback... m_pTracks->contentsChangeNotify(); } break; case DragEditTail: // Not quite a contents change, but for visual feedback... m_pTracks->selectionChangeNotify(); break; case DragMarker: // Marker positioning commit... if (m_pDragMarker) { // Yep, new marker location... pSession->execute( new qtractorTimeScaleMoveMarkerCommand( pSession->timeScale(), m_pDragMarker, iFrame)); } break; case DragStart: // Left-button indirect positioning... if (bModifier) { // Playhead positioning... pTrackView->setPlayHead(iFrame); // Immediately commited... pSession->setPlayHead(iFrame); } else { // Deferred left-button edit-head positioning... pTrackView->setEditHead(iFrame); } // Not quite a selection, rather just // for immediate visual feedback... m_pTracks->selectionChangeNotify(); // Fall thru... case DragNone: default: break; } } // Clean up. resetDragState(); } // Tempo-map dialog accessor. void qtractorTrackTime::mouseDoubleClickEvent ( QMouseEvent *pMouseEvent ) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Direct snap positioning... const QPoint& pos = viewportToContents(pMouseEvent->pos()); const unsigned long iFrame = pSession->frameSnap( pSession->frameFromPixel(pos.x() > 0 ? pos.x() : 0)); // Show tempo map dialog. qtractorTimeScaleForm form(pMainForm); form.setFrame(iFrame); form.exec(); } // Keyboard event handler. void qtractorTrackTime::keyPressEvent ( QKeyEvent *pKeyEvent ) { #ifdef CONFIG_DEBUG_0 fprintf(stderr, "qtractorTrackTime::keyPressEvent(key=%d)\n", pKeyEvent->key()); #endif switch (pKeyEvent->key()) { case Qt::Key_Escape: { // Restore uncommitted play-head position?... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession && m_dragState == DragPlayHead) m_pTracks->trackView()->setPlayHead(pSession->playHead()); resetDragState(); break; } default: qtractorScrollView::keyPressEvent(pKeyEvent); break; } } // Reset drag/select state. void qtractorTrackTime::resetDragState (void) { // Cancel any dragging/cursor out there... if (m_dragState == DragSelect) qtractorScrollView::updateContents(); if (m_dragCursor != DragNone) qtractorScrollView::unsetCursor(); // Force null state. m_dragState = DragNone; m_dragCursor = DragNone; m_pDragMarker = NULL; // HACK: give focus to track-view... m_pTracks->trackView()->setFocus(); } // Context menu event handler (dummy). void qtractorTrackTime::contextMenuEvent ( QContextMenuEvent */*pContextMenuEvent*/ ) { } // Trap for help/tool-tip events. bool qtractorTrackTime::eventFilter ( QObject *pObject, QEvent *pEvent ) { QWidget *pViewport = qtractorScrollView::viewport(); if (static_cast (pObject) == pViewport) { if (pEvent->type() == QEvent::ToolTip && m_dragCursor != DragNone && (m_pTracks->trackView())->isToolTips()) { QHelpEvent *pHelpEvent = static_cast (pEvent); if (pHelpEvent) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { unsigned long iFrame = 0; switch (m_dragCursor) { case DragMarker: if (m_pDragMarker) iFrame = m_pDragMarker->frame; break; case DragPlayHead: iFrame = pSession->playHead(); break; case DragEditHead: iFrame = pSession->editHead(); break; case DragEditTail: iFrame = pSession->editTail(); break; case DragLoopStart: iFrame = pSession->loopStart(); break; case DragLoopEnd: iFrame = pSession->loopEnd(); break; case DragPunchIn: iFrame = pSession->punchIn(); break; case DragPunchOut: iFrame = pSession->punchOut(); break; default: break; } showToolTip(iFrame); } } } else if (pEvent->type() == QEvent::Leave && m_dragState != DragNone) { qtractorScrollView::unsetCursor(); return true; } } // Not handled here. return qtractorScrollView::eventFilter(pObject, pEvent); } // Show dragging tooltip... void qtractorTrackTime::showToolTip ( unsigned long iFrame ) const { if (!m_pTracks->trackView()->isToolTips()) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorTimeScale *pTimeScale = pSession->timeScale(); if (pTimeScale == NULL) return; QString sToolTip; switch (m_dragCursor) { case DragMarker: if (m_pDragMarker) sToolTip += m_pDragMarker->text; break; case DragPlayHead: sToolTip += tr("Play-head"); break; case DragEditHead: sToolTip += tr("Edit-head"); break; case DragEditTail: sToolTip += tr("Edit-tail"); break; case DragLoopStart: sToolTip += tr("Loop-start"); break; case DragLoopEnd: sToolTip += tr("Loop-end"); break; case DragPunchIn: sToolTip += tr("Punch-in"); break; case DragPunchOut: sToolTip += tr("Punch-out"); break; default: break; } if (!sToolTip.isEmpty()) sToolTip += '\n'; sToolTip += pTimeScale->textFromFrame(iFrame); QToolTip::showText(QCursor::pos(), sToolTip, qtractorScrollView::viewport()); } void qtractorTrackTime::showToolTip ( const QRect& rect ) const { if (!m_pTracks->trackView()->isToolTips()) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorTimeScale *pTimeScale = pSession->timeScale(); if (pTimeScale == NULL) return; const unsigned long iFrameStart = pTimeScale->frameSnap( pTimeScale->frameFromPixel(rect.left())); const unsigned long iFrameEnd = pTimeScale->frameSnap( iFrameStart + pTimeScale->frameFromPixel(rect.width())); QToolTip::showText(QCursor::pos(), tr("Start:\t%1\nEnd:\t%2\nLength:\t%3") .arg(pTimeScale->textFromFrame(iFrameStart)) .arg(pTimeScale->textFromFrame(iFrameEnd)) .arg(pTimeScale->textFromFrame(iFrameStart, true, iFrameEnd - iFrameStart)), qtractorScrollView::viewport()); } // end of qtractorTrackTime.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorInsertPlugin.h0000644000175000001440000000012212215372276021625 xustar000000000000000027 mtime=1379267774.934138 26 atime=1381134667.73308 29 ctime=1381134667.73308006 qtractor-0.5.11/src/qtractorInsertPlugin.h0000644000175000001440000001453612215372276021126 0ustar00rncbcusers00000000000000// qtractorInsertPlugin.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. Copyright (C) 2011, Holger Dehnhardt. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorInsertPlugin_h #define __qtractorInsertPlugin_h #include "qtractorPlugin.h" // Forward declarations. class qtractorAudioBus; class qtractorInsertPluginParam; class qtractorAuxSendPluginParam; //---------------------------------------------------------------------------- // qtractorInsertPluginType -- Insert pseudo-plugin type instance. // class qtractorInsertPluginType : public qtractorPluginType { public: // Constructor. qtractorInsertPluginType(unsigned short iChannels) : qtractorPluginType(NULL, iChannels, qtractorPluginType::Insert) {} // Destructor. ~qtractorInsertPluginType() { close(); } // Derived methods. bool open(); void close(); // Compute the number of instances needed // for the given input/output audio channels. unsigned short instances( unsigned short iChannels, bool /*bMidi*/) const { return (iChannels == m_iAudioOuts ? 1 : 0); } // Factory method (static) static qtractorInsertPluginType *createType(unsigned short iChannels); // Specific named accessors. unsigned short channels() const { return index(); } }; //---------------------------------------------------------------------------- // qtractorInsertPlugin -- Insert pseudo-plugin instance. // class qtractorInsertPlugin : public qtractorPlugin { public: // Constructors. qtractorInsertPlugin(qtractorPluginList *pList, qtractorInsertPluginType *pInsertType); // Destructor. ~qtractorInsertPlugin(); // Channel/intsance number accessors. void setChannels(unsigned short iChannels); // Do the actual (de)activation. void activate(); void deactivate(); // The main plugin processing procedure. void process(float **ppIBuffer, float **ppOBuffer, unsigned int nframes); // Plugin configuration handlers. void configure(const QString& sKey, const QString& sValue); // Plugin configuration/state snapshot. void freezeConfigs(); void releaseConfigs(); // Audio specific accessor. qtractorAudioBus *audioBus() const; protected: // Plugin configuration (connections). void freezeConfigs(int iBusMode); private: // Instance variables. qtractorAudioBus *m_pAudioBus; qtractorInsertPluginParam *m_pSendGainParam; qtractorInsertPluginParam *m_pDryWetParam; // Custom optimized processors. void (*m_pfnProcessSendGain)(float **, unsigned int, unsigned short, float); void (*m_pfnProcessDryWet)(float **, float **, unsigned int, unsigned short, float); }; //---------------------------------------------------------------------------- // qtractorInsertPluginParam -- Insert plugin control input port instance. // class qtractorInsertPluginParam : public qtractorPluginParam { public: // Constructors. qtractorInsertPluginParam(qtractorPlugin *pPlugin, unsigned long iIndex) : qtractorPluginParam(pPlugin, iIndex) {} // Port range hints predicate methods. bool isBoundedBelow() const { return true; } bool isBoundedAbove() const { return true; } bool isDefaultValue() const { return true; } bool isLogarithmic() const { return true; } bool isSampleRate() const { return false; } bool isInteger() const { return false; } bool isToggled() const { return false; } bool isDisplay() const { return false; } }; //---------------------------------------------------------------------------- // qtractorAuxSendPluginType -- Aux-send pseudo-plugin type instance. // class qtractorAuxSendPluginType : public qtractorPluginType { public: // Constructor. qtractorAuxSendPluginType(unsigned short iChannels) : qtractorPluginType(NULL, iChannels, qtractorPluginType::AuxSend) {} // Destructor. ~qtractorAuxSendPluginType() { close(); } // Derived methods. bool open(); void close(); // Compute the number of instances needed // for the given input/output audio channels. unsigned short instances( unsigned short iChannels, bool /*bMidi*/) const { return (iChannels == m_iAudioOuts ? 1 : 0); } // Factory method (static) static qtractorAuxSendPluginType *createType(unsigned short iChannels); // Specific named accessors. unsigned short channels() const { return index(); } }; //---------------------------------------------------------------------------- // qtractorAuxSendPlugin -- Aux-send pseudo-plugin instance. // class qtractorAuxSendPlugin : public qtractorPlugin { public: // Constructors. qtractorAuxSendPlugin(qtractorPluginList *pList, qtractorAuxSendPluginType *pInsertType); // Destructor. ~qtractorAuxSendPlugin(); // Channel/intsance number accessors. void setChannels(unsigned short iChannels); // The main plugin processing procedure. void process(float **ppIBuffer, float **ppOBuffer, unsigned int nframes); // Plugin configuration handlers. void configure(const QString& sKey, const QString& sValue); // Plugin configuration/state snapshot. void freezeConfigs(); void releaseConfigs(); // Audio bus specific accessors. void setAudioBusName(const QString& sAudioBusName); const QString& audioBusName() const; // Audio bus to appear on plugin lists. void updateAudioBusName() const; protected: // Do the actual (de)activation. void activate(); void deactivate(); private: // Instance variables. qtractorAudioBus *m_pAudioBus; QString m_sAudioBusName; qtractorInsertPluginParam *m_pSendGainParam; // Custom optimized processors. void (*m_pfnProcessDryWet)(float **, float **, unsigned int, unsigned short, float); }; #endif // __qtractorInsertPlugin_h // end of qtractorInsertPlugin.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorEditRangeForm.cpp0000644000175000001440000000012312166134117022217 xustar000000000000000027 mtime=1373157455.942698 26 atime=1381134666.62608 30 ctime=1381134666.626080043 qtractor-0.5.11/src/qtractorEditRangeForm.cpp0000644000175000001440000002306112166134117021510 0ustar00rncbcusers00000000000000// qtractorEditRangeForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorEditRangeForm.h" #include "qtractorAbout.h" #include "qtractorSession.h" #include "qtractorOptions.h" #include #include //---------------------------------------------------------------------------- // qtractorEditRangeForm -- UI wrapper form. // Constructor. qtractorEditRangeForm::qtractorEditRangeForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::ApplicationModal); // Initialize dirty control state. m_pTimeScale = NULL; // Initial selection range (empty). m_iSelectStart = 0; m_iSelectEnd = 0; m_options = Clips | Automation; m_iUpdate = 0; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { m_pTimeScale = new qtractorTimeScale(*pSession->timeScale()); m_ui.RangeStartSpinBox->setTimeScale(m_pTimeScale); m_ui.RangeEndSpinBox->setTimeScale(m_pTimeScale); // Set proper time scales display format... m_ui.FormatComboBox->setCurrentIndex( int(m_pTimeScale->displayFormat())); // Default selection is whole session... m_iSelectStart = pSession->sessionStart(); m_iSelectEnd = pSession->sessionEnd(); // Populate range options... if (pSession->editHead() < pSession->editTail()) m_ui.EditRangeRadioButton->setChecked(true); else if (pSession->isPunching()) m_ui.PunchRangeRadioButton->setChecked(true); else if (pSession->isLooping()) m_ui.LoopRangeRadioButton->setChecked(true); else m_ui.CustomRangeRadioButton->setChecked(true); } // Update options check-boxes. qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) m_options = pOptions->iEditRangeOptions; updateOptions(); // Try to restore old window positioning. adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.SelectionRangeRadioButton, SIGNAL(toggled(bool)), SLOT(rangeChanged())); QObject::connect(m_ui.LoopRangeRadioButton, SIGNAL(toggled(bool)), SLOT(rangeChanged())); QObject::connect(m_ui.PunchRangeRadioButton, SIGNAL(toggled(bool)), SLOT(rangeChanged())); QObject::connect(m_ui.EditRangeRadioButton, SIGNAL(toggled(bool)), SLOT(rangeChanged())); QObject::connect(m_ui.CustomRangeRadioButton, SIGNAL(toggled(bool)), SLOT(rangeChanged())); QObject::connect(m_ui.FormatComboBox, SIGNAL(activated(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.RangeStartSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(valueChanged())); QObject::connect(m_ui.RangeStartSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.RangeEndSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(valueChanged())); QObject::connect(m_ui.RangeEndSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.ClipsCheckBox, SIGNAL(toggled(bool)), SLOT(optionsChanged())); QObject::connect(m_ui.AutomationCheckBox, SIGNAL(toggled(bool)), SLOT(optionsChanged())); QObject::connect(m_ui.LoopCheckBox, SIGNAL(toggled(bool)), SLOT(optionsChanged())); QObject::connect(m_ui.PunchCheckBox, SIGNAL(toggled(bool)), SLOT(optionsChanged())); QObject::connect(m_ui.MarkersCheckBox, SIGNAL(toggled(bool)), SLOT(optionsChanged())); QObject::connect(m_ui.TempoMapCheckBox, SIGNAL(toggled(bool)), SLOT(optionsChanged())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); // Done. stabilizeForm(); } // Destructor. qtractorEditRangeForm::~qtractorEditRangeForm (void) { // Don't forget to get rid of local time-scale instance... if (m_pTimeScale) delete m_pTimeScale; } // Set the current initial selection range. void qtractorEditRangeForm::setSelectionRange ( unsigned long iSelectStart, unsigned long iSelectEnd ) { m_iSelectStart = iSelectStart; m_iSelectEnd = iSelectEnd; if (m_ui.CustomRangeRadioButton->isChecked()) { m_ui.RangeStartSpinBox->setValue(m_iSelectStart, false); m_ui.RangeEndSpinBox->setValue(m_iSelectEnd, false); } rangeChanged(); } // Retrieve the current range, if the case arises. unsigned long qtractorEditRangeForm::rangeStart (void) const { return m_ui.RangeStartSpinBox->value(); } unsigned long qtractorEditRangeForm::rangeEnd (void) const { return m_ui.RangeEndSpinBox->value(); } // Retrieve range option flags. unsigned int qtractorEditRangeForm::rangeOptions (void) const { return m_options; } // Option flags accessors. void qtractorEditRangeForm::setOption ( Option option, bool bOn ) { if (bOn) m_options |= (unsigned int) (option); else m_options &= ~(unsigned int) (option); } bool qtractorEditRangeForm::isOption ( Option option ) const { return (m_options & (unsigned int) (option)); } // Update options settings. void qtractorEditRangeForm::updateOptions (void) { ++m_iUpdate; m_ui.ClipsCheckBox->setChecked(m_options & Clips); m_ui.AutomationCheckBox->setChecked(m_options & Automation); m_ui.LoopCheckBox->setChecked((m_options & Loop)); m_ui.PunchCheckBox->setChecked(m_options & Punch); m_ui.MarkersCheckBox->setChecked(m_options & Markers); m_ui.TempoMapCheckBox->setChecked(m_options & TempoMap); --m_iUpdate; } // Options changed. void qtractorEditRangeForm::optionsChanged (void) { if (m_iUpdate > 0) return; setOption(Clips, m_ui.ClipsCheckBox->isChecked()); setOption(Automation, m_ui.AutomationCheckBox->isChecked()); setOption(Loop, m_ui.LoopCheckBox->isChecked()); setOption(Punch, m_ui.PunchCheckBox->isChecked()); setOption(Markers, m_ui.MarkersCheckBox->isChecked()); setOption(TempoMap, m_ui.TempoMapCheckBox->isChecked()); stabilizeForm(); } // Range settings have changed. void qtractorEditRangeForm::rangeChanged (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; if (m_ui.SelectionRangeRadioButton->isChecked()) { m_ui.RangeStartSpinBox->setValue(m_iSelectStart, false); m_ui.RangeEndSpinBox->setValue(m_iSelectEnd, false); } else if (m_ui.LoopRangeRadioButton->isChecked()) { m_ui.RangeStartSpinBox->setValue(pSession->loopStart(), false); m_ui.RangeEndSpinBox->setValue(pSession->loopEnd(), false); } else if (m_ui.PunchRangeRadioButton->isChecked()) { m_ui.RangeStartSpinBox->setValue(pSession->punchIn(), false); m_ui.RangeEndSpinBox->setValue(pSession->punchOut(), false); } else if (m_ui.EditRangeRadioButton->isChecked()) { m_ui.RangeStartSpinBox->setValue(pSession->editHead(), false); m_ui.RangeEndSpinBox->setValue(pSession->editTail(), false); } stabilizeForm(); } // Range values have changed. void qtractorEditRangeForm::valueChanged (void) { m_ui.CustomRangeRadioButton->setChecked(true); stabilizeForm(); } // Display format has changed. void qtractorEditRangeForm::formatChanged ( int iDisplayFormat ) { bool bBlockSignals = m_ui.FormatComboBox->blockSignals(true); m_ui.FormatComboBox->setCurrentIndex(iDisplayFormat); qtractorTimeScale::DisplayFormat displayFormat = qtractorTimeScale::DisplayFormat(iDisplayFormat); m_ui.RangeStartSpinBox->setDisplayFormat(displayFormat); m_ui.RangeEndSpinBox->setDisplayFormat(displayFormat); if (m_pTimeScale) m_pTimeScale->setDisplayFormat(displayFormat); m_ui.FormatComboBox->blockSignals(bBlockSignals); stabilizeForm(); } // Stabilize current form state. void qtractorEditRangeForm::stabilizeForm (void) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorTimeScale *pTimeScale = pSession->timeScale(); if (pTimeScale == NULL) return; m_ui.SelectionRangeRadioButton->setEnabled(m_iSelectStart < m_iSelectEnd); m_ui.LoopRangeRadioButton->setEnabled(pSession->isLooping()); m_ui.PunchRangeRadioButton->setEnabled(pSession->isPunching()); m_ui.EditRangeRadioButton->setEnabled( pSession->editHead() < pSession->editTail()); m_ui.LoopCheckBox->setEnabled(pSession->isLooping()); m_ui.PunchCheckBox->setEnabled(pSession->isPunching()); m_ui.MarkersCheckBox->setEnabled(pTimeScale->markers().first() != NULL); m_ui.TempoMapCheckBox->setEnabled(pTimeScale->nodes().count() > 1); m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled( m_ui.RangeStartSpinBox->value() < m_ui.RangeEndSpinBox->value()); } // Dialog acceptance. void qtractorEditRangeForm::accept (void) { // Update options check-boxes. qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) pOptions->iEditRangeOptions = m_options; QDialog::accept(); } // end of qtractorEditRangeForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioMonitor.h0000644000175000001440000000012212114530147021602 xustar000000000000000026 mtime=1362276455.42997 26 atime=1381134669.03908 30 ctime=1381134669.039080081 qtractor-0.5.11/src/qtractorAudioMonitor.h0000644000175000001440000000461312114530147021076 0ustar00rncbcusers00000000000000// qtractorAudioMonitor.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorAudioMonitor_h #define __qtractorAudioMonitor_h #include "qtractorMonitor.h" //---------------------------------------------------------------------------- // qtractorAudioMonitor -- Audio monitor bridge value processor. class qtractorAudioMonitor : public qtractorMonitor { public: // Constructor. qtractorAudioMonitor(unsigned short iChannels, float fGain = 1.0f, float fPanning = 0.0f); // Destructor. ~qtractorAudioMonitor(); // Channel property accessors. void setChannels(unsigned short iChannels); unsigned short channels() const; // Value holder accessor. float value(unsigned short iChannel) const; // Batch processors. void process(float **ppFrames, unsigned int iFrames, unsigned short iChannels = 0); void process_meter(float **ppFrames, unsigned int iFrames, unsigned short iChannels = 0); // Reset channel gain trackers. void reset(); protected: // Rebuild the whole panning-gain array... void update(); private: // Instance variables. unsigned short m_iChannels; float *m_pfValues; float *m_pfGains; float *m_pfPrevGains; volatile int m_iProcessRamp; // Monitoring evaluator processor. void (*m_pfnProcess)(float *, unsigned int, float, float *); void (*m_pfnProcessRamp)(float *, unsigned int, float, float, float *); void (*m_pfnProcessMeter)(float *, unsigned int, float *); }; #endif // __qtractorAudioMonitor_h // end of qtractorAudioMonitor.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorSessionCursor.h0000644000175000001440000000012311701044034022007 xustar000000000000000027 mtime=1325680668.688662 26 atime=1381134666.49308 30 ctime=1381134666.493080041 qtractor-0.5.11/src/qtractorSessionCursor.h0000644000175000001440000000640411701044034021302 0ustar00rncbcusers00000000000000// qtractorSessionCursor.h // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorSessionCursor_h #define __qtractorSessionCursor_h #include "qtractorTrack.h" // Forward declarations. class qtractorClip; //---------------------------------------------------------------------- // class qtractorSessionCursor - declaration. // class qtractorSessionCursor : public qtractorList::Link { public: // Constructor. qtractorSessionCursor(qtractorSession *pSession, unsigned long iFrame = 0, qtractorTrack::TrackType syncType = qtractorTrack::None); // Destructor. ~qtractorSessionCursor(); // Session accessor. qtractorSession *session() const; // General bi-directional locate method. void seek(unsigned long iFrame, bool bSync = false); // Current frame position accessor. unsigned long frame() const; // Absolute frame-time posiion accessors. void setFrameTime(unsigned long iFrameTime); unsigned long frameTime() const; unsigned long frameTimeEx() const; // Clip sync flag accessor. void setSyncType(qtractorTrack::TrackType syncType); qtractorTrack::TrackType syncType() const; // Current track clip accessor. qtractorClip *clip(unsigned int iTrack) const; // Add a track to cursor. void addTrack (qtractorTrack *pTrack); // Update track after adding/removing a clip from cursor. void updateTrack (qtractorTrack *pTrack); // Remove a track from cursor. void removeTrack (qtractorTrack *pTrack); // Update current track clip under cursor. void updateTrackClip(qtractorTrack *pTrack); // Reset cursor. void reset(); // Reset track/clips cache. void resetClips(); // Frame-time processor (increment only). void process(unsigned int nframes); protected: // Clip locate method. qtractorClip *seekClip(qtractorTrack *pTrack, qtractorClip *pClip, unsigned long iFrame) const; // Update (stabilize) cursor. void updateClips(qtractorClip **ppClips, unsigned int iTracks); // Remove a track from cursor (by index). void removeTrack (unsigned int iTrack); private: // Instance variables. qtractorSession *m_pSession; unsigned long m_iFrame; unsigned long m_iFrameTime; unsigned long m_iFrameDelta; qtractorTrack::TrackType m_syncType; unsigned int m_iTracks; qtractorClip **m_ppClips; unsigned int m_iSize; }; #endif // __qtractorSessionCursor_h // end of qtractorSessionCursor.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorSessionDocument.cpp0000644000175000001440000000012311514076275022661 xustar000000000000000027 mtime=1295023293.370359 26 atime=1381134668.06908 30 ctime=1381134668.069080066 qtractor-0.5.11/src/qtractorSessionDocument.cpp0000644000175000001440000000412511514076275022152 0ustar00rncbcusers00000000000000// qtractorSessionDocument.cpp // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorSessionDocument.h" #include "qtractorSession.h" //------------------------------------------------------------------------- // qtractorSessionDocument -- Session file import/export helper class. // // Constructor. qtractorSessionDocument::qtractorSessionDocument ( QDomDocument *pDocument, qtractorSession *pSession, qtractorFiles *pFiles ) : qtractorDocument(pDocument, "session") { m_pSession = pSession; m_pFiles = pFiles; } // Default destructor. qtractorSessionDocument::~qtractorSessionDocument (void) { } // Session accessor. qtractorSession *qtractorSessionDocument::session (void) const { return m_pSession; } // File list accessor. qtractorFiles *qtractorSessionDocument::files (void) const { return m_pFiles; } // The elemental loader implementation. bool qtractorSessionDocument::loadElement ( QDomElement *pElement ) { return m_pSession->loadElement(this, pElement); } // The elemental saver implementation. bool qtractorSessionDocument::saveElement ( QDomElement *pElement ) { return m_pSession->saveElement(this, pElement); } // end of qtractorSessionDocument.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTempoAdjustForm.h0000644000175000001440000000012312166134117022261 xustar000000000000000027 mtime=1373157455.942698 26 atime=1381134670.52808 30 ctime=1381134670.602080106 qtractor-0.5.11/src/qtractorTempoAdjustForm.h0000644000175000001440000000464512166134117021561 0ustar00rncbcusers00000000000000// qtractorTempoAdjustForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorTempoAdjustForm_h #define __qtractorTempoAdjustForm_h #include "ui_qtractorTempoAdjustForm.h" // Forward declarations. class QTime; //---------------------------------------------------------------------------- // qtractorTempoAdjustForm -- UI wrapper form. class qtractorTempoAdjustForm : public QDialog { Q_OBJECT public: // Constructor. qtractorTempoAdjustForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorTempoAdjustForm(); // Range accessors. void setRangeStart(unsigned long iRangeStart); unsigned long rangeStart() const; void setRangeLength(unsigned long iRangeLength); unsigned long rangeLength() const; unsigned short rangeBeats() const; // Accepted results accessors. float tempo() const; unsigned short beatsPerBar() const; unsigned short beatDivisor() const; protected slots: void accept(); void reject(); void changed(); void adjust(); void tempoTap(); void tempoChanged(float, unsigned short, unsigned short); void rangeStartChanged(unsigned long); void rangeLengthChanged(unsigned long); void selectChanged(); void formatChanged(int); void stabilizeForm(); private: // The Qt-designer UI struct... Ui::qtractorTempoAdjustForm m_ui; // Instance variables... qtractorTimeScale *m_pTimeScale; QTime *m_pTempoTap; int m_iTempoTap; float m_fTempoTap; int m_iDirtySetup; int m_iDirtyCount; }; #endif // __qtractorTempoAdjustForm_h // end of qtractorTempoAdjustForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditEvent.h0000644000175000001440000000012212075634407021675 xustar000000000000000027 mtime=1358379271.965668 26 atime=1381134670.87808 29 ctime=1381134670.87808011 qtractor-0.5.11/src/qtractorMidiEditEvent.h0000644000175000001440000000767012075634407021177 0ustar00rncbcusers00000000000000// qtractorMidiEditEvent.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiEditEvent_h #define __qtractorMidiEditEvent_h #include "qtractorScrollView.h" #include "qtractorMidiEvent.h" #include // Forward declarations. class qtractorMidiEditor; class qtractorRubberBand; class QResizeEvent; class QMouseEvent; class QKeyEvent; class QToolButton; //---------------------------------------------------------------------------- // qtractorMidiEditEventScale -- MIDI event scale widget. class qtractorMidiEditEventScale : public QWidget { Q_OBJECT public: // Constructor. qtractorMidiEditEventScale(qtractorMidiEditor *pEditor, QWidget *pParent); // Default destructor. ~qtractorMidiEditEventScale(); protected: // Specific event handlers. void paintEvent(QPaintEvent *); // Draw IEC scale line and label. void drawLineLabel(QPainter *p, int y, const QString& sLabel); private: // Local instance variables. qtractorMidiEditor *m_pEditor; // Running variables. int m_iLastY; }; //---------------------------------------------------------------------------- // qtractorMidiEditEvent -- MIDI sequence event view widget. class qtractorMidiEditEvent : public qtractorScrollView { Q_OBJECT public: // Constructor. qtractorMidiEditEvent(qtractorMidiEditor *pEditor, QWidget *pParent); // Destructor. ~qtractorMidiEditEvent(); // Rectangular contents update. void updateContents(const QRect& rect); // Overall contents update. void updateContents(); // Current event selection accessors. void setEventType(qtractorMidiEvent::EventType eventType); qtractorMidiEvent::EventType eventType() const; void setController(unsigned char controller); unsigned char controller() const; protected: // Virtual size hint. QSize sizeHint() const { return QSize(480, 120); } // Resize event handler. void resizeEvent(QResizeEvent *pResizeEvent); // Draw the time scale. void drawContents(QPainter *pPainter, const QRect& rect); // Focus lost event. void focusOutEvent(QFocusEvent *pFocusEvent); // Keyboard event handler. void keyPressEvent(QKeyEvent *pKeyEvent); // Handle item selection with mouse. void mousePressEvent(QMouseEvent *pMouseEvent); void mouseMoveEvent(QMouseEvent *pMouseEvent); void mouseReleaseEvent(QMouseEvent *pMouseEvent); // Handle zoom with mouse wheel. void wheelEvent(QWheelEvent *pWheelEvent); // Trap for help/tool-tip and leave events. bool eventFilter(QObject *pObject, QEvent *pEvent); protected slots: // To have timeline in h-sync with main track view. void contentsXMovingSlot(int cx, int cy); // (Re)create the time scale pixmap. void updatePixmap(int cx, int cy); private: // The logical parent binding. qtractorMidiEditor *m_pEditor; // Local zoom control widgets. QToolButton *m_pHzoomOut; QToolButton *m_pHzoomIn; QToolButton *m_pHzoomReset; // Local double-buffering pixmap. QPixmap m_pixmap; // Current selection holders. qtractorMidiEvent::EventType m_eventType; unsigned char m_controller; }; #endif // __qtractorMidiEditEvent_h // end of qtractorMidiEditEvent.h qtractor-0.5.11/src/PaxHeaders.10084/vestige0000644000175000001440000000013212224470513016634 xustar000000000000000030 mtime=1381134667.283080053 30 atime=1381134667.283080053 30 ctime=1381134667.283080053 qtractor-0.5.11/src/vestige/0000755000175000001440000000000012224470513016200 5ustar00rncbcusers00000000000000qtractor-0.5.11/src/vestige/PaxHeaders.10084/aeffectx.h0000644000175000001440000000012311754441523020655 xustar000000000000000027 mtime=1337082707.599096 26 atime=1381134667.28308 30 ctime=1381134667.283080053 qtractor-0.5.11/src/vestige/aeffectx.h0000644000175000001440000002203111754441523020142 0ustar00rncbcusers00000000000000/* * aeffectx.h - simple header to allow VeSTige compilation and eventually work * * Copyright (c) 2006 Javier Serrano Polo * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * 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., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * */ #ifndef _AEFFECTX_H #define _AEFFECTX_H #define CCONST(a, b, c, d)( ( ( (int) a ) << 24 ) | \ ( ( (int) b ) << 16 ) | \ ( ( (int) c ) << 8 ) | \ ( ( (int) d ) << 0 ) ) const int audioMasterAutomate = 0; const int audioMasterVersion = 1; const int audioMasterCurrentId = 2; const int audioMasterIdle = 3; const int audioMasterPinConnected = 4; // unsupported? 5 const int audioMasterWantMidi = 6; const int audioMasterGetTime = 7; const int audioMasterProcessEvents = 8; const int audioMasterSetTime = 9; const int audioMasterTempoAt = 10; const int audioMasterGetNumAutomatableParameters = 11; const int audioMasterGetParameterQuantization = 12; const int audioMasterIOChanged = 13; const int audioMasterNeedIdle = 14; const int audioMasterSizeWindow = 15; const int audioMasterGetSampleRate = 16; const int audioMasterGetBlockSize = 17; const int audioMasterGetInputLatency = 18; const int audioMasterGetOutputLatency = 19; const int audioMasterGetPreviousPlug = 20; const int audioMasterGetNextPlug = 21; const int audioMasterWillReplaceOrAccumulate = 22; const int audioMasterGetCurrentProcessLevel = 23; const int audioMasterGetAutomationState = 24; const int audioMasterOfflineStart = 25; const int audioMasterOfflineRead = 26; const int audioMasterOfflineWrite = 27; const int audioMasterOfflineGetCurrentPass = 28; const int audioMasterOfflineGetCurrentMetaPass = 29; const int audioMasterSetOutputSampleRate = 30; // unsupported? 31 const int audioMasterGetSpeakerArrangement = 31; // deprecated in 2.4? const int audioMasterGetVendorString = 32; const int audioMasterGetProductString = 33; const int audioMasterGetVendorVersion = 34; const int audioMasterVendorSpecific = 35; const int audioMasterSetIcon = 36; const int audioMasterCanDo = 37; const int audioMasterGetLanguage = 38; const int audioMasterOpenWindow = 39; const int audioMasterCloseWindow = 40; const int audioMasterGetDirectory = 41; const int audioMasterUpdateDisplay = 42; const int audioMasterBeginEdit = 43; const int audioMasterEndEdit = 44; const int audioMasterOpenFileSelector = 45; const int audioMasterCloseFileSelector = 46; // currently unused const int audioMasterEditFile = 47; // currently unused const int audioMasterGetChunkFile = 48; // currently unused const int audioMasterGetInputSpeakerArrangement = 49; // currently unused const int effFlagsHasEditor = 1; const int effFlagsCanReplacing = 1 << 4; // very likely const int effFlagsIsSynth = 1 << 8; // currently unused const int effOpen = 0; const int effClose = 1; // currently unused const int effSetProgram = 2; // currently unused const int effGetProgram = 3; // currently unused const int effGetProgramName = 5; // currently unused const int effGetParamName = 8; // currently unused const int effSetSampleRate = 10; const int effSetBlockSize = 11; const int effMainsChanged = 12; const int effEditGetRect = 13; const int effEditOpen = 14; const int effEditClose = 15; const int effEditIdle = 19; const int effEditTop = 20; const int effProcessEvents = 25; const int effGetEffectName = 45; const int effGetParameterProperties = 47; // missing const int effGetVendorString = 47; const int effGetProductString = 48; const int effGetVendorVersion = 49; const int effCanDo = 51; // currently unused const int effGetVstVersion = 58; // currently unused const int kEffectMagic = CCONST( 'V', 's', 't', 'P' ); const int kVstLangEnglish = 1; const int kVstMidiType = 1;; const int kVstTransportPlaying = 1 << 1; /* validity flags for a VstTimeInfo structure, this info comes from the web */ const int kVstNanosValid (1 << 8); const int kVstPpqPosValid (1 << 9); const int kVstTempoValid (1 << 10); const int kVstBarsValid (1 << 11); const int kVstCyclePosValid (1 << 12); const int kVstTimeSigValid (1 << 13); const int kVstSmpteValid (1 << 14); const int kVstClockValid (1 << 15); const int kVstTransportChanged = 1; class RemoteVstPlugin; class VstMidiEvent { public: // 00 int type; // 04 int byteSize; // 08 int deltaFrames; // 0c? int flags; // 10? int noteLength; // 14? int noteOffset; // 18 char midiData[4]; // 1c? char detune; // 1d? char noteOffVelocity; // 1e? char reserved1; // 1f? char reserved2; } ; class VstEvent { char dump[sizeof( VstMidiEvent )]; } ; class VstEvents { public: // 00 int numEvents; // 04 void *reserved; // 08 VstEvent * events[]; } ; /* constants from http://www.rawmaterialsoftware.com/juceforum/viewtopic.php?t=3740&sid=183f74631fee71a493316735e2b9f28b */ enum Vestige2StringConstants { VestigeMaxNameLen = 64, VestigeMaxLabelLen = 64, VestigeMaxShortLabelLen = 8, VestigeMaxCategLabelLen = 24, VestigeMaxFileNameLen = 100 }; /* this struct taken from http://asseca.com/vst-24-specs/efGetParameterProperties.html */ struct VstParameterProperties { float stepFloat; /* float step */ float smallStepFloat; /* small float step */ float largeStepFloat; /* large float step */ char label[VestigeMaxLabelLen]; /* parameter label */ int32_t flags; /* @see VstParameterFlags */ int32_t minInteger; /* integer minimum */ int32_t maxInteger; /* integer maximum */ int32_t stepInteger; /* integer step */ int32_t largeStepInteger; /* large integer step */ char shortLabel[VestigeMaxShortLabelLen]; /* short label, recommended: 6 + delimiter */ int16_t displayIndex; /* index where this parameter should be displayed (starting with 0) */ int16_t category; /* 0: no category, else group index + 1 */ int16_t numParametersInCategory; /* number of parameters in category */ int16_t reserved; /* zero */ char categoryLabel[VestigeMaxCategLabelLen]; /* category label, e.g. "Osc 1" */ char future[16]; /* reserved for future use */ }; /* this enum taken from http://asseca.com/vst-24-specs/efGetParameterProperties.html */ enum VstParameterFlags { kVstParameterIsSwitch = 1 << 0, /* parameter is a switch (on/off) */ kVstParameterUsesIntegerMinMax = 1 << 1, /* minInteger, maxInteger valid */ kVstParameterUsesFloatStep = 1 << 2, /* stepFloat, smallStepFloat, largeStepFloat valid */ kVstParameterUsesIntStep = 1 << 3, /* stepInteger, largeStepInteger valid */ kVstParameterSupportsDisplayIndex = 1 << 4, /* displayIndex valid */ kVstParameterSupportsDisplayCategory = 1 << 5, /* category, etc. valid */ kVstParameterCanRamp = 1 << 6 /* set if parameter value can ramp up/down */ }; class AEffect { public: // Never use virtual functions!!! // 00-03 int magic; // dispatcher 04-07 intptr_t (* dispatcher)( AEffect * , int , int , intptr_t, void * , float ); // process, quite sure 08-0b void (* process)( AEffect * , float * * , float * * , int ); // setParameter 0c-0f void (* setParameter)( AEffect * , int , float ); // getParameter 10-13 float (* getParameter)( AEffect * , int ); // programs 14-17 int numPrograms; // Params 18-1b int numParams; // Input 1c-1f int numInputs; // Output 20-23 int numOutputs; // flags 24-27 int flags; // Fill somewhere 28-2b void *ptr1; void *ptr2; // Zeroes 2c-2f 30-33 34-37 38-3b char empty3[4 + 4 + 4]; // 1.0f 3c-3f float unkown_float; // An object? pointer 40-43 void *ptr3; // Zeroes 44-47 void *user; // Id 48-4b int32_t uniqueID; // Don't know 4c-4f char unknown1[4]; // processReplacing 50-53 void (* processReplacing)( AEffect * , float * * , float * * , int ); } ; typedef struct VstTimeInfo { /* info from online documentation of VST provided by Steinberg */ double samplePos; double sampleRate; double nanoSeconds; double ppqPos; double tempo; double barStartPos; double cycleStartPos; double cycleEndPos; int32_t timeSigNumerator; int32_t timeSigDenominator; int32_t smpteOffset; int32_t smpteFrameRate; int32_t samplesToNextClock; int32_t flags; } VstTimeInfo; typedef intptr_t (* audioMasterCallback)( AEffect * , int32_t, int32_t, intptr_t, void * , float ); #endif qtractor-0.5.11/src/PaxHeaders.10084/translations0000644000175000001440000000013212224470515017711 xustar000000000000000030 mtime=1381134669.668080091 30 atime=1381134669.060080082 30 ctime=1381134669.668080091 qtractor-0.5.11/src/translations/0000755000175000001440000000000012224470515017255 5ustar00rncbcusers00000000000000qtractor-0.5.11/src/translations/PaxHeaders.10084/qtractor_ja.ts0000644000175000001440000000012312224024425022642 xustar000000000000000027 mtime=1380985109.058459 26 atime=1381134669.48008 30 ctime=1381134669.668080091 qtractor-0.5.11/src/translations/qtractor_ja.ts0000644000175000001440000167474612224024425022162 0ustar00rncbcusers00000000000000 QObject Audio: %1 channels, %2 Hz 音声: %1 ãƒãƒ£ãƒ³ãƒãƒ«ã€%2 Hz (%1 dB) (%1% time stretch) (%1% タイムストレッãƒ) (%1 semitones pitch shift) %1 In %1 入力 %1 Out %1 出力 Audio files (%1) 音声ファイル (%1) All files (*.*) 全ファイル (*.*) %1 (%2) %3 channels, %4 frames, %5 Hz %6 %1 (%2) %3 ãƒãƒ£ãƒ³ãƒãƒ«ã€%4 フレームã€%5 Hz %6 Duplex 入出力 Output 出力 Input 入力 None ãªã— Name: %1 åå‰: %1 Start / End: %1 / %2 Offset / Length: %3 / %4 é–‹å§‹ / 終了: %1 / %2 オフセット / é•·ã• %3 / %4 (take %1) (テイク %1) Start / End: %1 / %2 Offs. / Len.: %3 / %4 é–‹å§‹ / 終了:→%1 / %2 オフセット / é•·ã•: %3 / %4 File: %1 ファイル: %1 take %1 テイク %1 reset takes テイクをリセット insert range ãƒ¬ãƒ³ã‚¸ã®æŒ¿å…¥ insert track range ãƒˆãƒ©ãƒƒã‚¯ãƒ¬ãƒ³ã‚¸ã®æŒ¿å…¥ automation select オートメーションã®é¸æŠž automation mode オートメーションã®ãƒ¢ãƒ¼ãƒ‰ automation play オートメーションã®å†ç”Ÿ automation record オートメーションã®è¨˜éŒ² automation logarithmic オートメーションã®å¯¾æ•°è¡¨ç¤º automation color オートメーションã®é…色 automation play all オートメーションをã™ã¹ã¦å†ç”Ÿ automation record all オートメーションをã™ã¹ã¦è¨˜éŒ² automation edit オートメーションã®ç·¨é›† automation clear オートメーションã®ã‚¯ãƒªã‚¢ automation clear all オートメーションをã™ã¹ã¦ã‚¯ãƒªã‚¢ automation edit list オートメーションã®ç·¨é›†ãƒªã‚¹ãƒˆ %1 Monitor %1 モニター create bus ãƒã‚¹ã®ä½œæˆ update bus ãƒã‚¹ã®æ›´æ–° delete bus ãƒã‚¹ã®å‰Šé™¤ bus pass-through ãƒã‚¹ã®ãƒ‘ススルー bus gain ãƒã‚¹ã®ã‚²ã‚¤ãƒ³ bus pan ãƒã‚¹ã®ãƒ‘ン Send Gain Sendã®ã‚²ã‚¤ãƒ³ Dry / Wet Cakewalk Instrument Definition File Cakewalkã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ«ãƒ¡ãƒ³ãƒˆå®šç¾©ãƒ•ァイル File ファイル Date 日付 %1 Bank %2 %1 ãƒãƒ³ã‚¯ %2 %1 - Bank %2 %1 - ãƒãƒ³ã‚¯ %2 (format %1) MIDI: (フォーマット %1) MIDI: Channel %1 ãƒãƒ£ãƒ³ãƒãƒ« %1 Track %1 トラック %1 , %1 tracks, %2 tpqn , %1 トラック〠%2 tpqn (%1% vol) (%1% ボリューム) set controller コントローラーをセット reset controller コントローラーをリセット %1 (format %2) %3 tracks, %4 tpqn %5 %1 (フォーマット %2) %3 トラックã€%4 tpqn %5 %1 (format %2) %3 %1 (フォーマット %2) %3 (default) (デフォルト) %1 Hz %1 Hz slave スレーブ %1 (%2) %1 (%2) Usage: %1 [options] [session-file] 使用法: %1 [オプション] [セッションファイル] Options: オプション: Set session identification (uuid) セッションã®ID (uuid) をセット Show help about command line options コマンドラインオプションã«é–¢ã™ã‚‹ãƒ˜ãƒ«ãƒ—を表示 Show version information ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…報を表示ã—ã¾ã™ Option -s requires an argument (session-id). -sオプションã¯å¼•æ•°ã¨ã—ã¦session-idã‚’å¿…è¦ã¨ã—ã¾ã™ã€‚ Qt: %1 (Any) (ä»»æ„) add plugin プラグインã®è¿½åŠ  add insert インサートã®è¿½åŠ  add aux-send Aux-Sendã®è¿½åŠ  aux-send bus Aux-Sendãƒã‚¹ã®è¿½åŠ  remove plugin プラグインã®é™¤åŽ» move plugin プラグインã®ç§»å‹• activate plugin プラグインを有効化 preset plugin プラグインã®ãƒ—リセット reset plugin プラグインã®ãƒªã‚»ãƒƒãƒˆ dedicated audio outputs 音声出力専用 direct access param ダイレクトアクセスパラメーター session loop セッションをループ session punch セッションパンムsession properties セッションã®ãƒ—ロパティー Beat add tempo node テンãƒãƒŽãƒ¼ãƒ‰ã‚’追加 update tempo node テンãƒãƒŽãƒ¼ãƒ‰ã‚’æ›´æ–° remove tempo node テンãƒãƒŽãƒ¼ãƒ‰ã‚’除去 move tempo node テンãƒãƒŽãƒ¼ãƒ‰ã‚’移動 add marker マーカーã®è¿½åŠ  update marker ãƒžãƒ¼ã‚«ãƒ¼ã®æ›´æ–° remove marker マーカーã®é™¤åŽ» move marker マーカーã®ç•°å‹• %1 Record %1 記録 %1 Mute %1 ミュート %1 Solo %1 ソロ %1 Volume %1 ボリューム %1 Gain %1 ゲイン %1 Pan %1 パニング add track トラックã®è¿½åŠ  remove track トラックã®é™¤åŽ» move track トラックã®ç§»å‹• resize track トラックã®ãƒªã‚µã‚¤ã‚º import track トラックã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ track properties トラックã®ãƒ—ロパティー Track assignment failed: Track: "%1" Input: "%2" Output: "%3" トラックã®å‰²ã‚Šå½“ã¦ã«å¤±æ•—ã—ã¾ã—ãŸ: トラック: "%1" 入力: "%2" 出力: "%3" track record トラックを録音 track mute トラックミュート track solo トラックをソロ track monitor トラックモニター track gain トラックゲイン track pan トラックパニング Automation (%1) オートメーション (%1) none ãªã— Automation オートメーション Audio 音声 MIDI MIDI Unknown 䏿˜Ž %1 (*.%2) qtractorAudioListView Name åå‰ Ch ãƒãƒ£ãƒ³ãƒãƒ« Frames フレーム Rate レート Time 時間 Path パス Open Audio Files 音声ファイルを開ã qtractorAudioMeter Gain (dB) ゲイン (dB) dB dB Pan: %1 パン: %1 Gain: %1 dB ゲイン: %1 dB qtractorBusForm Buses - Qtractor ãƒã‚¹ - Qtractor Bus list ãƒã‚¹ãƒªã‚¹ãƒˆ Buses ãƒã‚¹ Ch ãƒãƒ£ãƒ³ãƒãƒ« Mode モード Bus ãƒã‚¹ Properties プロパティ &Name: åå‰(&N): Bus name ãƒã‚¹ã®åå‰ &Mode: モード(&M): Bus mode ãƒã‚¹ã®ãƒ¢ãƒ¼ãƒ‰ Input 入力 Output 出力 Duplex 入出力 Bus monitor (pass-through) ãƒã‚¹ã‚’モニターã—ã¾ã™ (パススルー) M&onitor (pass-through) モニター(パススルー)(&O) Alt+O Audio 音声 Cha&nnels: ãƒãƒ£ãƒ³ãƒãƒ«(&N): Audio channels 音声ãƒãƒ£ãƒ³ãƒãƒ« Audio auto-connect 音声を自動接続 &Auto connect 自動接続(&A) Alt+A MIDI MIDI MIDI Instrument name MIDIインストルメントå MIDI SysEx setup MIDI SysExã®è¨­å®š SysE&x... Input Plugins 入力プラグイン Input bus plugins 入力ãƒã‚¹ãƒ—ラグイン Add input plugin 入力プラグインã®è¿½åŠ  &Add... 追加(&A)... Remove input plugin 入力プラグインを除去 &Remove 除去(&R) Alt+R Move input plugin up 入力プラグインを上ã¸ç§»å‹• &Up 上ã¸(&U) Alt+U Move input plugin down 入力プラグインを下ã¸ç§»å‹• &Down 下ã¸(&D) Alt+D Output Plugins 出力プラグイン Output bus plugins 出力ãƒã‚¹ã®ãƒ—ラグイン Add output plugin 出力プラグインを追加 Remove output plugin 出力プラグインを除去 Move output plugin up 出力プラグインを下ã¸ç§»å‹• Move output plugin down 出力プラグインを下ã¸ç§»å‹• Refresh bus list view ãƒã‚¹ãƒªã‚¹ãƒˆã®è¡¨ç¤ºã‚’æ›´æ–° &Refresh æ›´æ–°(&R) Create bus ãƒã‚¹ã‚’ä½œæˆ &Create 作æˆ(&C) Alt+C Update bus ãƒã‚¹ã‚’アップデート &Update アップデート(&U) Delete bus ãƒã‚¹ã‚’削除 &Delete 削除(&D) Close this dialog ã“ã®ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ã‚’é–‰ã˜ã¾ã™ Close é–‰ã˜ã‚‹ Warning 警告 Some settings have been changed. Do you want to apply the changes? 設定ã®ä¸€éƒ¨ãŒå¤‰æ›´ã•れã¾ã—㟠ã“ã®å¤‰æ›´ã‚’é©ç”¨ã—ã¾ã™ã‹? About to remove bus: "%1" (%2) Are you sure? ã“ã®ãƒã‚¹ã‚’除去ã—ã¾ã™: "%1" (%2) よã‚ã—ã„ã§ã™ã‹ï¼Ÿ Some settings have been changed. Do you want to discard the changes? 設定ã®ä¸€éƒ¨ãŒå¤‰æ›´ã•れã¾ã—㟠ã“ã®å¤‰æ›´ã‚’破棄ã—ã¾ã™ã‹ï¼Ÿ (No instrument) (インストルメントã¯ã‚りã¾ã›ã‚“) (none) (ãªã—) (1 item) (1アイテム) (%1 items) (%1アイテム) qtractorClientListView Readable Clients / Output Ports 出力å¯èƒ½ãªã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ / 出力ãƒãƒ¼ãƒˆ Writable Clients / Input Ports 入力å¯èƒ½ãªã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ / 入力ãƒãƒ¼ãƒˆ qtractorClipForm Clip - Qtractor クリップ - Qtractor &Name: åå‰(&N): Clip name クリップã®åå‰ &File: ファイル(&F): Clip filename クリップã®ãƒ•ァイルå Browse for clip file クリップファイルã®é¸æŠž Track/&Channel: トラック/ãƒãƒ£ãƒ³ãƒãƒ«(&C): Clip track/channel クリップã®ãƒˆãƒ©ãƒƒã‚¯/ãƒãƒ£ãƒ³ãƒãƒ« &Gain/Volume: ゲイン/ボリューム(&G): Clip gain/volume クリップã®ã‚²ã‚¤ãƒ³/ボリューム Parameters パラメーター Clip start クリップã®é–‹å§‹ä½ç½® Clip offset クリップã®ã‚ªãƒ•セットä½ç½® Clip length クリップã®é•·ã• Offs&et: オフセット(&E): &Length: é•·ã•(&L): &Start: é–‹å§‹(&S): Gain/Volume ゲイン/ボリューム Format フォーマット Time display format 時間表示フォーマット Frames フレーム Fra&mes フレーム(&M) Time (hh:mm:ss.zzz) 時間 (hh:mm:ss.zzz) &Time 時間(&T) BBT (bars.beats.ticks) BBT (ãƒãƒ¼ ビート ãƒãƒƒã‚¯) Time 時間 BBT Fade In/Out フェードイン/アウト Fade &In: フェードイン(&I): Clip fade-in length クリップã®ãƒ•ェードインã®é•·ã• Clip fade-in type クリップã®ãƒ•ェードインã®ã‚¿ã‚¤ãƒ— Fade &Out: フェードアウト(&O): Clip fade-out length クリップã®ãƒ•ェードアウトã®é•·ã• Clip fade-out type クリップã®ãƒ•ェードアウトã®ã‚¿ã‚¤ãƒ— Audio 音声 Time St&retch: タイムストレッãƒ(&R): Clip time-stretch percentage クリップã®ã‚¿ã‚¤ãƒ ã‚¹ãƒˆãƒ¬ãƒƒãƒã®ãƒ‘ーセンテージ % Pitch S&hift: ピッãƒã‚·ãƒ•ト(&H): Clip pitch-shift in semitones semitones &Gain: ゲイン(&G): dB dB &Volume: 音é‡(&V): new clip æ–°ã—ã„クリップ edit clip クリップを編集 Warning 警告 Some settings have been changed. Do you want to apply the changes? 設定ã®ä¸€éƒ¨ãŒå¤‰æ›´ã•れã¾ã—㟠ã“ã®å¤‰æ›´ã‚’é©ç”¨ã—ã¾ã™ã‹? MIDI MIDI MIDI files (*.%1 *.smf *.midi) MIDIファイル (*.%1 *.smf *.midi) %1 Clip File %1 クリップファイル qtractorConnect Connect 接続 Disconnect 切断 Disconnect All ã™ã¹ã¦åˆ‡æ–­ Refresh æ›´æ–° qtractorConnectForm qtractorConnectTest qtractor接続テスト Audio 音声 Select output client/ports 出力クライアント/ãƒãƒ¼ãƒˆã®é¸æŠž Select input client/ports 入力クライアント/ãƒãƒ¼ãƒˆã®é¸æŠž Connect currently selected ports ç¾åœ¨é¸æŠžã•れã¦ã„ã‚‹ãƒãƒ¼ãƒˆã‚’接続 &Connect 接続(&C) Alt+C Disconnect currently selected ports ç¾åœ¨é¸æŠžã•れã¦ã„ã‚‹ãƒãƒ¼ãƒˆã‚’切断 &Disconnect 切断(&D) Alt+D Disconnect all currently connected ports ç¾åœ¨æŽ¥ç¶šã•れã¦ã„ã‚‹ã™ã¹ã¦ã®ãƒãƒ¼ãƒˆã‚’切断 Disconnect &All ã™ã¹ã¦åˆ‡æ–­(&A) Alt+A Refresh current connections view ç¾åœ¨ã®æŽ¥ç¶šç”»é¢ã‚’æ›´æ–° &Refresh æ›´æ–°(&R) Alt+R MIDI MIDI (All) (ã™ã¹ã¦) qtractorConnections Connections 接続 qtractorCurveButton Automation (%1) オートメーション (%1) none ãªã— qtractorEditRangeForm Range - Qtractor レンジ - Qtractor Range レンジ Selection range é¸æŠžãƒ¬ãƒ³ã‚¸ &Selection é¸æŠž(&S) Loop range ループレンジ &Loop ループ(&L) Punch range パンãƒãƒ¬ãƒ³ã‚¸ &Punch パンãƒ(&P) Edit range 編集レンジ &Edit 編集(&E) Custom range ä»»æ„ã®ãƒ¬ãƒ³ã‚¸ &Custom カスタム(&C) St&art: é–‹å§‹(&A): Clip start クリップã®é–‹å§‹ä½ç½® En&d: 終了(&D): Clip offset クリップã®ã‚ªãƒ•セットä½ç½® Apply to Loop points in range レンジをループãƒã‚¤ãƒ³ãƒˆã«é©ç”¨ L&oop ループ(&O) Apply to Punch In/Out points in range レンジをパンãƒã‚¤ãƒ³/パンãƒã‚¢ã‚¦ãƒˆã«é©ç”¨ Pu&nch パンãƒ(&N) Mar&kers マーカー(&K) Te&mpo Map テンãƒãƒžãƒƒãƒ—(&M) &Format フォーマット(&F) Time display format 時間表示フォーマット Time 時間 BBT Format フォーマット Frames フレーム &Frames フレーム(&F) Time (hh:mm:ss.zzz) 時間 (hh:mm:ss.zzz) &Time 時間(&T) BBT (bars.beats.ticks) BBT (ãƒãƒ¼ ビート ãƒãƒƒã‚¯) Options オプション Apply to clips in range レンジをクリップã«é©ç”¨ Cl&ips クリップ(&I) A&utomation オートメーション(&U) Apply to Automation nodes in range レンジをオートメーションノードã«é©ç”¨ &Automation オートメーション(&A) Apply to Tempo Map nodes in range レンジをテンãƒãƒžãƒƒãƒ—ã«é©ç”¨ Apply to location Markers in range レンジをロケーションマーカーã«é©ç”¨ qtractorExportForm Export - Qtractor エクスãƒãƒ¼ãƒˆ - Qtractor &File: ファイル(&F): Export file name エクスãƒãƒ¼ãƒˆã™ã‚‹ãƒ•ァイルå Browse export file name エクスãƒãƒ¼ãƒˆã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž Range レンジ Session range セッションレンジ &Session セッション(&S) Loop range ループレンジ &Loop ループ(&L) Punch range パンãƒãƒ¬ãƒ³ã‚¸ &Punch パンãƒ(&P) Edit range 編集レンジ &Edit 編集(&E) Custom range ä»»æ„ã®ãƒ¬ãƒ³ã‚¸ &Custom カスタム(&C) St&art: é–‹å§‹(&A): Clip start クリップã®é–‹å§‹ä½ç½® En&d: 終了(&D): Clip offset クリップã®ã‚ªãƒ•セット Output 出力 Output bus name 出力ãƒã‚¹å Format フォーマット Time display format 時間表示フォーマット Frames フレーム Time 時間 BBT &Frames フレーム(&F) Time (hh:mm:ss.zzz) 時間 (hh:mm:ss.zzz) &Time 時間(&T) BBT (bars.beats.ticks) BBT (ãƒãƒ¼ ビート ãƒãƒƒã‚¯) Audio 音声 MIDI MIDI Export %1 %1ã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ Warning 警告 The file already exists: "%1" Do you want to replace it? ファイルã¯ã™ã§ã«å­˜åœ¨ã—ã¾ã™: "%1" ç½®ãã‹ãˆã¾ã™ã‹ï¼Ÿ Audio file export: "%1" started... 音声ファイルã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ: "%1" é–‹å§‹... Audio file export: "%1" complete. 音声ファイルã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ: "%1" 完了。 Audio file export: "%1" failed. 音声ファイルã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ: "%1" 失敗。 MIDI file export: "%1" started... MIDIファイルã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ: "%1" é–‹å§‹... MIDI file export: "%1" complete. MIDIファイルã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ: "%1" 完了。 MIDI file export: "%1" failed. MIDIファイルã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ: "%1" 失敗。 Export %1 File %1 ファイルã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ %1 files (*.%1) %1 ファイル (*.%1) qtractorFileListView New Group æ–°ã—ã„グループ Warning 警告 About to remove %1 file items. Are you sure? %1ファイルアイテムを削除ã—ã¾ã™ã€‚ よã‚ã—ã„ã§ã™ã‹ï¼Ÿ About to remove %1 file item(s). Are you sure? %1ファイルアイテムを除去ã—ã¾ã™ã€‚ よã‚ã—ã„ã§ã™ã‹ï¼Ÿ About to remove %1 item: "%2" Are you sure? %1アイテムを除去ã—ã¾ã™: "%2" よã‚ã—ã„ã§ã™ã‹ï¼Ÿ group グループ file ファイル qtractorFiles Audio 音声 MIDI MIDI Play file ファイルをå†ç”Ÿ New &Group æ–°è¦ã‚°ãƒ«ãƒ¼ãƒ—(&G) Add &Files... ファイルを追加(&F)... Cu&t 切りå–り(&T) &Copy コピー(&C) P&aste 貼り付ã‘(&A) R&ename リãƒãƒ¼ãƒ (&E) &Delete 削除(&D) Play å†ç”Ÿ Ctrl+X Ctrl+C Ctrl+V New &Group... æ–°ã—ã„グループ(&G)... &Paste 貼り付ã‘(&P) Re&name åå‰ã®å¤‰æ›´(&N) &Remove 除去(&R) Pla&y å†ç”Ÿ(&Y) Cl&eanup クリーンアップ(&E) Del Files ファイル MIDI Files MIDIファイル Audio Files 音声ファイル qtractorInstrumentForm Instruments - Qtractor インストルメント - Qtractor Instruments インストルメント Files ファイル Path パス Names åå‰ Import from instrument file インストルメントファイルã‹ã‚‰ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ &Import... インãƒãƒ¼ãƒˆ(&I)... Alt+I Remove instrument file インストルメントファイルã®é™¤åŽ» &Remove 除去(&R) Alt+R Move instrument file up on list order インストルメントファイルを上ã«ç§»å‹• &Up 上ã¸(&U) Alt+U Move instrument file down on list order インストルメントファイルを下ã«ç§»å‹• &Down 下ã¸(&D) Alt+D Reload all instrument files ã™ã¹ã¦ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ«ãƒ¡ãƒ³ãƒˆãƒ•ァイルをリロード Relo&ad リロード(&A) Alt+A Export to instrument file インストルメントファイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ E&xport... エクスãƒãƒ¼ãƒˆ(&X)... Alt+X Close this dialog ダイアログを閉ã˜ã¾ã™ Close é–‰ã˜ã‚‹ Import Instrument Files インストルメントファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ Instrument files (*.%1 *.sf2 *.midnam) インストルメントファイル (*.%1 *.sf2 *.midnam) Export Instrument File インストルメントファイルã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ Instrument files (*.%1) インストルメントファイル (*.%1) Warning 警告 The instrument file already exists: "%1" Do you want to replace it? インストルメントファイルã¯ã™ã§ã«å­˜åœ¨ã—ã¾ã™: "%1" ç½®ãã‹ãˆã¾ã™ã‹ï¼Ÿ Instrument settings have been changed. Do you want to apply the changes? インストルメントã®è¨­å®šãŒå¤‰æ›´ã•れã¾ã—ãŸã€‚ 変更をé©ç”¨ã—ã¾ã™ã‹ï¼Ÿ Patch Names for Banks ãƒãƒ³ã‚¯ã®ãƒ‘ッãƒå Controller Names = %1 コントローラーå = %1 RPN Names = %1 RPNå = %1 NRPN Names = %1 NRPNå = %1 Bank Select Method = %1 ãƒãƒ³ã‚¯ã‚»ãƒ¬ã‚¯ãƒˆæ–¹æ³• = %1 Patch Names パッãƒå Note Names ノートå Controller Names コントローラーå RPN Names RPNå NRPN Names NRPNå Bank Select Methods ãƒãƒ³ã‚¯ã‚»ãƒ¬ã‚¯ãƒˆæ–¹æ³• %1 = %2 Based On = %1 基準 = %1 Normal ノーマル Bank MSB ãƒãƒ³ã‚¯MSB Bank LSB ãƒãƒ³ã‚¯LSB Patch パッムUnknown 䏿˜Ž qtractorMainForm Qtractor &File ファイル(&F) Open &Recent 最近ã®ãƒ•ァイルを開ã(&R) &Edit 編集(&E) Select &Mode é¸æŠžãƒ¢ãƒ¼ãƒ‰(&M) &Select é¸æŠž(&S) I&nsert 挿入(&N) Remo&ve 除去(&V) &Track トラック(&T) &State 状態(&S) &Navigate ナビゲート(&N) Mo&ve 移動(&V) &Height 高ã•(&H) Impor&t Tracks トラックã¸ã‚¤ãƒ³ãƒãƒ¼ãƒˆ(&T) E&xport Tracks トラックをエクスãƒãƒ¼ãƒˆ(&X) M&ode モード(&O) A&utomation オートメーション(&U) Cl&ip クリップ(&I) T&ools ツール(&O) Ta&ke テイク(&K) &View 表示(&V) &Toolbars ツールãƒãƒ¼(&T) &Windows ウィンドウ(&W) &Zoom ズーム(&Z) S&nap スナップ(&N) T&ransport トランスãƒãƒ¼ãƒˆ(&R) &Help ヘルプ(&H) &New æ–°è¦(&N) New æ–°è¦ New session æ–°è¦ã‚»ãƒƒã‚·ãƒ§ãƒ³ New session file æ–°ã—ã„セッションファイルを作æˆã—ã¾ã™ Ctrl+N &Open... é–‹ã(&O)... Open é–‹ã Open session セッションを開ã Open session from file ファイルã‹ã‚‰ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’é–‹ãã¾ã™ Ctrl+O &Save ä¿å­˜(&S) Save ä¿å­˜ Save session セッションをä¿å­˜ Save session to file セッションをファイルã«ä¿å­˜ã—ã¾ã™ Ctrl+S Save &As... åå‰ã‚’付ã‘ã¦ä¿å­˜(&A)... Save As åå‰ã‚’付ã‘ã¦ä¿å­˜ Save as åå‰ã‚’付ã‘ã¦ä¿å­˜ Save current session with another file name ç¾åœ¨ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’別ãªãƒ•ァイルåã§ä¿å­˜ã—ã¾ã™ &Properties... プロパティ(&P)... Session Properties セッションã®ãƒ—ロパティ Session properties セッションã®ãƒ—ロパティ Edit current session properties ç¾åœ¨ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ãƒ—ロパティを編集ã—ã¾ã™ F2 E&xit 終了(&X) Exit 終了 Exit this application program ã“ã®ã‚½ãƒ•トウェアを終了ã—ã¾ã™ &Undo å…ƒã«æˆ»ã™(&U) Undo å…ƒã«æˆ»ã™ Undo last action 最後ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã‚’å…ƒã«æˆ»ã—ã¾ã™ Ctrl+Z &Redo やり直ã™(&R) Redo やり直㙠Redo last action 最後ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã‚’やり直ã—ã¾ã™ Ctrl+Shift+Z Cu&t 切りå–り(&T) Cut 切りå–り Cut selection to clipboard レンジをクリップボードã¸åˆ‡ã‚Šå–りã¾ã™ Ctrl+X &Copy コピー(&C) Copy コピー Copy selection to clipboard レンジをクリップボードã«ã‚³ãƒ”ーã—ã¾ã™ Ctrl+C &Paste 貼り付ã‘(&P) Paste 貼り付㑠Paste clipboard contents クリップボードã®å†…容を貼り付ã‘ã¾ã™ Ctrl+V Past&e Repeat... 繰り返ã—ã¦è²¼ã‚Šä»˜ã‘(&E)... Paste Repeat 繰り返ã—ã¦è²¼ã‚Šä»˜ã‘ Paste repeat 繰り返ã—ã¦è²¼ã‚Šä»˜ã‘ã‚‹ Paste/repeat clipboard contents クリップボードã®å†…容を繰り返ã—貼付ã‘ã¾ã™ Ctrl+Shift+V &Delete 削除(&D) Delete 削除 Delete selection レンジを削除ã—ã¾ã™ Del 削除 &Clip クリップ(&C) Clip クリップ Select clip ã‚¯ãƒªãƒƒãƒ—ã‚’é¸æŠž Clip selection mode クリップã§é¸æŠžã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã§ã™ &Range レンジ(&R) Range レンジ Select range ãƒ¬ãƒ³ã‚¸ã‚’é¸æŠž Range selection mode ãƒ¬ãƒ³ã‚¸ã‚’é¸æŠžã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã§ã™ R&ectangle 矩形(&E) Rect çŸ©å½¢é¸æŠž Select rectangle 矩形ã§é¸æŠžã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã§ã™ Rectangular selection mode 矩形ã§é¸æŠžã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã§ã™ &Automation オートメーション(&A) Automation オートメーション Automation edit mode オートメーションを編集ã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã§ã™ &All ã™ã¹ã¦(&A) Select All ã™ã¹ã¦ã‚’é¸æŠž Select all ã™ã¹ã¦é¸æŠž Mark all as selected ã™ã¹ã¦ã‚’é¸æŠžæ¸ˆã¿ã«ã—ã¾ã™ Ctrl+A &None ãªã—(&N) Select None é¸æŠžè§£é™¤ Select none é¸æŠžè§£é™¤ Mark all as unselected ã™ã¹ã¦ã®é¸æŠžã‚’解除ã—ã¾ã™ Ctrl+Shift+A &Invert å転(&I) Select Invert é¸æŠžã®å転 Select invert é¸æŠžã®å転 Invert selection é¸æŠžéƒ¨åˆ†ã‚’å転ã—ã¾ã™ Ctrl+I Select Track ãƒˆãƒ©ãƒƒã‚¯ã‚’é¸æŠž Select track ãƒˆãƒ©ãƒƒã‚¯ã‚’é¸æŠž Mark track as selected ãƒˆãƒ©ãƒƒã‚¯ã‚’é¸æŠžæ¸ˆã¿ã«ã—ã¾ã™ Ctrl+T Trac&k Range トラックレンジ(&K) Select Track Range トラックレンジã®é¸æŠž Select track range ãƒˆãƒ©ãƒƒã‚¯ãƒ¬ãƒ³ã‚¸ã‚’é¸æŠžã—ã¾ã™ Mark track range as selected ãƒˆãƒ©ãƒƒã‚¯ãƒ¬ãƒ³ã‚¸ã‚’é¸æŠžæ¸ˆã¿ã«ã—ã¾ã™ Ctrl+Shift+R Select Range é¸æŠžãƒ¬ãƒ³ã‚¸ Mark range as selected ãƒ¬ãƒ³ã‚¸ã‚’é¸æŠžæ¸ˆã¿ã«ã—ã¾ã™ Ctrl+R &Range... レンジ(&R)... Remove Range レンジã®é™¤åŽ» Remove range レンジを除去ã—ã¾ã™ Remove range as selected é¸æŠžã•れã¦ã„るレンジã®é™¤åŽ» Ctrl+Del Remove Track Range トラックレンジã®é™¤åŽ» Remove track range トラックレンジを除去ã—ã¾ã™ Remove track range as selected é¸æŠžã•れã¦ã„るトラックレンジã®é™¤åŽ» Ctrl+Shift+Del Insert Range ãƒ¬ãƒ³ã‚¸ã®æŒ¿å…¥ Insert range レンジを挿入 Insert range as selected é¸æŠžãƒ¬ãƒ³ã‚¸ã‚’æŒ¿å…¥ã—ã¾ã™ Ctrl+Ins Insert Track Range ãƒˆãƒ©ãƒƒã‚¯ãƒ¬ãƒ³ã‚¸ã®æŒ¿å…¥ Insert track range トラックレンジを挿入 Insert track range as selected é¸æŠžã—ãŸãƒˆãƒ©ãƒƒã‚¯ãƒ¬ãƒ³ã‚¸ã‚’挿入ã—ã¾ã™ Ctrl+Shift+Ins Sp&lit 分割(&L) Split Selection é¸æŠžã®åˆ†å‰² Split selection é¸æŠžã®åˆ†å‰² Split current selection ç¾åœ¨ã®é¸æŠžç¯„囲を分割ã—ã¾ã™ Ctrl+Y &Add Track... トラックを追加(&A)... Add Track トラックを追加 Add track トラックを追加 Add a new track to session ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«æ–°è¦ãƒˆãƒ©ãƒƒã‚¯ã‚’追加ã—ã¾ã™ Shift+Ins &Remove Track トラックを除去(&R) Remove Track トラックを除去 Remove track トラックを除去 Remove current track from session セッションã‹ã‚‰ãƒˆãƒ©ãƒƒã‚¯ã‚’除去ã—ã¾ã™ Shift+Del Track &Properties... トラックã®ãƒ—ロパティ(&P)... Track Properties トラックã®ãƒ—ロパティ Track properties トラックã®ãƒ—ロパティ Edit current track properties é¸æŠžã—ã¦ã„るトラックã®ãƒ—ロパティを編集ã—ã¾ã™ Shift+F2 &Inputs 入力(&I) Track Inputs トラック入力 Track inputs トラック入力 Show current track input bus connections ç¾åœ¨ã®ãƒˆãƒ©ãƒƒã‚¯ã¸ã®å…¥åŠ›ãƒã‚¹æŽ¥ç¶šã‚’表示ã—ã¾ã™ &Outputs 出力(&O) Track Outputs トラック出力 Track outputs トラック出力 Show current track output bus connections ç¾åœ¨ã®ãƒˆãƒ©ãƒƒã‚¯ã‹ã‚‰ã®å‡ºåŠ›ãƒã‚¹æŽ¥ç¶šã‚’表示ã—ã¾ã™ &Record 録音(&R) Record Track トラックã®éŒ²éŸ³ Record track トラックã®éŒ²éŸ³ Arm current track for recording ç¾åœ¨ã®ãƒˆãƒ©ãƒƒã‚¯ã‚’録音状態ã«ã—ã¾ã™ &Mute ミュート(&M) Mute Track トラックã®ãƒŸãƒ¥ãƒ¼ãƒˆ Mute track トラックã®ãƒŸãƒ¥ãƒ¼ãƒˆ Mute current track ç¾åœ¨ã®ãƒˆãƒ©ãƒƒã‚¯ã‚’ミュートã«ã—ã¾ã™ &Solo ソロ(&S) Solo Track トラックã®ã‚½ãƒ­ Solo track トラックã®ã‚½ãƒ­ Solo current track ç¾åœ¨ã®ãƒˆãƒ©ãƒƒã‚¯ã‚’ソロã«ã—ã¾ã™ M&onitor モニター(&O) Monitor Track トラックã®ãƒ¢ãƒ‹ã‚¿ãƒ¼ Monitor track トラックã®ãƒ¢ãƒ‹ã‚¿ãƒ¼ Monitor current track ç¾åœ¨ã®ãƒˆãƒ©ãƒƒã‚¯ã‚’モニターã—ã¾ã™ &First 先頭ã¸(&F) First Track 先頭ã®ãƒˆãƒ©ãƒƒã‚¯ First track 先頭ã®ãƒˆãƒ©ãƒƒã‚¯ Make current the first track 先頭ã®ãƒˆãƒ©ãƒƒã‚¯ã‚’é¸æŠžã—ã¾ã™ &Previous å‰ã¸(&P) Previous Track å‰ã®ãƒˆãƒ©ãƒƒã‚¯ Previous track å‰ã®ãƒˆãƒ©ãƒƒã‚¯ Make current the previous track å‰ã®ãƒˆãƒ©ãƒƒã‚¯ã‚’é¸æŠžã—ã¾ã™ &Next 次ã¸(&N) Next Track 次ã®ãƒˆãƒ©ãƒƒã‚¯ Next track 次ã®ãƒˆãƒ©ãƒƒã‚¯ Make current the next track 次ã®ãƒˆãƒ©ãƒƒã‚¯ã‚’é¸æŠžã—ã¾ã™ &Last 末尾ã¸(&L) Last Track 末尾ã®ãƒˆãƒ©ãƒƒã‚¯ Last track 末尾ã®ãƒˆãƒ©ãƒƒã‚¯ Make current the last track 末尾ã®ãƒˆãƒ©ãƒƒã‚¯ã‚’é¸æŠžã—ã¾ã™ N&one é¸æŠžè§£é™¤(&O) None Track é¸æŠžè§£é™¤ None track é¸æŠžè§£é™¤ None current track トラックã®é¸æŠžã‚’解除ã—ã¾ã™ &Top 最上段ã«(&T) Move Top 最上段ã«ç§»å‹• Move top 最上段ã«ç§»å‹• Move current track to top ç¾åœ¨ã®ãƒˆãƒ©ãƒƒã‚¯ã‚’最上段ã«ç§»å‹•ã—ã¾ã™ &Up 上ã«(&U) Move Up 上ã«ç§»å‹• Move up 上ã«ç§»å‹• Move current track up ç¾åœ¨ã®ãƒˆãƒ©ãƒƒã‚¯ã‚’上ã«ç§»å‹•ã—ã¾ã™ &Down 下ã«(&D) Move Down 下ã«ç§»å‹• Move down 下ã«ç§»å‹• Move current track down ç¾åœ¨ã®ãƒˆãƒ©ãƒƒã‚¯ã‚’下ã«ç§»å‹•ã—ã¾ã™ &Bottom 最下段ã«(&B) Move Bottom 最下段ã«ç§»å‹• Move bottom 最下段ã«ç§»å‹• Move current track to bottom ç¾åœ¨ã®ãƒˆãƒ©ãƒƒã‚¯ã‚’最下段ã«ç§»å‹•ã—ã¾ã™ &Increase 広ã’ã‚‹(&I) Increase Height 高ã•を広ã’ã‚‹ Increase height 高ã•を広ã’ã‚‹ Increase track height トラックã®é«˜ã•を広ã’ã¾ã™ Ctrl+Shift++ &Decrease ç‹­ã‚ã‚‹(&D) Decrease Height 高ã•ã‚’ç‹­ã‚ã‚‹ Decrease height 高ã•ã‚’ç‹­ã‚ã‚‹ Decrease track height トラックã®é«˜ã•ã‚’ç‹­ã‚ã¾ã™ Ctrl+Shift+- &Reset リセット(&R) Height Reset 高ã•ã®ãƒªã‚»ãƒƒãƒˆ Height reset 高ã•ã®ãƒªã‚»ãƒƒãƒˆ Reset track height トラックã®é«˜ã•をリセットã—ã¾ã™ Ctrl+Shift+1 Auto &Monitor オートモニター(&M) Auto Monitor オートモニター Auto monitor オートモニター Auto-monitor current track ç¾åœ¨ã®ãƒˆãƒ©ãƒƒã‚¯ã‚’オートモニタリングã—ã¾ã™ F6 &Audio... 音声(&A)... Inport Audio File 音声ファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ Import Audio file 音声ファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ Import tracks from Audio file 音声ファイルã‹ã‚‰ãƒˆãƒ©ãƒƒã‚¯ã‚’インãƒãƒ¼ãƒˆã—ã¾ã™ &MIDI... MIDI(&M)... Import MIDI File MIDIファイルをインãƒãƒ¼ãƒˆ Import MIDI file MIDIファイルをインãƒãƒ¼ãƒˆ Import tracks from MIDI file MIDIファイルã‹ã‚‰ãƒˆãƒ©ãƒƒã‚¯ã‚’インãƒãƒ¼ãƒˆã—ã¾ã™ Export Audio File 音声ファイルã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ Export Audio file 音声ファイルã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ Export tracks to Audio file 音声ファイルã¸ãƒˆãƒ©ãƒƒã‚¯ã‚’エクスãƒãƒ¼ãƒˆã—ã¾ã™ Export MIDI File MIDIファイルã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ Export MIDI file MIDIファイルã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ Export tracks to MIDI file トラックをMIDIファイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ Log&arithmic 対数表示(&A) Automation logarithmic オートメーションã®å¯¾æ•°è¡¨ç¤º Automation curve logarithmic scale オートメーションカーブを対数表示ã—ã¾ã™ C&olor... é…色(&O)... Automation color オートメーションã®é…色 Automation curve color オートメーションカーブã®é…色を指定ã—ã¾ã™ &Lock ロック(&L) Automation lock オートメーションã®ãƒ­ãƒƒã‚¯ Lock automation curve オートメーションカーブをロックã—ã¾ã™ &Play å†ç”Ÿ(&P) Automation playback オートメーションã®å†ç”Ÿ Playback automation curve オートメーションカーブをå†ç”Ÿã—ã¾ã™ Automation record オートメーションを記録 Record automation curve オートメーションカーブを記録ã—ã¾ã™ &Clear クリアー(&C) Automation clear オートメーションã®ã‚¯ãƒªã‚¢ãƒ¼ Clear automation curve オートメーションカーブをクリアーã—ã¾ã™ Loc&k All ã™ã¹ã¦ãƒ­ãƒƒã‚¯(&K) Automation lock all 全オートメーションをロックã—ã¾ã™ Lock all automation curves ã™ã¹ã¦ã®ã‚ªãƒ¼ãƒˆãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚«ãƒ¼ãƒ–をロックã—ã¾ã™ Play &All ã™ãºã¦å†ç”Ÿ(&A) Automation playback all 全オートメーションå†ç”Ÿ Playback all automation curves ã™ã¹ã¦ã®ã‚ªãƒ¼ãƒˆãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚«ãƒ¼ãƒ–ã‚’å†ç”Ÿã—ã¾ã™ Rec&ord All ã™ã¹ã¦è¨˜éŒ²(&O) Automation record all 全オートメーションã®è¨˜éŒ² Record all automation curves ã™ã¹ã¦ã®ã‚ªãƒ¼ãƒˆãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚«ãƒ¼ãƒ–を記録ã—ã¾ã™ C&lear All ã™ã¹ã¦ã‚¯ãƒªã‚¢ãƒ¼(&L) Automation clear all 全オートメーションクリアー Clear all automation curves ã™ã¹ã¦ã®ã‚ªãƒ¼ãƒˆãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚«ãƒ¼ãƒ–をクリアーã—ã¾ã™ &New... æ–°è¦(&N)... New Clip æ–°è¦ã‚¯ãƒªãƒƒãƒ— New clip æ–°è¦ã‚¯ãƒªãƒƒãƒ— Create new clip æ–°è¦ã«ã‚¯ãƒªãƒƒãƒ—を作æˆã—ã¾ã™ &Edit... 編集(&E)... Edit Clip クリップを編集 Edit clip クリップを編集 Edit current clip é¸æŠžã—ã¦ã„るクリップを編集ã—ã¾ã™ F4 &Unlink リンク解除(&U) Unlink Clip クリップã®ãƒªãƒ³ã‚¯ã‚’解除 Unlink clip クリップã®ãƒªãƒ³ã‚¯ã‚’解除 Unlink current clip ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—ã®ãƒªãƒ³ã‚¯ã‚’解除ã—ã¾ã™ &Split 分割(&S) Split Clip クリップを分割 Split clip クリップを分割 Split current clip at playhead æ¼”å¥ä½ç½®ã‹ã‚‰ã‚¯ãƒªãƒƒãƒ—を分割ã—ã¾ã™ &Merge... çµåˆ(&M)... Merge Clips クリップをçµåˆ Merge clips クリップをçµåˆ Merge selected clips é¸æŠžã—ã¦ã„るクリップをçµåˆã—ã¾ã™ N&ormalize ノーマライズ(&O) Normalize Clip クリップをノーマライズ Normalize clip クリップをノーマライズ Normalize current clip (gain/volume) クリップã®ã‚²ã‚¤ãƒ³/ボリュームをノーマライズã—ã¾ã™ &Quantize... クォンタイズ(&Q)... Quantize Clip クリップをクオンタイズ Quantize clip events クリップã®ã‚¤ãƒ™ãƒ³ãƒˆã‚’クォンタイズ Quantize current MIDI clip events MIDIクリップã®ã‚¤ãƒ™ãƒ³ãƒˆã‚’クォンタイズã—ã¾ã™ &Transpose... トランスãƒãƒ¼ã‚º(&T)... Transpose Clip クリップã®ãƒˆãƒ©ãƒ³ã‚¹ãƒãƒ¼ã‚º Transpose clip events クリップイベントã®ãƒˆãƒ©ãƒ³ã‚¹ãƒãƒ¼ã‚º Transpose current MIDI clip events ç¾åœ¨ã®MIDIクリップイベントをトランスãƒãƒ¼ã‚ºã—ã¾ã™ &Normalize... ノーマライズ(&N)... Normalize clip events クリップイベントã®ãƒŽãƒ¼ãƒžãƒ©ã‚¤ã‚º Normalize current MIDI clip events ç¾åœ¨ã®MIDIクリップイベントをノーマライズã—ã¾ã™ &Randomize... ランダマイズ(&R)... Randomize Clip クリップã®ãƒ©ãƒ³ãƒ€ãƒžã‚¤ã‚º Randomize clip events クリップイベントã®ãƒ©ãƒ³ãƒ€ãƒžã‚¤ã‚º Randomize current MIDI clip events ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—イベントをランダムã«ã—ã¾ã™ Resi&ze... リサイズ(&Z)... Resize Clip クリップã®ãƒªã‚µã‚¤ã‚º Resize clip events クリップイベントã®ãƒªã‚µã‚¤ã‚º Resize current MIDI clip events ç¾åœ¨ã®MIDIクリップイベントをリサイズã—ã¾ã™ Re&scale... リスケール(&S)... Rescale Clip クリップã®ãƒªã‚¹ã‚±ãƒ¼ãƒ« Rescale clip events クリップイベントã®ãƒªã‚¹ã‚±ãƒ¼ãƒ« Rescale current MIDI clip events ç¾åœ¨ã®MIDIクリップã®ã‚¤ãƒ™ãƒ³ãƒˆã‚’リスケールã—ã¾ã™ T&imeshift... タイムシフト(&I)... Timeshift Clip クリップã®ã‚¿ã‚¤ãƒ ã‚·ãƒ•ト Timeshift clip events クリップイベントã®ã‚¿ã‚¤ãƒ ã‚·ãƒ•ト Timeshift current MIDI clip events ç¾åœ¨ã®MIDIクリップã®ã‚¤ãƒ™ãƒ³ãƒˆã‚’タイムシフトã—ã¾ã™ &Tempo... テンãƒ(&T)... Tempo Adjust テンãƒã®èª¿æ•´ Adjust session tempo from current clip selection ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—é¸æŠžã‹ã‚‰ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ãƒ†ãƒ³ãƒã‚’調整ã—ã¾ã™ F7 &Range Set レンジを設定(&R) Clip Range クリップレンジ Clip range クリップレンジ Set edit-range from current clip extents ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—ã®é•·ã•をレンジã«é¸æŠžã—ã¾ã™ &Loop Set ループを設定(&L) Clip Loop クリップループ Clip loop クリップループ Set loop-range from current clip extents ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—ã®é•·ã•ã ã‘ループレンジを設定ã—ã¾ã™ &Import... インãƒãƒ¼ãƒˆ(&I)... Import Clip クリップã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ Import clip クリップã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ Import clip from file(s) ファイルã‹ã‚‰ã‚¯ãƒªãƒƒãƒ—をインãƒãƒ¼ãƒˆã—ã¾ã™ E&xport... エクスãƒãƒ¼ãƒˆ(&X)... Export Clip クリップã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ Export clip クリップã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ Export current clip to file ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—をファイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ First Take 最åˆã®ãƒ†ã‚¤ã‚¯ First take 最åˆã®ãƒ†ã‚¤ã‚¯ Select current clip first take ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—ã®æœ€åˆã®ãƒ†ã‚¤ã‚¯ã‚’é¸æŠžã—ã¾ã™ Previous Take å‰ã®ãƒ†ã‚¤ã‚¯ Previous take å‰ã®ãƒ†ã‚¤ã‚¯ Select current clip previous take ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—ã®å‰ã®ãƒ†ã‚¤ã‚¯ã‚’é¸æŠžã—ã¾ã™ Next Take 次ã®ãƒ†ã‚¤ã‚¯ Next take 次ã®ãƒ†ã‚¤ã‚¯ Select current clip next take ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—ã®æ¬¡ã®ãƒ†ã‚¤ã‚¯ã‚’é¸æŠžã—ã¾ã™ Shift+T Last Take 最後ã®ãƒ†ã‚¤ã‚¯ Last take 最後ã®ãƒ†ã‚¤ã‚¯ Select current clip last take ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—ã®æœ€å¾Œã®ãƒ†ã‚¤ã‚¯ã‚’é¸æŠžã—ã¾ã™ Reset Takes テイクã®ãƒªã‚»ãƒƒãƒˆ Reset takes テイクã®ãƒªã‚»ãƒƒãƒˆ Reset (unfold) current clip takes ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—ã®ãƒ†ã‚¤ã‚¯ã‚’リセットã—ã¾ã™ R&ange... レンジ(&R)... Take Range テイクã®ãƒ¬ãƒ³ã‚¸ Take range テイクレンジ Range (fold) current clip into takes ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—ã«ãƒ¬ãƒ³ã‚¸ã‚’設定ã—ã¾ã™ &Menubar メニューãƒãƒ¼(&M) Menubar メニューãƒãƒ¼ Show/hide the main program window menubar メインウィンドウã®ãƒ„ールãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ Ctrl+M &Statusbar ステータスãƒãƒ¼(&S) Statusbar ステータスãƒãƒ¼ Show/hide the main program window statusbar メインウィンドウã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ File Toolbar ファイルツールãƒãƒ¼ File toolbar ファイルツールãƒãƒ¼ Show/hide main program window file toolbar メインウィンドウã®ãƒ•ァイルツールãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ Edit Toolbar エディットツールãƒãƒ¼ Edit toolbar エディットツールãƒãƒ¼ Show/hide main program window edit toolbar エディットツールãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ Track Toolbar トラックツールãƒãƒ¼ Track toolbar トラックツールãƒãƒ¼ Show/hide main program window track toolbar トラックツールãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ View Toolbar ビューツールãƒãƒ¼ View toolbar ビューツールãƒãƒ¼ Show/hide main program window view toolbar ビューツールãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ &Options オプション(&O) Options Toolbar オプションツールãƒãƒ¼ Options toolbar オプションツールãƒãƒ¼ Show/hide main program window options toolbar オプションツールãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ Transport Toolbar トランスãƒãƒ¼ãƒˆãƒ„ールãƒãƒ¼ Transport toolbar トランスãƒãƒ¼ãƒˆãƒ„ールãƒãƒ¼ Show/hide main program window transport toolbar トランスãƒãƒ¼ãƒˆãƒ„ールãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ T&ime 時間(&I) Time Toolbar 時間ツールãƒãƒ¼ Time toolbar 時間ツールãƒãƒ¼ Show/hide main program window time toolbar 時間表示ツールãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ Thum&b 縮å°è¡¨ç¤º(&B) Thumb Toolbar 縮å°è¡¨ç¤ºãƒ„ールãƒãƒ¼ Thumb toolbar 縮å°è¡¨ç¤ºãƒ„ールãƒãƒ¼ Show/hide main program window thumb toolbar 縮å°è¡¨ç¤ºãƒ„ールãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ &Files ファイル(&F) Files ファイル Show/hide the files window ファイルウィンドウを表示/éš ã™ M&essages メッセージ(&E) Messages メッセージ Show/hide the messages window メッセージウィンドウを表示/éš ã™ &Connections 接続(&C) Connections 接続 Show/hide the connections window 接続ウィンドウを表示/éš ã™ F8 Mi&xer ミキサー(&X) Mixer ミキサー Show/hide the mixer window ミキサーウィンドウを表示/éš ã™ F9 &In イン(&I) Zoom In ズームイン Zoom in ズームイン Ctrl++ &Out アウト(&O) Zoom Out ズームアウト Zoom out ズームアウト Ctrl+- Zoom Reset ズームリセット Zoom reset ズームリセット Ctrl+1 &Horizontal 水平方å‘(&H) Horizontal Zoom 水平方å‘ズーム Horizontal zoom 水平方å‘ズーム Horizontal zoom mode 水平方å‘ã«ã‚ºãƒ¼ãƒ ã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã§ã™ &Vertical 垂直方å‘(&V) Vertical Zoom 垂直方å‘ズーム Vertical zoom 垂直方å‘ズーム Vertical zoom mode 垂直方å‘ã«ã‚ºãƒ¼ãƒ ã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã§ã™ All Zoom 垂直水平ズーム All zoom 垂直水平ズーム All zoom mode 垂直水平ã«ã‚ºãƒ¼ãƒ ã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã§ã™ &Grid グリッド(&G) Grid グリッド Snap grid view mode グリッドビューã«ã‚¹ãƒŠãƒƒãƒ—ã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã§ã™ &Zebra Zebra Bar zebra view mode Too&l Tips ツールãƒãƒƒãƒ—(&L) Tool tips ツールãƒãƒƒãƒ— Floating tool tips view mode ツールãƒãƒƒãƒ—をフローティング表示ã—ã¾ã™ &Refresh æ›´æ–°(&R) Refresh æ›´æ–° Refresh views ビューを更新 F5 &Instruments... インストルメント(&I)... Instruments インストルメント Change instrument definitions and files インストルメントã®è¨­å®šã¨ãƒ•ァイルã®å¤‰æ›´ã‚’ã—ã¾ã™ &Controllers... コントローラー(&C)... Controllers コントローラー Change MIDI controllers configuration MIDIコントローラー設定を変更ã—ã¾ã™ &Buses... ãƒã‚¹(&B)... Buses ãƒã‚¹ Change session bus definitions セッションãƒã‚¹å®šç¾©ã‚’変更ã—ã¾ã™ Tempo M&ap / Markers... テンãƒãƒžãƒƒãƒ—/マーカー(&A)... Tempo Map / Markers テンãƒãƒžãƒƒãƒ—/マーカー Tempo map / markers テンãƒãƒžãƒƒãƒ—/マーカー Change session tempo map / markers セッションã®ãƒ†ãƒ³ãƒãƒžãƒƒãƒ—/マーカーを変更ã—ã¾ã™ Tempo M&ap... テンãƒãƒžãƒƒãƒ—(&A)... Tempo Map テンãƒãƒžãƒƒãƒ— Tempo map テンãƒãƒžãƒƒãƒ— Change session tempo map セッションテンãƒãƒžãƒƒãƒ—ã®å¤‰æ›´ &Options... オプション(&O)... Options オプション Change general application program options ソフトウェア全般ã®ã‚ªãƒ—ションを変更ã—ã¾ã™ F12 &Backward 先頭ã¸(&B) Backward 先頭㸠Transport backward トランスãƒãƒ¼ãƒˆã‚’先頭ã¸ç§»å‹•ã—ã¾ã™ Backspace ãƒãƒƒã‚¯ã‚¹ãƒšãƒ¼ã‚¹ Re&wind 逆å†ç”Ÿ(&W) Rewind 逆å†ç”Ÿ Transport rewind トランスãƒãƒ¼ãƒˆã‚’逆å†ç”Ÿã—ã¾ã™ F&ast Forward æ—©é€ã‚Š(&A) Fast Forward æ—©é€ã‚Š Fast forward æ—©é€ã‚Š Transport fast forward トランスãƒãƒ¼ãƒˆã‚’æ—©é€ã‚Šã—ã¾ã™ &Forward 末尾ã¸(&F) Forward 末尾㸠Transport forward トランスãƒãƒ¼ãƒˆã‚’末尾ã¸ç§»å‹•ã—ã¾ã™ &Loop ループ(&L) Loop ループ Transport loop トランスãƒãƒ¼ãƒˆã‚’ループã—ã¾ã™ Ctrl+Shift+L Loop &Set ループセット(&S) Loop Set ループセット Loop set ループセット Transport loop set Ctrl+L &Stop åœæ­¢(&S) Stop åœæ­¢ Transport stop トランスãƒãƒ¼ãƒˆã‚’åœæ­¢ã—ã¾ã™ Play å†ç”Ÿ Transport play/pause トランスãƒãƒ¼ãƒˆã‚’å†ç”Ÿ/ä¸€æ™‚åœæ­¢ã—ã¾ã™ Space スペース Record 記録 Transport record トランスãƒãƒ¼ãƒˆã‚’録音ã—ã¾ã™ &Punch パンãƒ(&P) Punch パンムPunch in/out パンãƒã‚¤ãƒ³/アウト Transport punch in/out Ctrl+Shift+P Punch Se&t パンãƒã‚»ãƒƒãƒˆ(&P) Punch Set パンãƒã‚»ãƒƒãƒˆ Punch in/out set パンãƒã‚¤ãƒ³/アウトセット Transport punch in/out set Ctrl+P &Metronome メトロノーム(&M) Metronome メトロノーム F&ollow Playhead å†ç”Ÿã«è¿½éš(&O) Follow Playhead å†ç”Ÿã«è¿½éš Follow playhead å†ç”Ÿã‚’追ã„ã‹ã‘ã¾ã™ A&uto Backward 自動ã§å…ˆé ­ã«æˆ»ã‚‹(&U) Auto Backward 自動ã§å…ˆé ­ã«æˆ»ã™ Auto backward 自動ã§å…ˆé ­ã«æˆ»ã‚Šã¾ã™ &Continue Past End 終了ä½ç½®ã‚’無視(&C) Continue Past End 終了ä½ç½®ã‚’無視 Continue past end 終了ä½ç½®ã‚’無視ã—ã¾ã™ Pa&nic パニック(&N) Panic パニック All MIDI tracks shut off (panic) ã™ã¹ã¦ã®MIDIトラックをオフã«ã—ã¾ã™ (パニック) &Shortcuts... ショートカット(&S)... Shortcuts ショートカット Keyboard shortcuts キーボードショートカットを表示ã—ã¾ã™ &About... Qtractorã«ã¤ã„ã¦(&A)... About Qtractorã«ã¤ã„㦠Show information about this application program ã“ã®ã‚½ãƒ•トウェアã«é–¢ã™ã‚‹æƒ…報を表示ã—ã¾ã™ About &Qt... Qtã«ã¤ã„ã¦(&Q)... About Qt Qtã«ã¤ã„㦠Show information about the Qt toolkit Qtツールキットã«é–¢ã™ã‚‹æƒ…報を表示ã—ã¾ã™ Current time (playhead) ç¾åœ¨ã®æ™‚é–“ (先頭) Current tempo (BPM) ç¾åœ¨ã®ãƒ†ãƒ³ãƒ (BPM) Snap/beat スナップ/ビート Track トラック Current track name ç¾åœ¨ã®ãƒˆãƒ©ãƒƒã‚¯å MOD 変更 Session modification state セッションã®å¤‰æ›´çŠ¶æ…‹ REC 記録 Session record state セッションã®éŒ²éŸ³çŠ¶æ…‹ MUTE ミュート Session muting state セッションã®ãƒŸãƒ¥ãƒ¼ãƒˆçŠ¶æ…‹ SOLO ソロ Session soloing state セッションã®ã‚½ãƒ­çŠ¶æ…‹ LOOP ループ Session looping state セッションã®ãƒ«ãƒ¼ãƒ—状態 Session total time セッションã®åˆè¨ˆæ™‚é–“ Session sample rate セッションã®ã‚µãƒ³ãƒ—リング周波数 Could not set default session directory: %1 Sorry. デフォルトã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’設定ã§ãã¾ã›ã‚“ã§ã—㟠%1 ã”ã‚ã‚“ãªã•ã„。 Ready 準備ãŒã§ãã¾ã—㟠Untitled%1 タイトルãªã—%1 New session: "%1". æ–°ã—ã„セッション: "%1"。 Session files (*.%1 *.%2 *.%3) セッションファイル(*.%1 *.%2 *.%3) Session files (*.%1 *.%2) セッションファイル(*.%1 *.%2) Template files (*.%1) テンプレートファイル(*.%1) Archive files (*.%1) アーカイブファイル(*.%1) Open Session セッションを開ã Save Session セッションをä¿å­˜ Warning 警告 The file already exists: "%1" Do you want to replace it? ファイルã¯ã™ã§ã«å­˜åœ¨ã—ã¦ã„ã¾ã™: "%1" ç½®ãã‹ãˆã¾ã™ã‹ï¼Ÿ Backup session: "%1" as "%2". セッションã®ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—: "%1" ã‚’ "%2"ã«ã€‚ Could not backup existing session: %1 as %2 Sorry. 既存ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã§ãã¾ã›ã‚“ã§ã—ãŸ: %1 ã‚’ %2 ã« ã”ã‚ã‚“ãªã•ã„。 The current session has been changed: "%1" Do you want to save the changes? ç¾åœ¨ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯å¤‰æ›´ã•れã¦ã„ã¾ã™: "%1" 変更をä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ About to remove archive directory: "%1" Are you sure? アーカイブディレクトリを除去ã—ã¾ã™: "%1" よã‚ã—ã„ã§ã™ã‹ï¼Ÿ Session closed. セッションを閉ã˜ã¾ã—ãŸã€‚ The directory already exists: "%1" Do you want to replace it? ã“ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¯ã™ã§ã«å­˜åœ¨ã—ã¦ã„ã¾ã™: "%1" ç½®ãã‹ãˆã¾ã™ã‹ï¼Ÿ Opening "%1"... "%1"ã‚’é–‹ã„ã¦ã„ã¾ã™... Session could not be loaded from "%1". Sorry. セッションã¯"%1"ã‹ã‚‰ ロードã•れã¾ã›ã‚“ã§ã—ãŸã€‚ ã”ã‚ã‚“ãªã•ã„。 Open session: "%1". セッションを開ã: "%1"。 Saving "%1"... "%1"ã‚’ä¿å­˜ã—ã¦ã„ã¾ã™... Session could not be saved to "%1". Sorry. セッションã¯%1ã« ä¿å­˜ã•れã¾ã›ã‚“ã§ã—ãŸã€‚ ã”ã‚ã‚“ãªã•ã„。 Save session: "%1". セッションã®ä¿å­˜: "%1"。 About to clear automation: "%1" Are you sure? オートメーションをクリアーã—ã¾ã™: "%1" よã‚ã—ã„ã§ã™ã‹ï¼Ÿ About to clear all automation: "%1" Are you sure? ã™ã¹ã¦ã®ã‚ªãƒ¼ãƒˆãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’クリアーã—ã¾ã™: "%1" よã‚ã—ã„ã§ã™ã‹ï¼Ÿ take range テイクレンジ session セッション or ã‚ã‚‹ã„㯠program プログラム Information インフォメーション Some settings may be only effective next time you start this %1. 設定ã®ã†ã¡ã„ãã¤ã‹ã¯ã€æ¬¡å›žä»¥é™ã« ã“ã®%1ã‚’é–‹å§‹ã—ãŸæ™‚ã«æœ‰åйã¨ãªã‚Šã¾ã™ã€‚ Debugging option enabled. デãƒãƒƒã‚®ãƒ³ã‚°ã‚ªãƒ—ã‚·ãƒ§ãƒ³ã¯æœ‰åйã§ã™ã€‚ Ogg Vorbis (libvorbis) file support disabled. Ogg Vorbis (libvorbis) ファイルサãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ MPEG-1 Audio Layer 3 (libmad) file support disabled. MPEG-1 Audio Layer 3 (libmad) ファイルサãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ Sample-rate conversion (libsamplerate) disabled. ã‚µãƒ³ãƒ—ãƒªãƒ³ã‚°å‘¨æ³¢æ•°å¤‰æ› (libsamplerate) ã¯ç„¡åйã§ã™ã€‚ Pitch-shifting support (librubberband) disabled. ピッãƒã‚·ãƒ•トサãƒãƒ¼ãƒˆ (librubberband) ã¯ç„¡åйã§ã™ã€‚ OSC service support (liblo) disabled. OSCサービスサãƒãƒ¼ãƒˆ (liblo) ã¯ç„¡åйã§ã™ã€‚ LADSPA Plug-in support disabled. LADSPAプラグインサãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ DSSI Plug-in support disabled. DSSIプラグインサãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ VST Plug-in support disabled. VSTプラグインサãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ VeSTige header support enabled. VesTigeヘッダーサãƒãƒ¼ãƒˆã¯æœ‰åйã§ã™ã€‚ LV2 Plug-in support disabled. LV2プラグインサãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ LV2 Plug-in UI support disabled. LV2プラグインユーザーインターフェイスサãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ LV2 Plug-in UI support (libsuil) disabled. LV2プラグインユーザーインターフェイスサãƒãƒ¼ãƒˆ (libsuil) ã¯ç„¡åйã§ã™ã€‚ LV2 Plug-in MIDI/Event support disabled. LV2プラグインã®MIDI/イベントサãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ LV2 Plug-in State Files support disabled. LV2プラグインã®çŠ¶æ…‹ãƒ•ã‚¡ã‚¤ãƒ«ã‚µãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ LV2 Plug-in support (libslv2) enabled. (DEPRECATED) LV2プラグインサãƒãƒ¼ãƒˆ(libslv2)有効 (éžæŽ¨å¥¨) Set current snap to %1 %1 ã«ã‚¹ãƒŠãƒƒãƒ—ã—ã¾ã™ Current time (play-head) ç¾åœ¨ã®æ™‚é–“ (å†ç”Ÿã®å…ˆé ­) LV2 Plug-in support (liblilv) disabled. LV2プラグインサãƒãƒ¼ãƒˆ (liblilv) ã¯ç„¡åйã§ã™ã€‚ LV2 Plug-in UI instantiation support (libsuil) disabled. LV2プラグインã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェイスインストールサãƒãƒ¼ãƒˆ (libsuil) 無効。 LV2 Plug-in QT4 UI support disabled. LV2プラグインã®Qt4ユーザーインターフェイスサãƒãƒ¼ãƒˆç„¡åŠ¹ã€‚ LV2 Plug-in GTK UI support disabled. LV2プラグインã®GTKユーザーインターフェイスサãƒãƒ¼ãƒˆç„¡åŠ¹ã€‚ LV2 Plug-in External UI support disabled. LV2プラグインã®å¤–部ユーザーインターフェイスサãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ LV2 Plug-in MIDI/Atom support disabled. LV2プラグインã®MIDI/Atomサãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ LV2 Plug-in Worker/Schedule support disabled. LV2プラグインã®ãƒ¯ãƒ¼ã‚«ãƒ¼/スケジューラーサãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ LV2 Plug-in State support disabled. LV2プラグインã®ã‚¹ãƒ†ãƒ¼ãƒˆã‚µãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ LV2 Plug-in State Files support enabled. (FUBAR) LV2プラグインã®ã‚¹ãƒ†ãƒ¼ãƒˆãƒ•ァイルサãƒãƒ¼ãƒˆæœ‰åŠ¹ã€‚ (FUBAR) LV2 Plug-in Programs support disabled. LV2プラグインã®ãƒ—ログラムサãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ LV2 Plug-in Presets support disabled. LV2プラグインã®ãƒ—リセットサãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ LV2 Plug-in Time/position support disabled. LV2プラグインã®ã‚¿ã‚¤ãƒ /ãƒã‚¸ã‚·ãƒ§ãƒ³ã‚µãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ LV2 Plug-in Options support disabled. LV2プラグインオプションサãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ LV2 Plug-in Buf-size support disabled. JACK Session support disabled. JACKセッションサãƒãƒ¼ãƒˆã¯ç„¡åй. JACK Latency support disabled. JACKレイテンシサãƒãƒ¼ãƒˆç„¡åй. Version ãƒãƒ¼ã‚¸ãƒ§ãƒ³ Build ビルド Website ウェブサイト This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 or later. record clip クリップã®éŒ²éŸ³ [modified] [変更ã•れã¦ã„ã¾ã™] %1 Hz Session started. セッションã¯é–‹å§‹ã—ã¾ã—ãŸã€‚ The original session sample rate (%1 Hz) is not the same of the current audio engine (%2 Hz). Saving and reloading from a new session file is highly recommended. セッションã®ã‚ªãƒªã‚¸ãƒŠãƒ«ã‚µãƒ³ãƒ—リング周波数 (%1 Hz) 㯠ç¾åœ¨ã®éŸ³å£°ã‚¨ãƒ³ã‚¸ãƒ³ã®ã‚‚ã® (%2 Hz) ã¨ç•°ãªã‚Šã¾ã™ã€‚ セッションをä¿å­˜ã—ã€å†åº¦èµ·å‹•ã™ã‚‹ã“ã¨ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚ The audio/MIDI engine could not be started. Make sure the JACK audio server (jackd) and/or the ALSA Sequencer kernel module (snd-seq-midi) are up and running and then restart the session. 音声/MIDIエンジンãŒã‚¹ã‚¿ãƒ¼ãƒˆã—ã¦ã„ã¾ã›ã‚“。 JACK音声サーãƒãƒ¼ (jackd) ãã—ã¦/ã‚ã‚‹ã„㯠ALSAシーケンサーカーãƒãƒ«ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ« (snd-seq-midi) ㌠スタートã—ã¦ã„ãŸã‚‰ã€ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’å†å§‹å‹•ã—ã¦ãã ã•ã„。 NSM support disabled. NSMサãƒãƒ¼ãƒˆã¯ç„¡åйã§ã™ã€‚ &Hold ホールド(&H) &Linear リニア(&L) &Spline スプライン(&S) Take %1 テイク %1 None ãªã— Error エラー XRUN(%1 skipped) XRUN(%1スキップ) XRUN(%1): some frames might have been lost. XRUN(%1): ã„ãã¤ã‹ã®ãƒ•レームãŒå¤±ã‚れã¾ã—ãŸã€‚ Audio connections change. 音声接続ãŒå¤‰æ›´ã•れã¾ã—ãŸã€‚ MIDI connections change. MIDI接続ãŒå¤‰æ›´ã•れã¾ã—ãŸã€‚ Playing ended. å†ç”ŸãŒçµ‚了ã—ã¾ã—ãŸã€‚ The audio engine has been shutdown. Make sure the JACK audio server (jackd) is up and running and then restart session. 音声エンジンã¯çµ‚了ã—ã¾ã—ãŸã€‚ JACK音声サーãƒãƒ¼(jackd)ãŒèµ·å‹•ã—実行ã•れã¦ã„ã‚‹ãªã‚‰ セッションをå†å§‹å‹•ã—ã¦ãã ã•ã„。 STOP åœæ­¢ PLAY å†ç”Ÿ FFWD 進む REW 戻る REC ON 録音オン REC OFF 録音オフ RESET リセット LOCATE %1 SHUTTLE %1 STEP %1 ステップ %1 TRACK RECORD %1 %2 TRACK MUTE %1 %2 トラック ミュート %1 %2 TRACK SOLO %1 %2 トラック ソロ %1 %2 Unknown sub-command 䏿˜Žãªã‚µãƒ–コマンドã§ã™ Not implemented 実装ã•れã¦ã„ã¾ã›ã‚“ MIDI CTL: %1, Channel %2, Param %3, Value %4 MIDI コントロール: %1, ãƒãƒ£ãƒ³ãƒãƒ« %2, パラメーター %3, 値 %4 (track %1, gain %2) (トラック %1, ゲイン %2) (track %1, panning %2) (トラック %1, パン %2) START é–‹å§‹ CONTINUE 継続 SONGPOS %1 ソングãƒã‚¸ã‚·ãƒ§ãƒ³ %1 %1 BPM Playing "%1"... "%1"ã‚’å†ç”Ÿ... &Frames フレーム(&F) &Time 時間(&T) qtractorMessages Messages メッセージ Logging stopped --- %1 --- ロギングã®åœæ­¢ --- %1 --- Logging started --- %1 --- ロギングã®é–‹å§‹ --- %1 --- qtractorMeter Pan パン Gain ゲイン qtractorMidiControlForm Controllers - Qtractor コントローラー - Qtractor Controller files コントローラーファイル Files ファイル Path パス Import controller files コントローラーファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ &Import... インãƒãƒ¼ãƒˆ(&I)... Alt+I Remove controller file コントローラーファイルã®é™¤åŽ» &Remove 除去(&R) Alt+R Move controller file up on list order コントローラーファイルを上ã«ç§»å‹• &Up 上ã¸(&U) Alt+U Move controller file down on list order コントローラーファイルを下ã«ç§»å‹• &Down 下ã¸(&D) Alt+D &Type タイプ(&T) &Channel ãƒãƒ£ãƒ³ãƒãƒ«(&C) &Parameter パラメーター(&P) Trac&k Offset トラックオフセット(&K) C&ommand コマンド(&O) MIDI Event type MIDIイベントタイプ MIDI Channel MIDIãƒãƒ£ãƒ³ãƒãƒ« MIDI Controller (parameter) MIDIコントローラー(パラメーター) MIDI parameter (track offset) MIDIパラメーター(トラックオフセット) + Track offset トラックã®ã‚ªãƒ•セット Command action コマンドã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ Command feedback コマンドã®ãƒ•ィードãƒãƒƒã‚¯ &Feedback フィードãƒãƒƒã‚¯(&F) Map/update controller command コントローラーコマンドをマップ/æ›´æ–° &Map マップ(&M) Alt+M Controller map コントローラーマップ Type タイプ Channel ãƒãƒ£ãƒ³ãƒãƒ« Parameter パラメータ Track トラック Command コマンド Feedback フィードãƒãƒƒã‚¯ Unmap/remove controller command コントローラーコマンドをアンマップ/除去ã—ã¾ã™ U&nmap アンマップ(&N) Alt+N Reload/apply all controller files ã™ã¹ã¦ã®ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ãƒ¼ãƒ•ァイルをリロード/é©ç”¨ã—ã¾ã™ Relo&ad リロード(&A) Alt+A Export to controller file コントローラーファイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ E&xport... エクスãƒãƒ¼ãƒˆ(&X)... Alt+X Close this dialog ダイアログを閉ã˜ã¾ã™ Close é–‰ã˜ã‚‹ Import Controller Files コントローラーファイルをインãƒãƒ¼ãƒˆã—ã¾ã™ Controller files (*.%1) コントローラーファイル(*.%1) Warning 警告 About to remove controller file: "%1" Are you sure? コントローラーファイルを除去ã—ã¾ã™: %1 よã‚ã—ã„ã§ã™ã‹ï¼Ÿ Export Controller File コントローラーファイルをエクスãƒãƒ¼ãƒˆã—ã¾ã™ The controller file already exists: "%1" Do you want to replace it? コントローラーファイルã¯ã™ã§ã«å­˜åœ¨ã—ã¦ã„ã¾ã™: %1 ç½®ãã‹ãˆã¾ã™ã‹ï¼Ÿ Saved controller mappings may not be effective the next time you start this program. "%1" Do you want to apply to controller files? ä¿å­˜ã•れã¦ã„ã‚‹ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ãƒ¼ãƒžãƒƒãƒ”ãƒ³ã‚°ã¯æ¬¡å›žèµ·å‹•時㫠効果ãŒãªã„ã§ã—ょã†ã€‚ %1 コントローラーファイルをé©ç”¨ã—ã¾ã™ã‹ï¼Ÿ Controller mappings have been changed. コントローラーマッピングã¯å¤‰æ›´ã•れã¾ã—ãŸã€‚ Do you want to save the changes? 変更をä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ Yes ã¯ã„ No ã„ã„㈠qtractorMidiControlObserverForm MIDI Controller - Qtractor MIDIコントローラー - Qtractor &Type: タイプ(&T): MIDI event type MIDIイベントタイプ Cha&nnel: ãƒãƒ£ãƒ³ãƒãƒ«(&N): MIDI channel MIDIãƒãƒ£ãƒ³ãƒãƒ« &Parameter: パラメーター(&P): MIDI parameter MIDIパラメーター &Logarithmic 対数表記(&L) &Feedback フィードãƒãƒƒã‚¯(&F) In&vert å転(&I) &Hook Control input connections ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«å…¥åŠ›ã®æŽ¥ç¶š &Inputs 入力(&I) Control output connections ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«å‡ºåŠ›ã®æŽ¥ç¶š &Outputs 出力(&O) MIDI Controller MIDIコントローラー MIDI controller is already assigned. Do you want to replace the mapping? MIDIコントローラーã¯ã™ã§ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã¦ã„ã¾ã™ã€‚ マッピングを置ãã‹ãˆã¾ã™ã‹ï¼Ÿ Some settings have been changed. Do you want to apply the changes? 設定ã®ä¸€éƒ¨ãŒå¤‰æ›´ã•れã¾ã—㟠ã“ã®å¤‰æ›´ã‚’é©ç”¨ã—ã¾ã™ã‹? &MIDI Controller... MIDIコントローラー(&M)... &Automation オートメーション(&A) &Lock ロック(&L) &Play å†ç”Ÿ(&P) &Record 録音(&R) &Clear クリアー(&C) qtractorMidiEditEvent Zoom in (horizontal) ズームイン(水平方å‘) Zoom out (horizontal) ズームアウト(水平方å‘) Zoom reset (horizontal) ズームリセット(水平方å‘) qtractorMidiEditList C%1 qtractorMidiEditTime Play-head Edit-head Edit-tail Loop-start ループã®å…ˆé ­ Loop-end ãƒ«ãƒ¼ãƒ—ã®æœ«å°¾ Punch-in パンãƒã‚¤ãƒ³ Punch-out パンãƒã‚¢ã‚¦ãƒˆ Start: %1 End: %2 Length: %3 é–‹å§‹: %1 終了: %2 é•·ã•: %3 qtractorMidiEditView Zoom in (vertical) ズームイン(垂直方å‘) Zoom out (vertical) ズームアウト(垂直方å‘) Zoom reset (vertical) ズームリセット(垂直方å‘) qtractorMidiEditor MIDI Editor MIDIエディタ cut 切りå–り delete 削除 insert range ãƒ¬ãƒ³ã‚¸ã®æŒ¿å…¥ remove range レンジã®é™¤åŽ» move 移動 edit 編集 resize リサイズ rescale リスケール paste 貼り付㑠Time: %1 Type: 時間: %1 種類: Note On (%1) %2 Velocity: %3 Duration: %4 ノートオン (%1) %2 ベロシティー %3 デュレーション %4 Key Press (%1) %2 Value: %3 キープレス (%1) %2 値: %3 Controller (%1) Name: %2 Value: %3 コントローラー (%1) åå‰: %2 値: %3 Pgm Change (%1) Pgmãƒã‚§ãƒ³ã‚¸ (%1) Chan Press (%1) ãƒãƒ£ãƒ³ãƒãƒ«ãƒ—レス (%1) Pitch Bend (%1) ピッãƒãƒ™ãƒ³ãƒ‰ (%1) SysEx (%1 bytes) Data: SysEx (%1ãƒã‚¤ãƒˆ) データ: Unknown (%1) 䏿˜Ž (%1) Start: %1 End: %2 Length: %3 é–‹å§‹: %1 終了: %2 é•·ã•: %3 qtractorMidiEditorForm MIDI Editor MIDIエディタ &Track トラック(&T) &File ファイル(&F) Select &Mode é¸æŠžãƒ¢ãƒ¼ãƒ‰(&M) &Select é¸æŠž(&S) I&nsert 挿入(&N) Remo&ve 除去(&V) &Tools ツール(&T) &Edit 編集(&E) &View 表示(&V) &Toolbars ツールãƒãƒ¼(&T) &Windows ウィンドウ(&W) &Zoom ズーム(&Z) S&nap スナップ(&N) Sc&ale スケール(&A) T&ransport トランスãƒãƒ¼ãƒˆ(&R) &Help ヘルプ(&H) &Save ä¿å­˜(&S) Save ä¿å­˜ Save current MIDI clip to existing file name ç¾åœ¨ã®MIDIクリップをファイルã¸ä¿å­˜ã—ã¾ã™ Save &As... åå‰ã‚’付ã‘ã¦ä¿å­˜(&A)... Save As åå‰ã‚’付ã‘ã¦ä¿å­˜ Save as åå‰ã‚’付ã‘ã¦ä¿å­˜ Save current MIDI clip with another file name ç¾åœ¨ã®MIDIクリップを別ãªãƒ•ァイルåã§ä¿å­˜ã—ã¾ã™ &Unlink リンク解除(&U) Unlink リンク解除 Unlink current MIDI clip ç¾åœ¨ã®MIDIクリップã®ãƒªãƒ³ã‚¯ã‚’解除 &Inputs 入力(&I) Track Inputs トラック入力 Track inputs トラック入力 Show current MIDI clip/track input bus connections ç¾åœ¨ã®ãƒˆãƒ©ãƒƒã‚¯ã®MIDI入力ãƒã‚¹æŽ¥ç¶šã‚’表示ã—ã¾ã™ &Outputs 出力(&O) Track Outputs トラック出力 Track outputs トラック出力 Show current MIDI clip/track output bus connections ç¾åœ¨ã®ãƒˆãƒ©ãƒƒã‚¯ã®MIDI出力ãƒã‚¹æŽ¥ç¶šã‚’表示ã—ã¾ã™ &Properties... プロパティ(&P)... Track Properties トラックã®ãƒ—ロパティ Track properties トラックã®ãƒ—ロパティ Edit current MIDI clip/track properties é¸æŠžã—ã¦ã„ã‚‹MIDIトラックã®ãƒ—ロパティを編集ã—ã¾ã™ Shift+F2 Properties プロパティ Edit current MIDI clip properties ç¾åœ¨ã®MIDIクリップã®ãƒ—ロパティを編集ã—ã¾ã™ F4 &Range Set レンジã®è¨­å®š(&R) Clip Range クリップレンジ Clip range クリップレンジ Set edit-range from clip extents ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—ã®é•·ã•をレンジã«ã—ã¾ã™ &Loop Set ループã®è¨­å®š(&L) Clip Loop クリップループ Clip loop クリップループ Set loop-range from clip extents ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—ã®é•·ã•ã ã‘ループレンジを設定ã—ã¾ã™ &Close é–‰ã˜ã‚‹(&C) Close é–‰ã˜ã‚‹ Close this MIDI clip editor ã“ã®MIDIクリップエディターを閉ã˜ã¾ã™ &Undo å…ƒã«æˆ»ã™(&U) Undo å…ƒã«æˆ»ã™ Undo last edit operation 最後ã®ç·¨é›†æ“ä½œã‚’å…ƒã«æˆ»ã—ã¾ã™ Ctrl+Z &Redo やり直ã™(&R) Redo やり直㙠Redo last edit operation 最後ã®ç·¨é›†æ“作をやり直ã—ã¾ã™ Ctrl+Shift+Z Cu&t 切りå–り(&T) Cut 切りå–り Cut current selection into the local clipboard ç¾åœ¨ã®é¸æŠžã‚’ローカルクリップボードã¸åˆ‡ã‚Šå–りã¾ã™ Ctrl+X &Copy コピー(&C) Copy コピー Copy current selection to the local clipboard ç¾åœ¨ã®é¸æŠžã‚’ローカルクリップボードã¸ã‚³ãƒ”ーã—ã¾ã™ Ctrl+C &Paste 貼り付ã‘(&P) Paste 貼り付㑠Paste local clipboard contents into the current MIDI clip ローカルクリップボードã®å†…容をç¾åœ¨ã®MIDIクリップã«è²¼ã‚Šä»˜ã‘ã¾ã™ Ctrl+V Past&e Repeat... 繰り返ã—貼り付ã‘(&E)... Paste Repeat 繰り返ã—ã¦è²¼ã‚Šä»˜ã‘ Paste repeat 繰り返ã—ã¦è²¼ã‚Šä»˜ã‘ Paste/repeat local clipboard contents into the current MIDI clip ローカルクリップボードã®å†…容をç¾åœ¨ã®MIDIクリップã«ç¹°ã‚Šè¿”ã—貼付ã‘ã¾ã™ Ctrl+Shift+V &Delete 削除(&D) Delete 削除 Delete current selection ç¾åœ¨ã®é¸æŠžã‚’削除ã—ã¾ã™ Del 削除 Edit Of&f 編集オフ(&F) Edit Off 編集ã®ã‚ªãƒ• Edit off 編集ã®ã‚ªãƒ• Set edit mode off 編集モードをオフã«ã—ã¾ã™ Edit &On 編集オン(&O) Edit On 編集オン Edit on 編集オン Set edit mode on 編集モードをオンã«ã—ã¾ã™ Edit &Draw ドロー編集(&D) Edit draw mode ドロー編集モード Edit draw mode (notes) ノートをæã編集モードã§ã™ &All ã™ã¹ã¦(&A) Select All ã™ã¹ã¦ã‚’é¸æŠž Select all ã™ã¹ã¦ã‚’é¸æŠžã—ã¾ã™ Ctrl+A &None ãªã—(&N) Select None é¸æŠžè§£é™¤ Select none é¸æŠžã‚’è§£é™¤ã—ã¾ã™ Ctrl+Shift+A &Invert å転(&I) Select Invert é¸æŠžã®å転 Select invert é¸æŠžã‚’å転ã—ã¾ã™ Ctrl+I &Range レンジ(&R) Select Range ãƒ¬ãƒ³ã‚¸é¸æŠž Select range ãƒ¬ãƒ³ã‚¸ã‚’é¸æŠž Mark range as selected ãƒ¬ãƒ³ã‚¸ã‚’é¸æŠžæ¸ˆã¿ã«ã—ã¾ã™ Ctrl+R Insert Range ãƒ¬ãƒ³ã‚¸ã®æŒ¿å…¥ Insert range レンジを挿入 Insert range as selected é¸æŠžãƒ¬ãƒ³ã‚¸ã‚’æŒ¿å…¥ã—ã¾ã™ Ctrl+Ins Remove Range レンジã®é™¤åŽ» Remove range レンジを除去ã—ã¾ã™ Remove range as selected é¸æŠžã•れã¦ã„るレンジを除去ã—ã¾ã™ Ctrl+Del &Quantize... クォンタイズ(&Q)... Quantize クォンタイズ Quantize selection é¸æŠžã‚’ã‚¯ã‚ªãƒ³ã‚¿ã‚¤ã‚ºã—ã¾ã™ &Transpose... トランスãƒãƒ¼ã‚º(&T)... Transpose トランスãƒãƒ¼ã‚º Transpose selection é¸æŠžã‚’ãƒˆãƒ©ãƒ³ã‚¹ãƒãƒ¼ã‚ºã—ã¾ã™ &Normalize... ノーマライズ(&N)... Normalize ノーマライズ Normalize selection é¸æŠžã‚’ãƒŽãƒ¼ãƒžãƒ©ã‚¤ã‚ºã—ã¾ã™ &Randomize... ランダマイズ(&R)... Randomize ランダマイズ Randomize selection é¸æŠžã‚’ãƒ©ãƒ³ãƒ€ãƒžã‚¤ã‚ºã—ã¾ã™ Resi&ze... リサイズ(&Z)... Resize リサイズ Resize selection é¸æŠžã‚’ãƒªã‚µã‚¤ã‚ºã—ã¾ã™ Re&scale... リスケール(&S)... Rescale リスケール Rescale selection é¸æŠžã‚’ãƒªã‚¹ã‚±ãƒ¼ãƒ«ã—ã¾ã™ T&imeshift... タイムシフト(&I)... Timeshift タイムシフト Timeshift selection é¸æŠžã‚’ã‚¿ã‚¤ãƒ ã‚·ãƒ•ãƒˆã—ã¾ã™ &Menubar メニューãƒãƒ¼(&M) Menubar メニューãƒãƒ¼ Show/hide the menubar メインウィンドウã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ Ctrl+M &Statusbar ステータスãƒãƒ¼(&S) Statusbar ステータスãƒãƒ¼ Show/hide the statusbar メインウィンドウã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ File Toolbar ファイルツールãƒãƒ¼ File toolbar ファイルツールãƒãƒ¼ Show/hide the file toolbar メインウィンドウã®ãƒ•ァイルツールãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ Edit Toolbar エディットツールãƒãƒ¼ Edit toolbar エディットツールãƒãƒ¼ Show/hide the edit toolbar エディットツールãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ View Toolbar ビューツールãƒãƒ¼ View toolbar ビューツールãƒãƒ¼ Show/hide the view toolbar ビューツールãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ &Transport トランスãƒãƒ¼ãƒˆ(&T) Transport Toolbar トランスãƒãƒ¼ãƒˆãƒ„ールãƒãƒ¼ Transport toolbar トランスãƒãƒ¼ãƒˆãƒ„ールãƒãƒ¼ Show/hide the transport toolbar トランスãƒãƒ¼ãƒˆãƒ„ールãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ &Scale スケール(&S) Scale Toolbar スケールツールãƒãƒ¼ Scale toolbar スケールツールãƒãƒ¼ Show/hide the scale toolbar 音階ツールãƒãƒ¼ã‚’表示/éš ã—ã¾ã™ Note &Duration ノートデュレーション(&D) Note Duration ノートデュレーション Note duration ノートデュレーション Whether note events are shown proportional to duration デュレーションã«å¾“ã„ノートイベントを表示ã—ã¾ã™ Note &Color ピッãƒç€è‰²(&C) Note Color ピッãƒã®ç€è‰² Note color ピッãƒã®ç€è‰² Whether note events are colored according to pitch ピッãƒã«å¾“ã„ノートイベントをç€è‰²ã—ã¾ã™ &Value Color ベロシティーç€è‰²(&V) Value Color ベロシティーç€è‰² Value color ベロシティーç€è‰² Whether note events are colored according to value (velocity) ベロシティã«å¾“ã„ノートイベントをç€è‰²ã—ã¾ã™ &Events イベント(&E) View events イベントã®è¡¨ç¤º Show/hide the events list イベントリストを表示/éš ã—ã¾ã™ &Preview Notes ノートã®ãƒ—レビュー(&P) Preview Notes ノートã®ãƒ—レビュー Preview notes ノートã®ãƒ—レビュー Preview notes while editing (scrub) 編集中ã«ãƒŽãƒ¼ãƒˆã‚’プレビューã—ã¾ã™ F&ollow Playhead å†ç”Ÿã«è¿½éš(&O) Follow Playhead å†ç”Ÿã«è¿½éš Follow playhead å†ç”Ÿç®‡æ‰€ã‚’追ã„ã‹ã‘ã¾ã™ &In イン(&I) Zoom In ズームイン Zoom in ズームイン Ctrl++ &Out アウト(&O) Zoom Out ズームアウト Zoom out ズームアウト Ctrl+- &Reset リセット(&R) Zoom Reset ズームリセット Zoom reset ズームリセット Ctrl+1 &Horizontal 水平方å‘(&H) Horizontal Zoom 水平方å‘ズーム Horizontal zoom 水平方å‘ズーム Horizontal zoom mode 水平方å‘ã«ã‚ºãƒ¼ãƒ ã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã§ã™ &Vertical 垂直方å‘(&V) Vertical Zoom 垂直方å‘ズーム Vertical zoom 垂直方å‘ズーム Vertical zoom mode 垂直方å‘ã«ã‚ºãƒ¼ãƒ ã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã§ã™ All Zoom 垂直水平ズーム All zoom 垂直水平ズーム All zoom mode 垂直方å‘ã«ã‚‚水平方å‘ã«ã‚‚ズームã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã§ã™ &Zebra Zebra Bar zebra view mode &Grid グリッド(&G) Grid グリッド Snap grid view mode グリッドã«ã‚¹ãƒŠãƒƒãƒ—ã™ã‚‹ãƒ“ューモードã§ã™ Too&l Tips ツールãƒãƒƒãƒ—(&L) Tool tips ツールãƒãƒƒãƒ— Floating tool tips view mode ツールãƒãƒƒãƒ—をフローティング表示ã—ã¾ã™ &Refresh æ›´æ–°(&R) Refresh æ›´æ–° Refresh views ビューを更新ã—ã¾ã™ F5 &Backward 先頭ã¸(&B) Backward 先頭㸠Transport backward トランスãƒãƒ¼ãƒˆã‚’先頭ã¸ç§»å‹•ã—ã¾ã™ Backspace ãƒãƒƒã‚¯ã‚¹ãƒšãƒ¼ã‚¹ Re&wind 逆å†ç”Ÿ(&W) Rewind 逆å†ç”Ÿ Transport rewind トランスãƒãƒ¼ãƒˆã‚’逆å†ç”Ÿã—ã¾ã™ F&ast Forward æ—©é€ã‚Š(&A) Fast Forward æ—©é€ã‚Š Fast forward æ—©é€ã‚Š Transport fast forward トランスãƒãƒ¼ãƒˆã‚’æ—©é€ã‚Šã—ã¾ã™ &Forward 末尾ã¸(&F) Forward 末尾㸠Transport forward トランスãƒãƒ¼ãƒˆã‚’末尾ã¸ç§»å‹•ã—ã¾ã™ &Loop ループ(&L) Loop ループ Transport loop トランスãƒãƒ¼ãƒˆã‚’ループã—ã¾ã™ Ctrl+Shift+L Loop &Set ループセット(&S) Loop Set ループセット Loop set ループセット Transport loop set ループセットをトランスãƒãƒ¼ãƒˆã—ã¾ã™ Ctrl+L &Stop åœæ­¢(&S) Stop åœæ­¢ Transport stop トランスãƒãƒ¼ãƒˆã‚’åœæ­¢ã—ã¾ã™ &Play å†ç”Ÿ(&P) Play å†ç”Ÿ Transport play/pause トランスãƒãƒ¼ãƒˆã‚’å†ç”Ÿ/ä¸€æ™‚åœæ­¢ã—ã¾ã™ Space スペース &Record 録音(&R) Record 録音 Transport record トランスãƒãƒ¼ãƒˆã‚’録音ã—ã¾ã™ &Punch パンãƒ(&P) Punch パンムPunch in/out パンãƒã‚¤ãƒ³/アウト Transport punch in/out Ctrl+Shift+P Punch Se&t パンãƒã‚»ãƒƒãƒˆ(&T) Punch Set パンãƒã‚»ãƒƒãƒˆ Punch in/out set パンãƒã‚¤ãƒ³/アウトを設定 Transport punch in/out set Ctrl+P Pa&nic パニック(&N) Panic パニック All MIDI tracks shut off (panic) ã™ã¹ã¦ã®MIDIトラックをオフã«ã—ã¾ã™ (パニック) &Shortcuts... ショートカット(&S)... Shortcuts ショートカット Keyboard shortcuts キーボードショートカット &About... Qtractorã«ã¤ã„ã¦(&A)... About ã«ã¤ã„㦠Show information about this application program ã“ã®ã‚½ãƒ•トウェアã«é–¢ã™ã‚‹æƒ…報を表示ã—ã¾ã™ About &Qt... Qtã«ã¤ã„ã¦(&Q)... About Qt Qtã«ã¤ã„㦠Show information about the Qt toolkit Qtツールキットã«é–¢ã™ã‚‹æƒ…報を表示ã—ã¾ã™ Set current snap to %1 %1 ã«ã‚¹ãƒŠãƒƒãƒ—ã—ã¾ã™ Note On ノートオン Key Press キープレス Note Velocity ノートã®ãƒ™ãƒ­ã‚·ãƒ†ã‚£ãƒ¼ Controller コントローラー Pgm Change Pgmãƒã‚§ãƒ³ã‚¸ Chan Press ãƒãƒ£ãƒ³ãƒãƒ«ãƒ—レス Pitch Bend ピッãƒãƒ™ãƒ³ãƒ‰ Sys Ex システムエクスクルーシブ Snap/beat スナップ/ビート Note type ノートタイプ Value type 値ã®ã‚¿ã‚¤ãƒ— Controller type コントローラータイプ Scale key スケールキー Scale type スケールタイプ MIDI clip name MIDIクリップå MIDI file name MIDIファイルå MIDI track/channel MIDIトラック/ãƒãƒ£ãƒ³ãƒãƒ« MOD 変更 MIDI modification state MIDIã®å¤‰æ›´çŠ¶æ…‹ 00:00:00.000 MIDI clip duration MIDIクリップã®ãƒ‡ãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ Warning 警告 The current MIDI clip has been changed: "%1" Do you want to save the changes? ç¾åœ¨ã®MIDIクリップã¯å¤‰æ›´ã•れã¦ã„ã¾ã™: "%1" 変更をä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ Save MIDI Clip MIDIクリップã®ä¿å­˜ MIDI files (*.%1 *.smf *.midi) MIDIファイル(*.%1 *.smf *.midi) MIDI file save: "%1", track-channel: %2. MIDIファイルã®ä¿å­˜: %1, トラックãƒãƒ£ãƒ³ãƒãƒ«: %2。 Channel %1 ãƒãƒ£ãƒ³ãƒãƒ« %1 Track %1 トラック %1 [modified] [変更ã•れã¾ã—ãŸ] qtractorMidiEventItemDelegate edit %1 編集 %1 qtractorMidiEventList Events イベント qtractorMidiEventListModel Time 時間 Type タイプ Name åå‰ Value 値 Duration/Data デュレーション/データ Frame フレーム BBT Note On (%1) ノートオン (%1) Note Off (%1) ノートオフ (%1) Key Press (%1) キープレス (%1) Controller (%1) コントローラー (%1) Pgm Change Pgmãƒã‚§ãƒ³ã‚¸ Chan Press ãƒãƒ£ãƒ³ãƒãƒ«ãƒ—レス Pitch Bend ピッãƒãƒ™ãƒ³ãƒ‰ SysEx SysEx Meta (%1) メタ (%1) Unknown (%1) 䏿˜Ž (%1) qtractorMidiListView Name åå‰ Fmt Tracks トラック tpqn tpqn Path パス Open MIDI Files MIDIファイルを開ã MIDI files (*.%1 *.smf *.midi) MIDIファイル (*.%1 *.smf *.midi) qtractorMidiMeter Volume (%) ボリューム (%) % Pan: %1 パン: %1 Volume: %1% ボリューム: %1% qtractorMidiSysexForm MIDI SysEx - Qtractor MIDI SysEx - Qtractor Name åå‰ Size サイズ Data (hex) データ (16進数表記) Import from SysEx file SysExファイルã‹ã‚‰ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ &Import... インãƒãƒ¼ãƒˆ(&I)... Alt+I Export to SysEx file SysExファイルã¸ã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ E&xport... エクスãƒãƒ¼ãƒˆ(&X)... Alt+X Move SysEx item up on list order SysExアイテムを上ã«ç§»å‹• &Up 上ã¸(&U) Alt+U Move SysEx item down on list order SysExアイテムを下ã«ç§»å‹• &Down 下ã¸(&D) Alt+D Open SysEx SysExã‚’é–‹ã Sysex name SysExå Save SysEx SysExã®ä¿å­˜ Delete SysEx SysExã®å‰Šé™¤ Create SysEx item SysExアイテムã®å‰Šé™¤ &Add 追加(&A) Alt+A Update SysEx item SysExã‚¢ã‚¤ãƒ†ãƒ ã®æ›´æ–° Upda&te æ›´æ–°(&T) Alt+T Remove SysEx item SysExアイテムã®é™¤åŽ» &Remove 除去(&R) Alt+R SysEx files (*.%1) SysExファイル (*.%1) MIDI files (*.mid *.smf *.midi) MIDIファイル (*.mid *.smf *.midi) All files (*.*) 全ファイル (*.*) Import SysEx Files SysExファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ Export SysEx File SysExファイルã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ Warning 警告 The SysEx file already exists: "%1" Do you want to replace it? SysExファイルã¯ã™ã§ã«å­˜åœ¨ã—ã¦ã„ã¾ã™: "%1" ç½®ãã‹ãˆã¾ã™ã‹ï¼Ÿ Sysex files (*.%1) SysExファイル (*.%1) About to replace SysEx: "%1" Are you sure? SysExã‚’ç½®ãã‹ãˆã¾ã™: "%1" よã‚ã—ã„ã§ã™ã‹ï¼Ÿ About to delete SysEx: "%1" Are you sure? SysExを削除ã—ã¾ã™: "%1" よã‚ã—ã„ã§ã™ã‹ï¼Ÿ SysEx settings have been changed. Do you want to apply the changes? SysEx設定ã¯å¤‰æ›´ã•れã¾ã—ãŸã€‚ 変更をé©ç”¨ã—ã¾ã™ã‹ï¼Ÿ Error エラー SysEx could not be loaded: "%1". Sorry. SysExã¯ãƒ­ãƒ¼ãƒ‰ã•れã¾ã›ã‚“: "%1" ã”ã‚ã‚“ãªã•ã„。 qtractorMidiToolsForm MIDI Tools MIDIツール Preset name プリセットå Save preset プリセットã®ä¿å­˜ Delete preset プリセットã®å‰Šé™¤ &Quantize クオンタイズ(&Q) Quantize selected events é¸æŠžã—ãŸã‚¤ãƒ™ãƒ³ãƒˆã‚’クオンタイズ &Time: 時間(&T): Quantize time ã‚¯ã‚ªãƒ³ã‚¿ã‚¤ã‚ºã®æ™‚é–“ Quantize time percent ã‚¯ã‚ªãƒ³ã‚¿ã‚¤ã‚ºæ™‚é–“å‰²åˆ % &Duration: デュレーション(&D): Quantize duration クオンタイズã®ãƒ‡ãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ Quantize duration percent クオンタイズã®ãƒ‡ãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³å‰²åˆ S&wing: スウィング(&W): Swing-quantize time スウィングクオンタイズ時間 Swing-quantize percent ã‚¹ã‚¦ã‚£ãƒ³ã‚°ã‚¯ã‚ªãƒ³ã‚¿ã‚¤ã‚ºå‰²åˆ Swing-quantize type スウィングクオンタイズã®ã‚¿ã‚¤ãƒ— Linear Quadratic Cubic &Scale: スケール(&S): Scale-quantize key スケールクオンタイズキー Scale-quantize type スケールクオンタイズã®ã‚¿ã‚¤ãƒ— &Transpose トランスãƒãƒ¼ã‚º(&T) Transpose selected events é¸æŠžã•れãŸã‚¤ãƒ™ãƒ³ãƒˆã®ãƒˆãƒ©ãƒ³ã‚¹ãƒãƒ¼ã‚º &Note: ノート(&N): Transpose note ノートã®ãƒˆãƒ©ãƒ³ã‚¹ãƒãƒ¼ã‚º Transpose time 時間ã®ãƒˆãƒ©ãƒ³ã‚¹ãƒãƒ¼ã‚º Transpose time format トランスãƒãƒ¼ã‚ºæ™‚間フォーマット Frames フレーム Time 時間 BBT &Normalize ノーマライズ(&N) Normalize selected events é¸æŠžã•れãŸã‚¤ãƒ™ãƒ³ãƒˆã®ãƒŽãƒ¼ãƒžãƒ©ã‚¤ã‚º &Percent: 割åˆ(&P): Normalize percent 割åˆã®ãƒŽãƒ¼ãƒžãƒ©ã‚¤ã‚º &Value: 値(&V): Normalize value 値ã®ãƒŽãƒ¼ãƒžãƒ©ã‚¤ã‚º &Randomize ランダマイズ(&R) Randomize selected events é¸æŠžã•れãŸã‚¤ãƒ™ãƒ³ãƒˆã®ãƒŽãƒ¼ãƒžãƒ©ã‚¤ã‚º Randomize note/pitch ノート/ピッãƒã®ãƒŽãƒ¼ãƒžãƒ©ã‚¤ã‚º Randomize time 時間ã®ãƒŽãƒ¼ãƒžãƒ©ã‚¤ã‚º Randomize duration デュレーションã®ãƒ©ãƒ³ãƒ€ãƒžã‚¤ã‚º Randomize value 値ã®ãƒ©ãƒ³ãƒ€ãƒžã‚¤ã‚º Resi&ze リサイズ(&Z) Resize selected events é¸æŠžã•れãŸã‚¤ãƒ™ãƒ³ãƒˆã®ãƒªã‚µã‚¤ã‚º Resize duration デュレーションã®ãƒªã‚µã‚¤ã‚º Resize duration format デュレーションã®ãƒ•ォーマット Percentage å‰²åˆ Resize value 値ã®ãƒªã‚µã‚¤ã‚º Resize value mode 値ã®ãƒªã‚µã‚¤ã‚ºãƒ¢ãƒ¼ãƒ‰ Flat Ramp Resize final value 最後ã®å€¤ã®ãƒªã‚µã‚¤ã‚º Re&scale リスケール(&S) Rescale selected events é¸æŠžã•れãŸã‚¤ãƒ™ãƒ³ãƒˆã®ãƒªã‚¹ã‚±ãƒ¼ãƒ« Rescale time ãƒªã‚¹ã‚±ãƒ¼ãƒ«ã®æ™‚é–“ Rescale duration リスケールã®ãƒ‡ãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ Rescale value リスケールã®å€¤ T&imeshift タイムシフト(&I) Timeshift selected events é¸æŠžã•れãŸã‚¤ãƒ™ãƒ³ãƒˆã®ã‚¿ã‚¤ãƒ ã‚·ãƒ•ト Timeshift タイムシフト P: P: Timeshift parameter タイムシフトã®ãƒ‘ラメーター Timeshift parameter (log) タイムシフトパラメーター (対数) Timeshift curve タイムシフトカーブ P = 0 : no change. P > 0 : accelerating shift. P < 0 : slowing down shift. Edit head/tail (blue) markers define the shift range. P = 0 : 変化ãªã— P > 0: 加速シフト P < 0: 減速シフト (é’色ã®)編集マーカーã®å…ˆé ­ã‹ã‚‰æœ«å°¾ã¾ã§ãŒã‚·ãƒ•ト範囲ã§ã™ã€‚ Timeshift duration タイムシフトデュレーション (default) (デフォルト) Warning 警告 About to delete preset: "%1" Are you sure? プリセットを削除ã—ã¾ã™: "%1" よã‚ã—ã„ã§ã™ã‹ï¼Ÿ none ãªã— quantize クォンタイズ transpose トランスãƒãƒ¼ã‚º normalize ノーマライズ randomize ランダマイズ resize リサイズ rescale リスケール timeshift タイムシフト qtractorMixer Inputs 入力 Tracks トラック Outputs 出力 Mixer ミキサー qtractorMixerRack &Inputs 入力(&I) &Outputs 出力(&O) &Monitor モニター(&M) &Buses... ãƒã‚¹(&B)... qtractorMixerStrip inputs 入力 outputs 出力 Connect %1 %1 ã®æŽ¥ç¶š %1 In %1 入力 %1 Out %1 出力 (Audio) (音声) Gain ゲイン (MIDI) Volume ボリューム (None) (ãªã—) Pan パン qtractorMonitorButton monitor モニター Monitor (rec) モニター(録音) Monitor (thru) モニター(スルー) qtractorOptionsForm Options - Qtractor オプション - Qtractor &General 全般(&G) Session セッション Default session &file format: デフォルトã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãƒ•ァイルフォーマット(&F): Default session file format (suffix) デフォルトã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãƒ•ァイルフォーマット(æ‹¡å¼µå­) Whether to create new sessions based on template テンプレートã«åŸºã¥ã„ã¦æ–°ã—ã„セッションを作æˆã™ã‚‹ã‹ã©ã†ã‹ &New session template: æ–°è¦ã‚»ãƒƒã‚·ãƒ§ãƒ³ãƒ†ãƒ³ãƒ—レート(&N): New session template æ–°è¦ã‚»ãƒƒã‚·ãƒ§ãƒ³ãƒ†ãƒ³ãƒ—レート Browse for new session template æ–°è¦ã‚»ãƒƒã‚·ãƒ§ãƒ³ãƒ†ãƒ³ãƒ—レートを一覧 Whether to save backup versions of existing sessions 既存ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ä¿å­˜ã™ã‚‹ã‹ã©ã†ã‹ Save &backup versions of existing sessions 既存ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã®ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ä¿å­˜(&B) Save &backup versions of existing sessions: スペースãŒç‹­ãã¦å®Œè¨³ã™ã‚‹ã¨åŽã¾ã‚‰ãªã„ ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã‚’ãƒãƒ¼ã‚¸ãƒ§ãƒ³åˆ¥ã«ä¿å­˜(&B): Which mode to rename existing session files 既存ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ãƒ•ァイルをリãƒãƒ¼ãƒ ã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ Increment previous version (default) å‰ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’インクリメント(デフォルト) Increment current version ç¾åœ¨ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’インクリメント Options オプション Whether to ask for confirmation on removal 削除ã®ç¢ºèªã‚’ã™ã‚‹ã‹ã©ã†ã‹ &Confirm removals 削除ã®ç¢ºèª(&C) Alt+C Number of &recent files: 最近使ã£ãŸãƒ•ァイルã®è¡¨ç¤ºæ•°(&R): The maximum number of recent files to keep in menu 最近ã®ãƒ•ァイルメニューã«è¡¨ç¤ºã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã®æœ€å¤§æ•° Whether to capture standard output (stdout/stderr) into messages window 標準出力(stdout/stderror)をキャプãƒãƒ£ãƒ¼ã—メッセージウィンドウã«è¡¨ç¤ºã™ã‚‹ã‹ã©ã†ã‹ Capture standard &output 標準出力ã®ã‚­ãƒ£ãƒ—ãƒãƒ£ãƒ¼(&O) Alt+O Whether to show the complete directory path of loaded session files ロードã—ãŸã‚»ãƒƒã‚·ãƒ§ãƒ³ãƒ•ァイルã®ãƒ•ルパスを表示ã™ã‚‹ã‹ã©ã†ã‹ S&how complete path of session files セッションファイルã®ãƒ•ルパス表示(&H) Alt+P Whether to remove audio peak files on session close セッション終了ã®éš›ã«éŸ³å£°ãƒ”ークファイルを除去ã™ã‚‹ã‹ã©ã†ã‹ Auto-remove audio pea&k files 音声ピークファイルã®è‡ªå‹•除去(&K) Alt+K Whether to keep all tool windows on top of the main window ã™ã¹ã¦ã®ãƒ„ãƒ¼ãƒ«ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’ãƒ¡ã‚¤ãƒ³ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚ˆã‚Šã‚‚å¸¸ã«æ‰‹å‰ã«è¡¨ç¤ºã™ã‚‹ã‹ã©ã†ã‹ Keep tool &windows always on top ãƒ„ãƒ¼ãƒ«ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’å¸¸ã«æ‰‹å‰ã«è¡¨ç¤º(&W) Whether to try dropping multiple audio files into the same track 複数ã®éŸ³å£°ãƒ•ァイルをåŒã˜ãƒˆãƒ©ãƒƒã‚¯ã«ãƒ‰ãƒ­ãƒƒãƒ—ã§ãるよã†ã«ã™ã‚‹ã‹ã©ã†ã‹ &Drop multiple audio files into the same track 複数ã®éŸ³å£°ãƒ•ァイルをåŒã˜ãƒˆãƒ©ãƒƒã‚¯ã«ãƒ‰ãƒ­ãƒƒãƒ—(&D) Alt+S Whether to reverse mouse middle-button role on keyboard modifiers (Shift/Ctrl) マウスã®ãƒŸãƒ‰ãƒ«ãƒœã‚¿ãƒ³ã®å½¹å‰²ã‚’ã€ã‚­ãƒ¼ãƒœãƒ¼ãƒ‰ã®ä¿®é£¾ã‚­ãƒ¼ï¼ˆShift/Ctl)ã§é€†è»¢ã•ã›ã‚‹ã‹ã©ã†ã‹ Re&verse middle-button modifier role (Shift/Ctrl) 修飾キーã§ãƒŸãƒ‰ãƒ«ãƒœã‚¿ãƒ³ã®å½¹å‰²ã‚’逆転(&V) Transport トランスãƒãƒ¼ãƒˆ Transport &mode: トランスãƒãƒ¼ãƒˆãƒ¢ãƒ¼ãƒ‰(&M): Transport control mode (JACK) トランスãƒãƒ¼ãƒˆã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ãƒ¢ãƒ¼ãƒ‰(JACK) None ãªã— Slave スレーブ Master マスター Full フル &Loop recording mode (takes): ループ録音モード (テイク)(&L): Loop recording mode (takes) ループ録音モード (テイク) First æœ€åˆ Last 最後 &Audio 音声(&A) Capture / Export キャプãƒãƒ£ / エクスãƒãƒ¼ãƒˆ Audio compression quality to use on capture (record) and export キャプãƒãƒ£ãƒ¼(録音)ã¨ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã®éš›ã®éŸ³å£°åœ§ç¸®ã‚¯ã‚ªãƒªãƒ†ã‚£ãƒ¼ Audio sample format to use on capture (record) and export キャプãƒãƒ£ãƒ¼(録音)ã¨ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã®éš›ã®éŸ³å£°ã‚µãƒ³ãƒ—ルフォーマット Audio file type to use on capture (record) and export キャプãƒãƒ£ãƒ¼(録音)ã¨ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã®éš›ã®éŸ³å£°ãƒ•ァイルタイプ File &type: ファイルタイプ(&T): Sample &format: サンプルフォーマット(&F): &Quality: 圧縮クオリティー(&Q): Playback å†ç”Ÿ Whether to apply time-stretching when tempo changes テンãƒãŒå¤‰æ›´ã•れãŸéš›ã«ã‚¿ã‚¤ãƒ ã‚¹ãƒˆãƒ¬ãƒƒãƒã‚’é©ç”¨ã™ã‚‹ã‹ã©ã†ã‹ Aut&omatic time-stretching 自動タイムストレッãƒ(&O) Sample-&rate converter type: サンプリング周波数変更タイプ(&R): Sample-rate converter quality サンプリング周波数変æ›ã‚¯ã‚ªãƒªãƒ†ã‚£ãƒ¼ Sinc (Best Quality) Sinc (ベストクオリティー) Sinc (Medium Quality) Sinc (中ãらã„ã®ã‚¯ã‚ªãƒªãƒ†ã‚£ãƒ¼) Sinc (Fastest) Sinc (最速) Zero Order Hold Linear Whether to use WSOLA time-stretching WSOLAタイムストレッãƒã‚’使ã†ã‹ã©ã†ã‹ &WSOLA time-stretching WSOLAタイムストレッãƒ(&W) Alt+W Whether to apply WSOLA quick seek time-stretching WSOLAクイックシークタイムストレッãƒãƒ³ã‚°ã‚’é©ç”¨ã™ã‚‹ã‹ã©ã†ã‹ WSOLA quic&k seek WSOLAクイックシーク(&K) Whether to have separate audition/pre-listening player output ports オーディション/プレリスティングプレイヤー専用ã«å‡ºåŠ›ãƒãƒ¼ãƒˆã‚’å€‹åˆ¥ã«æŒã¤ã‹ã©ã†ã‹ Dedicated au&dition/pre-listening player outputs: オーディション/プレリスティングプレイヤー専用出力(&D): Alt+D Whether to auto-connect dedicated audio player outputs 音声プレイヤー専用出力ã«è‡ªå‹•接続ã™ã‚‹ã‹ã©ã†ã‹ Auto-&connect 自動接続(&C) Metronome メトロノーム Whether to enable the audio metronome 音声メトロノームを有効ã«ã™ã‚‹ã‹ã©ã†ã‹ &Enable audio metronome 音声メトロノームを有効(&E) Alt+E &File (bar): ファイル (ãƒãƒ¼) (&F): Metronome Audio filename (bar) メトロノーム用音声ファイルå (ãƒãƒ¼) Browse for sample audio file (bar) éŸ³å£°ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž (ãƒãƒ¼) &Gain (bar): ゲイン (ãƒãƒ¼) (&G): Metronome gain (bar) メトロノームゲイン (ãƒãƒ¼) dB &File (beat): ファイル (beat) (&F): Metronome Audio filename (beat) メトロノーム用音声ファイルå (beat) Browse for sample audio file (beat) éŸ³å£°ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž (ãƒãƒ¼) &Gain (beat): ゲイン (beat) (&G): Metronome gain (beat) メトロノームゲイン (beat) Whether to have separate audio metronome output ports 音声メトロノームã®å‡ºåŠ›ãƒãƒ¼ãƒˆã‚’分離ã™ã‚‹ã‹ã©ã†ã‹ Dedicated a&udio metronome outputs: 音声メトロノーム専用出力(&U): Alt+U Whether to auto-connect dedicated audio metronome outputs 音声メトロノーム専用出力を自動接続 Auto-co&nnect 自動接続(&N) Alt+N &MIDI MIDI(&M) File &format: ファイルフォーマット(&F): MIDI file format to use on capture (record) and export キャプãƒãƒ£ãƒ¼(録音)ã¨ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã«ä½¿ã†MIDIファイルフォーマット &Quantize: クォンタイズ(&Q): MIDI capture (record) quantization MIDIキャプãƒãƒ£ãƒ¼(録音)ã®ã‚¯ã‚ªãƒ³ã‚¿ã‚¤ã‚º Queue &timer (resolution): キュータイマー (è§£åƒåº¦) (&T): Queue timer (resolution) キュータイマー (è§£åƒåº¦) Whether to have separate MIDI player output ports MIDIプレイヤー出力用ã®ãƒãƒ¼ãƒˆã‚’設ã‘ã‚‹ã‹ã©ã†ã‹ Dedicated MIDI p&layer outputs MIDIプレイヤー専用出力(&L) Alt+L Control コントロール &MMC: MIDI Machine Control (MMC) mode MIDIマシンコントロール(MMC)モード Input 入力 Output 出力 Duplex 入出力 &Device: デãƒã‚¤ã‚¹(&D): MIDI Machine Control (MMC) device id. MIDIマシンコントロール (MMC) デãƒã‚¤ã‚¹ID。 &SPP: MIDI Song Position pointer (SPP) control mode MIDIソングãƒã‚¸ã‚·ãƒ§ãƒ³ãƒã‚¤ãƒ³ã‚¿ãƒ¼ (SPP) コントロールモード Cloc&k: クロック(&K): MIDI Clock control mode MIDIクロックコントロールモード Whether to have separate MIDI control ports MIDIコントロール用ã®åˆ¥ãªãƒãƒ¼ãƒˆã‚’設ã‘ã‚‹ã‹ã©ã†ã‹ Dedicated MIDI &control input/output MIDIコントロール専用入出力(&C) Whether to enable the MIDI metronome MIDIメトロノームを有効ã«ã™ã‚‹ã‹ã©ã†ã‹ &Enable MIDI metronome MIDIメトロノーム有効(&E) &Channel: ãƒãƒ£ãƒ³ãƒãƒ«(&C): Metronome MIDI channel メトロノームMIDIãƒãƒ£ãƒ³ãƒãƒ« &Note (bar): ノート(ãƒãƒ¼) (&N): Metronome MIDI note (bar) メトロノームMIDIノート (ãƒãƒ¼) &Velocity (bar): ベロシティー(ãƒãƒ¼) (&V): Metronome MIDI velocity (bar) メトロノームMIDIベロシティー (ãƒãƒ¼) &Duration (bar): デュレーション(ãƒãƒ¼) (&D): &Note (beat): ノート(beat) (&N): Metronome MIDI note (beat) メトロノームMIDIノート(beat) &Velocity (beat): ベロシティー(beat) (&V): Metronome MIDI velocity (beat) メトロノームMIDIベロシティー(beat) &Duration (beat): デュレーション(beat) (&D): Whether to have separate MIDI metronome output port MIDIメトロノーム出力用ã®åˆ¥ãªãƒãƒ¼ãƒˆã‚’設ã‘ã‚‹ã‹ã©ã†ã‹ Dedicated M&IDI metronome output MIDIメトロノーム専用出力(&I) Alt+I &Display 表示(&D) Defaults è¦å®š &Time display format: 時間表示フォーマット(&T): Time display format 時間表示フォーマット Frames フレーム Time 時間 BBT &Base font size: 基本フォントサイズ(&B): Base application font size (pt.) フォントã®ãƒ™ãƒ¼ã‚¹ã‚µã‚¤ã‚º(pt.) (default) (デフォルト) 6 7 8 9 10 11 12 Meters メーター &Audio: 音声(&A): Audio meter level 音声メーターレベル Over オーãƒãƒ¼ 0 dB 3 dB 6 dB 10 dB Audio meter color 音声メーターã®é…色 Select custom audio meter color 音声メーターã«ä»»æ„ã®é…è‰²ã‚’é¸æŠž ... &MIDI: MIDI meter level MIDIメーターレベル Peak ピーク MIDI meter color MIDIメーターé…色 Select custom MIDI meter color MIDIメーターã«ä»»æ„ã®é…è‰²ã‚’é¸æŠž Reset meter colors to default メーターã®é…色をデフォルトã«ãƒªã‚»ãƒƒãƒˆ &Reset リセット(&R) Alt+R Messages メッセージ Sample messages text font display テキストフォントã®ã‚µãƒ³ãƒ—ル表示 Select font for the messages text display メッセージテキストã®ãƒ•ã‚©ãƒ³ãƒˆã‚’é¸æŠž &Font... フォント(&F)... Alt+F Whether to keep a maximum number of lines in the messages window ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã®æœ€å¤§è¡Œæ•°ã‚’ç¶­æŒã™ã‚‹ã‹ã©ã†ã‹ M&essages limit: メッセージリミット(&E): Alt+M The maximum number of message lines to keep in view ビューã«è¡¨ç¤ºã•ã‚Œã‚‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®æœ€å¤§æ•° lines 行 Logging ログ Messages log file メッセージログファイル Browse for the messages log file location メッセージログファイルã®å ´æ‰€ã‚’é¸æŠž Whether to activate a messages logging to file. メッセージã®ãƒ­ã‚°ã‚’ãƒ•ã‚¡ã‚¤ãƒ«ã«æ®‹ã™ã‹ã©ã†ã‹ã€‚ Messages &log file: メッセージログファイル(&L): &Plugins プラグイン(&P) Paths パス Plugin type プラグインã®ç¨®é¡ž Plugin path プラグインã®ãƒ‘ス Browse plugin path ãƒ—ãƒ©ã‚°ã‚¤ãƒ³ãƒ‘ã‚¹ã‚’é¸æŠž Add plugin path プラグインパスã®è¿½åŠ  &Add 追加(&A) Plugin paths プラグインパス Remove plugin path プラグインパスã®é™¤åŽ» &Remove 除去(&R) Move up path パスを上ã«ç§»å‹• &Up 上ã¸(&U) &Down 下ã¸(&D) &LV2 Presets directory: LV2プリセットディレクトリー(&L): LV2 Presets directory (default: ~/.lv2) LV2プリセットディレクトリー(デフォルト: ~/.lv2) Browse LV2 Presets directory LV2プリセットディレクトリーã®é¸æŠž Instruments インストルメント Whether to have separate audio output ports 音声出力用ã«åˆ¥ãªãƒãƒ¼ãƒˆã‚’設ã‘ã‚‹ã‹ã©ã†ã‹ Dedicated audi&o outputs: 音声専用出力(&O): Whether to auto-connect dedicated audio output ports 音声専用出力ã«è‡ªå‹•接続ã™ã‚‹ã‹ã©ã†ã‹ Au&to-connect 自動接続(&T) Alt+T Editor エディター Whether to open plugin's editor (GUI) by default デフォルトã§ãƒ—ラグインã®ã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼(GUI)ã‚’é–‹ãã‹ã©ã†ã‹ Open plugin's &editor (GUI) by default プラグインã®ã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼(GUI)をデフォルトã§é–‹ã(&E) Alt+G Experimental エクスペリメンタル Whether to use a dummy plugin type when scanning for VST plugins VSTプラグインを検出ã™ã‚‹éš›ã«ãƒ€ãƒŸãƒ¼ãƒ—ラグインタイプを用ã„ã‚‹ã‹ã©ã†ã‹ Dummy &VST plugin scan (RECOMMENDED) ダミーã®VSTプラグインをスキャン(推奨)(&V) Alt+V Signed 16-Bit Signed 24-Bit Signed 32-Bit Float 32-Bit Float 64-Bit SMF Format 0 SMF Format 1 (Any) (ä»»æ„) Warning 警告 Some settings have been changed. Do you want to apply the changes? 設定ã®ä¸€éƒ¨ãŒå¤‰æ›´ã•れã¾ã—㟠ã“ã®å¤‰æ›´ã‚’é©ç”¨ã—ã¾ã™ã‹? Metronome Bar Audio File メトロノームã®ãƒãƒ¼ç”¨éŸ³å£°ãƒ•ァイル Metronome Beat Audio File メトロノームã®Beat用ã®éŸ³å£°ãƒ•ァイル Plug-in Directory プラグインディレクトリー LV2 Presets Directory LV2プリセットディレクトリー Messages Log メッセージログ Log files (*.%1) ログファイル (*.%1) Session Template セッションã®ãƒ†ãƒ³ãƒ—レート Session template files (*.qtr *.qts *.%1) セッションã®ãƒ†ãƒ³ãƒ—レートファイル(*.qtr *.qts *.%1) qtractorPasteRepeatForm Paste Repeat - Qtractor 繰り返ã—ã¦è²¼ã‚Šä»˜ã‘ - Qtractor Repeat 繰り返㙠&Count: 回数(&C): Repeat count 繰り返ã—回数 &Period: é•·ã•(&P): Repeat period 繰り返ã™é•·ã• Repeat period format 繰り返ã—é•·ã®ãƒ•ォーマット Frames フレーム Time 時間 BBT Warning 警告 Some settings have been changed. Do you want to apply the changes? 設定ã®ä¸€éƒ¨ãŒå¤‰æ›´ã•れã¾ã—㟠ã“ã®å¤‰æ›´ã‚’é©ç”¨ã—ã¾ã™ã‹? qtractorPluginForm qtractorPluginForm qtractorプラグイン Open preset プリセットを開ã Preset name プリセットå Save preset プリセットã®ä¿å­˜ Delete preset プリセットã®å‰Šé™¤ Plugin parameters プラグインã®ãƒ‘ラメーター Params パラメーター Edit plugin プラグインã®ç·¨é›† Edit 編集 Activate plugin ãƒ—ãƒ©ã‚°ã‚¤ãƒ³ã®æœ‰åŠ¹åŒ– Active アクティベート Outputs (Sends) 出力 (Send) Sends センド Inputs (Returns) インプット (Return) Returns リターン Aux Send Bus: Auxセンドãƒã‚¹: Manage buses ãƒã‚¹ã®ç®¡ç† ... Direct Access Parameter ダイレクトアクセスã®ãƒ‘ラメーター Direct Access ダイレクトアクセス (default) (デフォルト) Page %1 ページ %1 (none) (ãªã—) Open Preset プリセットを開ã Preset files (*.%1) プリセットファイル (*.%1) Error エラー Preset could not be loaded from "%1". Sorry. %1 ã‹ã‚‰ãƒ—リセットをロードã™ã‚‹ã“ã¨ãŒ ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ ã”ã‚ã‚“ãªã•ã„。 Save Preset プリセットã®ä¿å­˜ Warning 警告 About to delete preset: "%1" (%2) Are you sure? プリセットを削除ã—ã¾ã™: "%1" (%2) よã‚ã—ã„ã§ã™ã‹ï¼Ÿ &None ãªã—(&N) qtractorPluginListView copy plugin プラグインをコピー activate all plugins ã™ã¹ã¦ã®ãƒ—ラグインを有効化 deactivate all plugins ã™ã¹ã¦ã®ãƒ—ラグインを無効化 remove all plugins ã™ã¹ã¦ã®ãƒ—ラグインを除去 &Move Here ã“ã“ã¸ç§»å‹•(&M) &Copy Here ã“ã“ã¸ã‚³ãƒ”ー(&C) C&ancel キャンセル(&A) &Add Plugin... プラグインを追加(&A)... Add &Insert インサートを追加(&I) Add &Aux Send Auxセンドを追加(&A) &Sends センド(&S) &Returns リターン(&R) Ac&tivate アクティベート(&T) Acti&vate All ã™ã¹ã¦ã‚’有効化(&V) Deactivate Al&l ã™ã¹ã¦ã‚’無効化(&L) &Remove 除去(&R) Re&move All ã™ã¹ã¦ã‚’除去(&M) Move &Up 上ã«ç§»å‹•(&U) Move &Down 下ã«ç§»å‹•(&D) &None ãªã—(&N) &Properties... プロパティ(&P)... &Edit 編集(&E) &Outputs 出力(&O) &Dedicated 専用(&D) &Auto-connect 自動接続(&A) qtractorPluginSelectForm Plugins - Qtractor プラグイン - Qtractor Reset filter フィルターã®ãƒªã‚»ãƒƒãƒˆ X Plugin search string (regular expression) プラグイン検索キーワード(正è¦è¡¨ç¾ã‚’使用å¯èƒ½ï¼‰ Plugin type プラグインã®ã‚¿ã‚¤ãƒ— Available plugins 利用å¯èƒ½ãªãƒ—ラグイン Name åå‰ Audio 音声 MIDI MIDI Control コントロール Modes モード Path パス Index インデックス Instances インスタンス Type タイプ &Activate 有効化(&A) Activate plugin on insert 挿入時ã«ãƒ—ラグインを有効化ã™ã‚‹ Alt+A Plugin scanning in progress... プラグインを検索中ã§ã™... GUI EXT RT qtractorSessionForm Session - Qtractor セッション - Qtractor Session セッション &Name: åå‰(&N): Session name セッションå &Directory: ディレクトリ(&D): Session directory セッションã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒª Browse for session directory ã‚»ãƒƒã‚·ãƒ§ãƒ³ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’é¸æŠžã—ã¾ã™ ... &Description: 説明(&D): Session description セッションã®èª¬æ˜Ž Properties プロパティ Time 時間 Sample &Rate: サンプルレート(&R): Sample rate (Hz) サンプルレート(Hz) 44100 48000 96000 192000 &Tempo: テンãƒ(&T): Tempo (BPM) / Signature テンム(BPM) / æ‹å­è¨˜å· T&icks/Beat: ãƒãƒƒã‚¯/ビート(&I): Resolution (ticks/beat; tpqn) è§£åƒåº¦ (ãƒãƒƒã‚¯/ビート; tpqn) View 表示 &Snap/Beat: スナップ/ビート(&S): Snap/beat スナップ/ビート &Pixels/Beat: ピクセル/ビート(&P): Pixels/beat ピクセル/ビート &Horizontal Zoom: 水平ズーム率(&H): Horizontal Zoom (%) 水平ズーム率 (%) % % &Vertical Zoom: 垂直ズーム率(&V): Vertical Zoom (%) 垂直ズーム率 (%) Warning 警告 Session directory does not exist: "%1" Do you want to create it? セッションディレクトリãŒã‚りã¾ã›ã‚“: "%1" ディレクトリを作æˆã—ã¾ã™ã‹ï¼Ÿ Some settings have been changed. Do you want to apply the changes? 設定ã®ä¸€éƒ¨ãŒå¤‰æ›´ã•れã¾ã—㟠ã“ã®å¤‰æ›´ã‚’é©ç”¨ã—ã¾ã™ã‹? Session Directory セッションディレクトリ qtractorShortcutForm Keyboard Shortcuts キーボードショートカット Action æ“作 Description 説明 Shortcut ショートカット Warning 警告 Keyboard shortcut (%1) already assigned. キーボードショートカット (%1) ã¯ã™ã§ã«ã‚¢ã‚µã‚¤ãƒ³ã•れã¦ã„ã¾ã™ Keyboard shortcuts have been changed. Do you want to apply the changes? キーボードショートカットãŒå¤‰æ›´ã•れã¾ã—㟠ã“ã®å¤‰æ›´ã‚’é©ç”¨ã—ã¾ã™ã‹? qtractorTakeRangeForm Take - Qtractor テイク - QTractor Range レンジ Selection range é¸æŠžãƒ¬ãƒ³ã‚¸ &Selection é¸æŠž(&S) Loop range ループレンジ &Loop ループ(&L) Punch range パンãƒãƒ¬ãƒ³ã‚¸ &Punch パンãƒ(&P) Time 時間 BBT Edit range 編集レンジ &Edit 編集(&E) Custom range ä»»æ„ã®ãƒ¬ãƒ³ã‚¸ &Custom カスタム(&C) St&art: é–‹å§‹(&A): Clip start クリップã®é–‹å§‹æ™‚é–“ En&d: 終了(&D): Clip offset クリップã®ã‚ªãƒ•セット Select テイクã®é¸æŠž Current take ç¾åœ¨ã®ãƒ†ã‚¤ã‚¯ Format フォーマット Time display format 時間表示フォーマット Frames フレーム &Frames フレーム(&F) Time (hh:mm:ss.zzz) 時間 (hh:mm:ss.zzz) &Time 時間(&T) BBT (bars.beats.ticks) BBT (ãƒãƒ¼ ビート ãƒãƒƒã‚¯) Take %1 テイク %1 qtractorTempoAdjustForm Tempo - Qtractor テンム- Qtractor Metronome メトロノーム Temp&o: テンãƒ(&O): Tempo/Time signature テンム/ æ‹å­è¨˜å· T&ap タップ(&A) Range レンジ &Start: é–‹å§‹(&S): Range start レンジã®é–‹å§‹ Time 時間 BBT &Length: é•·ã•(&L): Range length レンジã®é•·ã• B&eats: ビート(&E): Range beats レンジã®ãƒ“ート A&djust 調整(&D) Format フォーマット Time display format 時間表示フォーマット Frames フレーム Fra&mes フレーム(&M) Time (hh:mm:ss.zzz) 時間 (hh:mm:ss.zzz) &Time 時間(&T) BBT (bars.beats.ticks) BBT (ãƒãƒ¼ ビート ãƒãƒƒã‚¯) Warning 警告 Some settings have been changed. Do you want to apply the changes? 設定ã®ä¸€éƒ¨ãŒå¤‰æ›´ã•れã¾ã—㟠ã“ã®å¤‰æ›´ã‚’é©ç”¨ã—ã¾ã™ã‹? qtractorThumbView Thumb view サムãƒã‚¤ãƒ«ãƒ“ュー qtractorTimeScaleForm Tempo Map - Qtractor テンãƒãƒžãƒƒãƒ— - QTractor Tempo map テンãƒãƒžãƒƒãƒ— Bar ãƒãƒ¼ Time 時間 Tempo テンムSignature æ‹å­ Node ノード &Bar: ãƒãƒ¼(&B): Tempo Map / Markers - Qtractor テンãƒãƒžãƒƒãƒ— /マーカー - Qtractor Tempo map / Markers テンãƒãƒžãƒƒãƒ— / マーカー Marker マーカー Location ロケーション Bar location ãƒãƒ¼ã®ãƒ­ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ T&ime: 時間(&I): Bar/Time node ãƒãƒ¼/時間ノード Time/frame location 時間/フレームã®ãƒ­ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ &Tempo: テンãƒ(&T): Tempo (BPM) / Signature テンム(BPM) / æ‹å­è¨˜å· T&ap タップ(&A) Marker text マーカーテキスト ... Marker color マーカーã®è‰² Refresh tempo map テンãƒãƒžãƒƒãƒ—ã®æ›´æ–° Re&fresh æ›´æ–°(&F) Alt+F Add node ノードを追加 &Add 追加(&A) Alt+A Update node ノードをアップデート &Update アップデート(&U) Alt+U Remove node ノードを除去 &Remove 除去(&R) Alt+R Close this dialog ダイアログを閉ã˜ã¾ã™ Close é–‰ã˜ã‚‹ Warning 警告 Some settings have been changed. Do you want to apply the changes? 設定ã®ä¸€éƒ¨ãŒå¤‰æ›´ã•れã¾ã—㟠ã“ã®å¤‰æ›´ã‚’é©ç”¨ã—ã¾ã™ã‹? About to remove tempo node: %1 (%2) %3 %4/%5 Are you sure? テンãƒãƒŽãƒ¼ãƒ‰ã‚’除去ã—ã¾ã™: %1 (%2) %3 %4/%% よã‚ã—ã„ã§ã™ã‹? Some settings have been changed. Do you want to discard the changes? 設定ã®ä¸€éƒ¨ãŒå¤‰æ›´ã•れã¾ã—㟠ã“ã®å¤‰æ›´ã‚’破棄ã—ã¾ã™ã‹? &Refresh æ›´æ–°(&R) qtractorTimeSpinBox &Frames フレーム(&F) &Time 時間(&T) &BBT qtractorTrackButton Record 録音 Mute ミュート Solo ソロ qtractorTrackForm Track - Qtractor トラック - Qtractor Track トラック &Name: åå‰(&N): Track name description トラックåã®èª¬æ˜Ž Type 種類 Audio track type 音声トラックタイプ &Audio 音声(&A) Alt+A MIDI track type MIDIトラックタイプ &MIDI MIDI(&M) Alt+M Input / Output 入力 / 出力 Input bus name 入力ãƒã‚¹å Output bus name 出力ãƒã‚¹å Manage buses ãƒã‚¹ã®ç®¡ç† ... MIDI / Instrument MIDI/インストルメント &Program: プログラム(&P): &Bank: ãƒãƒ³ã‚¯(&B): Bank &Select Method: ãƒãƒ³ã‚¯ã‚»ãƒ¬ã‚¯ãƒˆæ–¹æ³•(&S): &Omni MIDI Omni: Capture All Channels MIDI Omni: å…¨ãƒãƒ£ãƒ³ãƒãƒ«ã‚’記録 Alt+O &Channel: ãƒãƒ£ãƒ³ãƒãƒ«(&C): MIDI Channel (1-16) MIDIãƒãƒ£ãƒ³ãƒãƒ« (1-16) MIDI Patch: Instrument MIDIパッãƒ:インストルメント MIDI Patch: Bank Select Method MIDIパッãƒ:ãƒãƒ³ã‚¯ã‚»ãƒ¬ã‚¯ãƒˆæ–¹æ³• MIDI Patch: Bank MIDIパッãƒ:ãƒãƒ³ã‚¯ MIDI Patch: Program MIDIパッãƒ:プログラム View / Colors 表示 / 色 &Foreground: 剿™¯(&F): Foreground color 剿™¯è‰² Select custom track foreground color ä»»æ„ã®ãƒˆãƒ©ãƒƒã‚¯å‰æ™¯è‰²ã‚’é¸æŠž Bac&kground: 背景(&K): Background color 背景色 Select custom track background color ä»»æ„ã®èƒŒæ™¯è‰²ã‚’é¸æŠž Plugins プラグイン Track plugins トラックプラグイン Add plugin プラグインを追加 &Add... 追加(&A)... Remove plugin プラグインを除去 &Remove 除去(&R) Alt+R Move plugin up プラグインを上ã¸ç§»å‹• &Up 上ã¸(&U) Alt+U Move plugin down プラグインを下ã¸ç§»å‹• &Down 下ã¸(&D) Alt+D Normal ノーマル Bank MSB ãƒãƒ³ã‚¯MSB Bank LSB ãƒãƒ³ã‚¯LSB Patch パッムWarning 警告 Some settings have been changed. Do you want to apply the changes? 設定ã®ä¸€éƒ¨ãŒå¤‰æ›´ã•れã¾ã—㟠ã“ã®å¤‰æ›´ã‚’é©ç”¨ã—ã¾ã™ã‹? (No instrument) (インストルメントãªã—) (None) (ãªã—) qtractorTrackItemWidget Automation オートメーション qtractorTrackListHeaderModel Nr ç•ªå· Track Name トラックå Bus ãƒã‚¹ Ch Patch パッムInstrument インストルメント qtractorTrackTime Play-head å†ç”Ÿå…ˆé ­ Edit-head 編集先頭 Edit-tail 編集末尾 Loop-start ループスタート Loop-end ループエンド Punch-in パンãƒã‚¤ãƒ³ Punch-out パンãƒã‚¢ã‚¦ãƒˆ Start: %1 End: %2 Length: %3 é–‹å§‹: %1 終了: %2 é•·ã•: %3 qtractorTrackView Zoom in (horizontal) ズームイン(水平方å‘) Zoom out (horizontal) ズームアウト(水平方å‘) Zoom in (vertical) ズームイン(垂直方å‘) Zoom out (vertical) ズームアウト(垂直方å‘) Zoom reset ズームリセット add clip クリップを追加 Start: %1 End: %2 Length: %3 é–‹å§‹: %1 終了: %2 é•·ã•: %3 clip %1 クリップ %1 fade-in フェードイン fade-out フェードアウト clip stretch クリップã®ä¼¸é•· clip resize クリップリサイズ %1 automation %1 オートメーション %1 clip %1 クリップ move automation オートメーションã®ç§»å‹• paste automation オートメーションã®è²¼ã‚Šä»˜ã‘ cut 切りå–り delete 削除 split 分割 move clip クリップã®ç§»å‹• paste clip クリップã®è²¼ã‚Šä»˜ã‘ qtractorTracks Tracks トラック new clip æ–°è¦ã‚¯ãƒªãƒƒãƒ— split clip クリップã®åˆ†å‰² clip normalize クリップã®ãƒŽãƒ¼ãƒžãƒ©ã‚¤ã‚º quantize クォンタイズ transpose トランスãƒãƒ¼ã‚º normalize ノーマライズ randomize ランダマイズ resize リサイズ rescale リスケール timeshift タイムシフト clip tool %1 クリップツール %1 clip import クリップã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ Audio file import "%1" on %2 %3. 音声ファイル "%1" ã‚’ %2 %3 ã¸ã‚¤ãƒ³ãƒãƒ¼ãƒˆã€‚ Audio file import: "%1". 音声ファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ: "%1"。 MIDI file import "%1" track-channel %2 on %3 %4. MIDIファイル "%1" をトラックãƒãƒ£ãƒ³ãƒãƒ« %2 ã®%3 %4 ã¸ã‚¤ãƒ³ãƒãƒ¼ãƒˆã€‚ MIDI file import: "%1", track-channel: %2. MIDIファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ: "%1", トラックãƒãƒ£ãƒ³ãƒãƒ«: %2。 clip merge クリップã®ãƒžãƒ¼ã‚¸ Merge/Export Audio Clip 音声クリップã®ãƒžãƒ¼ã‚¸/エクスãƒãƒ¼ãƒˆ Audio files (*.%1) 音声ファイル (*.%1) Audio clip merge/export: "%1" started... 音声クリップã®ãƒžãƒ¼ã‚¸/エクスãƒãƒ¼ãƒˆ: "%1" ã‚’é–‹å§‹... Audio clip merge/export: "%1" complete. 音声クリップã®ãƒžãƒ¼ã‚¸/エクスãƒãƒ¼ãƒˆ: "%1" 完了。 Merge/Export MIDI Clip MIDIクリップをマージ/エクスãƒãƒ¼ãƒˆ MIDI files (*.%1 *.smf *.midi) MIDIファイル (*.%1 *.smf *.midi) MIDI clip merge/export: "%1" started... MIDIクリップã®ãƒžãƒ¼ã‚¸/エクスãƒãƒ¼ãƒˆ: "%1" é–‹å§‹... MIDI clip merge/export: "%1" complete. MIDIクリップã®ãƒžãƒ¼ã‚¸/エクスãƒãƒ¼ãƒˆ: "%1" 完了。 Insert Range ãƒ¬ãƒ³ã‚¸ã®æŒ¿å…¥ insert range ãƒ¬ãƒ³ã‚¸ã®æŒ¿å…¥ insert track range ãƒˆãƒ©ãƒƒã‚¯ãƒ¬ãƒ³ã‚¸ã®æŒ¿å…¥ Remove Range レンジã®é™¤åŽ» remove range レンジを除去ã—ã¾ã™ remove track range トラックレンジを除去ã—ã¾ã™ Warning 警告 About to remove track: "%1" Are you sure? トラックを除去ã—ã¾ã™: "%1" よã‚ã—ã„ã§ã™ã‹? MIDI file import "%1" on %2 %3. MIDIファイル "%1" ã‚’ %2 %3 ã¸ã‚¤ãƒ³ãƒãƒ¼ãƒˆã€‚ MIDI file import: "%1". MIDIファイルをインãƒãƒ¼ãƒˆ: "%1"。 qtractor-0.5.11/src/translations/PaxHeaders.10084/qtractor_it.ts0000644000175000001440000000012312223511102022654 xustar000000000000000027 mtime=1380880962.062114 26 atime=1381134669.06008 30 ctime=1381134669.152080083 qtractor-0.5.11/src/translations/qtractor_it.ts0000644000175000001440000163405212223511102022156 0ustar00rncbcusers00000000000000 QObject Audio: %1 channels, %2 Hz Audio: %1 canali, %2 Hz (%1 dB) (%1 dB) (%1% time stretch) (%1% allarga tempo) (%1 semitones pitch shift) (%1 semitoni trasposti) %1 In %1 Ingressi %1 Out %1 Uscite Audio files (%1) File audio (%1) All files (*.*) Tutti i file (*.*) %1 (%2) %3 channels, %4 frames, %5 Hz %6 %1 (%2) %3 canali, %4 campioni, %5 Hz %6 Duplex Duplex Output Uscita Input Ingresso None Nessuno (take %1) (ripresa %1) Name: %1 Nome: %1 Start / End: %1 / %2 Offset / Length: %3 / %4 Start / End: %1 / %2 Offs. / Len.: %3 / %4 Inizio/Fine: %1 / %2 Posiz./Durata: %3 / %4 File: %1 File: %1 take %1 ripresa %1 reset takes reset riprese automation select selezione automazione automation mode modalità automazione automation play riproduzione automazione automation record registra automazione automation logarithmic automazione logaritmica automation color colore automazione automation play all riproduci tutte le automazioni automation record all registra tutte le automazioni automation edit modifica automazione automation clear pulisci automazione automation clear all pulisci tutte le automazioni automation edit list lista modifiche automazioni %1 Monitor %1 Monitor create bus crea bus update bus aggiorna bus delete bus rimuovi bus bus pass-through pass-through bus bus gain guadagno bus bus pan bilanciamento bus Send Gain Mandata Guadagno Dry / Wet Dry / Wet Cakewalk Instrument Definition File File di definizione strumento Cakewalk File File Date Data %1 Bank %2 %1 Banco %2 %1 - Bank %2 %1 - Banco %2 (format %1) MIDI: (formato %1) MIDI: Channel %1 Canale %1 Track %1 Traccia %1 , %1 tracks, %2 tpqn , %1 tracce, %2 tpqn (%1% vol) (%1% vol) set controller imposta controller reset controller resetta controller %1 (format %2) %3 tracks, %4 tpqn %5 %1 (formato %2) %3 tracce, %4 tpqn %5 %1 (format %2) %3 %1 (formato %2) %3 (default) (predefinito) %1 Hz %1 Hz slave slave %1 (%2) %1 (%2) Usage: %1 [options] [session-file] Utilizzo: %1 [opzioni] [file di sessione] Options: Opzioni: Set session identification (uuid) Imposta identificativo sessione (uuid) Show help about command line options Mostra opzioni della riga di comando Show version information Mostra informazioni di versione Option -s requires an argument (session-id). L'opzione -s richiede un argomento (ID sessione). Qt: %1 Qt: %1 (Any) (Qualsiasi) add plugin aggiungi plugin add insert aggiungi insert add aux-send aggiungi send-aux aux-send bus bus send-aux remove plugin rimuovi plugin move plugin sposta plugin activate plugin attiva plugin preset plugin plugin di preset reset plugin resetta plugin dedicated audio outputs uscite audio dedicate direct access param parametro accesso diretto session loop loop sessione session punch punch sessione session properties proprietà sessione Beat Battito add tempo node aggiungi nodo tempo update tempo node aggiorna nodo tempo remove tempo node rimuovi nodo tempo move tempo node add marker update marker remove marker move marker %1 Record %1 Registrazione %1 Mute %1 Muto %1 Solo %1 Solo %1 Volume %1 Gain %1 Pan add track aggiungi traccia remove track rimuovi traccia move track sposta traccia resize track ridimensiona traccia import track importa traccia track properties proprietà traccia Track assignment failed: Track: "%1" Input: "%2" Output: "%3" Assegnazione traccia fallita: Traccia: "%1" Ingresso: "%2" Uscita: "%3" track record registra traccia track mute silenzia traccia track solo traccia in solo track monitor monitor traccia track gain guadagno traccia track pan bilanciamento traccia Automation (%1) Automazione (%1) none nessuno Automation Automazione Audio Audio MIDI MIDI Unknown Sconosciuto %1 (*.%2) %1 (*.%2) qtractorAudioListView Name Nome Ch Canale Frames Campioni Rate Campionamento Time Tempo Path Percorso Open Audio Files Apri File Audio qtractorAudioMeter Gain (dB) Guadagno (dB) dB dB Pan: %1 Bilanciamento: %1 Gain: %1 dB Guadagno: %1 dB qtractorBusForm Buses - Qtractor Bus - Qtractor Bus list Lista bus Buses Bus Ch Canali Mode Modalità Bus Bus Properties Proprietà &Name: &Nome: Bus name Nome bus &Mode: &Modalità: Bus mode Modalità bus Input Ingresso Output Uscita Duplex Duplex Bus monitor (pass-through) Monitor bus (pass-through) M&onitor (pass-through) M&onitor (pass-through) Alt+O Alt+O Audio Audio Cha&nnels: Ca&nali: Audio channels Canali audio Audio auto-connect Connessione automatica audio &Auto connect Connessione &Automatica Alt+A Alt+A MIDI MIDI MIDI Instrument name Nome strumento MIDI MIDI SysEx setup Configurazione SysEx MIDI SysE&x... SysE&x... Input Plugins Plugin di Ingresso Input bus plugins Plugin bus di ingresso Add input plugin Aggiungi plugin in ingresso &Add... &Aggiungi... Remove input plugin Rimuovi plugin di ingresso &Remove &Rimuovi Alt+R Alt+R Move input plugin up Sposta in su plugin ingresso &Up S&U Alt+U Alt+U Move input plugin down Sposta in giù plugin di ingresso &Down &Giù Alt+D Alt+D Output Plugins Plugin di Uscita Output bus plugins Plugin bus di uscita Add output plugin Aggiungi plugin di uscita Remove output plugin Rimuovi plugin di uscita Move output plugin up Sposta in su plugin di output Move output plugin down Sposta in giù plugin di output Refresh bus list view Aggiorna lista bus &Refresh Aggio&rna Create bus Crea bus &Create &Crea Alt+C Alt+C Update bus Aggiorna bus &Update &Aggiorna Delete bus Rimuovi bus &Delete &Rimuovi Close this dialog Chiudi questa finestra Close Chiudi Warning Attenzione Some settings have been changed. Do you want to apply the changes? Alcune impostazioni sono state modificate. Vuoi applicare le modifiche? About to remove bus: "%1" (%2) Are you sure? Sto per rimuovere il bus: "%1" (%2) Sei sicuro? Some settings have been changed. Do you want to discard the changes? Alcune impostazioni sono state modificate. Vuoi annullare le modifiche? (No instrument) (Nessuno strumento) (none) (nessuno) (1 item) (1 elemento) (%1 items) (%1 elementi) qtractorClientListView Readable Clients / Output Ports Client Leggibili / Porte di Uscita Writable Clients / Input Ports Client Scrivibili / Porte di Ingresso qtractorClipForm Clip - Qtractor Clip - Qtractor &Name: amp;Nome: Clip name Nome clip &File: &File: Clip filename Nome del clip Browse for clip file Sfoglia file di clip Track/&Channel: Traccia/&Canale: Clip track/channel Traccia clip/canale &Gain/Volume: &Guadagno/Volume: Clip gain/volume Guadagno clip/volume Parameters Parametri Clip start Inizio clip Clip offset Posizione clip Clip length Lunghezza clip Offs&et: Posizion&e: &Length: &Lunghezza: &Start: &Inizio: Gain/Volume Format Formato Time display format >Formato visualizzazione tempo Frames Campioni Fra&mes Ca&mpioni Time (hh:mm:ss.zzz) Tempo (hh:mm:ss.zzz) &Time &Tempo BBT (bars.beats.ticks) BBT (battute.battiti.tick) &BBT &BBT Time Tempo BBT BBT Fade In/Out Fade In/Out Fade &In: Fade &In: Clip fade-in length Fade-in clip Clip fade-in type Tipo di fade-in clip Fade &Out: Fade &Out: Clip fade-out length Fade-out clip Clip fade-out type Tipo di fade-out clip Audio Audio Time St&retch: Alla&rga Tempo: Clip time-stretch percentage Percentuale di allrgamento tempo del clip % % Pitch S&hift: Pitch S&hift: Clip pitch-shift in semitones Pitch shift del clip in semitoni semitones semitoni &Gain: &Guadagno: dB dB &Volume: &Volume: new clip nuovo clip edit clip modifica clip Warning Attenzione Some settings have been changed. Do you want to apply the changes? Alcune impostazioni sono state modificate. Vuoi applicare le modifiche? MIDI MIDI MIDI files (*.%1 *.smf *.midi) File MIDI (*.%1 *.smf *.midi) %1 Clip File %1 File di Clip qtractorConnect Connect Connetti Disconnect Disconnetti Disconnect All Disconnetti Tutti Refresh Aggiorna qtractorConnectForm qtractorConnectTest qtractorConnectTest Audio Audio Select output client/ports Seleziona client/porta di uscita Select input client/ports Seleziona client/porta di ingresso Connect currently selected ports Connetti porte attualmente selezionate &Connect &Connetti Alt+C Alt+C Disconnect currently selected ports Disconnetti porte attualmente selezionate &Disconnect &Disconnetti Alt+D Alt+D Disconnect all currently connected ports Disconnetti tutte le porte attualmente connesse Disconnect &All Disconnetti Tutto Alt+A Alt+A Refresh current connections view Aggiorna vista corrente delle connessioni &Refresh Aggio&rna Alt+R Alt+R MIDI MIDI (All) (Tutto) qtractorConnections Connections Connessioni qtractorEditRangeForm Range - Qtractor Range Intervallo Selection range Intervallo selezione &Selection &Selezione Loop range &Loop Punch range &Punch Edit range &Edit Modifica Custom range &Custom St&art: Clip start Inizio clip En&d: Clip offset Posizione clip Apply to Loop points in range L&oop Apply to Punch In/Out points in range Pu&nch Mar&kers Te&mpo Map &Format Time display format >Formato visualizzazione tempo Time Tempo BBT BBT Format Formato Frames &Frames Campioni Time (hh:mm:ss.zzz) Tempo (hh:mm:ss.zzz) &Time &Tempo BBT (bars.beats.ticks) BBT (battute.battiti.tick) &BBT &BBT Options Opzioni Apply to clips in range Cl&ips A&utomation A&utomazione Apply to Automation nodes in range &Automation &Automazione Apply to Tempo Map nodes in range Apply to location Markers in range qtractorExportForm Export - Qtractor Esporta - Qtractor &File: &File: Export file name Esporta nome file Browse export file name Sfoglia esporta nome file Range Intervallo Session range Intervallo sessione &Session &Sessione Loop range Intervallo di loop &Loop &Loop Punch range Intervallo di punch &Punch &Punch Edit range Modifica intervallo &Edit Modifica Custom range Intervallo personalizzato &Custom Personalizzato St&art: Inizio: Clip start Inizio clip En&d: Fine: Clip offset Posizione clip Output Uscita Output bus name Nome bus uscita Format Formato Time display format >Formato visualizzazione tempo Frames Campioni Time Tempo BBT BBT &Frames Campioni Time (hh:mm:ss.zzz) Tempo (hh:mm:ss.zzz) &Time &Tempo BBT (bars.beats.ticks) BBT (battute.battiti.tick) &BBT &BBT Audio Audio MIDI MIDI Export %1 Esporta %1 Warning Attenzione The file already exists: "%1" Do you want to replace it? File già esistente: "%1" Vuoi sostituirlo? Audio file export: "%1" started... Esportazione file audio: "%1" iniziata... Audio file export: "%1" complete. Esportazione file audio: "%1" completata. Audio file export: "%1" failed. Esportazione file audio: "%1" fallita. MIDI file export: "%1" started... Esportazione file MIDI: "%1" iniziata... MIDI file export: "%1" complete. Esportazione file MIDI: "%1" completata. MIDI file export: "%1" failed. Esportazione file MIDI: "%1" fallita. Export %1 File Esporta %1 File %1 files (*.%1) %1 file (*.%1) qtractorFileListView New Group Nuovo Gruppo Warning Attenzione About to remove %1 file items. Are you sure? Si sta per rimuovere %1 file. Sei sicuro? About to remove %1 file item(s). Are you sure? About to remove %1 item: "%2" Are you sure? Si sta per rimuovere %1 elemento: "%2" Sei sicuro? group gruppo file file qtractorFiles Audio Audio MIDI MIDI Play file Riproduci file New &Group Nuovo &Gruppo Add &Files... Aggiungi &File... Cu&t &Taglia &Copy &Copia P&aste Incoll&a R&ename Rinomina &Delete Elimina Play Riproduci Ctrl+G Ctrl+G Ctrl+F Ctrl+F Ctrl+X Ctrl+X Ctrl+C Ctrl+C Ctrl+V Ctrl+V Ctrl+E Ctrl+E New &Group... &Paste Incolla Re&name &Remove Pla&y Cl&eanup Del Canc Files File MIDI Files File MIDI Audio Files File Audio qtractorInstrumentForm Instruments - Qtractor Strumenti - Qtractor Instruments Strumenti Files File Path Percorso Names Nomi Import from instrument file Importa da file strumenti &Import... &Importa... Alt+I Alt+I Remove instrument file Elimina file strumenti &Remove Elimina Alt+R Alt+R Move instrument file up on list order Sposta file strumenti più su nella lista &Up S&u Alt+U Alt+U Move instrument file down on list order Sposta file strumenti più giù nella lista &Down Giù Alt+D Alt+D Reload all instrument files Ricarica tutti i file di strumenti Relo&ad Ric&arica Alt+A Alt+A Export to instrument file Esporta su file strumenti E&xport... Esporta... Alt+X Alt+X Close this dialog Chiudi questa finestra Close Chiudi Import Instrument Files Importa file strumenti Instrument files (*.%1 *.sf2 *.midnam) File strumenti (*.%1 *.sf2 *.midnam) Export Instrument File Esporta file strumenti Instrument files (*.%1) File strumenti (*.%1) Warning Attenzione The instrument file already exists: "%1" Do you want to replace it? Il file degli strumenti esiste già: "%1" Vuoi sostituirlo? Instrument settings have been changed. Do you want to apply the changes? I parametri degli strumenti sono stati modificati. Vuoi applicare le modifiche? Patch Names for Banks Nome della patch per i banchi Controller Names = %1 Nomi dei controller = %1 RPN Names = %1 Nomi degli RPN = %1 NRPN Names = %1 Nomi degli NRPN = %1 Bank Select Method = %1 Metodo di selezione del banco = %1 Patch Names Nomi Patch Note Names Nomi Note Controller Names Nomi Controller RPN Names Nomi RPN NRPN Names Nomi NRPN Bank Select Methods Metodi di selezione del banco %1 = %2 %1 = %2 Based On = %1 Basato su = %1 Normal Normale Bank MSB MSB Banco Bank LSB LSB Banco Patch Patch Unknown Sconosciuto qtractorMainForm Qtractor Qtractor &File &File Open &Recent Apri &Recente &Edit Modifica Select &Mode Seleziona &Modalità &Select &Seleziona I&nsert Remo&ve &Track &Traccia &State &Stato &Navigate &Navigazione Mo&ve Sposta &Height Altezza Impor&t Tracks Impor&ta Tracce E&xport Tracks Esporta Tracce M&ode M&odalità A&utomation A&utomazione Cl&ip Cl&ip T&ools Strumenti Ta&ke Ripresa &View &Vista &Toolbars Barre S&trumenti &Windows Finestre &Zoom &Zoom S&nap Alli&neamento T&ransport T&rasporto &Help Aiuto &New &Nuovo New Nuovo New session Nuiova sessione New session file Nuovo file sessione Ctrl+N Ctrl+N &Open... Apri... Open Apri Open session Apri sessione Open session from file Apri file sessione Ctrl+O Ctrl+O &Save &Salva Save Salva Save session Salva sessione Save session to file Salva sessione su file Ctrl+S Ctrl+S Save &As... S&alva Come... Save As Salva Come Save as Salva come Save current session with another file name Salva sessione corrente con un altro nome file &Properties... &Proprietà... Session Properties Proprietà Sessione Session properties Proprietà sessione Edit current session properties Modifica proprietà sessione corrente F2 F2 E&xit E&sci Exit Esci Exit this application program Esci da questa applicazione &Undo Ann&ulla Undo Annulla Undo last action Annulla l'ultima azione Ctrl+Z Ctrl+Z &Redo &Ripristina Redo Ripristina Redo last action Ripristina l'ultima azione Ctrl+Shift+Z Ctrl+Shift+Z Cu&t Taglia Cut Taglia Cut selection to clipboard Taglia la selezione nella clipboard Ctrl+X Ctrl+X &Copy &Copia Copy Copia Copy selection to clipboard Copia la selezione nella clipboard Ctrl+C Ctrl+C &Paste Incolla Paste Incolla Paste clipboard contents Incolla il contenuto della clipboard Ctrl+V Ctrl+V Past&e Repeat... Ripeti incolla... Paste Repeat Ripeti Incolla... Paste repeat Ripeti incolla Paste/repeat clipboard contents Incolla nuovamente il contenuto della clipboard Ctrl+Shift+V Ctrl+Shift+V &Delete Elimina Delete Elimina Delete selection Elimina la selezione Del Canc &Clip &Clip Clip &Clip Select clip Seleziona clip Clip selection mode Modalità selezione clip &Range Inte&rvallo Range Intervallo Select range Seleziona intervallo Range selection mode Modalità selezione intervallo R&ectangle R&ettangolo Rect Rettangolo Select rectangle Seleziona rettangolo Rectangular selection mode Modalità selezione rettangolo &Automation &Automazione Automation Automazione Automation edit mode Modalità modifica automazione &All Tutto Select All Seleziona Tutto Select all Seleziona Tutto Mark all as selected Contrassegna tutto come selezionato Ctrl+A Ctrl+A &None &Nessuno Select None Seleziona nessuno Select none Seleziona nessuno Mark all as unselected Contrassegna tutto come non selezionato Ctrl+Shift+A Ctrl+Shift+A &Invert &Inverti Select Invert Inverti Selezione Select invert Inverti selezione Invert selection Inverti selezione Ctrl+I Ctrl+I Select Track Seleziona Traccia Select track Seleziona traccia Mark track as selected Contrassegna traccia come selezionata Ctrl+T Ctrl+T Trac&k Range Intervallo Traccia Select Track Range Seleziona Intervallo Traccia Select track range Seleziona intervallo traccia Mark track range as selected Contrassegna intervallo traccia come selezionato Ctrl+Shift+R Ctrl+Shift+R Select Range Seleziona Intervallo Mark range as selected Contrassegna intervallo come selezionato Ctrl+R Ctrl+R &Range... Remove Range Remove range Remove range as selected Ctrl+Del Remove Track Range Remove track range Remove track range as selected Ctrl+Shift+Del Insert Range Insert range Insert range as selected Ctrl+Ins Insert Track Range Insert track range Insert track range as selected Ctrl+Shift+Ins Sp&lit Split Selection Split selection Split current selection Ctrl+Y &Add Track... &Aggiungi Traccia... Add Track Aggiungi Traccia Add track Aggiungi traccia Add a new track to session Aggiunge una nuova traccia alla sessione Shift+Ins Shift+Ins &Remove Track &Rimuovi Traccia Remove Track Rimuovi Traccia Remove track Rimuovi traccia Remove current track from session Rimuovi traccia corrente dalla sessione Shift+Del Shift+Canc Track &Properties... &Proprietà Traccia... Track Properties Proprietà Traccia Track properties Proprietà traccia Edit current track properties Modifica le proprietà della traccia corrente Shift+F2 Shift+F2 &Inputs &Ingressi Track Inputs Ingressi Traccia Track inputs Ingressi traccia Show current track input bus connections Mostra connessioni bus di ingresso della traccia corrente &Outputs Uscite Track Outputs Uscite Traccia Track outputs Uscite traccia Show current track output bus connections Mostra connessioni bus di uscita della traccia corrente &Record &Registra Record Track Registra Traccia Record track Registra traccia Arm current track for recording Imposta la traccia corrente per registrare &Mute &Mute Mute Track Silenzia Traccia Mute track Silenzia traccia Mute current track Silenzia la traccia corrente &Solo &Solo Solo Track Traccia in solo Solo track Traccia in solo Solo current track Attiva solo la traccia corrente M&onitor M&onitor Monitor Track Monitorizza Traccia Monitor track Monitorizza traccia Monitor current track Monitorizza la traccia corrente &First Prima First Track Prima Traccia First track Prima traccia Make current the first track Sposta la traccia corrente come prima traccia &Previous &Precedente Previous Track Traccia Precedente Previous track Traccia precedente Make current the previous track Sposta traccia corrente prima della precedente &Next Successiva Next Track Traccia Successiva Next track Traccia successiva Make current the next track Sposta traccia corrente dopo la successiva &Last U&ltima Last Track Ultima Traccia Last track Ultima traccia Make current the last track Sposta la traccia corrente come ultima N&one Nessuna None Track Nessuna Traccia None track Nessuna traccia None current track Nessuna traccia corrente &Top Cima Move Top Sposta in cima Move top Sposta in cima Move current track to top Sposta la traccia corrente in cima &Up S&u Move Up Sposta Su Move up Sposta su Move current track up Sposta su la traccia corrente &Down Giù Move Down Sposta Giù Move down Sposta giù Move current track down Sposta giù la traccia corrente &Bottom Fondo Move Bottom Sposta in fondo Move bottom Sposta in fondo Move current track to bottom Sposta in fondo la traccia corrente &Increase Aumenta Increase Height Aumenta Altezza Increase height Aumenta altezza Increase track height Aumenta altezza traccia Ctrl+Shift++ Ctrl+Shift++ &Decrease &Diminuisci Decrease Height Diminuisci Altezza Decrease height Diminuisci altezza Decrease track height Diminuisci altezza traccia Ctrl+Shift+- Ctrl+Shift+- &Reset &Resetta Height Reset Resetta Altezza Height reset Resetta altezza Reset track height Resetta altezza traccia Ctrl+Shift+1 Ctrl+Shift+1 Auto &Monitor &Monitor Automatico Auto Monitor Monitor Automatico Auto monitor Monitor automatico Auto-monitor current track Monitor automatico della traccia corrente F6 F6 &Audio... &Audio... Inport Audio File Importa File Audio Import Audio file Importa file audio Import tracks from Audio file Importa tracce da file audio &MIDI... &MIDI... Import MIDI File Importa File MIDI Import MIDI file Importa file MIDI Import tracks from MIDI file Importa tracce da file MIDI Export Audio File Esporta File Audio Export Audio file Esporta file audio Export tracks to Audio file Esporta tracce su file audio Export MIDI File Esporta File MIDI Export MIDI file Esporta file MIDI Export tracks to MIDI file Esporta tracce su file MIDI Log&arithmic Log&aritmico Automation logarithmic Automazione logaritmica Automation curve logarithmic scale Curva di automazione con scala logaritmica C&olor... C&olore... Automation color Colore automazione Automation curve color Colore curva automazione &Lock B&locca Automation lock Blocca automazione Lock automation curve Blocca curva di automazione &Play Ri&produzione Automation playback Riproduzione automazione Playback automation curve Riproduzione curva di automazione Automation record Registra automazione Record automation curve Registra curva di automazione &Clear Pulis&ci Automation clear Pulisci automazione Clear automation curve Pulisci curva di automazione Loc&k All Blocca Tutto Automation lock all Blocca tutta le automazioni Lock all automation curves Blocca tutta le curve di automazione Play &All Riproduci Tutte Automation playback all Riproduci tutte le automazioni Playback all automation curves Rec&ord All Riproduci tutte le curve di automazione Automation record all Registra tutte le automazioni Record all automation curves Registra tutte le curve di automazione C&lear All Pu&lisci Tutto Automation clear all Pulisci tutte le automazioni Clear all automation curves Pulisci tutte le curve di automazione &New... &Nuovo... New Clip Nuovo Clip New clip Nuovo clip Create new clip Crea nuovo clip &Edit... Modifica... Edit Clip Modifica Clip Edit clip Modifica clip Edit current clip Modifica clip corrente F4 F4 &Unlink Scollega Unlink Clip Scollega Clip Unlink clip Scollega clip Unlink current clip Scollega clip corrente &Split Dividi Split Clip Dividi Clip Split clip Dividi clip Split current clip at playhead Dividi clip corrente in testa &Merge... Unisci Merge Clips Unisci Clip Merge clips Unisci clip Merge selected clips Unisci i clip selezionati N&ormalize N&ormalizza Normalize Clip Normalizza Clip Normalize clip Normalizza clip Normalize current clip (gain/volume) Normalizza clip corrente (guadagno/volume) &Quantize... &Quantizza... Quantize Clip Quantizza Clip Quantize clip events Quantizza eventi clip Quantize current MIDI clip events Quantizza eventi del clip MIDI corrente &Transpose... &Trasponi... Transpose Clip Trasponi Clip Transpose clip events Trasponi eventi clip Transpose current MIDI clip events Trasponi eventi clip MIDI corrente &Normalize... &Normalizza... Normalize clip events Normalizza eventi clip Normalize current MIDI clip events Normalizza eventi clip MIDI corrente &Randomize... &Randomizza... Randomize Clip Randomizza Clip Randomize clip events Randomizza eventi clip Randomize current MIDI clip events Randomizza eventi clip MIDI corrente Resi&ze... Ridimensiona Resize Clip Ridimensiona Clip Resize clip events Ridimensiona eventi clip Resize current MIDI clip events Ridimensiona eventi clip MIDI corrente Re&scale... &Scala... Rescale Clip Scala Clip Rescale clip events Scala eventi clip Rescale current MIDI clip events Scala eventi clip MIDI corrente T&imeshift... T&imeshift... Timeshift Clip Clip Timeshift Timeshift clip events Timeshift eventi clip Timeshift current MIDI clip events Timeshift eventi clip MIDI corrente &Tempo... &Tempo... Tempo Adjust Aggiusta Tempo Adjust session tempo from current clip selection Aggiusta tempo sessione da selezione clip corrente F7 F7 &Range Set Imposta Inte&rvallo Clip Range Intervallo Clip Clip range Intervallo clip Set edit-range from current clip extents Imposta intervallo modifica da estensione clip corrente &Loop Set Imposta &Loop Clip Loop Loop Clip Clip loop Loop clip Set loop-range from current clip extents Imposta intervallo loop da estensione clip corrente &Import... &Importa... Import Clip Importa Clip Import clip Importa clip Import clip from file(s) Importa clip da file E&xport... Esporta... Export Clip Esporta Clip Export clip Esporta clip Export current clip to file Esporta clip su file First Take Prima ripresa First take Prima ripresa Select current clip first take Seleziona prima ripresa del clip corrente Previous Take Ripresa Precedente Previous take Ripresa precedente Select current clip previous take Seleziona ripresa precedente del clip corrente Next Take Ripresa Successiva Next take Ripresa successiva Select current clip next take Seleziona ripresa successiva del clip corrente Shift+T Shift+T Last Take Ultima Ripresa Last take Ultima ripresa Select current clip last take Seleziona ultima ripresa del clip corrente Reset Takes Reset Riprese Reset takes Reset riprese Reset (unfold) current clip takes Reset riprese clip corrente R&ange... Interv&allo... Take Range Intervallo Ripresa Take range Intervallo ripresa Range (fold) current clip into takes Raggruppa clip corrente in riprese &Menubar Barra &Menu Menubar Barra Menu Show/hide the main program window menubar Mostra/nascondi barra dei menu della finestra principale Ctrl+M Ctrl+M &Statusbar Barra di &Stato Statusbar Barra di stato Show/hide the main program window statusbar Mostra/nascondi barra di stato della finestra principale File Toolbar Barra Strumenti File File toolbar Barra Strumenti file Show/hide main program window file toolbar Mostra/nascondi barra strumenti file della finestra principale Edit Toolbar Modifica Barra Strumenti Edit toolbar Modifica barra strumenti Show/hide main program window edit toolbar Mostra/nascondi modifica barra strumenti della finestra principale Track Toolbar Barra Strumenti Traccia Track toolbar Barra strumenti traccia Show/hide main program window track toolbar Mostra/nascondi barra strumenti traccia della finestra principale View Toolbar Barra Strumenti Vista View toolbar Barra strumenti vista Show/hide main program window view toolbar Mostra/nascondi barra strumenti vista della finestra principale &Options &Opzioni Options Toolbar Barra Strumenti Opzioni Options toolbar Barra strumenti opzioni Show/hide main program window options toolbar Mostra/nascondi barra strumenti opzioni della finestra principale Transport Toolbar Barra Strumenti Avanzamento Transport toolbar Barra strumenti avanzamento Show/hide main program window transport toolbar Mostra/nascondi barra strumenti avanzamento della finestra principale T&ime Tempo Time Toolbar Barra Strumenti Tempo Time toolbar Barra strumenti tempo Show/hide main program window time toolbar Mostra/nascondi barra strumenti tempo della finestra principale Thum&b Anterpime Thumb Toolbar Barra Strumenti Anteprime Thumb toolbar Barra strumenti anteprime Show/hide main program window thumb toolbar Mostra/nascondi barra strumenti anteprime della finestra principale &Files &File Files File Show/hide the files window Mostra/nascondi la finestra dei file M&essages M&essaggi Messages Messaggi Show/hide the messages window Mostra/nascondi la finestra dei messaggi &Connections &Connessioni Connections Connessioni Show/hide the connections window Mostra/nascondi la finestra delle connessioni F8 F8 Mi&xer Mi&xer Mixer Mixer Show/hide the mixer window Mostra/nascondi la finestra del mixer F9 F9 &In &Ingrandimento Zoom In Ingrandimento Zoom in Ingrandimento Ctrl++ Ctrl++ &Out Rimpicciolimento Zoom Out Rimpicciolimento Zoom out Rimpicciolimento Ctrl+- Ctrl+- Zoom Reset Reset Ridimensionamento Zoom reset Reset ridimensionamento Ctrl+1 Ctrl+1 &Horizontal Orizzontale Horizontal Zoom Orizzontale Horizontal zoom Ridimensionamento orizzontale Horizontal zoom mode Modalità ridimensionamento orizzontale &Vertical &Verticale Vertical Zoom Ridimensionamento Verticale Vertical zoom Ridimensionamento verticale Vertical zoom mode Modalità ridimensionamento verticale All Zoom Ridimensiona Tutto All zoom Ridimensiona tutto All zoom mode Modalità ridimensiona tutto &Grid &Griglia Grid Griglia Snap grid view mode Vista griglia di allineamento &Zebra Strisce Zebra Strisce Bar zebra view mode Modalità vista a strisce Too&l Tips Suggerimenti Tool tips Suggerimenti Floating tool tips view mode Modalità vista suggerimenti &Refresh Aggio&rna Refresh Aggiorna Refresh views Aggiorna viste F5 F5 &Instruments... Strument&i... Instruments Strumenti Change instrument definitions and files Modifica file e definizioni strumenti &Controllers... &Controller... Controllers Controller Change MIDI controllers configuration Modifica configurazione controller MIDI &Buses... &Bus... Buses Bus Change session bus definitions Modifica definizioni dei bus della sessione Tempo M&ap / Markers... Tempo Map / Markers Tempo map / markers Change session tempo map / markers Tempo M&ap... M&appa Tempo Tempo Map Mappa Tempo Tempo map Mappa tempo Change session tempo map Modifica la mappa del tempo della sessione &Options... &Opzioni... Options Opzioni Change general application program options Modifica le opzioni generali del programma F12 F12 &Backward Indietro Backward Indietro Transport backward Avanzamento indietro Backspace Backspace Re&wind Riavvolgimento Rewind Riavvolgimento Transport rewind Riavvolgimento avanzamento F&ast Forward F&ast Forward Fast Forward Fast Forward Fast forward Fast forward Transport fast forward Fast forward avanzamento &Forward &Avanti Forward Avanti Transport forward Avanzamento avanti &Loop &Loop Loop Loop Transport loop Avanzamento ciclico Ctrl+Shift+L Ctrl+Shift+L Loop &Set Impo&sta Loop Loop Set Imposta Loop Loop set Imposta loop Transport loop set Imposta loop avanzamento Ctrl+L Ctrl+L &Stop &Stop Stop Stop Transport stop Interrompi avanzamento Play Play Transport play/pause Avvia avanzamento Space Spazio Record Registra Transport record Registra avanzamento &Punch amp;Punch Punch Punch Punch in/out Punch in/out Transport punch in/out Punch in/out avanzamento Ctrl+Shift+P Ctrl+Shift+P Punch Se&t Impo&sta Punch Punch Set Imposta Punch Punch in/out set Impostazione punch in/out Transport punch in/out set Impostazione punch in/out avanzamento Ctrl+P Ctrl+P &Metronome &Metronomo Metronome Metronomo F&ollow Playhead Segui Ripr&oduzione Follow Playhead Segui Riproduzione Follow playhead Segui riproduzione A&uto Backward Riavvolgimento A&utomatico Auto Backward Riavvolgimento Automatico Auto backward Riavvolgimento automatico &Continue Past End &Continua Oltre la Fine Continue Past End Continua Oltre la Fine Continue past end Continua oltre la fine Pa&nic Pa&nico Panic Panico All MIDI tracks shut off (panic) Spegni tutte le tracce MIDI (panico) &Shortcuts... &Scorciatoie... Shortcuts Scorciatoie Keyboard shortcuts Scorciatoie tastiera &About... Inform&azioni su... About Informazioni su Show information about this application program Mostra informazioni riguardo questo programma About &Qt... Informazioni su &Qt... About Qt Informazioni su Qt Show information about the Qt toolkit Mostra informazioni sulle librerie Qt Current time (playhead) Tempo corrente (riproduzione) Current tempo (BPM) Tempo corrente (BPM) Snap/beat Allineamento/battito Track Traccia Current track name Nome traccia corrente MOD MOD Session modification state Stato modifica sessione REC REC Session record state Stato registrazione sessione MUTE MUTE Session muting state Stato silenziamento sessione SOLO SOLO Session soloing state Stato solo sessione LOOP LOOP Session looping state Stato loop sessione Session total time Tempo totale sessione Session sample rate Frequenza di campionamento sessione Could not set default session directory: %1 Sorry. Impossibile utilizzare la directory di default della sessione: %1 Spiacente. Ready Pronto Untitled%1 SenzaTitolo%1 New session: "%1". Nuova sessione: "%1". Session files (*.%1 *.%2 *.%3) File di sessione (*.%1 *.%2 *.%3) Session files (*.%1 *.%2) File di sessione (*.%1 *.%2) Template files (*.%1) File di template (*.%1) Archive files (*.%1) File di archivio (*.%1) Open Session Apri Sessione Save Session Salva Sessione Warning Attenzione The file already exists: "%1" Do you want to replace it? Il file esiste già: "%1" Vuoi sostituirlo? Backup session: "%1" as "%2". Could not backup existing session: %1 as %2 Sorry. The current session has been changed: "%1" Do you want to save the changes? La sessione corrente è stata modificata: "%1" Vuoi salvare le modifiche? About to remove archive directory: "%1" Are you sure? Sto per rimuovere la cartella di archivio: "%1" Sei sicuro? Session closed. Sessione chiusa. The directory already exists: "%1" Do you want to replace it? La cartella esiste già: "%1" Vuoi sostituirla? Opening "%1"... Apertura "%1"... Session could not be loaded from "%1". Sorry. La sessione non può essere caricata da "%1". Spiacente. Open session: "%1". Sessione aperta: "%1". Saving "%1"... Salvataggio "%1"... Session could not be saved to "%1". Sorry. La sessione non può essere salvata su "%1". Spiacente. Save session: "%1". Sessione salvata: "%1". About to clear automation: "%1" Are you sure? Si sta per eliminare l'automazione: "%1" Sei sicuro? About to clear all automation: "%1" Are you sure? Si sta per eliminare tutte le automazioni: "%1" Sei sicuro? take range intervallo ripresa session sessione or o program programma Information Informazioni Some settings may be only effective next time you start this %1. Alcune impostazioni potrebbero avere effetto solo al prossimo avvio di questo %1. Debugging option enabled. Opzione di debug attiva. Ogg Vorbis (libvorbis) file support disabled. Supporto file Ogg Vorbis (libvorbis) disabilitato. MPEG-1 Audio Layer 3 (libmad) file support disabled. Supporto file MPEG-1 Audio Layer 3 (libmad) disabilitato. Sample-rate conversion (libsamplerate) disabled. Conversione frequenza di campionamento (libsamplerate) disabilitata. Pitch-shifting support (librubberband) disabled. Supporto pitch-shift (librubberband) disabilitato. OSC service support (liblo) disabled. Supporto servizio OSC (liblo) disabilitato. LADSPA Plug-in support disabled. Supporto Plug-in LADSPA disabilitato. DSSI Plug-in support disabled. Supporto Plug-in DSSI disabilitato. VST Plug-in support disabled. Supporto Plug-in VST disabilitato. VeSTige header support enabled. Supporto header VeSTige disabilitato. LV2 Plug-in support disabled. Supporto Plug-in LV2 disabilitato. LV2 Plug-in UI support disabled. LV2 Plug-in UI support (libsuil) disabled. LV2 Plug-in MIDI/Event support disabled. Supporto MIDI/eventi Plug-in LV2 disabilitato. LV2 Plug-in State Files support disabled. LV2 Plug-in support (libslv2) enabled. (DEPRECATED) Supporto Plug-in LV2 (libslv2) abilitato. Set current snap to %1 Current time (play-head) LV2 Plug-in support (liblilv) disabled. Supporto Plug-in LV2 (liblilv) disabilitato. LV2 Plug-in UI instantiation support (libsuil) disabled. Supporto istanza UI Plug-in LV2 (libsuil) disabilitato. LV2 Plug-in QT4 UI support disabled. Supporto UI QT4 Plug-in LV2 disabilitato. LV2 Plug-in GTK UI support disabled. Supporto UI GTK Plug-in LV2 disabilitato. LV2 Plug-in External UI support disabled. Supporto UI esterna Plug-in LV2 disabilitato. LV2 Plug-in MIDI/Atom support disabled. Supporto MIDI/Atom plugin LV2 disabilitato. LV2 Plug-in Worker/Schedule support disabled. Supporto Worker/Schedule plugin LV2 disabilitato. LV2 Plug-in State support disabled. Supporto stato Plug-in LV2 disabilitato. LV2 Plug-in State Files support enabled. (FUBAR) Supporto Stato File plugin LV2 abilitato. LV2 Plug-in Programs support disabled. Supporto programmi Plug-in LV2 disabilitato. LV2 Plug-in Presets support disabled. Supporto preset plugin LV2 disabilitato. LV2 Plug-in Time/position support disabled. Supporto Tempo/posizione plugin LV2 disabilitato. LV2 Plug-in Options support disabled. LV2 Plug-in Buf-size support disabled. JACK Session support disabled. Supporto sessione JACK disabilitato. JACK Latency support disabled. Supporto latenza JACK disabilitato. Version Versione Build Build Website Sito This program is free software; you can redistribute it and/or modify it Questo programma è un software gratuito; è possibile ridistribuirlo e/o modificarlo under the terms of the GNU General Public License version 2 or later. nei termini della GNU General Public License versione 2 o successiva. record clip registra clip [modified] [modificato] %1 Hz %1 Hz Session started. Sessione avviata. The original session sample rate (%1 Hz) is not the same of the current audio engine (%2 Hz). Saving and reloading from a new session file is highly recommended. La frequenza di campionamento originale della sessione (%1 Hz) non è la stessa del motore audio corrente (%2 Hz). Salvare e ricaricare da un nuovo file di sessione è particolarmente raccomandato. The audio/MIDI engine could not be started. Make sure the JACK audio server (jackd) and/or the ALSA Sequencer kernel module (snd-seq-midi) are up and running and then restart the session. Il motore audio/MIDI non può essere avviato. Sii sicuro che il server audio JACK (jackd) e/o il modulo kernel del sequencer ALSA (snd-seq-midi) siano attivi ed in esecuzione, poi riavvia la sessione. NSM support disabled. &Hold &Hold &Linear &Lineare &Spline &Spline Take %1 Ripresa %1 None Nessuno Error Errore XRUN(%1 skipped) XRUN(%1 saltato) XRUN(%1): some frames might have been lost. XRUN(%1): alcuni campioni potrebbero essere stati persi. Audio connections change. Cambiamento connessioni audio. MIDI connections change. Cambiamento connessioni MIDI. Playing ended. Riproduzione terminata. The audio engine has been shutdown. Make sure the JACK audio server (jackd) is up and running and then restart session. Il motore audio è stato fermato. Accertati che il server audio JACK (jackd) sia avviato ed in esecuzione, poi riavvia la sessione. STOP STOP PLAY PLAY FFWD FFWD REW REW REC ON REC ON REC OFF REC OFF RESET RESET LOCATE %1 TROVA %1 SHUTTLE %1 SHUTTLE %1 STEP %1 STEP %1 TRACK RECORD %1 %2 REGISTRA TRACCIA %1 %2 TRACK MUTE %1 %2 MUTE TRACCIA %1 %2 TRACK SOLO %1 %2 SOLO TRACCIA %1 %2 Unknown sub-command Sotto-comando sconosciuto Not implemented Non implementato MIDI CTL: %1, Channel %2, Param %3, Value %4 MIDI CTL: %1, Canale %2, Parametro %3, Valore %4 (track %1, gain %2) (traccia %1, guadagno %2) (track %1, panning %2) (traccia %1, bilanciamento %2) START AVVIA CONTINUE CONTINUA SONGPOS %1 SONGPOS %1 %1 BPM %1 BPM Playing "%1"... Riproduzione "%1"... &Frames Campioni &Time &Tempo &BBT &BBT qtractorMessages Messages Messaggi Logging stopped --- %1 --- Log interrotto --- %1 --- Logging started --- %1 --- Log avviato --- %1 --- qtractorMeter Pan Bilanciamento Gain Guadagno qtractorMidiControlForm Controllers - Qtractor Controllers - Qtractor Controller files File dei controller Files File Path Percorso Import controller files Importa file del controller &Import... &Importa... Alt+I Alt+I Remove controller file Elimina file del controller &Remove Elimina Alt+R Alt+R Move controller file up on list order Sposta in su nella lista il file del controller &Up S&u Alt+U Alt+U Move controller file down on list order Sposta in giù nella lista il file del controller &Down Giù Alt+D Alt+D &Type &Tipo &Channel &Canale &Parameter &Parametro Trac&k Offset Posizione Traccia C&ommand C&omando MIDI Event type Tipo di evento MIDI MIDI Channel Canale MIDI MIDI Controller (parameter) Controller MIDI (parametro) MIDI parameter (track offset) Parametro MIDI (posizione traccia) + + Track offset Posizione traccia Command action Azione comando Command feedback Feedback comando &Feedback &Feedback Map/update controller command Mappa/aggiorna comando controller &Map &Mappa Alt+M Alt+M Controller map Mappa controller Type Tipo Channel Canale Parameter Parametro Track Traccia Command Comando Feedback Feedback Unmap/remove controller command Pulisci/rimuovi comando controller U&nmap Pulisci Alt+N Alt+N Reload/apply all controller files Ricarica/applica tutti i file dei controller Relo&ad Ric&arica Alt+A Alt+A Export to controller file Esporta su file di controller E&xport... Esporta... Alt+X Alt+X Close this dialog Chiudi questa finestra Close Chiudi Import Controller Files Importa File di Controller Controller files (*.%1) File di controller (*.%1) Warning Attenzione About to remove controller file: "%1" Are you sure? Stai per rimuovere il file del controller: "%1" Sei sicuro? Export Controller File Esporta File di Controller The controller file already exists: "%1" Do you want to replace it? Il file del controller esiste già: "%1" Vuoi sostituirlo? Saved controller mappings may not be effective the next time you start this program. "%1" Do you want to apply to controller files? La mappa del controller potrebbe non essere attiva al prossimo riavvio di questo programma. "%1" Vuoi applicarla ai file dei controller? Controller mappings have been changed. La mappa del controller è stata modificata. Do you want to save the changes? Vuoi salvare le modifiche? Yes Si No No qtractorMidiControlObserverForm MIDI Controller - Qtractor Controller MIDI - Qtractor &Type: &Tipo: MIDI event type Tipo di evento MIDI Cha&nnel: Ca&nale: MIDI channel Canale MIDI &Parameter: &Parametro: MIDI parameter Parametro MIDI &Logarithmic &Logaritmico &Feedback &Feedback In&vert In&verso &Hook Aggancio Control input connections Controlla le connessioni di ingresso &Inputs &Ingressi Control output connections Controlla le connessioni di uscita &Outputs Uscite MIDI Controller Controller MIDI MIDI controller is already assigned. Do you want to replace the mapping? Il controller MIDI è già assegnato. Vuoi sostituire la mappatura? Some settings have been changed. Do you want to apply the changes? Alcune impostazioni sono state modificate. Vuoi applicare le modifiche? &MIDI Controller... Controller &MIDI... &Automation &Automazione &Lock B&locca &Play Ri&produci &Record &Registra &Clear Pulis&ci qtractorMidiEditEvent Zoom in (horizontal) Ingrandimento (orizzontale) Zoom out (horizontal) Rimpicciolimento (orizzontale) Zoom reset (horizontal) Ripristina ingrandimento (orizzontale) qtractorMidiEditList C%1 C%1 qtractorMidiEditTime Play-head Edit-head Edit-tail Loop-start Loop-end Punch-in Punch-out Start: %1 End: %2 Length: %3 qtractorMidiEditView Zoom in (vertical) Ingrandimento (verticale) Zoom out (vertical) Rimpicciolimento (verticale) Zoom reset (vertical) Ripristina ingrandimento(verticale) qtractorMidiEditor MIDI Editor Editor MIDI cut taglia delete cancella insert range remove range move sposta edit modifica resize ridimensiona rescale scala paste incolla Time: %1 Type: Tempo: %1 Tipo: Note On (%1) %2 Velocity: %3 Duration: %4 Nota On (%1) %2 Pressione: %3 Durata: %4 Key Press (%1) %2 Value: %3 Tasto Premuto (%1) %2 Valore: %3 Controller (%1) Name: %2 Value: %3 Controller (%1) Nome: %2 Valore: %3 Pgm Change (%1) Pgm Change (%1) Chan Press (%1) Chan Press (%1) Pitch Bend (%1) Pitch Bend (%1) SysEx (%1 bytes) Data: SysEx (%1 bytes) Dati: Unknown (%1) Sconosciuto (%1) Start: %1 End: %2 Length: %3 Inizio: %1 Fine: %2 Durata: %3 qtractorMidiEditorForm MIDI Editor Editor MIDI &Track &Traccia &File &File Select &Mode Seleziona &Modalità &Select &Selezione I&nsert Remo&ve &Tools S&trumenti &Edit Modifica &View &Vista &Toolbars Barre S&trumenti &Windows Finestre &Zoom &Zoom S&nap Alli&neamento Sc&ale Sc&alamento T&ransport &Riproduzione &Help Aiuto &Save &Salva Save Salva Save current MIDI clip to existing file name Salva il clip MIDI corrente su un file esistente Save &As... S&alva Come... Save As Salva Come Save as Salva come Save current MIDI clip with another file name Salva il clip MIDI corrente su un altro file &Unlink Disconnetti Unlink Disconnetti Unlink current MIDI clip Disconnetti il clip MIDI corrente &Inputs &Ingressi Track Inputs Ingressi Traccia Track inputs Ingressi traccia Show current MIDI clip/track input bus connections Mostra le connessioni dei bus di ingresso della traccia/clip MIDI corrente &Outputs Uscite Track Outputs Uscite Traccia Track outputs Uscite traccia Show current MIDI clip/track output bus connections Mostra le connessioni dei bus di uscita della traccia/clip MIDI corrente &Properties... &Proprietà... Track Properties Proprietà Traccia Track properties Proprietà traccia Edit current MIDI clip/track properties Modifica le proprietà della traccia/clip MIDI corrente Shift+F2 Shift+F2 Properties Proprietà Edit current MIDI clip properties Modifica le proprietà del clip MIDI corrente F4 F4 &Range Set Imposta Inte&rvallo Clip Range Intervallo Clip Clip range Intervallo clip Set edit-range from clip extents Imposta intervallo di modifica dagli estremi del clip &Loop Set Imposta &Loop Clip Loop Loop Clip Clip loop Loop clip Set loop-range from clip extents Imposta intervallo del loop dagli estremi del clip &Close &Chiudi Close Chiudi Close this MIDI clip editor Chiudi questo editor di clip MIDI &Undo Ann&ulla Undo Annulla Undo last edit operation Annulla l'ultima operazione di modifica Ctrl+Z Ctrl+Z &Redo &Ripristina Redo Ripristina Redo last edit operation Ripristina l'ultima operazione di modifica Ctrl+Shift+Z Ctrl+Shift+Z Cu&t &Taglia Cut Taglia Cut current selection into the local clipboard Taglia la selezione corrente nella clipboard locale Ctrl+X Ctrl+X &Copy &Copia Copy Copia Copy current selection to the local clipboard Copia la selezione corrente nella clipboard locale Ctrl+C Ctrl+C &Paste Incolla Paste Incolla Paste local clipboard contents into the current MIDI clip Incolla il contenuto della clipboard nel clip MIDI corrente Ctrl+V Ctrl+V Past&e Repeat... Rip&eti Incolla... Paste Repeat Ripeti Incolla Paste repeat Ripeti incolla Paste/repeat local clipboard contents into the current MIDI clip Ripeti/incolla il contenuto della clipboard nel clip MIDI corrente Ctrl+Shift+V Ctrl+Shift+V &Delete Cancella Delete Cancella Delete current selection Cancella la selezione corrente Del Canc Edit Of&f Disabilita Modi&fiche Edit Off Disabilita Modifiche Edit off Disabilita modifiche Set edit mode off Imposta modalità di modifiche disabilitate Edit &On Abilita M&odifiche Edit On Abilita Modifiche Edit on Abilita modifiche Set edit mode on Imposta modalità di modifiche abilitate Edit &Draw Modifca &Disegno Edit draw mode Modalità modifica disegno Edit draw mode (notes) Modalità modifica disegno (note) &All Tutto Select All Seleziona Tutto Select all Seleziona tutto Ctrl+A Ctrl+A &None &Niente Select None Seleziona Niente Select none Seleziona niente Ctrl+Shift+A Ctrl+Shift+A &Invert &Inverti Select Invert Selezione Inversa Select invert Selezione inversa Ctrl+I Ctrl+I &Range Inte&rvallo Select Range Seleziona Intervallo Select range Seleziona intervallo Mark range as selected Marca intervallo come selezionato Ctrl+R Ctrl+R Insert Range Insert range Insert range as selected Ctrl+Ins Remove Range Remove range Remove range as selected Ctrl+Del &Quantize... &Quantizza... Quantize Quantizza Quantize selection Quantizza selezione &Transpose... &Trasposizione... Transpose Trasposizione Transpose selection Trasponi selezione &Normalize... &Normalizza... Normalize Normalizza Normalize selection Normalizza selezione &Randomize... &Randomizza... Randomize Randomizza Randomize selection Randomizza selezione Resi&ze... Ridimensiona... Resize Ridimensiona Resize selection Ridimensiona selezione Re&scale... &Scala... Rescale Scala Rescale selection Scala selezione T&imeshift... T&imeshift... Timeshift Timeshift Timeshift selection Timeshift selezione &Menubar Barra del &Menu Menubar Barra del menu Show/hide the menubar Mostra/nascondi barra del menu Ctrl+M Ctrl+M &Statusbar Barra di &Stato Statusbar Barra di Stato Show/hide the statusbar Mostra/nascondi barra di stato File Toolbar Barra Strumenti File File toolbar Barra strumenti file Show/hide the file toolbar Mostra/nascondi barra strumenti file Edit Toolbar Barra Strumenti Modifica Edit toolbar Barra strumenti modifica Show/hide the edit toolbar Mostra/nascondi barra strumenti modifica View Toolbar Barra Strumenti Vista View toolbar Barra strumenti vista Show/hide the view toolbar Mostra/nascondi barra strumenti vista &Transport Avanzamen&to Transport Toolbar Barra Strumenti Avanzamento Transport toolbar Barra strumenti avanzamento Show/hide the transport toolbar Mostra/nascondi barra strumenti avanzamento &Scale &Scalamento Scale Toolbar Barra Strumenti Scalamento Scale toolbar Barra strumenti scalamento Show/hide the scale toolbar Mostra/nascondi barra strumenti scalamento Note &Duration &Durata Nota Note Duration Durata Nota Note duration Durata nota Whether note events are shown proportional to duration Se mostrare gli eventi delle note proporzionali alla durata Note &Color &Colore Nota Note Color Colore Nota Note color Colore nota Whether note events are colored according to pitch Se le note sono colorate in base alla loro altezza &Value Color Colore &Valore Value Color Colore Valore Value color Colore valore Whether note events are colored according to value (velocity) Se le note sono colorate in base al loro valore (intensit�) &Events &Eventi View events Mostra eventi Show/hide the events list Mostra/nascondi la lista degli eventi &Preview Notes Ante&prima Note Preview Notes Anteprima Note Preview notes Anteprima note Preview notes while editing (scrub) Anteprima note durante la modifica F&ollow Playhead Segui Ripr&oduzione Follow Playhead Segui Riproduzione Follow playhead Segui riproduzione &In &In Zoom In Ingrandisci Zoom in Ingrandisci Ctrl++ Ctrl++ &Out &Out Zoom Out Rimpicciolisci Zoom out Rimpicciolisci Ctrl+- Ctrl+- &Reset &Ripristina Zoom Reset Ripristina Ingrandimento Zoom reset Ripristina ingrandimento Ctrl+1 Ctrl+1 &Horizontal Orizzontale Horizontal Zoom Ingrandimento Orizzontale Horizontal zoom Ingrandimento orizzontale Horizontal zoom mode Modalità ingrandimento orizzontale &Vertical &Verticale Vertical Zoom Ingrandimento Verticale Vertical zoom Ingrandimento verticale Vertical zoom mode Modalità ingrandimento verticale All Zoom Ingrandisci Tutto All zoom Ingrandisci tutto All zoom mode Modalità ingrandisci tutto &Zebra Colonne Zebra Colonne Bar zebra view mode Modalità vista a colonne &Grid &Griglia Grid Griglia Snap grid view mode Modalità allineamento alla griglia Too&l Tips Suggerimenti Tool tips Suggerimenti Floating tool tips view mode Modalità vista suggerimenti &Refresh Aggio&rna Refresh Aggiorna Refresh views Aggiorna viste F5 F5 &Backward Indietro Backward Indietro Transport backward Avanzamento indietro Backspace Backspace Re&wind Riavvolgi Rewind Riavvolgi Transport rewind Riavvolgi Avanzamento F&ast Forward &Avanti Veloce Fast Forward Avanti Veloce Fast forward Avanti veloce Transport fast forward Avanti veloce avanzamento &Forward Avanti Forward Avanti Transport forward Avanti avanzamento &Loop Loop Loop Loop Transport loop Loop avanzamento Ctrl+Shift+L Ctrl+Shift+L Loop &Set Impo&sta Loop Loop Set Imposta Loop Loop set Imposta loop Transport loop set Imposta loop avanzamento Ctrl+L Ctrl+L &Stop &Stop Stop Stop Transport stop Ferma avanzamento &Play &Play Play Play Transport play/pause Avvia avanzamento Space Barra spazio &Record &Registra Record Registra Transport record Registra avanzamento &Punch Punch Punch Punch Punch in/out Punch in/out Transport punch in/out Punch in/out avanzamento Ctrl+Shift+P Ctrl+Shift+P Punch Se&t Impo&sta Punch Punch Set Imposta Punch Punch in/out set Imposta punch in/out Transport punch in/out set Imposta punch in/out avanzamento Ctrl+P Ctrl+P Pa&nic Pa&nico Panic Panico All MIDI tracks shut off (panic) Spegni tutte le tracce MIDI (panico) &Shortcuts... &Scorciatoie Shortcuts Scorciatoie Keyboard shortcuts Scorciatoie tastiera &About... Inform&azioni su... About Informazioni su Show information about this application program Mostra informazioni su questo programma About &Qt... Informazioni su &Qt About Qt Informazioni su Qt Show information about the Qt toolkit Mostra informazioni su Qt Set current snap to %1 Note On Nota On Key Press Tasto premuto Note Velocity Intensità Nota Controller Controller Pgm Change Pgm Change Chan Press Chan Press Pitch Bend Pitch Bend Sys Ex Sys Ex Snap/beat Allineamento/Battito Note type Tipo nota Value type Tipo valore Controller type Tipo controller Scale key Chiave scala Scale type Tipo scala MIDI clip name Nome clip MIDI MIDI file name Nome file MIDI MIDI track/channel Traccia/Canale MIDI MOD MOD MIDI modification state Stato modifica MIDI 00:00:00.000 00:00:00.000 MIDI clip duration Durata clip MIDI Warning Attenzione The current MIDI clip has been changed: "%1" Do you want to save the changes? Il clip MIDI corrente è stato modificato: "%1" Vuoi salvare i cambiamenti? Save MIDI Clip Salva Clip MIDI MIDI files (*.%1 *.smf *.midi) File MIDI (*.%1 *.smf *.midi) MIDI file save: "%1", track-channel: %2. Salvataggio file MIDI: "%1", traccia-canale: %2. Channel %1 Canale %1 Track %1 Traccia %1 [modified] [modificato] qtractorMidiEventItemDelegate edit %1 modifica %1 qtractorMidiEventList Events Eventi qtractorMidiEventListModel Time Tempo Type Tipo Name Nome Value Valore Duration/Data Durata Frame Campione BBT BBT Note On (%1) Nota On (%1) Note Off (%1) Nota Off (%1) Key Press (%1) Tasto Premuto (%1) Controller (%1) Controller (%1) Pgm Change Pgm Change Chan Press Chan Press Pitch Bend Pitch Bend SysEx SysEx Meta (%1) Meta (%1) Unknown (%1) Sconosciuto (%1) qtractorMidiListView Name Nome Fmt Formato Tracks Tracce tpqn tpqn Path Percorso Open MIDI Files Apri File MIDI MIDI files (*.%1 *.smf *.midi) File MIDI (*.%1 *.smf *.midi) qtractorMidiMeter Volume (%) Volume (%) % % Pan: %1 Pan: %1 Volume: %1% Volume: %1% qtractorMidiSysexForm MIDI SysEx - Qtractor MIDI SysEx - Qtractor Name Nome Size Dimensione Data (hex) Dati (esa) Import from SysEx file Importa da file SysEx &Import... &Importa... Alt+I Alt+I Export to SysEx file Esporta su file SysEx E&xport... Esporta... Alt+X Alt+X Move SysEx item up on list order Sposta su elemento SysEx nella lista &Up S&u Alt+U Alt+U Move SysEx item down on list order Sposta giù elemento SysEx nella lista &Down Giù Alt+D Alt+D Open SysEx Apri SysEx Sysex name Nome SysEx Save SysEx Salva SysEx Delete SysEx Elimina SysEx Create SysEx item Crea SysEx &Add &Aggiungi Alt+A Alt+A Update SysEx item Aggiorna elemento SysEx Upda&te Aggiorna Alt+T Alt+T Remove SysEx item Rimuovi elemento SysEx &Remove &Rimuovi Alt+R Alt+R SysEx files (*.%1) File SysEx (*.%1) MIDI files (*.mid *.smf *.midi) File MIDI (*.mid *.smf *.midi) All files (*.*) Tutti i file (*.*) Import SysEx Files Importa File SysEx Export SysEx File Esporta File SysEx Warning Attenzione The SysEx file already exists: "%1" Do you want to replace it? Il file SysEx esiste già: "%1" Vuoi sostituirlo? Sysex files (*.%1) File SysEx (*.%1) About to replace SysEx: "%1" Are you sure? Sto per sostituire il SysEx: "%1" Sei sicuro? About to delete SysEx: "%1" Are you sure? Sto per cancellare il SysEx: "%1" Sei sicuro? SysEx settings have been changed. Do you want to apply the changes? Le impostazioni SysEx sono state modificate. Vuoi applicare i cambiamenti? Error Errore SysEx could not be loaded: "%1". Sorry. Impossibile caricare SysEx: "%1". Spiacente. qtractorMidiToolsForm MIDI Tools Strumenti MIDI Preset name Nome Preset Save preset Salva Preset Delete preset Elimina Preset &Quantize &Quantizza Quantize selected events Quantizza gli eventi selezionati &Time: &Tempo: Quantize time Quantizza tempo Quantize time percent Percentuale quantizzazione tempo % % &Duration: &Durata: Quantize duration Quantizza durata Quantize duration percent Percentuale quantizzazione durata S&wing: S&wing: Swing-quantize time Tempo quantizzazione swing Swing-quantize percent Percentuale quantizzazione swing Swing-quantize type Tipo quantizzazione swing Linear Lineare Quadratic Quadratica Cubic Cubica &Scale: &Scala: Scale-quantize key Chiave scala quantizzazione Scale-quantize type Tipo scala quantizzazione &Transpose &Trasposizione Transpose selected events Trasponi eventi selezionati &Note: &Nota: Transpose note Trasponi nota Transpose time Trasponi tempo Transpose time format Formato trasposizione tempo Frames Campioni Time Tempo BBT BBT &Normalize &Normalizza Normalize selected events Normalizza eventi selezionati &Percent: &Percentuale: Normalize percent Percentuale normalizzazione &Value: &Valore: Normalize value Valore normalizzazione &Randomize &Randomizza Randomize selected events Randomizza eventi selezionati Randomize note/pitch Randomizza nota/altezza Randomize time Randomizza tempo Randomize duration Randomizza durata Randomize value Valore randomizzazione Resi&ze Ridimensiona Resize selected events Ridimensiona eventi selezionati Resize duration Ridimensiona durata Resize duration format Formato ridimensionamento durata Percentage Percentuale Resize value Valore ridimensionamento Resize value mode Modalità valore ridimensionamento Flat Piatto Ramp Rampa Resize final value Valore ridimensionamento finale Re&scale &Scala Rescale selected events Scala eventi selezionati Rescale time Scala tempo Rescale duration Scala durata Rescale value Valore scalamento T&imeshift T&imeshift Timeshift selected events T&imeshift eventi selezionati Timeshift Timeshift P: P: Timeshift parameter Parametro timeshift Timeshift parameter (log) Parametro timeshift (log) Timeshift curve Curva timeshift P = 0 : no change. P > 0 : accelerating shift. P < 0 : slowing down shift. Edit head/tail (blue) markers define the shift range. P = 0 : nessun cambiamento. P > 0 : accelerazione shift. P < 0 : decelerazione shift. Modificando i marcatori di testa/coda (blu) viene definito l'intervallo di shift. Timeshift duration Durata timeshift (default) (default) Warning Attenzione About to delete preset: "%1" Are you sure? Sto per eliminare il preset: "%1" Sei sicuro? none nessuno quantize quantizza transpose trasposizione normalize normalizza randomize randomizza resize ridimensiona rescale scala timeshift timeshift qtractorMixer Inputs Ingressi Tracks Tracce Outputs Uscite Mixer Mixer qtractorMixerRack &Inputs &Ingressi &Outputs &Uscite &Monitor &Monitor &Buses... &Bus... qtractorMixerStrip inputs ingressi outputs uscite Connect %1 Connetti %1 %1 In %1 In %1 Out %1 Out (Audio) (Audio) Gain Guadagno (MIDI) (MIDI) Volume Volume (None) (Nessuno) Pan Bilanciamento qtractorMonitorButton monitor monitor Monitor (rec) Monitor (reg) Monitor (thru) Monitor (thru) qtractorOptionsForm Options - Qtractor Opzioni - Qtractor &General &Generale Session Sessione Default session &file format: Formato &file sessione predefinita: Default session file format (suffix) Formato file sessione predefinita (suffisso) Whether to create new sessions based on template Se creare una nuova sessione da un template &New session template: &Nuovo template di sessione: New session template Nuovo template di sessione Browse for new session template Sfoglia per nuovo template di sessione Whether to save backup versions of existing sessions Save &backup versions of existing sessions: Which mode to rename existing session files Increment previous version (default) Increment current version Options Opzioni Whether to ask for confirmation on removal Chiedi conferma di rimozione &Confirm removals &Conferma rimozioni Alt+C Alt+C Number of &recent files: Numero di file &recenti: The maximum number of recent files to keep in menu Numero massimo di file recenti da mostrare nel menu Whether to capture standard output (stdout/stderr) into messages window Cattura lo standard output (stdout/stderr) nella finestra messaggi Capture standard &output Cattura standard &output Alt+O Alt+O Whether to show the complete directory path of loaded session files Mostra percorso completo dei file di sessione caricati S&how complete path of session files Mostra percorso completo dei file di sessione caricati Alt+P Alt+P Whether to remove audio peak files on session close Rimuovi file audio picchi alla chiusura della sessione Auto-remove audio pea&k files Rimuovi automaticamente file di picco Alt+K Alt+K Whether to keep all tool windows on top of the main window Mantieni tutte le finestre strumenti sopra la finestra principale Keep tool &windows always on top Mantieni finestre strumenti sempre sopra Whether to try dropping multiple audio files into the same track Cerca di caricare file audio multipli nella stessa traccia &Drop multiple audio files into the same track Caricare file audio multipli nella stessa traccia Alt+S Alt+S Whether to reverse mouse middle-button role on keyboard modifiers (Shift/Ctrl) Re&verse middle-button modifier role (Shift/Ctrl) Transport Avanzamento Transport &mode: Modalità avanzamento Transport control mode (JACK) Modalità controllo avanzamento (JACK) None Nessuno Slave Slave Master Master Full Full &Loop recording mode (takes): Modalità registrazione &loop (riprese): Loop recording mode (takes) Modalità registrazione loop (riprese) First Primo Last Ultimo &Audio &Audio Capture / Export Cattura / Esporta Audio compression quality to use on capture (record) and export Qualità compressione audio da usare durante la cattura (registrazione) e esportazione Audio sample format to use on capture (record) and export Formato campionamento audio da usare durante la cattura (registrazione) e esportazione Audio file type to use on capture (record) and export Tipo file audio da usare durante la cattura (registrazione) e esportazione File &type: &Tipo file: Sample &format: &Formato campionamento: &Quality: &Qualità: Playback Riproduzione Whether to apply time-stretching when tempo changes Applica adattamento tempo quando il tempo cambia Aut&omatic time-stretching Adattament&o automatico tempo Sample-&rate converter type: Tipo di conve&rsione frequanza campionamento: Sample-rate converter quality Qualità conversione frequenza di campionamento Sinc (Best Quality) Sinc (Qualità migliore) Sinc (Medium Quality) Sinc (Qualità media) Sinc (Fastest) Sinc (Più veloce) Zero Order Hold Zero Order Hold Linear Lineare Whether to use WSOLA time-stretching Usa adattamento tempo WSOLA &WSOLA time-stretching Adattamento tempo &WSOLA Alt+W Alt+W Whether to apply WSOLA quick seek time-stretching Applica ricerca veloce adattamento tempo WSOLA WSOLA quic&k seek Ricerca veloce WSOLA Whether to have separate audition/pre-listening player output ports Porte di uscita separate per anteprima/pre-ascolto Dedicated au&dition/pre-listening player outputs: Porte di uscita &dedicate per anteprima/pre-ascolto: Alt+D Alt+D Whether to auto-connect dedicated audio player outputs Connessione automatica porte di uscita dedicate Auto-&connect &Connessione automatica Metronome Metronomo Whether to enable the audio metronome Abilita metronomo audio &Enable audio metronome Abilita m&etronomo audio Alt+E Alt+E &File (bar): &File (barra): Metronome Audio filename (bar) Nome file audio metronomo (barra) Browse for sample audio file (bar) Sfoglia file audio campione (barra) &Gain (bar): &Guadagno (barra): Metronome gain (bar) Guadagno metronomo (barra) dB dB &File (beat): &File (battito): Metronome Audio filename (beat) Nome file audio metronomo (battito) Browse for sample audio file (beat) Sfoglia file audio campione (battito) &Gain (beat): &Gain (battito): Metronome gain (beat) Guadagno metronomo (battito) Whether to have separate audio metronome output ports Porte audio separate per metronomo Dedicated a&udio metronome outputs: Uscite a&udio dedicate metronomo: Alt+U Alt+U Whether to auto-connect dedicated audio metronome outputs Connessione automatica uscite audio dedicate metronomo Auto-co&nnect Co&nnessione automatica Alt+N Alt+N &MIDI &MIDI File &format: &Formato file: MIDI file format to use on capture (record) and export Formato file MIDI da usare durante la cattura (registrazione) e esportazione &Quantize: &Quantizzazione: MIDI capture (record) quantization Quantizzazione cattura (registrazione) MIDI Queue &timer (resolution): &Timer coda (risoluzione) Queue timer (resolution) Timer coda (risoluzione) Whether to have separate MIDI player output ports Porte di uscita separate per MIDI Dedicated MIDI p&layer outputs Porte di uscita dedicate per MIDI Alt+L Alt+L Control Controllo &MMC: &MMC: MIDI Machine Control (MMC) mode Modalità MIDI Machine Control (MMC) Input Ingresso Output Uscita Duplex Duplex &Device: &Dispositivo: MIDI Machine Control (MMC) device id. ID dispositivo MIDI Machine Control (MMC) &SPP: &SPP: MIDI Song Position pointer (SPP) control mode Modalità controllo MIDI Song Position pointer (SPP) Cloc&k: Cloc&k: MIDI Clock control mode Modalità controllo clock MIDI Whether to have separate MIDI control ports Porte di controllo separate per MIDI Dedicated MIDI &control input/output Ingresso/uscita controllo dedicata per MIDI Whether to enable the MIDI metronome Abilita metronomo MIDI &Enable MIDI metronome Abilita m&etronomo MIDI &Channel: &Canale: Metronome MIDI channel Canale metronomo MIDI &Note (bar): &Nota (barra): Metronome MIDI note (bar) Nota metronomo MIDI (barra) &Velocity (bar): Intensità (barra): Metronome MIDI velocity (bar) Intensità metronomo MIDI (barra) &Duration (bar): &Durata (barra): &Note (beat): &Nota (battito): Metronome MIDI note (beat) Nota metronomo MIDI (battito) &Velocity (beat): Intensità (battito): Metronome MIDI velocity (beat) Intensità metronomo MIDI (battito) &Duration (beat): &Durata (battito): Whether to have separate MIDI metronome output port Porta di uscita separata per metronomo MIDI Dedicated M&IDI metronome output Uscita dedicata metronomo M&IDI Alt+I Alt+I &Display Visualizzazione Defaults Predefinite &Time display format: Formato visualizzazione &tempo: Time display format >Formato visualizzazione tempo Frames Battute Time Tempo BBT BBT &Base font size: Dimensione &base font: Base application font size (pt.) Dimensione base font applicazione (punti) (default) (predefinito) 6 6 7 7 8 8 9 9 10 10 11 11 12 12 Meters VU Meter &Audio: &Audio: Audio meter level Livello VU meter audio Over Sopra 0 dB 0 dB 3 dB 3 dB 6 dB 6 dB 10 dB 10 dB Audio meter color Colore VU meter audio Select custom audio meter color Seleziona colore personalizzato VU meter audio ... ... &MIDI: &MIDI: MIDI meter level Livello VU meter MIDI Peak Picco MIDI meter color Colore VU meter MIDI Select custom MIDI meter color >Seleziona colore personalizzato VU meter MIDI Reset meter colors to default Ripristina colori predefiniti VU meter &Reset &Ripristina Alt+R Alt+R Messages Messaggi Sample messages text font display Font messaggi campione Select font for the messages text display Seleziona font messaggi &Font... &Font... Alt+F Alt+F Whether to keep a maximum number of lines in the messages window Mantieni numero massimo di linee nella finestra messaggi M&essages limit: Limite m&essaggi: Alt+M Alt+M The maximum number of message lines to keep in view Il numero massimo di linee da mostrare nella vista lines lines Logging Log Messages log file File messaggi di log Browse for the messages log file location Sfoglia locazione file messaggi di log Whether to activate a messages logging to file. Archivia messaggi di log su file. Messages &log file: File messaggi di &log: &Plugins &Plugins Paths Percorsi Plugin type Tipo plugin Plugin path Percorso plugin Browse plugin path Sfoglia percorso plugin Add plugin path Aggiungi percorso plugin &Add &Aggiungi Plugin paths Percorsi plugin Remove plugin path Rimuovi percorso plugin &Remove &Rimuovi Move up path Sposta su percorso &Up S&u &Down Giù &LV2 Presets directory: Directory preset &LV2: LV2 Presets directory (default: ~/.lv2) Directory preset LV2 (default: ~/.lv2) Browse LV2 Presets directory Sfoglia directory preset LV2 Instruments Strumenti Whether to have separate audio output ports Porte audio di uscita separate Dedicated audi&o outputs: Porte audi&o di uscita dedicate: Whether to auto-connect dedicated audio output ports Connessione automatica porte audio di uscita Au&to-connect Connessione au&tomatica Alt+T Alt+T Editor Editor Whether to open plugin's editor (GUI) by default Apri di default la GUI dell'editor delle plugin Open plugin's &editor (GUI) by default Apri di default la GUI dell'editor delle plugin Alt+G Alt+G Experimental Sperimentale Whether to use a dummy plugin type when scanning for VST plugins Usa tipo finto durante la scansione delle plugin VST Dummy &VST plugin scan (RECOMMENDED) Scansione plugin &VST finta (RACCOMANDATO) Alt+V Alt+V Signed 16-Bit 16-Bit con segno Signed 24-Bit 24-Bit con segno Signed 32-Bit 32-Bit con segno Float 32-Bit 32-Bit Float Float 64-Bit 64-Bit Float SMF Format 0 Formato 0 SMF SMF Format 1 Formato 1 SMF (Any) (Qualsiasi) Warning Attenzione Some settings have been changed. Do you want to apply the changes? Alcune impostazioni sono state modificate. Vuoi applicare le modifiche? Metronome Bar Audio File File Audio Barra Metronomo Metronome Beat Audio File File Audio Battito Metronomo Plug-in Directory Cartella Plug-in LV2 Presets Directory Directory dei Preset LV2 Messages Log Messaggi di Log Log files (*.%1) File di Log (*.%1) Session Template Template Sessione Session template files (*.qtr *.qts *.%1) File Template Sessione (*.qtr *.qts *.%1) qtractorPasteRepeatForm Paste Repeat - Qtractor Ripeti incolla - Qtractor Repeat Ripeti &Count: &Conta: Repeat count Ripeti conta &Period: &Periodo: Repeat period Ripeti periodo Repeat period format Ripeti formato periodo Frames Campioni Time Tempo BBT BBT Warning Attenzione Some settings have been changed. Do you want to apply the changes? Alcune impostazioni sono state modificate. Vuoi applicare le modifiche? qtractorPluginForm qtractorPluginForm qtractorPluginForm Open preset Apri preset Preset name Nome preset Save preset Salva preset Delete preset Elimina preset Plugin parameters Parametro plugin Params Parametri Edit plugin Modifica plugin Edit Modifica Activate plugin Attiva plugin Active Attiva Outputs (Sends) Uscite (Mandate) Sends Mandate Inputs (Returns) Ingressi (Ritorni) Returns Ritorni Aux Send Bus: Bus Mandata Aux: Manage buses Gestione bus ... ... Direct Access Parameter Parametro Accesso Diretto Direct Access Accesso Diretto (default) (predefinito) Page %1 Pagina %1 (none) (nessuno) Open Preset Apri Preset Preset files (*.%1) File preset (*.%1) Error Errore Preset could not be loaded from "%1". Sorry. Il preset non può essere caricato da "%1". Spiacente. Save Preset Salva Preset Warning Attenzione About to delete preset: "%1" (%2) Are you sure? Sto per cancellare il preset: "%1" (%2) Sei sicuro? &None &Nessuno qtractorPluginListView copy plugin copia plugin activate all plugins attiva tutte le plugin deactivate all plugins disattiva tutte le plugin remove all plugins rimuovi tutte le plugin &Move Here Sposta Qui &Copy Here &Copia Qui C&ancel &Annulla &Add Plugin... &Aggiungi Plugin Add &Insert Aggoingi &Insert Add &Aux Send Aggiungi Mandata &Aux &Sends Mandate &Returns &Ritorni Ac&tivate A&ttiva Acti&vate All Atti&va Tutto Deactivate Al&l Disattiva Tutto &Remove &Rimuovi Re&move All Ri&muovi Tutto Move &Up Sposta S&u Move &Down Sposta Giù &None &Nessuno &Properties... &Proprietà... &Edit Modifica &Outputs Uscite &Dedicated &Dedicate &Auto-connect Connessione &Automatica qtractorPluginSelectForm Plugins - Qtractor Plugin - Qtractor Reset filter Ripristina filtro X X Plugin search string (regular expression) Stringa ricerca plugin (espressione regolare) Plugin type Tipo plugin Available plugins Plugin disponibili Name Nome Audio Audio MIDI MIDI Control Controllo Modes Modalità Path Percorso Index Indice Instances Istanze Type Tipo &Activate &Attiva Activate plugin on insert Attiva plugin su insert Alt+A Alt+A Plugin scanning in progress... Scansione plugin in corso... GUI GUI EXT EXT RT RT qtractorSessionForm Session - Qtractor Sessione - Qtractor Session Sessione &Name: &Nome: Session name Nome sessione &Directory: &Directory: Session directory Cartella sessione Browse for session directory Sflogia cartella sessione ... ... &Description: &Descrizione: Session description Descrizione sessione Properties Proprietà Time Tempo Sample &Rate: F&requenza Campionamento Sample rate (Hz) Frequenza campionamento (Hz) 44100 44100 48000 48000 96000 96000 192000 192000 &Tempo: &Tempo: Tempo (BPM) / Signature Tempo (BPM) / Signature T&icks/Beat: T&icks/Battito: Resolution (ticks/beat; tpqn) Risoluzione (ticks/battito; tpqn) View Vista &Snap/Beat: Allineamento/Battito Snap/beat Allineamento/battito &Pixels/Beat: &Pixel/Battito Pixels/beat Pixel/battito &Horizontal Zoom: Ingrandimento Orizzontale: Horizontal Zoom (%) Ingrandimento Orizzontale (%) % % &Vertical Zoom: Ingrandimento &Verticale: Vertical Zoom (%) Ingrandimento Verticale (%) Warning Attenzione Session directory does not exist: "%1" Do you want to create it? La cartella della sessione non esiste: "%1" Vuoi crearla? Some settings have been changed. Do you want to apply the changes? Alcune impostazioni sono state modificate. Vuoi applicare le modifiche? Session Directory Cartella Sessione qtractorShortcutForm Keyboard Shortcuts Scorciatoie Tastiera Action Azione Description Descrizione Shortcut Scorciatoia Warning Attenzione Keyboard shortcut (%1) already assigned. Keyboard shortcuts have been changed. Do you want to apply the changes? Le scorciatoie della tastiera sono state modificate. Vuoi applicare le modifiche? qtractorTakeRangeForm Take - Qtractor Ripresa - Qtractor Range Intervallo Selection range Intervallo selezione &Selection &Selezione Loop range Intervallo loop &Loop &Loop Punch range Intervallo punch &Punch &Punch Time Tempo BBT BBT Edit range Intervallo modifica &Edit Modifica Custom range Intervallo custom &Custom &Custom St&art: Inizio Clip start Inizio clip En&d: Fine Clip offset Posizione clip Select Seleziona Current take Ripresa corrente Format Formato Time display format >Formato visualizzazione tempo Frames Campioni &Frames Campioni Time (hh:mm:ss.zzz) Tempo (hh:mm:ss.zzz) &Time &Tempo BBT (bars.beats.ticks) BBT (battute.battiti.tick) &BBT &BBT Take %1 Ripresa %1 qtractorTempoAdjustForm Tempo - Qtractor Tempo - Qtractor Metronome Metronomo Temp&o: Temp&o: Tempo/Time signature Tempo/Time signature T&ap T&ap Range Intervallo &Start: Inizio: Range start Inizio intervallo Time Tempo BBT BBT &Length: &Lunghezza Range length Lunghezza intervallo B&eats: Battut&e: Range beats Intervallo battiti A&djust Aggiusta Format Formato Time display format >Formato visualizzazione tempo Frames Campioni Fra&mes Ca&mpioni Time (hh:mm:ss.zzz) Tempo (hh:mm:ss.zzz) &Time &Tempo BBT (bars.beats.ticks) BBT (battute.battiti.tick) &BBT &BBT Warning Attenzione Some settings have been changed. Do you want to apply the changes? Alcune impostazioni sono state modificate. Vuoi applicare le modifiche? qtractorThumbView Thumb view Vista anteprime qtractorTimeScaleForm Tempo Map - Qtractor Mappa Tempo - Qtractor Tempo map Mappa tempo Bar Battuta Time Tempo Tempo Tempo Signature Marchio Node Nodo &Bar: &Battuta: Tempo Map / Markers - Qtractor Tempo map / Markers Marker Location Bar location T&ime: Tempo: Bar/Time node Nodo Battuta/Tempo Time/frame location &Tempo: &Tempo: Tempo (BPM) / Signature Tempo (BPM) / Segno T&ap T&ap Marker text ... ... Marker color Refresh tempo map Aggiorna mappa tempo Re&fresh Aggiorna Alt+F Alt+F Add node Aggiungi nodo &Add &Aggiungi Alt+A Alt+A Update node Aggiorna nodo &Update Aggiorna Alt+U Alt+U Remove node Rimuovi nodo &Remove &Rimuovi Alt+R Alt+R Close this dialog Chiudi questa finestra Close Chiudi Warning Attenzione Some settings have been changed. Do you want to apply the changes? Alcune impostazioni sono state modificate. Vuoi applicare le modifiche? About to remove tempo node: %1 (%2) %3 %4/%5 Are you sure? Sto per rimuovere il nodo temporale: %1 (%2) %3 %4/%5 Sei sicuro? Some settings have been changed. Do you want to discard the changes? Alcune impostazioni sono state modificate. Vuoi scartare le modifiche? &Refresh Aggiorna qtractorTimeSpinBox &Frames Campioni &Time &Tempo &BBT &BBT qtractorTrackButton Record Regisra Mute Mute Solo Solo qtractorTrackForm Track - Qtractor Traccia - Qtractor Track Traccia &Name: &Nome: Track name description Descrizione nome traccia Type Tipo Audio track type Tipo traccia audio &Audio &Audio Alt+A Alt+A MIDI track type Tipo traccia MIDI &MIDI &MIDI Alt+M Alt+M Input / Output Ingresso / Uscita Input bus name Nome bus ingresso Output bus name Nome bus uscita Manage buses Gestione bus ... ... MIDI / Instrument MIDI / Strumento &Program: &Programma: &Bank: &Banco: Bank &Select Method: Metodo &Selezione Banco: &Omni &Omni MIDI Omni: Capture All Channels MIDI Omni: Cattura Tutti i Canali Alt+O Alt+O &Channel: &Canale: MIDI Channel (1-16) Canale MIDI (1-16) MIDI Patch: Instrument Patch MIDI: Strumento MIDI Patch: Bank Select Method Patch MIDI: Metodo Selezione Banco MIDI Patch: Bank Patch MIDI: Banco MIDI Patch: Program Patch MIDI: Programma View / Colors Vista / Colori &Foreground: Primo piano Foreground color Colore primo piano Select custom track foreground color Seleziona colore personalizzato primo piano traccia Bac&kground: Sfondo Background color Colore sfondo Select custom track background color Seleziona colore personalizzato sfondo traccia Plugins Plugins Track plugins Plugin traccia Add plugin Aggiungi plugin &Add... &Aggiungi... Remove plugin Rimuovi plugin &Remove &Rimuovi Alt+R Alt+R Move plugin up Sposta su plugin &Up S&u Alt+U Alt+U Move plugin down Sposta giù plugin &Down Giù Alt+D Alt+D Normal Normale Bank MSB MSB Banco Bank LSB LSB Banco Patch Patch Warning Attenzione Some settings have been changed. Do you want to apply the changes? Alcune impostazioni sono state modificate. Vuoi applicare le modifiche? (No instrument) (Nessuno strumento) (None) (Nessuno) qtractorTrackListHeaderModel Nr Nr Track Name Nome Traccia Bus Bus Ch Can Patch Patch Instrument Strumento qtractorTrackTime Play-head Edit-head Edit-tail Loop-start Loop-end Punch-in Punch-out Start: %1 End: %2 Length: %3 qtractorTrackView Zoom in (horizontal) Ingrandimento (orizzontale) Zoom out (horizontal) Rimpicciolimento (orizzontale) Zoom in (vertical) Ingrandimento (verticale) Zoom out (vertical) Rimpicciolimento (verticale) Zoom reset Ripristina ingrandimento add clip aggiungi clip Start: %1 End: %2 Length: %3 Inizio: %1 Fine: %2 Lunghezza: %3 clip %1 clip %1 fade-in fade-in fade-out fade-out clip stretch allarga clip clip resize ridimensiona clip %1 automation %1 clip %1 clip move automation paste automation cut taglia delete elimina split move clip sposta clip paste clip incolla clip qtractorTracks Tracks Tracce new clip nuovo clip split clip dividi clip clip normalize normalizza clip quantize quantizza transpose trasponi normalize normalizza randomize randomizza resize ridimensiona rescale scala timeshift timeshift clip tool %1 strumento clip %1 clip import importa clip Audio file import "%1" on %2 %3. Importa file audio "%1" su %2 %3. Audio file import: "%1". Importa file audio: "%1". MIDI file import "%1" track-channel %2 on %3 %4. Importa file MIDI "%1" traccia-canale %2 on %3 %4. MIDI file import: "%1", track-channel: %2. Importa file MIDI: "%1", traccia-canale: %2. clip merge fondi clip Merge/Export Audio Clip Fondi/Esporta Clip Audio Audio files (*.%1) File Audio (*.%1) Audio clip merge/export: "%1" started... Fusione/esportazione clip audio: "%1" in corso... Audio clip merge/export: "%1" complete. Fusione/esportazione clip audio: "%1" completa. Merge/Export MIDI Clip Fondi/Esporta Clip MIDI MIDI files (*.%1 *.smf *.midi) File MIDI (*.%1 *.smf *.midi) MIDI clip merge/export: "%1" started... Fusione/esportazione clip MIDI: "%1" in corso... MIDI clip merge/export: "%1" complete. Fusione/esportazione clip MIDI: "%1" completa. Insert Range insert range insert track range Remove Range remove range remove track range Warning Attenzione About to remove track: "%1" Are you sure? Sto per rimuovere la traccia: "%1" Sei sicuro? MIDI file import "%1" on %2 %3. Importazione file MIDI "%1" su %2 %3. MIDI file import: "%1". Importazione file MIDI: "%1". qtractor-0.5.11/src/translations/PaxHeaders.10084/qtractor_fr.ts0000644000175000001440000000012312223511102022647 xustar000000000000000027 mtime=1380880962.062114 26 atime=1381134669.34608 30 ctime=1381134669.444080088 qtractor-0.5.11/src/translations/qtractor_fr.ts0000644000175000001440000164705412223511102022157 0ustar00rncbcusers00000000000000 QObject Audio: %1 channels, %2 Hz Audio: %1 canaux, %2 Hz (%1 dB) (%1 dB) (%1% time stretch) (%1% étirement temporel) (%1 semitones pitch shift) (%1 demi-tons de décalage de la tonalité) %1 In %1 Entrée %1 Out %1 Sortie Audio files (%1) Fichiers audio (%1) All files (*.*) Tous les fichiers (*.*) %1 (%2) %3 channels, %4 frames, %5 Hz %6 %1 (%2) %3 canaux, %4 trames, %5 Hz %6 Duplex Duplex Output Sortie Input Entrée None Rien (take %1) (prise %1) Name: %1 Nom: %1 Start / End: %1 / %2 Offset / Length: %3 / %4 Début / Fin: %1 / %2 Décalage / Longueur: %3 / %4 Start / End: %1 / %2 Offs. / Len.: %3 / %4 Début / Fin: %1 / %2 Déc. / Long.: %3 / %4 File: %1 Fichier: %1 take %1 prise %1 reset takes réinitialiser les prises insert range Insérer plage insert track range Insérer plage de piste automation select automation sélection automation mode mode automation automation play automation jouer automation record automation enregistrer automation logarithmic automation logarithmique automation color automation couleur automation play all automation tout jouer automation record all automation tout enregistrer automation edit automation éditer automation clear automation nettoyer automation clear all automation tout nettoyer automation edit list automation éditer la liste %1 Monitor %1 Moniteur create bus créer un bus update bus mettre à jour le bus delete bus supprimer le bus bus pass-through bus transite bus gain gain du bus bus pan panoramique du bus Send Gain Gain d'Envoie Dry / Wet Dry / Wet Cakewalk Instrument Definition File Fichier de définition d'instrument Cakewalk File Fichier Date Date %1 Bank %2 %1 Banque %2 %1 - Bank %2 %1 - Banque %2 (format %1) MIDI: (format %1) MIDI: Channel %1 Canal %1 Track %1 Piste %1 , %1 tracks, %2 tpqn , %1 pistes, %2 tpqn (%1% vol) (%1% vol) set controller active le contrôleur reset controller réinitialise le contrôleur %1 (format %2) %3 tracks, %4 tpqn %5 %1 (format %2) %3 pistes, %4 tpqn %5 %1 (format %2) %3 %1 (format %2) %3 (default) (défaut) %1 Hz %1 Hz slave esclave %1 (%2) %1 (%2) Usage: %1 [options] [session-file] Utilisation: %1 [options] [fichier-session] Options: Options: Set session identification (uuid) Définir l'identificateur de session (uuid) Show help about command line options Afficher l'aide à propos des options de ligne de commande Show version information Afficher les informations de version Option -s requires an argument (session-id). Option -s nécessite un argument (session-id). Qt: %1 Qt: %1 (Any) (Tous) add plugin ajouter un greffon add insert ajouter un insert add aux-send ajouter un aux-send aux-send bus bus aux-send remove plugin enlever le greffon move plugin déplacer le greffon activate plugin activer le greffon preset plugin pré-réglage du greffon reset plugin réinitialiser le greffon dedicated audio outputs sorties audio dédiées direct access param paramètre accès direct session loop session boucle session punch session punch session properties propriétés de la session Beat Battement add tempo node ajouter un noeud tempo update tempo node mise à jour du noeud tempo remove tempo node enlever le noeud tempo move tempo node déplacer le noeud tempo add marker ajouter un marqueur update marker mettre à jour un marqueur remove marker enlever un marqueur move marker déplacer un marqueur %1 Record %1 Enregistrer %1 Mute %1 Muet %1 Solo %1 Solo %1 Volume %1 Volume %1 Gain %1 Gain %1 Pan %1 Pan add track ajouter une piste remove track enlever une piste move track déplacer une piste resize track redimensionner une piste import track importer une piste track properties propriétés de la piste Track assignment failed: Track: "%1" Input: "%2" Output: "%3" Echec de l'affectation de la piste: Piste: "%1" Entrée: "%2" Sortie: "%3" track record piste enregistrer track mute piste muet track solo piste solo track monitor piste contrôler track gain piste gain track pan piste panoramique Automation (%1) Automation (%1) none rien Automation Automation Audio Audio MIDI MIDI Unknown Inconnu %1 (*.%2) %1 (*.%2) qtractorAudioListView Name Nom Ch Can Frames Trames Rate Vitesse Time Temps Path Chemin Open Audio Files Ouvrir fichiers audio qtractorAudioMeter Gain (dB) Gain (dB) dB dB Pan: %1 Pan: %1 Gain: %1 dB Gain: %1 dB qtractorBusForm Buses - Qtractor Bus - Qtractor Bus list Liste des bus Buses Bus Ch Can Mode Mode Bus Bus Properties Propriétés &Name: &Nom: Bus name Nom de bus &Mode: &Mode: Bus mode Mode du bus Input Entrée Output Sortie Duplex Duplex Bus monitor (pass-through) Bus de contrôle (transit) M&onitor (pass-through) C&ontrôle (transit) Alt+O Alt+O Audio Audio Cha&nnels: Ca&naux: Audio channels Canaux audio Audio auto-connect Auto-connection audio &Auto connect &Auto connecte Alt+A Alt+A MIDI MIDI MIDI Instrument name Nom d'instrument MIDI MIDI SysEx setup Configuration MIDI SysEx SysE&x... SysE&x... Input Plugins Greffons d'entrée Input bus plugins Bus d'entrée greffons Add input plugin Ajouter un greffon d'entrée &Add... &Ajouter... Remove input plugin Enlever le greffon d'entrée &Remove &Enlever Alt+R Alt+E Move input plugin up Déplacer le greffon d'entrée vers le haut &Up &Haut Alt+U Alt+H Move input plugin down Déplacer le greffon d'entrée vers le bas &Down &Bas Alt+D Alt+B Output Plugins Greffons de sortie Output bus plugins Bus de sortie greffons Add output plugin Ajouter un greffon de sortie Remove output plugin Enlever un greffon de sortie Move output plugin up Déplacer le greffon de sortie vers le haut Move output plugin down Déplacer le greffon de sortie vers le bas Refresh bus list view Rafraichir la vue de liste des bus &Refresh &Rafraichir Create bus Créer un bus &Create &Créer Alt+C Alt+C Update bus Mise à jour du bus &Update &Mettre à jour Delete bus Supprimer le bus &Delete &Supprimer Close this dialog Fermer ce dialogue Close Fermer Warning Attention Some settings have been changed. Do you want to apply the changes? Des réglages ont changé. Voulez vous appliquer les changements? About to remove bus: "%1" (%2) Are you sure? Sur le point d'enlever un bus: "%1" (%2) Etes vous sur? Some settings have been changed. Do you want to discard the changes? Des réglages ont changé. Voulez-vous abandonner les changements? (No instrument) (Pas d'instrument) (none) (rien) (1 item) (1 élément) (%1 items) (%1 éléments) qtractorClientListView Readable Clients / Output Ports Clients en lecture / Ports de Sortie Writable Clients / Input Ports Clients en écriture / Ports d'entrée qtractorClipForm Clip - Qtractor &Name: &Nom: Clip name Nom du clip &File: &Fichier: Clip filename Nom de fichier du clip Browse for clip file Parcourir les fichiers clip Track/&Channel: Piste/&Canal: Clip track/channel Clip piste/canal &Gain/Volume: &Gain/Volume: Clip gain/volume Clip gain/volume Parameters Paramètres Clip start Début du clip Clip offset Décalage du clip Clip length Longueur du clip Offs&et: Décalag&e: &Length: &Longueur: &Start: &Début: Gain/Volume Gain/Volume Format Format Time display format Format d'affichage du temps Frames Trames Fra&mes Tra&mes Time (hh:mm:ss.zzz) Temps (hh:mm:ss.zzz) &Time &Temps BBT (bars.beats.ticks) BBT (barres.battements.clicks) &BBT &BBT Time Temps BBT BBT Fade In/Out Fondu en ouverture/fermeture Fade &In: Fondu en &ouverture: Clip fade-in length Clip longueur du fondu en ouverture Clip fade-in type Clip type de fondu en ouverture Fade &Out: Fondu en &fermeture: Clip fade-out length Clip longueur du fondu en fermeture Clip fade-out type Clip type de fondu en fermeture Audio Audio Time St&retch: Eti&rement temporel: Clip time-stretch percentage Clip pourcentage d'étirement temporel % % Pitch S&hift: Décalage de t&onalité: Clip pitch-shift in semitones Clip décalage de tonalité en demi-tons semitones demi-tons &Gain: &Gain: dB dB &Volume: &Volume: new clip nouveau clip edit clip éditer le clip Warning Attention Some settings have been changed. Do you want to apply the changes? Des réglages ont changé. Voulez vous appliquer les changements? MIDI MIDI MIDI files (*.%1 *.smf *.midi) Fichiers MIDI (*.%1 *.smf *.midi) %1 Clip File %1 fichier clip qtractorConnect Connect Connecter Disconnect Déconnecter Disconnect All Tout Déconnecter Refresh Rafraichir qtractorConnectForm qtractorConnectTest qtractor Test Connection Audio Audio Select output client/ports Sélectionner la sortie client/ports Select input client/ports Sélectionner l'entrée client/ports Connect currently selected ports Connecter les ports actuellements sélectionnés &Connect &Connecter Alt+C Alt+C Disconnect currently selected ports Déconnecter les ports actuellements sélectionnés &Disconnect &Déconnecter Alt+D Alt+D Disconnect all currently connected ports Déconnecter tous les ports actuellements sélectionnés Disconnect &All &Tout Déconnecter Alt+A Alt+T Refresh current connections view Rafraichir la vue courante des connections &Refresh &Rafraichir Alt+R Alt+R MIDI MIDI (All) (Tout) qtractorConnections Connections Connections qtractorEditRangeForm Range - Qtractor Plage - Qtractor Range Plage Selection range Plage de sélection &Selection &Sélection Loop range Plage de boucle &Loop Bouc&le Punch range Plage de punch &Punch &Punch Edit range Editer la plage &Edit &Editer Custom range Plage spéciale &Custom &Spéciale St&art: &Début: Clip start Début du clip En&d: F&in: Clip offset Décalage du clip Apply to Loop points in range Appliquer aux points de la boucle dans la plage L&oop B&oucle Apply to Punch In/Out points in range Appliquer aux points Punch In/Out de la plage Pu&nch Pu&nch Mar&kers Mar&queurs Te&mpo Map Carte de Te&mpo &Format &Format Time display format Format d'affichage du temps Time Temps BBT BBT Format Format Frames Trames &Frames &Trames Time (hh:mm:ss.zzz) Temps (hh:mm:ss.zzz) &BBT &BBT Options Options Apply to clips in range Appliquer aux clips de la plage Cl&ips Cl&ips A&utomation A&utomation Apply to Automation nodes in range Appliquer aux noeuds d'Automation de la plage &Automation &Automation Apply to Tempo Map nodes in range Appliquer aux noeuds de carte de tempo de la plage Apply to location Markers in range Appliquer à la localisation des marqueurs de la plage qtractorExportForm Export - Qtractor Exporter - Qtractor &File: &Fichier: Export file name Nom de fichier d'exportation Browse export file name Parcourir les fichiers d'exportation Range Plage Session range Plage de session &Session &Session Loop range Plage de boucle &Loop Bouc&le Punch range Plage de Punch &Punch &Punch Edit range Editer la plage &Edit &Editer Custom range Plage spéciale &Custom &Spéciale St&art: &Début: Clip start Début du clip En&d: F&in: Clip offset Décalage du clip Output Sortie Output bus name Nom du bus de sortie Format Format Time display format Format d'affichage du temps Frames Trames Time Temps BBT BBT &Frames &Trames Time (hh:mm:ss.zzz) Temps (hh:mm:ss.zzz) &Time &Temps BBT (bars.beats.ticks) BBT (barres.battements.clicks) &BBT &BBT Audio Audio MIDI MIDI Export %1 Exporter %1 Warning Attention The file already exists: "%1" Do you want to replace it? Le fichier existe déjà: "%1" Voulez-vous le remplacer? Audio file export: "%1" started... Exportation du fichier audio: "%1" commencée... Audio file export: "%1" complete. Exportation du fichier audio: "%1" terminée. Audio file export: "%1" failed. Exportation du fichier audio: "%1" échec. MIDI file export: "%1" started... Exportation du fichier MIDI: "%1" commencée... MIDI file export: "%1" complete. Exportation du fichier MIDI: "%1" terminée. MIDI file export: "%1" failed. Exportation du fichier MIDI: "%1" échec. Export %1 File Exporter %1 fichier %1 files (*.%1) %1 fichiers (*.%1) qtractorFileListView New Group Nouveau Groupe Warning Attention About to remove %1 file items. Are you sure? Sur le point de supprimer %1 éléments de type fichier Etes-vous sur? About to remove %1 file item(s). Are you sure? Sur le point de supprimer %1 élément(s) de type fichier Etes-vous sur? About to remove %1 item: "%2" Are you sure? Sur le point de supprimer %1 élément: "%2" Etes-vous sur? group groupe file fichier qtractorFiles Audio Audio MIDI MIDI Play file Jouer le fichier New &Group Nouveau &Groupe Add &Files... Ajouter des &Fichiers... Cu&t Cou&per &Copy &Copier P&aste Co&ller R&ename R&enommer &Delete &Supprimer Play Jouer Ctrl+X Ctrl+P Ctrl+C Ctrl+C Ctrl+V Ctrl+L New &Group... Nouveau &Groupe... &Paste Co&ller Re&name Re&nommer &Remove &Supprimer Pla&y J&ouer Cl&eanup N&ettoyer Del Suppr Files Fichiers MIDI Files Fichiers MIDI Audio Files Fichiers Audio qtractorInstrumentForm Instruments - Qtractor Instruments - Qtractor Instruments Instruments Files Fichiers Path Chemin Names Noms Import from instrument file Importer à partir d'un fichier instrument &Import... &Importer... Alt+I Alt+I Remove instrument file Supprimer le fichier instrument &Remove &Supprimer Alt+R Alt+S Move instrument file up on list order Déplacer le fichier instrument vers le haut de la liste &Up &Haut Alt+U Alt+H Move instrument file down on list order Déplacer le fichier instrument vers le bas de la liste &Down &Bas Alt+D Alt+B Reload all instrument files Recharger tous les fichiers instrument Relo&ad Rech&arger Alt+A Alt+A Export to instrument file Exporter vers un fichier instrument E&xport... E&xporter... Alt+X Alt+X Close this dialog Fermer ce dialogue Close Fermer Import Instrument Files Importer des fichiers instrument Instrument files (*.%1 *.sf2 *.midnam) Fichiers instrument (*.%1 *.sf2 *.midnam) Export Instrument File Exporter le fichier instrument Instrument files (*.%1) Fichiers instrument (*.%1) Warning Attention The instrument file already exists: "%1" Do you want to replace it? Le fichier instrument existe déjà: "%1" Voulez-vous le remplacer? Instrument settings have been changed. Do you want to apply the changes? Les réglages de l'instrument ont été changés. Voulez-vous appliquer les changements? Patch Names for Banks Noms de patches pour les banques Controller Names = %1 Noms de contrôleur = %1 RPN Names = %1 Noms RPN = %1 NRPN Names = %1 Noms NRPN = %1 Bank Select Method = %1 Méthode de sélection de banque = %1 Patch Names Noms de Patch Note Names Noms de Note Controller Names Noms de Contrôleur RPN Names Noms RPN NRPN Names Noms NRPN Bank Select Methods Méthodes de Sélection de Banque %1 = %2 %1 = %2 Based On = %1 Basé Sur = %1 Normal Normal Bank MSB Banque MSB Bank LSB Banque LSB Patch Patch Unknown Inconnu qtractorMainForm Qtractor Qtractor &File &Fichier Open &Recent Ouvrir &Récent &Edit &Editer Select &Mode Sélectionner &Mode &Select &Sélectionner I&nsert I&nsérer Remo&ve Enle&ver &Track Pis&te &State &Etat &Navigate &Naviguer Mo&ve &Déplacer &Height &Hauteur Impor&t Tracks &Importer Pistes E&xport Tracks &Exporter Pistes M&ode M&ode A&utomation A&utomation Cl&ip Cl&ip T&ools &Outils Ta&ke &Prise &View &Vue &Toolbars &Barre d'outils &Windows &Fenêtres &Zoom &Zoom S&nap &Ancrer T&ransport T&ransport &Help &Aide &New &Nouveau New Nouveau New session Nouvelle session New session file Nouveau fichier de session Ctrl+N Ctrl+N &Open... &Ouvrir... Open Ouvrir Open session Ouvrir session Open session from file Ouvrir session à partir d'un fichier Ctrl+O Ctrl+O &Save &Sauvegarder Save Sauvegarder Save session Sauvegarder session Save session to file Sauvegarder session dans un fichier Ctrl+S Ctrl+S Save &As... Sauveg&arder Sous... Save As Sauvegarder Sous Save as Sauvegarder sous Save current session with another file name Sauvegarder la session courante sous un autre nom de fichier &Properties... &Propriétés... Session Properties Propriétés de Session Session properties Propriétés de session Edit current session properties Editer les propriétés de la session courante F2 F2 E&xit So&rtir Exit Sortir Exit this application program Sortir de cette application &Undo &Défaire Undo Défaire Undo last action Défaire la dernière action Ctrl+Z Ctrl+Z &Redo &Refaire Redo Refaire Redo last action Refaire la dernière action Ctrl+Shift+Z Ctrl+Shift+Z Cu&t Co&uper Cut Couper Cut selection to clipboard Couper la sélection vers le presse-papiers Ctrl+X Ctrl+X &Copy &Copier Copy Copier Copy selection to clipboard Copier la sélection vers le presse-papiers Ctrl+C Ctrl+C &Paste Co&ller Paste Coller Paste clipboard contents Coller le contenu du presse-papiers Ctrl+V Ctrl+V Past&e Repeat... Répéter Coll&er... Paste Repeat Répéter Coller Paste repeat Répéter coller Paste/repeat clipboard contents Répéter/coller le contenu du presse-papiers Ctrl+Shift+V Ctrl+Shift+V &Delete &Supprimer Delete Supprimer Delete selection Supprimer la sélection Del Suppr &Clip &Clip Clip Clip Select clip Sélectionner le clip Clip selection mode Mode de sélection du clip &Range &Plage Range Plage Select range Sélectionner la plage Range selection mode Mode de sélection de la plage R&ectangle R&ectangle Rect Rect Select rectangle Sélectionner le rectangle Rectangular selection mode Mode de sélection rectangulaire &Automation &Automation Automation Automation Automation edit mode Mode d'édition de l'automation &All &Tout Select All Sélectionner Tout Select all Sélectionner tout Mark all as selected Marquer comme sélectionné Ctrl+A Ctrl+A &None &Rien Select None Sélectionner Rien Select none Sélectionner rien Mark all as unselected Marquer tout comme désélectionné Ctrl+Shift+A Ctrl+Shift+A &Invert &Inverser Select Invert Sélectionner Inverser Select invert Sélectionner inverser Invert selection Inverser la sélection Ctrl+I Ctrl+I Select Track Sélectionner Piste Select track Sélectionner piste Mark track as selected Marquer la piste comme sélectionnée Ctrl+T Ctrl+T Trac&k Range Pla&ge de piste Select Track Range Sélectionner la Plage de Piste Select track range Sélectionner la plage de piste Mark track range as selected Marquer la plage de piste comme sélectionnée Ctrl+Shift+R Ctrl+Shift+R Select Range Sélectionner la Plage Mark range as selected Marquer la plage comme sélectionnée Ctrl+R Ctrl+R &Range... &Plage... Remove Range Enlever Plage Remove range Enlever plage Remove range as selected Enlever la plage sélectionnée Ctrl+Del Ctrl+Suppr Remove Track Range Enlever la Plage de Piste Remove track range Enlever la plage de piste Remove track range as selected Enlever la plage de piste sélectionnée Ctrl+Shift+Del Ctrl+Shift+Suppr Insert Range Insérer Plage Insert range Insérer plage Insert range as selected Insérer plage comme sélectionnée Ctrl+Ins Ctrl+Ins Insert Track Range Insérer Plage de Piste Insert track range Insérer plage de piste Insert track range as selected Insérer plage de piste comme sélectionné Ctrl+Shift+Ins Ctrl+Shift+Ins Sp&lit Di&viser Split Selection Diviser la Sélection Split selection Diviser la sélection Split current selection Diviser la sélection courante Ctrl+Y Ctrl+Y &Add Track... &Ajouter Piste... Add Track Ajouter Piste Add track Ajouter piste Add a new track to session Ajouter une nouvelle piste à la session Shift+Ins Shift+Ins &Remove Track &Supprimer Piste Remove Track Supprimer Piste Remove track Supprimer piste Remove current track from session Supprimer la piste courante de la session Shift+Del Shift+Suppr Track &Properties... &Propriétés de Piste... Track Properties Propriétés de Piste Track properties Propriétés de piste Edit current track properties Editer les propriétés de la piste courante Shift+F2 Shift+F2 &Inputs &Entrées Track Inputs Entrées de Piste Track inputs Entrées de piste Show current track input bus connections Afficher les connections du bus d'entrée de la piste courante &Outputs &Sorties Track Outputs Sorties de Piste Track outputs Sorties de piste Show current track output bus connections Afficher les connections du bus de sortie de la piste courante &Record &Enregistrer Record Track Enregistrer la Piste Record track Enregistrer la piste Arm current track for recording Armer la piste courante pour l'enregistrement &Mute &Muet Mute Track Eteindre la Piste Mute track Eteindre la piste Mute current track Eteindre la piste courante &Solo &Solo Solo Track Piste Solo Solo track Piste solo Solo current track Piste courante solo M&onitor M&oniteur Monitor Track Monitorer la Piste Monitor track Monitorer la piste Monitor current track Monitorer la piste courante &First &Premier First Track Première Piste First track Première piste Make current the first track Rendre la première piste courante &Previous &Précédent Previous Track Précédente Piste Previous track Précédente piste Make current the previous track Rendre la précédente piste courante &Next &Prochain Next Track Prochaine Piste Next track Prochaine piste Make current the next track Rendre la prochaine piste courante &Last &Dernier Last Track Dernière Piste Last track Dernière piste Make current the last track Rendre la dernière piste courante N&one &Rien None Track Aucune Piste None track Aucune piste None current track Aucune piste courante &Top &Sommet Move Top Déplacer au Sommet Move top Déplacer au sommet Move current track to top Déplacer la piste courante au sommet &Up &Haut Move Up Déplacer vers le Haut Move up Déplacer vers le haut Move current track up Déplacer la piste courante vers le haut &Down &Bas Move Down Déplacer vers le Bas Move down Déplacer vers le bas Move current track down Déplacer la piste courante vers le bas &Bottom &Fond Move Bottom Déplacer au Fond Move bottom Déplacer au fond Move current track to bottom Déplacer la piste courante au fond &Increase &Augmenter Increase Height Augmenter la Hauteur Increase height Augmenter la hauteur Increase track height Augmenter la hauteur de la piste Ctrl+Shift++ Ctrl+Shift++ &Decrease &Diminuer Decrease Height Diminuer la Hauteur Decrease height Diminuer la hauteur Decrease track height Diminuer la hauteur de la piste Ctrl+Shift+- Ctrl+Shift+- &Reset &Réinitialiser Height Reset Réinitialiser la Hauteur Height reset Réinitialiser la hauteur Reset track height Réinitialiser la hauteur de la piste Ctrl+Shift+1 Ctrl+Shift+1 Auto &Monitor &Moniteur Auto Auto Monitor Moniteur Auto Auto monitor Moniteur auto Auto-monitor current track Monitorer automatiquement la piste courante F6 F6 &Audio... &Audio... Inport Audio File Importer un Fichier Audio Import Audio file Importer un fichier Audio Import tracks from Audio file Importer des pistes à partir d'un fichier Audio &MIDI... &MIDI... Import MIDI File Importer un Fichier MIDI Import MIDI file Importer un fichier MIDI Import tracks from MIDI file Importer des pistes à partir d'un fichier MIDI Export Audio File Exporter un Fichier Audio Export Audio file Exporter un fichier Audio Export tracks to Audio file Exporter des pistes vers un fichier Audio Export MIDI File Exporter un Fichier MIDI Export MIDI file Exporter un fichier MIDI Export tracks to MIDI file Exporter des pistes vers un fichier MIDI Log&arithmic Log&arithmique Automation logarithmic Automation logarithmique Automation curve logarithmic scale Echelle logarithmique de la courbe d'automation C&olor... C&ouleur... Automation color Couleur pour l'automation Automation curve color Couleur de la courbe d'automation &Lock &Verrouiller Automation lock Verrouillage automation Lock automation curve Verrouillage de la courbe d'automation &Play &Jouer Automation playback Lecture automation Playback automation curve Lecture de la courbe d'automation Automation record Enregistrement automation Record automation curve Enregistrement de la courbe d'automation &Clear &Nettoyer Automation clear Nettoyer automation Clear automation curve Nettoyer la courbe d'automation Loc&k All &Verrouiller tout Automation lock all Verrouiller toutes les automations Lock all automation curves Verrouiller toutes les courbes d'automation Play &All &Jouer tout Automation playback all Lecture complète automation Playback all automation curves Lecture de toutes les courbes d'automation Rec&ord All &Enregistrer tout Automation record all Enregistrer tout automation Record all automation curves Enregistrer toutes les courbes d'automation C&lear All N&ettoyer tout Automation clear all Nettoyer tout automation Clear all automation curves Nettoyer toutes les courbes d'automation &New... &Nouveau... New Clip Nouveau Clip New clip Nouveau clip Create new clip Créer un nouveau clip &Edit... &Editer... Edit Clip Editer Clip Edit clip Editer clip Edit current clip Editer le clip courant F4 F4 &Unlink &Délier Unlink Clip Délier Clip Unlink clip Délier clip Unlink current clip Délier le clip courant &Split &Diviser Split Clip Diviser Clip Split clip Diviser clip Split current clip at playhead Diviser le clip courant au niveau de la tête de lecture &Merge... &Fusionner... Merge Clips Fusionner Clips Merge clips Fusionner clips Merge selected clips Fusionner les clips sélectionnés N&ormalize N&ormaliser Normalize Clip Normaliser Clip Normalize clip Normaliser clip Normalize current clip (gain/volume) Normaliser le clip courant (gain/volume) &Quantize... &Quantifier... Quantize Clip Quantifier Clip Quantize clip events Quantifier les évènements du clip Quantize current MIDI clip events Quantifier les éléments MIDI courants du clip &Transpose... &Transposer... Transpose Clip Transposer Clip Transpose clip events Transposer les évènements du clip Transpose current MIDI clip events Transposer les évènements MIDI courants du clip &Normalize... &Normaliser... Normalize clip events Normaliser les évènements du clip Normalize current MIDI clip events Normaliser les évènements MIDI courants du clip &Randomize... &Randomiser... Randomize Clip Randomiser Clip Randomize clip events Randomiser les évènement du clip Randomize current MIDI clip events Randomiser les évènements MIDI courants du clip Resi&ze... Re&dimensionner... Resize Clip Redimensionner Clip Resize clip events Redimensionner les évènements du clip Resize current MIDI clip events Redimensionner les évènements MIDI courants du clip Re&scale... Re&mettre à l'échelle... Rescale Clip Remettre à l'échelle le Clip Rescale clip events Remettre à l'échelle les évènements du clip Rescale current MIDI clip events Remettre à l'échelles les évènements MIDI courants du clip T&imeshift... Dé&calage temporel... Timeshift Clip Décalage temporel du clip Timeshift clip events Décalage temporel des évènements du clip Timeshift current MIDI clip events Décalage temporel des évènement MIDI courants du clip &Tempo... &Tempo... Tempo Adjust Ajustement du Tempo Adjust session tempo from current clip selection Ajuster le tempo de la session à partir de la sélection du clip F7 F7 &Range Set &Réglage de Plage Clip Range Plage de Clip Clip range Plage de clip Set edit-range from current clip extents Régler la plage d'édition à partir de la longueur courante du clip &Loop Set Réglage de bouc&le Clip Loop Boucle Clip Clip loop Boucle clip Set loop-range from current clip extents Régler la plage de bouclage à partir de la longueur du clip &Import... &Importer... Import Clip Importer Clip Import clip Importer clip Import clip from file(s) Importer clip à partir du fichier(s) E&xport... E&xporter... Export Clip Exporter Clip Export clip Exporter clip Export current clip to file Exporter le clip courant vers un fichier First Take Première Prise First take Première prise Select current clip first take Sélectionner la première prise du clip courant Previous Take Précédente Prise Previous take Précédente prise Select current clip previous take Sélectionner la précédente prise du clip courant Next Take Prochaine Prise Next take Prochaine prise Select current clip next take Sélectionner la prochaine prise du clip courant Shift+T Shift+T Last Take Dernière Prise Last take Dernière prise Select current clip last take Sélectionner la dernière prise du clip courant Reset Takes Nettoyer les Prises Reset takes Nettoyer les prises Reset (unfold) current clip takes Nettoyer (déplier) les prises du clip courant R&ange... Pl&age... Take Range Plage de Prise Take range Plage de prise Range (fold) current clip into takes Plage (plier) le clip courant en prises &Menubar Barre de &menu Menubar Barre de menu Show/hide the main program window menubar Montrer/Cacher la barre de menu de la fenêtre du programme principal Ctrl+M Ctrl+M &Statusbar Barre de &status Statusbar Barre de status Show/hide the main program window statusbar Montrer/Cacher la barre de status de la fenêtre du programme principal File Toolbar Barre d'outils fichier File toolbar Barre d'outils fichier Show/hide main program window file toolbar Montrer/Cacher la barre d'outils fichier de la fenêtre du programme principal Edit Toolbar Editer la barre d'outils Edit toolbar Editer la barre d'outils Show/hide main program window edit toolbar Montrer/Cacher l'édition de la barre d'outils de la fenêtre du programme principal Track Toolbar Barre d'outils Piste Track toolbar Barre d'outils piste Show/hide main program window track toolbar Montrer/Cacher la barre d'outils piste de la fenêtre du programme principal View Toolbar Barre d'outils Vue View toolbar Barre d'outils vue Show/hide main program window view toolbar Montrer/Cacher la barre d'outils vue de la fenêtre du programme principal &Options &Options Options Toolbar Barre d'outils Options Options toolbar Barre d'outils options Show/hide main program window options toolbar Montrer/cacher la barre d'outils options de la fenêtre du programme principal Transport Toolbar Barre d'outils Transport Transport toolbar Barre d'outils transport Show/hide main program window transport toolbar Montrer/Cacher la barre d'outils transport de la fenêtre du programme principal T&ime T&emps Time Toolbar Barre d'outils Temps Time toolbar Barre d'outils temps Show/hide main program window time toolbar Montrer/Cacher la barre d'outils temps de la fenêtre du programme principal Thum&b V&ignette Thumb Toolbar Barre d'outils Vignette Thumb toolbar Barre d'outils vignette Show/hide main program window thumb toolbar Montrer/cacher la barre d'outils vignette de la fenêtre du programme principal &Files &Fichiers Files Fichiers Show/hide the files window Montrer/cacher la fenêtre des fichiers M&essages M&essages Messages Messages Show/hide the messages window Montrer/cacher la fenêtre des messages &Connections &Connections Connections Connections Show/hide the connections window Montrer/cacher la fenêtre des connections F8 F8 Mi&xer Mi&xeur Mixer Mixeur Show/hide the mixer window Montrer/cacher la fenêtre mixeur F9 F9 &In &Entrée Zoom In Zoom Avant Zoom in Zoom avant Ctrl++ Ctrl++ &Out &Sortie Zoom Out Zoom Arrière Zoom out Zoom arrière Ctrl+- Ctrl+- Zoom Reset Réinitialiser le Zoom Zoom reset Réinitialiser le zoom Ctrl+1 Ctrl+1 &Horizontal &Horizontal Horizontal Zoom Zoom Horizontal Horizontal zoom Zoom horizontal Horizontal zoom mode Mode zoom horizontal &Vertical &Vertical Vertical Zoom Zoom Vertical Vertical zoom Zoom vertical Vertical zoom mode Mode zoom vertical All Zoom Tout Zoomer All zoom Tout zoomer All zoom mode Mode zoom total &Grid &Grille Grid Grille Snap grid view mode Mode vue grille magnétique &Zebra &Zèbrures Zebra Zèbrures Bar zebra view mode Mode vue barre zèbrée Too&l Tips Info-bu&lles Tool tips Info-bulles Floating tool tips view mode Mode vue info-bulles flottantes &Refresh &Rafraichir Refresh Rafraichir Refresh views Rafraichir les vues F5 F5 &Instruments... &Instruments... Instruments Instruments Change instrument definitions and files Changer les définitions et fichiers des instruments &Controllers... &Contrôleurs... Controllers Contrôleurs Change MIDI controllers configuration Changer la configuration des contrôleurs MIDI &Buses... &Bus... Buses Bus Change session bus definitions Changer les définitions des bus de session Tempo M&ap / Markers... C&arte de Tempo / Marqueurs... Tempo Map / Markers Carte de Tempo / Marqueurs Tempo map / markers Carte de tempo / marqueurs Change session tempo map / markers Changer la carte de tempo de la session / marqueurs Tempo M&ap... C&arte de Tempo... Tempo Map Carte de Tempo Tempo map Carte de tempo Change session tempo map Changer la carte de tempo de la session &Options... &Options... Options Options Change general application program options Changer les options générales de l'application F12 F12 &Backward &Arrière Backward Arrière Transport backward Transport en arrière Backspace Backspace Re&wind Re&mbobinner Rewind Rembobinner Transport rewind Transport rembobinner F&ast Forward Av&ance Rapide Fast Forward Avance Rapide Fast forward Avance rapide Transport fast forward Transport avance rapide &Forward &Avance Forward Avance Transport forward Transport avance &Loop &Boucle Loop Boucle Transport loop Transport boucle Ctrl+Shift+L Ctrl+Shift+L Loop &Set &Réglage boucle Loop Set Réglage Boucle Loop set Réglage boucle Transport loop set Transport réglage boucle Ctrl+L Ctrl+L &Stop &Stop Stop Stop Transport stop Transport stop Play Jouer Transport play/pause Transport jouer/pause Space Espace Record Enregistrer Transport record Transport enregistrer &Punch &Punch Punch Punch Punch in/out Punch in/out Transport punch in/out Transport punch in/out Ctrl+Shift+P Ctrl+Shift+P Punch Se&t Ré&glage Punch Punch Set Réglage Punch Punch in/out set Réglage punch in/out Transport punch in/out set Transport réglage punch in/out Ctrl+P Ctrl+P &Metronome &Métronome Metronome Métronome F&ollow Playhead S&uivre la tête de lecture Follow Playhead Suivre la tête de lecture Follow playhead Suivre la tête de lecture A&uto Backward A&uto arrière Auto Backward Auto Arrière Auto backward Auto arrière &Continue Past End &Continuer au delà de la fin Continue Past End Continuer au delà de la fin Continue past end Continuer au delà de la fin Pa&nic Pa&nique Panic Panique All MIDI tracks shut off (panic) Toutes les pistes MIDI éteintes (panique) &Shortcuts... &Raccourcis... Shortcuts Raccourcis Keyboard shortcuts Raccourcis clavier &About... &A propos... About A propos Show information about this application program Afficher les informations à propos de ce programme About &Qt... A propos de &Qt... About Qt A propos de Qt Show information about the Qt toolkit Afficher les informations à propos du toolkit Qt Current time (playhead) Temps courant (tête de lecture) Current tempo (BPM) Tempo courant (BPM) Snap/beat Snap/battement Track Piste Current track name Nom de la piste courante MOD MOD Session modification state Etat de modification de la session REC ENR Session record state Etat d'enregistrement de la session MUTE MUET Session muting state Etat muet de la session SOLO SOLO Session soloing state Etat solo de la session LOOP BOUCLE Session looping state Etat de bouclage de la session Session total time Durée totale de la session Session sample rate Fréquence d'échantillonnage de la session Could not set default session directory: %1 Sorry. Ne peut pas sélectionner le répertoire par défaut de la session: %1 Désolé. Ready Prêt Untitled%1 Sans titre%1 New session: "%1". Nouvelle session: "%1". Session files (*.%1 *.%2 *.%3) Fichiers session (*.%1 *.%2 *.%3) Session files (*.%1 *.%2) Fichiers session (*.%1 *.%2) Template files (*.%1) Fichiers modèle (*.%1) Archive files (*.%1) Fichiers archive (*.%1) Open Session Ouvrir une session Save Session Sauvegarder une session Warning Attention The file already exists: "%1" Do you want to replace it? Le fichier existe déjà: "%1" Voulez-vous le remplacer? Backup session: "%1" as "%2". Session de sauvegarde: "%1" en "%2". Could not backup existing session: %1 as %2 Sorry. Ne peut pas sauvegarder la session existante: %1 en %2 Désolé. The current session has been changed: "%1" Do you want to save the changes? La session courante a été changée: "%1" Voulez-vous sauvegarder les changements? About to remove archive directory: "%1" Are you sure? Sur le point de supprimer le répertoire archive: "%1" Etes-vous sur? Session closed. Session fermée. The directory already exists: "%1" Do you want to replace it? Le répertoire existe déjà: "%1" Voulez-vous le remplacer? Opening "%1"... Ouvre "%1"... Session could not be loaded from "%1". Sorry. La session n'a pas pu être chargée à partir de "%1". Désolé. Open session: "%1". Ouvre la session: "%1". Saving "%1"... Sauvegarde "%1"... Session could not be saved to "%1". Sorry. La session n'a pas pu être sauvée vers "%1". Désolé. Save session: "%1". Sauvegarde la session: "%1". About to clear automation: "%1" Are you sure? Sur le point de nettoyer l'automation: "%1" Etes-vous sur? About to clear all automation: "%1" Are you sure? Sur le point de nettoyer toutes les automations: "%1" Etes-vous sur? take range plage de prise session session or ou program programme Information Information Some settings may be only effective next time you start this %1. Certains réglages ne seront effectifs que la prochaine fois que vous démarrerez %1. Debugging option enabled. Option de débuggage activée. Ogg Vorbis (libvorbis) file support disabled. Support des fichiers Ogg Vorbis (libvorbis) désactivé. MPEG-1 Audio Layer 3 (libmad) file support disabled. Support des fichiers MPEG-1 Audio Layer 3 (libmad) désactivé. Sample-rate conversion (libsamplerate) disabled. Conversion de fréquence d'échantillonnage (libsamplerate) désactivé. Pitch-shifting support (librubberband) disabled. Support du décalage de tonalité (librubberband) désactivé. OSC service support (liblo) disabled. Support du service OSC (liblo) désactivé. LADSPA Plug-in support disabled. Support des greffons LADSPA désactivé. DSSI Plug-in support disabled. Support des greffons DSSI désactivé. VST Plug-in support disabled. Support des greffons VST désactivé. VeSTige header support enabled. Support de l'entête VeSTige activé. LV2 Plug-in support disabled. Support du greffon LV2 désactivé. LV2 Plug-in UI support disabled. Support du GUI des greffons LV2 désactivé. LV2 Plug-in UI support (libsuil) disabled. Support du GUI des greffons (libsuil) LV2 désactivé. LV2 Plug-in MIDI/Event support disabled. Support MIDI/évènement greffon LV2 désactivé. LV2 Plug-in MIDI/Atom support disabled. Suppor MIDI/Atom greffon LV2 désactivé. LV2 Plug-in State Files support disabled. Support fichiers état greffon LV2 désactivé. LV2 Plug-in support (libslv2) enabled. (DEPRECATED) Support greffon LV2 (libslv2) activé (OBSOLETE) Set current snap to %1 Placer l'accroche courante sur %1 Current time (play-head) Temps courant (tête de lecture) LV2 Plug-in support (liblilv) disabled. Support greffon LV2 (liblilv) désactivé. LV2 Plug-in UI instantiation support (libsuil) disabled. Support instantiation UI greffon LV2 (libsuil) désactivé. LV2 Plug-in QT4 UI support disabled. Support UI QT4 greffon LV2 désactivé. LV2 Plug-in GTK UI support disabled. Support UI GTK greffon LV2 désactivé. LV2 Plug-in External UI support disabled. Support UI externe greffon LV2 désactivé. LV2 Plug-in Worker/Schedule support disabled. Support Worker/Schedule greffon LV2 désactivé. LV2 Plug-in State support disabled. Support état greffon LV2 désactivé. LV2 Plug-in State Files support enabled. (FUBAR) Support fichiers état greffon LV2 activé (FUBAR) LV2 Plug-in Programs support disabled. Support des programmes greffon LV2 désactivé. LV2 Plug-in Presets support disabled. Support réglages greffon LV2 désactivé. LV2 Plug-in Time/position support disabled. Support Temps/position greffon LV2 désactivé. LV2 Plug-in Options support disabled. Support pour les options du greffon LV2 désactivé. LV2 Plug-in Buf-size support disabled. Support du Buf-size pour les greffons LV2 désactivé. JACK Session support disabled. Support de session JACK désactivé. JACK Latency support disabled. Support de la latence JACK désactivé. Version Version Build Compilation Website Site web This program is free software; you can redistribute it and/or modify it Ce programme est un logiciel libre; vous pouvez le redistribuer et/ou le modifier under the terms of the GNU General Public License version 2 or later. sous les conditions de la license générale GNU version 2 ou plus. record clip enregistre clip [modified] [modifié] %1 Hz %1 Hz Session started. Session démarrée. The original session sample rate (%1 Hz) is not the same of the current audio engine (%2 Hz). Saving and reloading from a new session file is highly recommended. La fréquence originale de la session (%1 Hz) n'est pas la même que celle du moteur audio courant (%2 Hz). Sauvegarder et recharger à partir d'un nouveau fichier session est fortement recommandé. The audio/MIDI engine could not be started. Make sure the JACK audio server (jackd) and/or the ALSA Sequencer kernel module (snd-seq-midi) are up and running and then restart the session. Le moteur audio/MIDI ne peut pas être démarré. Assurez-vous que le serveur audio JACK (jackd) et/ou le module noyau séquenceur ALSA (snd-seq-midi) est près et en fonctionnement puis redémarrer la session. NSM support disabled. Support de NSM désactivé. &Hold &Maintien &Linear &Linéaire &Spline &Spline Take %1 Prise %1 None Rien Error Erreur XRUN(%1 skipped) XRUN(%1 sauté) XRUN(%1): some frames might have been lost. XRUN(%1): des trames peuvent avoir été perdues. Audio connections change. Les connections audio changent. MIDI connections change. Les connections MIDI changent. Playing ended. Lecture terminée. The audio engine has been shutdown. Make sure the JACK audio server (jackd) is up and running and then restart session. Le moteur audio a été arrêté. Assurez-vous que le serveur audio JACK (jackd) est près et en fonctionnement puis redémarrez la session. STOP STOP PLAY JOUER FFWD FFWD REW REW REC ON ENR ON REC OFF ENR OFF RESET REINIT LOCATE %1 LOCALISE %1 SHUTTLE %1 NAVETTE %1 STEP %1 PAS %1 TRACK RECORD %1 %2 PISTE ENREGISTREMENT %1 %2 TRACK MUTE %1 %2 PISTE MUET %1 %2 TRACK SOLO %1 %2 PISTE SOLO %1 %2 Unknown sub-command Sous-commande inconnue Not implemented Pas implémenté MIDI CTL: %1, Channel %2, Param %3, Value %4 MIDI CTL: %1, Canal %2, Param %3, Valeur %4 (track %1, gain %2) (piste %1, gain %2) (track %1, panning %2) (piste %1, panoramique %2) START DEMARRE CONTINUE CONTINUE SONGPOS %1 SONGPOS %1 %1 BPM %1 BPM Playing "%1"... Joue "%1"... &Frames &Trames &Time T&emps &BBT &BBT qtractorMessages Messages Messages Logging stopped --- %1 --- Journalisation arrêtée --- %1 --- Logging started --- %1 --- Journalisation démarrée --- %1 --- qtractorMeter Pan Pan Gain Gain qtractorMidiControlForm Controllers - Qtractor Contrôleurs - Qtractor Controller files Fichiers de contrôleur Files Fichiers Path Chemin Import controller files Importer des fichiers de contrôleur &Import... &Importer... Alt+I Alt+I Remove controller file Supprimer un ficher de contrôleur &Remove &Supprimer Alt+R Alt+S Move controller file up on list order Déplacer le fichier contrôleur vers le haut de la liste &Up &Haut Alt+U Alt+H Move controller file down on list order Déplacer le fichier contrôleur vers le bas de la liste &Down &Bas Alt+D Alt+B &Type &Type &Channel &Canal &Parameter &Paramètre Trac&k Offset Dé&calage de la piste C&ommand C&ommande MIDI Event type MIDI Type d'évènement MIDI Channel MIDI Canal MIDI Controller (parameter) MIDI Contrôleur (paramètre) MIDI parameter (track offset) MIDI Paramètre (décalage de la piste) + + Track offset Décalage de la piste Command action Commande d'action Command feedback Commande de retour &Feedback &Retour Map/update controller command Associer/mise à jour de la commande du contrôleur &Map &Associer Alt+M Alt+A Controller map Association de contrôleur Type Type Channel Canal Parameter Paramètre Track Piste Command Commande Feedback Retour Unmap/remove controller command Dés-associer/supprimer la commande du contrôleur U&nmap &Dés-associer Alt+N Alt+D Reload/apply all controller files Recharger/appliquer tous les fichiers contrôleur Relo&ad Rech&arger Alt+A Alt+A Export to controller file Exporter vers un fichier contrôleur E&xport... E&xporter... Alt+X Alt+X Close this dialog Fermer cette fenêtre Close Fermer Import Controller Files Importer des fichiers contrôleur Controller files (*.%1) Fichiers contrôleur (*.%1) Warning Attention About to remove controller file: "%1" Are you sure? Sur le point de supprimer un fichier contrôleur: "%1" Etes-vous sur? Export Controller File Exporter le fichier contrôleur The controller file already exists: "%1" Do you want to replace it? Le fichier contrôleur existe déjà: "%1" Voulez-vous le remplacer? Saved controller mappings may not be effective the next time you start this program. "%1" Do you want to apply to controller files? L'association des contrôleur ne sera pas effective la prochaine fois que vous démarrerez ce programme. "%1" Voulez-vous mettre à jour les fichiers contrôleur? Controller mappings have been changed. L'association des contrôleur a été changée. Do you want to save the changes? Voulez-vous sauvegarder les changements? Yes Oui No Non qtractorMidiControlObserverForm MIDI Controller - Qtractor Contrôleur MIDI - Qtractor &Type: &Type: MIDI event type MIDI Type d'évènement Cha&nnel: Ca&nal: MIDI channel Canal MIDI &Parameter: &Paramètre: MIDI parameter Paramètre MIDI &Logarithmic &Logarithmique &Feedback &Retour In&vert In&verser &Hook &Ancrer Control input connections Connections des entrées de contrôles &Inputs &Entrée Control output connections Connections des sorties de contrôle &Outputs &Sorties MIDI Controller Contrôleur MIDI MIDI controller is already assigned. Do you want to replace the mapping? Le contrôleur MIDI est déjà associé. Voulez-vous remplacer l'association? Some settings have been changed. Do you want to apply the changes? Des réglages ont été changés. Voulez-vous appliquer les changements? &MIDI Controller... Contrôleur &MIDI... &Automation &Automation &Lock Verroui&ller &Play &Jouer &Record En&registrer &Clear &Nettoyer qtractorMidiEditEvent Zoom in (horizontal) Zoom - aggrandir (horizontal) Zoom out (horizontal) Zoom - rétrécir (horizontal) Zoom reset (horizontal) Zoom - réinitialiser (horizontal) qtractorMidiEditList C%1 C%1 qtractorMidiEditTime Play-head Jouer le début Edit-head Editer le début Edit-tail Editer la fin Loop-start Boucle-début Loop-end Boucle-fin Punch-in Punch-in Punch-out Punch-out Start: %1 End: %2 Length: %3 Début: %1 Fin: %2 Longueur: %3 qtractorMidiEditView Zoom in (vertical) Zoom - aggrandir (vertical) Zoom out (vertical) Zoom - rétrécir (vertical) Zoom reset (vertical) Zoom - réinitialiser (vertical) qtractorMidiEditor MIDI Editor Editeur MIDI cut couper delete supprimer insert range Insérer plage remove range enlever plage move déplacer edit éditer resize redimensionner rescale remise à l'échelle paste coller Time: %1 Type: Temps: %1 Type: Note On (%1) %2 Velocity: %3 Duration: %4 Note On (%1) %2 Velocité: %3 Durée: %4 Key Press (%1) %2 Value: %3 Touche Appuyée (%1) %2 Valeur: %3 Controller (%1) Name: %2 Value: %3 Contrôleur (%1) Nom: %2 Valeur: %3 Pgm Change (%1) Pgm Change (%1) Chan Press (%1) Can Appuyé (%1) Pitch Bend (%1) Pitch Bend (%1) SysEx (%1 bytes) Data: SysEx (%1 bytes) Données: Unknown (%1) Inconnu (%1) Start: %1 End: %2 Length: %3 Début: %1 Fin: %2 Longueur: %3 qtractorMidiEditorForm MIDI Editor Editeur MIDI &Track &Piste &File &Fichier Select &Mode &Mode sélection &Select &Sélection I&nsert I&nsérer Remo&ve Enle&ver &Tools &Outils &Edit &Editer &View &Vue &Toolbars &Barre d'outils &Windows &Fenêtres &Zoom &Zoom S&nap A&ncrer Sc&ale E&chelle T&ransport T&ransport &Help &Aide &Save &Sauvegarder Save Sauvegarder Save current MIDI clip to existing file name Sauvegarder le clip MIDI courant vers le nom de fichier existant Save &As... S&auvegarder Sous... Save As Sauvegarder Sous Save as Sauvegarder sous Save current MIDI clip with another file name Sauvegarder le clip MIDI courant vers un autre nom de fichier &Unlink &Délier Unlink Délier Unlink current MIDI clip Délier le clip MIDI courant &Inputs &Entrées Track Inputs Entrées Piste Track inputs Entrées piste Show current MIDI clip/track input bus connections Afficher les connections du bus d'entrée du clip/piste MIDI courant &Outputs &Sorties Track Outputs Sorties Piste Track outputs Sorties piste Show current MIDI clip/track output bus connections Afficher les connections du bus de sortie du clip/piste MIDI courant &Properties... &Propriétés... Track Properties Propriétés Piste Track properties Propriétés piste Edit current MIDI clip/track properties Editer les propriétés MIDI du clip/piste courant Shift+F2 Shift+F2 Properties Propriétés Edit current MIDI clip properties Editer les propriétés du clip MIDI courant F4 F4 &Range Set &Réglage Plage Clip Range Plage Clip Clip range Plage clip Set edit-range from clip extents Régler la plage d'édition à partir des dimensions du clip &Loop Set Réglage &Boucle Clip Loop Boucle Clip Clip loop Boucle clip Set loop-range from clip extents Régler la plage de boucle à partir des dimensions du clip &Close &Fermer Close Fermer Close this MIDI clip editor Fermer cet éditeur de clip MIDI &Undo &Défaire Undo Défaire Undo last edit operation Défaire la dernière opération d'édition Ctrl+Z Ctrl+Z &Redo &Refaire Redo Refaire Redo last edit operation Refaire la dernière opération d'édition Ctrl+Shift+Z Ctrl+Shift+Z Cu&t Cou&per Cut Couper Cut current selection into the local clipboard Couper la sélection courante dans le presse-papiers local Ctrl+X Ctrl+X &Copy &Copier Copy Copier Copy current selection to the local clipboard Copier la sélection courante dans le presse-papiers local Ctrl+C Ctrl+C &Paste Co&ller Paste Coller Paste local clipboard contents into the current MIDI clip Coller le contenu du presse-papiers local dans le clip MIDI courant Ctrl+V Ctrl+V Past&e Repeat... Répét&er Coller... Paste Repeat Répéter Coller Paste repeat Répéter coller Paste/repeat local clipboard contents into the current MIDI clip Coller/répéter le contenu du presse-papiers local dans le clip MIDI courant Ctrl+Shift+V Ctrl+Shift+V &Delete &Supprimer Delete Supprimer Delete current selection Supprimer la sélection courante Del Suppr Edit Of&f Edition Of&f Edit Off Edition Off Edit off Edition off Set edit mode off Régler le mode édition à off Edit &On Edition &On Edit On Edition On Edit on Edition on Set edit mode on Régler le mode édition à on Edit &Draw Edition &Dessin Edit draw mode Mode édition dessin Edit draw mode (notes) Mode édition dessin (notes) &All &Tout Select All Sélectionner Tout Select all Sélectionner tout Ctrl+A Ctrl+A &None &Rien Select None Sélectionner Rien Select none Sélectionner rien Ctrl+Shift+A Ctrl+Shift+A &Invert &Inverser Select Invert Sélectionner Inverse Select invert Sélectionner inverse Ctrl+I Ctrl+I &Range &Plage Select Range Sélectionner Plage Select range Sélectionner plage Mark range as selected Marquer la plage comme sélectionnée Ctrl+R Ctrl+P Insert Range Insérer Plage Insert range Insérer plage Insert range as selected Insérer plage comme sélectionnée Ctrl+Ins Ctrl+Ins Remove Range Enlever Plage Remove range Enlever plage Remove range as selected Enlever la plage sélectionnée Ctrl+Del Ctrl+Suppr &Quantize... &Quantifier... Quantize Quantifier Quantize selection Quantifier la sélection &Transpose... &Transposer... Transpose Transposer Transpose selection Transposer la sélection &Normalize... &Normaliser... Normalize Normaliser Normalize selection Normaliser la sélection &Randomize... &Randomiser... Randomize Randomiser Randomize selection Randomiser la sélection Resi&ze... Redimen&sionner... Resize Redimensionner Resize selection Redimensionner la sélection Re&scale... Remi&se à l'échelle... Rescale Remise à l'échelle Rescale selection Remise à l'échelle de la sélection T&imeshift... Déc&alage temporel... Timeshift Décalage temporel Timeshift selection Décalage temporel de la sélection &Menubar Barre de &Menu Menubar Barre de menu Show/hide the menubar Montrer/Cacher la barre de menu Ctrl+M Ctrl+M &Statusbar Barre de &Status Statusbar Barre de status Show/hide the statusbar Montrer/Cacher la barre de status File Toolbar Barre d'outils Fichier File toolbar Barre d'outils fichier Show/hide the file toolbar Montrer/Cacher la barre d'outils fichier Edit Toolbar Barre d'outils Edition Edit toolbar Barre d'outils édition Show/hide the edit toolbar Montrer/Cacher la barre d'outils édition View Toolbar Barre d'outils Vue View toolbar Barre d'outils vue Show/hide the view toolbar Montrer/Cacher la barre d'outils vue &Transport &Transport Transport Toolbar Barre d'outils Transport Transport toolbar Barre d'outils transport Show/hide the transport toolbar Montrer/Cacher la barre d'outils transport &Scale &Echelle Scale Toolbar Barre d'outils Echelle Scale toolbar Barre d'outils échelle Show/hide the scale toolbar Montrer/Cacher la barre d'outils échelle Note &Duration &Durée Note Note Duration Durée Note Note duration Durée note Whether note events are shown proportional to duration Si les évènements de note sont affichés proportionnellement à leur durée Note &Color &Couleur Note Note Color Couleur Note Note color Couleur note Whether note events are colored according to pitch Si les évènements de note sont coloriés en accord avec leur hauteur &Value Color &Valeur Couleur Value Color Valeur Couleur Value color Valeur couleur Whether note events are colored according to value (velocity) Si les évènements de note sont coloriés en accord avec le valeur (vélocité) &Events &Evènements View events Voir évènements Show/hide the events list Montrer/Cacher la liste des évènements &Preview Notes &Prévisualisation Notes Preview Notes Prévisualisation Notes Preview notes Prévisualisation notes Preview notes while editing (scrub) Prévisualiser les notes pendant l'édition (scrub) F&ollow Playhead S&uivre la Tête de lecture Follow Playhead Suivre la Tête de lecture Follow playhead Suivre la tête de lecture &In &Entrée Zoom In Zoom Avant Zoom in Zoom avant Ctrl++ Ctrl++ &Out &Sortie Zoom Out Zoom arrière Zoom out Zoom arrière Ctrl+- Ctrl+- &Reset &Réinitialiser Zoom Reset Réinitialiser Zoom Zoom reset Réinitialiser zoom Ctrl+1 Ctrl+1 &Horizontal &Horizontal Horizontal Zoom Zoom Horizontal Horizontal zoom Zoom horizontal Horizontal zoom mode Mode de zoom horizontal &Vertical &Vertical Vertical Zoom Zoom Vertical Vertical zoom Zoom vertical Vertical zoom mode Mode de zoom vertical All Zoom Tout Zoomer All zoom Tout zoomer All zoom mode Mode de zoom total &Zebra &Zèbrures Zebra Zèbrures Bar zebra view mode Mode de visualisation barres zèbrées &Grid &Grille Grid Grille Snap grid view mode Mode de vue capture sur la grille Too&l Tips Info-bu&lles Tool tips Info-bulles Floating tool tips view mode Mode de vue info-bulles flottantes &Refresh &Rafraichier Refresh Rafraichir Refresh views Rafraichir les vues F5 F5 &Backward &Arrière Backward Arrière Transport backward Transport arrière Backspace Backspace Re&wind Re&mbobinner Rewind Rembobinner Transport rewind Transport rembobinner F&ast Forward Av&ance Rapide Fast Forward Avance Rapide Fast forward Avance rapide Transport fast forward Transport avance rapide &Forward A&vance Forward Avance Transport forward Transport avance &Loop Bouc&le Loop Boucle Transport loop Transport boucle Ctrl+Shift+L Ctrl+Shift+L Loop &Set Ré&glage Boucle Loop Set Réglage Boucle Loop set Réglage boucle Transport loop set Transport réglage boucle Ctrl+L Ctrl+L &Stop &Stop Stop Stop Transport stop Transport stop &Play &Jouer Play Jouer Transport play/pause Transport jouer/pause Space Espace &Record &Enregistrer Record Enregistrer Transport record Transport enregistrer &Punch &Punch Punch Punch Punch in/out Punch in/out Transport punch in/out Transport punch in/out Ctrl+Shift+P Ctrl+Shift+P Punch Se&t Réglage Pu&nch Punch Set Réglage Punch Punch in/out set Réglage Punch in/out Transport punch in/out set Transport réglage punch in/out Ctrl+P Ctrl+P Pa&nic Pa&nique Panic Panique All MIDI tracks shut off (panic) Toutes les pistes MIDI éteintes (panique) &Shortcuts... &Raccourcis... Shortcuts Raccourcis Keyboard shortcuts Raccourcis clavier &About... &A propos... About A propos Show information about this application program Afficher des informations à propos de cette application About &Qt... A propos de &Qt... About Qt A propos de Qt Show information about the Qt toolkit Afficher des informations à propos du toolkit Qt Set current snap to %1 Placer l'accrocher courante sur %1 Note On Note On Key Press Touche Appuyée Note Velocity Vélocité Note Controller Contrôleur Pgm Change Changement Pgm Chan Press Can Appuyé Pitch Bend Pitch Bend Sys Ex Sys Ex Snap/beat Capture/Battement Note type Type note Value type Type valeur Controller type Type contrôleur Scale key Clef échelle Scale type Type échelle MIDI clip name Nom du clip MIDI MIDI file name Nom du fichier MIDI MIDI track/channel Piste/Canal MIDI MOD MOD MIDI modification state Etat de modification MIDI 00:00:00.000 00:00:00.000 MIDI clip duration Durée du clip MIDI Warning Attention The current MIDI clip has been changed: "%1" Do you want to save the changes? Le clip MIDI courant a été changé: "%1" Voulez-vous sauvegarder les changements? Save MIDI Clip Sauvegarder le clip MIDI MIDI files (*.%1 *.smf *.midi) Fichiers MIDI (*.%1 *.smf *.midi) MIDI file save: "%1", track-channel: %2. Sauvegarde fichier MIDI: "%1", piste-canal: %2. Channel %1 Canal %1 Track %1 Piste %1 [modified] [modifié] qtractorMidiEventItemDelegate edit %1 éditer %1 qtractorMidiEventList Events Evènements qtractorMidiEventListModel Time Temps Type Type Name Nom Value Valeur Duration/Data Durée/Donnée Frame Trame BBT BBT Note On (%1) Note On (%1) Note Off (%1) Note Off (%1) Key Press (%1) Touche Appuyée (%1) Controller (%1) Contrôleur (%1) Pgm Change Pgm Change Chan Press Can Appuyé Pitch Bend Pitch Bend SysEx SysEx Meta (%1) Méta (%1) Unknown (%1) Inconnu (%1) qtractorMidiListView Name Nom Fmt Fmt Tracks Pistes tpqn tpqn Path Chemin Open MIDI Files Ouvrir Fichiers MIDI MIDI files (*.%1 *.smf *.midi) Fichiers MIDI (*.%1 *.smf *.midi) qtractorMidiMeter Volume (%) Volume (%) % % Pan: %1 Pan: %1 Volume: %1% Volume: %1% qtractorMidiSysexForm MIDI SysEx - Qtractor MIDI SysEx - Qtractor Name Nom Size Taille Data (hex) Donnée (hex) Import from SysEx file Importer à partir d'un fichier SysEx &Import... &Importer... Alt+I Alt+I Export to SysEx file Exporter vers un fichier SysEx E&xport... E&xporter... Alt+X Alt+X Move SysEx item up on list order Déplacer l'élément SysEx vers le haut dans la liste &Up &Haut Alt+U Alt+H Move SysEx item down on list order Déplacer l'élément SysEx vers le bas dans la liste &Down &Bas Alt+D Alt+B Open SysEx Ouvrir SysEx Sysex name Nom SysEx Save SysEx Sauvegarder SysEx Delete SysEx Supprimer SysEx Create SysEx item Créer un élément SysEx &Add &Ajouter Alt+A Alt+A Update SysEx item Mettre à jour un élément SysEx Upda&te Me&ttre à jour Alt+T Alt+T Remove SysEx item Supprimer un élément SysEx &Remove &Supprimer Alt+R Alt+S SysEx files (*.%1) Fichiers SysEx (*.%1) MIDI files (*.mid *.smf *.midi) Fichiers MIDI (*.mid *.smf *.midi) All files (*.*) Tous les fichiers (*.*) Import SysEx Files Importer Fichiers SysEx Export SysEx File Exporter Fichier SysEx Warning Attention The SysEx file already exists: "%1" Do you want to replace it? Le fichier SysEx existe déjà: "%1" Voulez-vous le remplacer? Sysex files (*.%1) Fichiers Sysex (*.%1) About to replace SysEx: "%1" Are you sure? Sur le point de remplacer SysEx: "%1" Etes-vous sur? About to delete SysEx: "%1" Are you sure? Sur le point de supprimer SysEx: "%1" Etes-vous sur? SysEx settings have been changed. Do you want to apply the changes? Les réglages SysEx ont été changés. Voulez-vous appliquer les changements? Error Erreur SysEx could not be loaded: "%1". Sorry. SysEx n'a pas pu être chargé: "%1". Désolé. qtractorMidiToolsForm MIDI Tools Outils MIDI Preset name Nom réglage Save preset Sauvegarder réglage Delete preset Supprimer réglage &Quantize &Quantifier Quantize selected events Quantifier les évènements sélectionnés &Time: &Temps: Quantize time Quantifier temps Quantize time percent Quantifier temps pourcent % % &Duration: &Durée: Quantize duration Quantifier durée Quantize duration percent Quantifier durée pourcent S&wing: F&luctuation: Swing-quantize time Fluctuation-quantifier temps Swing-quantize percent Fluctuation-quantifier pourcent Swing-quantize type Fluctuation-quantifier type Linear Linéaire Quadratic Quadratique Cubic Cubique &Scale: &Echelle: Scale-quantize key Echelle-quantifier clef Scale-quantize type Echelle-quantifier type &Transpose &Transpose Transpose selected events Transpose les évènements sélectionnés &Note: &Note: Transpose note Transposer note Transpose time Transposer temps Transpose time format Transposer format du temps Frames Trames Time Temps BBT BBT &Normalize &normaliser Normalize selected events Normaliser les évènements sélectionnés &Percent: &Pourcent: Normalize percent Normaliser pourcent &Value: &Valeur: Normalize value Normaliser valeur &Randomize &Randomiser Randomize selected events Randomiser les évènements sélectionnés Randomize note/pitch Randomiser note/hauteur Randomize time Randomiser temps Randomize duration Randomiser durée Randomize value Randomiser valeur Resi&ze Redimen&sionner Resize selected events Redimensionner les évènements sélectionnés Resize duration Redimensionner durée Resize duration format Redimensionner format de la durée Percentage Pourcentage Resize value Redimensionner valeur Resize value mode Mode redimensionnement valeur Flat Plat Ramp Rampe Resize final value Redimensionner valeur finale Re&scale R&emettre à l'échelle Rescale selected events Remettre à l'échelle les évènements sélectionnés Rescale time Remettre à l'échelle temps Rescale duration Remettre à l'échelle durée Rescale value Remettre à l'échelle valeur T&imeshift Dé&calage temporel Timeshift selected events Décalage temporel des évènements sélectionnés Timeshift Décalage temporel P: P: Timeshift parameter Paramètre de décalage temporel Timeshift parameter (log) Paramètre de décalage temporel (log) Timeshift curve Courbe de décalage temporel P = 0 : no change. P > 0 : accelerating shift. P < 0 : slowing down shift. Edit head/tail (blue) markers define the shift range. P = 0 : pas de changement. P > 0 : décalage accéléré. P < 0 : décalage ralenti. Editer les marqueurs tête/queue (bleu) pour définir la plage de décalage. Timeshift duration Durée de décalage temporel (default) (défaut) Warning Attention About to delete preset: "%1" Are you sure? Sur le point de supprimé un réglage: "%1" Etes-vous sur? none rien quantize quantifier transpose transposer normalize normaliser randomize randomiser resize redimensionner rescale remise à l'échelle timeshift décaler temporellement qtractorMixer Inputs Entrées Tracks Pistes Outputs Sorties Mixer Mixeur qtractorMixerRack &Inputs &Entrées &Outputs &Sorties &Monitor &Moniteur &Buses... &Bus... qtractorMixerStrip inputs entrées outputs sorties Connect %1 Connecter %1 %1 In %1 Entrée %1 Out %1 Sortie (Audio) (Audio) Gain Gain (MIDI) (MIDI) Volume Volume (None) (Rien) Pan Pan qtractorMonitorButton monitor moniteur Monitor (rec) Moniteur (enr) Monitor (thru) Moniteur (thru) qtractorOptionsForm Options - Qtractor Options - Qtractor &General &Général Session Session Default session &file format: Format de &fichier par défaut de la session: Default session file format (suffix) Format de fichier par défaut de la session (suffixe) Whether to create new sessions based on template Si on doit créer une nouvelle session à partir d'un modèle &New session template: &Nouveau modèle de session: New session template Nouveau modèle de session Browse for new session template Parcourir pour le nouveau modèle de session Whether to save backup versions of existing sessions S'il faut sauvegarder des versions de sessions existantes Save &backup versions of existing sessions Sauver des &versions de sauvegarde de sessions existantes Save &backup versions of existing sessions: Sauver &des versions de sauvegarde de sessions existantes: Which mode to rename existing session files Quel mode pour le renommage de fichiers de session existants Increment previous version (default) Incrémente la version précédente (défaut) Increment current version Incrémente la version courante Options Options Whether to ask for confirmation on removal Si on doit demander une confirmation en cas de suppression &Confirm removals &Confirmer les suppressions Alt+C Alt+C Number of &recent files: Nombre de fichiers &récents: The maximum number of recent files to keep in menu Le nombre maximum de fichiers récent à conserver dans le menu Whether to capture standard output (stdout/stderr) into messages window Si on doit capturer la sortie standard (stdout/stderr) vers la fenêtre de messages Capture standard &output Capturer la s&ortie standard Alt+O Alt+O Whether to show the complete directory path of loaded session files Si ont doit afficher le chemin complet des répertoires des fichiers de session chargés S&how complete path of session files Afficher le c&hemin complet des fichiers de session Alt+P Alt+H Whether to remove audio peak files on session close Si on doit supprimer les fichiers de pic audio lors de la fermeture de session Auto-remove audio pea&k files Auto-supprime les &fichiers pic audio Alt+K Alt+F Whether to keep all tool windows on top of the main window Si on doit conserver toutes les fenêtres d'outils au dessus de la fenêtre principale Keep tool &windows always on top Conser&ver les fenêtres outils toujours au dessus Whether to try dropping multiple audio files into the same track Si on doit essayer de déposer plusieurs fichiers audio dans la même piste &Drop multiple audio files into the same track &Déposer plusieurs fichiers audio dans la même piste Alt+S Alt+D Whether to reverse mouse middle-button role on keyboard modifiers (Shift/Ctrl) Si on doit inverser le rôle du bouton du milieu avec les modificateur clavier (Shift/Ctrl) Re&verse middle-button modifier role (Shift/Ctrl) In&verser le rôle du bouton du milieu avec le modificateur (Shift/Ctrl) Transport Transport Transport &mode: &Mode transport: Transport control mode (JACK) Mode de contrôle du transport (JACK) None Rien Slave Esclave Master Maitre Full Complet &Loop recording mode (takes): Mode d'enregistrement de bouc&les (prises): Loop recording mode (takes) Mode d'enregistrement de boucles (prises) First Première Last Dernière &Audio &Audio Capture / Export Capture / Exporte Audio compression quality to use on capture (record) and export Qualité de compression audio à utiliser lors de la capture (enregistrement) et de l'exportation Audio sample format to use on capture (record) and export Format d'échantillon audio à utiliser lors de la capture (enregistrement) et de l'exportation Audio file type to use on capture (record) and export Type de fichier audio à utiliser lors de la capture (enregistrement) et de l'exportation File &type: &Type de fichier: Sample &format: &Format d'échantillon: &Quality: &Qualité: Playback Jouer Whether to apply time-stretching when tempo changes Si on doit appliquer l'étirement temporel lorsque le tempo change Aut&omatic time-stretching Etirement temporel aut&omatique Sample-&rate converter type: Type de conve&rtisseur de fréquence d'échantillonnage: Sample-rate converter quality Qualité du convertisseur de fréquence d'échantillonnage Sinc (Best Quality) Sinc (Meilleure qualité) Sinc (Medium Quality) Sinc (Qualité moyenne) Sinc (Fastest) Sinc (Rapide) Zero Order Hold Bloqueur d'ordre zéro Linear Linéaire Whether to use WSOLA time-stretching Si on doit utiliser l'étirement temporel WSOLA &WSOLA time-stretching Etirement temporel &WSOLA Alt+W Alt+W Whether to apply WSOLA quick seek time-stretching Si on doit appliquer la recherche rapide WSOLA pour l'étirement temporel WSOLA quic&k seek Rec&herche rapide WSOLA Whether to have separate audition/pre-listening player output ports Si on doit avoir des ports de sortie séparés pour le lecteur audio pour l'audition/pré-écoute Dedicated au&dition/pre-listening player outputs: Sorties dédiées pour le lecteur audio pour l'au&dition/pré-écoute: Alt+D Alt+D Whether to auto-connect dedicated audio player outputs Si on doit auto-connecter les sorties dédiées pour le lecteur audio Auto-&connect Auto-&connecter Metronome Métronome Whether to enable the audio metronome Si on doit activer le métronome audio &Enable audio metronome Activ&er le métronome audio Alt+E Alt+E &File (bar): &Fichier (barre): Metronome Audio filename (bar) Fichier audio métronome (barre) Browse for sample audio file (bar) Parcourir pour le fichier audio échantillon (barre) &Gain (bar): &Gain (barre): Metronome gain (bar) Métronome gain (barre) dB dB &File (beat): &Fichier (battement): Metronome Audio filename (beat) Nom de fichier audio métronome (battement) Browse for sample audio file (beat) Parcourir pour le fichier échantillon audio (battement) &Gain (beat): &Gain (battement): Metronome gain (beat) Métronome gain (battement) Whether to have separate audio metronome output ports Si on doit avoir des ports de sortie audio dédiés pour le métronome Dedicated a&udio metronome outputs: Sorties a&udio métronome dédiées: Alt+U Alt+U Whether to auto-connect dedicated audio metronome outputs Si on doit auto-connecter les sorties audio métronome dédiées Auto-co&nnect Auto-co&nnecter Alt+N Alt+N &MIDI &MIDI File &format: Format de &fichier: MIDI file format to use on capture (record) and export Format de fichier MIDI à utiliser lors de la capture (enregistrement) et l'exportation &Quantize: &Quantifier: MIDI capture (record) quantization Quantification de la capture MIDI (enregistrement) Queue &timer (resolution): File d'attente minu&teur (résolution): Queue timer (resolution) File d'attente minuteur (résolution) Whether to have separate MIDI player output ports Si on doit avoir des ports de sorties séparés pour le lecteur MIDI Dedicated MIDI p&layer outputs Sorties &lecteur MIDI dédiées Alt+L Alt+L Control Contrôle &MMC: &MMC: MIDI Machine Control (MMC) mode Mode de contrôle machine MIDI (MMC) Input Entrée Output Sortie Duplex Duplex &Device: &Périphérique: MIDI Machine Control (MMC) device id. ID du périphérique de contrôle machine MIDI (MMC). &SPP: &SPP: MIDI Song Position pointer (SPP) control mode Mode de contrôle pointeur de position de chanson MIDI (SPP) Cloc&k: Ho&rloge: MIDI Clock control mode Mode de contrôle horloge MIDI Whether to have separate MIDI control ports Si on doit avoir des ports de contrôle MIDI séparés Dedicated MIDI &control input/output Entrée/sortie de &contrôle MIDI dédiée Whether to enable the MIDI metronome Si on doit activer le métronome MIDI &Enable MIDI metronome &Activer le métronome MIDI &Channel: &Canal: Metronome MIDI channel Canal du métronome MIDI &Note (bar): &Note (barre): Metronome MIDI note (bar) Note MIDI métronome (barre) &Velocity (bar): &Vélocité (barre): Metronome MIDI velocity (bar) Vélocité du métronome MIDI (barre) &Duration (bar): &Durée (barre): &Note (beat): &Note (battement): Metronome MIDI note (beat) Note MIDI métronome (battement) &Velocity (beat): &Vélocité (battement): Metronome MIDI velocity (beat) Vélocité MIDI métronome (battement) &Duration (beat): &Durée (battement): Whether to have separate MIDI metronome output port Si on doit avoir un port de sortie MIDI séparé pour le métronome Dedicated M&IDI metronome output Sortie M&IDI métronome dédiée Alt+I Alt+I &Display A&fficher Defaults Défauts &Time display format: Format d'affichage du &temps: Time display format Format d'affichage du temps Frames Trames Time Temps BBT BBT &Base font size: Taille de la police de &base: Base application font size (pt.) Taille de base de la police de l'application (pt.) (default) (défaut) 6 6 7 7 8 8 9 9 10 10 11 11 12 12 Meters Mètres &Audio: &Audio: Audio meter level Niveau audiomètre Over Au delà 0 dB 0 dB 3 dB 3 dB 6 dB 6 dB 10 dB 10 dB Audio meter color Couleur audiomètre Select custom audio meter color Sélectionner une couleur personnalisée pour l'audiomètre ... ... &MIDI: &MIDI: MIDI meter level Niveau MIDImètre Peak Pic MIDI meter color Couleur MIDImètre Select custom MIDI meter color Sélectionner une couleur personnalisée pour le MIDImètre Reset meter colors to default Réinitialiser les couleurs avec les valeurs par défaut &Reset &Réinitialiser Alt+R Alt+R Messages Messages Sample messages text font display Exemple d'affichage des polices de texte des messages Select font for the messages text display Sélectionner une police pour l'affichage du texte des messages &Font... &Police... Alt+F Alt+P Whether to keep a maximum number of lines in the messages window Si on doit conserver un maximum de nombre de lignes dans la fenêtre de messages M&essages limit: Limite des m&essages: Alt+M Alt+M The maximum number of message lines to keep in view Le nombre maximum de lignes de messages à conserver dans la vue lines lignes Logging Enregistrement Messages log file Fichier d'enregistrement des messages Browse for the messages log file location Parcourir pour le fichier d'enregistrement des messages Whether to activate a messages logging to file. Si on doit activer l'enregistrement des messages vers un fichier. Messages &log file: Fichier d'enregis&trement des messages: &Plugins &Greffons Paths Chemins Plugin type Type de greffon Plugin path Chemin greffon Browse plugin path Parcourir le chemin du greffon Add plugin path Ajouter un chemin de greffon &Add &Ajouter Plugin paths Chemins de greffons Remove plugin path Supprimer un chemin de greffon &Remove &Supprimer Move up path Déplacer vers le haut &Up &Haut &Down &Bas &LV2 Presets directory: Répertoire des réglages &LV2: LV2 Presets directory (default: ~/.lv2) Répertoire des réglages LV2 (défaut: ~/.lv2) Browse LV2 Presets directory Parcourir le répertoire des réglages LV2 Instruments Instruments Whether to have separate audio output ports Si on doit avoir des ports audio séparés Dedicated audi&o outputs: Sorties audi&o dédiées: Whether to auto-connect dedicated audio output ports Si on doit auto-connecter les sorties audio dédiées Au&to-connect Au&to-connecter Alt+T Alt+T Editor Editeur Whether to open plugin's editor (GUI) by default Si on doit ouvrir l'éditeur (GUI) du greffon par défaut Open plugin's &editor (GUI) by default Ouvrir l'édit&eur (GUI) du greffon par défaut Alt+G Alt+G Experimental Expérimental Whether to use a dummy plugin type when scanning for VST plugins Si on doit utiliser un type de greffon factice lors du scan des greffons VST Dummy &VST plugin scan (RECOMMENDED) Scan factice des greffons &VST (RECOMMENDE) Alt+V Alt+V Signed 16-Bit 16-Bits signé Signed 24-Bit 24-Bits signé Signed 32-Bit 32-Bits signé Float 32-Bit Flottant 32-Bits Float 64-Bit Flottant 64-Bits SMF Format 0 Format SMF 0 SMF Format 1 Format SMF 1 (Any) (Tout) Warning Attention Some settings have been changed. Do you want to apply the changes? Des réglages ont été changés. Voulez-vous appliquer les changements? Metronome Bar Audio File Fichier audio métronome - Barre Metronome Beat Audio File Fichier audio métronome - Battement Plug-in Directory Répertoire Greffon LV2 Presets Directory Répertoire des réglages LV2 Messages Log Journal des messages Log files (*.%1) Fichiers journal (*.%1) Session Template Modèle de session Session template files (*.qtr *.qts *.%1) Fichiers de modèle de session (*.qtr *.qts *.%1) qtractorPasteRepeatForm Paste Repeat - Qtractor Répéter Coller - Qtractor Repeat Répéter &Count: &Compte: Repeat count Répéter compte &Period: &Période: Repeat period Répéter période Repeat period format Format répétition période Frames Trames Time Temps BBT BBT Warning Attention Some settings have been changed. Do you want to apply the changes? Certains réglages ont été changés. Voulez-vous appliquer les changements? qtractorPluginForm qtractorPluginForm qtractorPluginForm Open preset Ouvrir réglages Preset name Nom du réglage Save preset Savegarder réglages Delete preset Supprimer réglages Plugin parameters Paramètres greffon Params Paramètres Edit plugin Editer greffon Edit Editer Activate plugin Activer greffon Active Activer Outputs (Sends) Sorties (Envois) Sends Envois Inputs (Returns) Entrées (Retours) Returns Retours Aux Send Bus: Bus d'envoie aux: Manage buses Gèrer les bus ... ... Direct Access Parameter Paramètre d'accès direct Direct Access Accès direct (default) (défaut) Page %1 Page %1 (none) (rien) Open Preset Ouvrir réglage Preset files (*.%1) Fichiers réglages (*.%1) Error Erreur Preset could not be loaded from "%1". Sorry. Le réglages ne peut pas être chargé à partir de "%1". Désolé. Save Preset Sauvegarder réglage Warning Attention About to delete preset: "%1" (%2) Are you sure? Sur le point de supprimer le réglage: "%1" (%2) Etes-vous sur? &None &Rien qtractorPluginListView copy plugin copie greffon activate all plugins activer tous les greffons deactivate all plugins désactiver tous les greffons remove all plugins supprimer tous les greffons &Move Here &Déplacer Ici &Copy Here &Copier Ici C&ancel Ab&andon &Add Plugin... &Ajouter Greffon... Add &Insert Ajouter &Insert Add &Aux Send Ajouter Envoie &Auxiliaire &Sends &Envois &Returns &Retours Ac&tivate Ac&tiver Acti&vate All Acti&ver tout Deactivate Al&l Désactiver &tout &Remove &Supprimer Re&move All Suppri&mer tout Move &Up Déplacer vers le &Haut Move &Down Déplacer vers le &Bas &None &Rien &Properties... &Propriétés... &Edit &Editer &Outputs &Sorties &Dedicated &Dédié &Auto-connect &Auto-connecter qtractorPluginSelectForm Plugins - Qtractor Greffons - Qtractor Reset filter Réinitialiser le filtre X X Plugin search string (regular expression) Chaîne de recherche de greffon (expression régulière) Plugin type Type de greffon Available plugins Greffons disponibles Name Nom Audio Audio MIDI MIDI Control Contrôle Modes Modes Path Chemin Index Index Instances Instances Type Type &Activate &Activer Activate plugin on insert Activer le greffon à l'insertion Alt+A Alt+A Plugin scanning in progress... Scan des greffons en cours... GUI GUI EXT EXT RT RT qtractorSessionForm Session - Qtractor Session - Qtractor Session Session &Name: &Nom: Session name Nom de session &Directory: &Répertoire: Session directory Répertoire de session Browse for session directory Parcourir le répertoire de session ... ... &Description: &Description: Session description Description de la session Properties Propriétés Time Temps Sample &Rate: &Fréquence d'échantillonnage: Sample rate (Hz) Fréquence d'échantillonnage (Hz) 44100 44100 48000 48000 96000 96000 192000 192000 &Tempo: &Tempo: Tempo (BPM) / Signature Tempo (BPM) / Signature T&icks/Beat: C&oches/Battement: Resolution (ticks/beat; tpqn) Résolution (coches/battement; tpqn) View Vue &Snap/Beat: &Capture/Battement: Snap/beat Capture/battement &Pixels/Beat: &Pixels/Battement: Pixels/beat Pixels/Battement &Horizontal Zoom: Zoom &Horizontal: Horizontal Zoom (%) Zoom Horizontal (%) % % &Vertical Zoom: Zoom &Vertical: Vertical Zoom (%) Zoom Vertical (%) Warning Attention Session directory does not exist: "%1" Do you want to create it? Le répertoire de session n'existe pas: "%1" Voulez-vous le créer? Some settings have been changed. Do you want to apply the changes? Certains réglages ont été modifiés. Voulez-vous appliquer les changements? Session Directory Répertoire de session qtractorShortcutForm Keyboard Shortcuts Raccourcis Clavier Action Action Description Description Shortcut Raccourci Warning Attention Keyboard shortcut (%1) already assigned. Le raccourci clavier (%1) est déjà affecté. Keyboard shortcuts have been changed. Do you want to apply the changes? Des raccourcis clavier ont été modifiés. Voulez-vous appliquer les changements? qtractorTakeRangeForm Take - Qtractor Prise - Qtractor Range Plage Selection range Plage de sélection &Selection &Sélection Loop range Plage de boucle &Loop &Boucle Punch range Plage de punch &Punch &Punch Time Temps BBT BBT Edit range Plage d'édition &Edit &Edition Custom range Plage personnalisée &Custom &Personalisé St&art: &Début: Clip start Début clip En&d: &Fin: Clip offset Décalage clip Select Sélection Current take Prise courante Format Format Time display format Format d'affichage du temps Frames Trames &Frames &Trames Time (hh:mm:ss.zzz) Temps (hh:mm:ss.zzz) &Time &Temps BBT (bars.beats.ticks) BBT (barres.battements.coches) &BBT &BBT Take %1 Prise %1 qtractorTempoAdjustForm Tempo - Qtractor Tempo - Qtractor Metronome Métronome Temp&o: Temp&o: Tempo/Time signature Tempo/Signature temporelle T&ap T&ape Range Plage &Start: &Début: Range start Plage de départ Time Temps BBT BBT &Length: &Longueur: Range length Longueur de la plage B&eats: Batt&ements: Range beats Plage de battements A&djust A&juster Format Format Time display format Format d'affichage du temps Frames Trames Fra&mes Tra&mes Time (hh:mm:ss.zzz) Temps (hh:mm:ss.zzz) &Time &Temps BBT (bars.beats.ticks) BBT (barres.battements.coches) &BBT &BBT Warning Attention Some settings have been changed. Do you want to apply the changes? Certains réglages ont été modifiés. Voulez-vous appliquer les changements? qtractorThumbView Thumb view Vue vignette qtractorTimeScaleForm Tempo Map - Qtractor Carte de tempo - Qtractor Tempo map Carte de tempo Bar Barre Time Temps Tempo Tempo Node Noeud &Bar: &Barre: Tempo Map / Markers - Qtractor Carte de tempo / marqueurs - Qtractor Tempo map / Markers Carte de Tempo / Marqueurs Marker Marqueur Location Position Bar location Position de la mesure T&ime: T&emps: Bar/Time node Noeud Barre/Temps Time/frame location Position du temps / cadre &Tempo: &Tempo: Tempo (BPM) / Signature Tempo (BPM) / Signature T&ap T&ape Marker text Texte du marqueur ... ... Marker color Couleur du marqueur Refresh tempo map Rafraichir la carte tempo Re&fresh Ra&fraichir Alt+F Alt+F Add node Ajouter un noeud &Add &Ajouter Alt+A Alt+A Update node Mettre à jour un noeud &Update &Mettre à jour Alt+U Alt+M Remove node Supprimer un noeud &Remove &Supprimer Alt+R Alt+S Close this dialog Fermer cette fenêtre Close Fermer Warning Attention Some settings have been changed. Do you want to apply the changes? Certains réglages ont été modifiés. Voulez-vous appliquer les changements? About to remove tempo node: %1 (%2) %3 %4/%5 Are you sure? Sur le point de supprimer un noeud tempo: %1 (%2) %3 %4/%5 Etes-vous sur? Some settings have been changed. Do you want to discard the changes? Certains réglages ont été modifiés. Voulez-vous abandonner ces changements? &Refresh &Rafraichir qtractorTimeSpinBox &Frames T&rames &Time &Temps &BBT &BBT qtractorTrackButton Record Enregistrer Mute Muet Solo Solo qtractorTrackForm Track - Qtractor Piste - Qtractor Track Piste &Name: &Nom: Track name description Description du nom de piste Type Type Audio track type Type piste audio &Audio &Audio Alt+A Alt+A MIDI track type Type piste MIDI &MIDI &MIDI Alt+M Alt+M Input / Output Entrée / Sortie Input bus name Nom du bus d'entrée Output bus name Nom du bus de sortie Manage buses Gérer les bus ... ... MIDI / Instrument MIDI / Instrument &Program: &Programme: &Bank: &Banque: Bank &Select Method: Méthode de &sélection de banque: &Omni &Omni MIDI Omni: Capture All Channels MIDI Omni: Capture tous les canaux Alt+O Alt+O &Channel: &Canal: MIDI Channel (1-16) Canal MIDI (1-16) MIDI Patch: Instrument MIDI Patch: Instrument MIDI Patch: Bank Select Method MIDI Patch: Méthode de sélection de banque MIDI Patch: Bank MIDI Patch: Banque MIDI Patch: Program MIDI Patch: Programme View / Colors Vue / Couleurs &Foreground: &Premier plan: Foreground color Couleur du premier plan Select custom track foreground color Sélectionner une couleur de piste personnalisée pour le premier plan Bac&kground: &Arrière plan: Background color Couleur d'arrière plan Select custom track background color Sélectionner une couleur de piste personnalisée pour l'arrière plan Plugins Greffons Track plugins Greffons Piste Add plugin Ajouter greffon &Add... &Ajouter... Remove plugin Supprimer greffon &Remove &Supprimer Alt+R Alt+S Move plugin up Déplacer le greffon vers le haut &Up &Haut Alt+U Alt+H Move plugin down Déplacer le greffon vers le bas &Down &Bas Alt+D Alt+B Normal Normal Bank MSB Banque MSB Bank LSB Banque LSB Patch Patch Warning Attention Some settings have been changed. Do you want to apply the changes? Des réglages ont été modifiés. Voulez-vous appliquer les changements? (No instrument) (Pas d'instrument) (None) (Rien) qtractorTrackListHeaderModel Nr Nr Track Name Nom de Piste Bus Bus Ch Can Patch Patch Instrument Instrument qtractorTrackTime Play-head Jouer le début Edit-head Editer le début Edit-tail Editer la fin Loop-start Boucle-début Loop-end Boucle-fin Punch-in Punch-in Punch-out Punch-out Start: %1 End: %2 Length: %3 Début: %1 Fin: %2 Longueur: %3 qtractorTrackView Zoom in (horizontal) Zoom avant (horizontal) Zoom out (horizontal) Zoom arrière (horizontal) Zoom in (vertical) Zoom avant (vertical) Zoom out (vertical) Zoom arrière (vertical) Zoom reset Réinitialiser le zoom add clip ajouter un clip Start: %1 End: %2 Length: %3 Début: %1 Fin: %2 Longueur: %3 clip %1 clip %1 fade-in fondu en ouverture fade-out fondu en fermeture clip stretch étirement clip clip resize redimensionnement clip %1 automation %1 automation %1 clip %1 clip move automation déplacer l'automation paste automation coller l'automation cut couper delete supprimer split diviser move clip déplacer clip paste clip coller clip qtractorTracks Tracks Pistes new clip nouveau clip split clip diviser clip clip normalize normaliser clip quantize quantifier transpose transposer normalize normaliser randomize randomiser resize redimensionner rescale remise à l'échelle timeshift décalage temporel clip tool %1 outil clip %1 clip import importer clip Audio file import "%1" on %2 %3. Importation fichier audio"%1" sur %2 %3. Audio file import: "%1". Importation fichier audio: "%1". MIDI file import "%1" track-channel %2 on %3 %4. Importation fichier MIDI "%1" piste-canal %2 sur %3 %4. MIDI file import: "%1", track-channel: %2. Importation fichier MIDI: "%1", piste-canal: %2. clip merge fusionner clip Merge/Export Audio Clip Fusionner/Exporter clip audio Audio files (*.%1) Fichiers audio (*.%1) Audio clip merge/export: "%1" started... Fusion/Exportation du clip audio: "%1" démarrée... Audio clip merge/export: "%1" complete. Fusion/exportation du clip audio: "%1" terminée. Merge/Export MIDI Clip Fusionner/Exporter Clip MIDI MIDI files (*.%1 *.smf *.midi) Fichiers MIDI (*.%1 *.smf *.midi) MIDI clip merge/export: "%1" started... Fusion/Exportation clip MIDI: "%1" démarrée... MIDI clip merge/export: "%1" complete. Fusion/Exportation clip MIDI: "%1" terminée. Insert Range Insérer Plage insert track range Insérer plage de piste Remove Range Enlever Plage insert range Insérer plage remove range enlever plage remove track range enlever la plage de piste Warning Attention About to remove track: "%1" Are you sure? Sur le point de supprimer une piste: "%1" Etes-vous sur? MIDI file import "%1" on %2 %3. Importation fichier MIDI "%1" sur %2 %3. MIDI file import: "%1". Importation fichier MIDI: "%1". qtractor-0.5.11/src/translations/PaxHeaders.10084/qtractor_cs.ts0000644000175000001440000000012312223511102022645 xustar000000000000000027 mtime=1380880962.062114 26 atime=1381134669.15308 30 ctime=1381134669.244080084 qtractor-0.5.11/src/translations/qtractor_cs.ts0000644000175000001440000177554612223511102022165 0ustar00rncbcusers00000000000000 C C C# C# D D D# D# E E F F F# F# G G G# G# A A A# A# B B Acoustic Bass Drum Akustický basový buben Bass Drum 1 Basový buben 1 Side Stick Další paliÄka Acoustic Snare Akustický virblový/malý buben Hand Clap Potlesk Electric Snare Elektrický virblový/malý buben Low Floor Tom Nízký podlahový Tom Closed Hi-Hat ZavÅ™ená hajtka (Äinely ovládané nožním pedálem) High Floor Tom Vysoký podlahový Tom Pedal Hi-Hat Pedálová hajtka (Äinely ovládané nožním pedálem) Low Tom Nízký Tom Open Hi-Hat OtevÅ™ená hajtka (Äinely ovládané nožním pedálem) Low-Mid Tom Nízký-stÅ™ední Tom Hi-Mid Tom Vysoký-stÅ™ední Tom Crash Cymbal 1 Nárazový cymbál 1 High Tom Vysoký Tom Ride Cymbal 1 Jezdící cymbál 1 Chinese Cymbal Čínský cymbál Ride Bell Jezdící zvonek Tambourine Tamburína Splash Cymbal Nápadný cymbál Cowbell Kravský zvonec (i bicí nástroj) Crash Cymbal 2 Nárazový cymbál 2 Vibraslap Vibrující plácání Ride Cymbal 2 Jezdící cymbál 2 Hi Bongo Vysoké bongo (malý bubínek) Low Bongo Nízké bongo (malý bubínek) Mute Hi Conga Ztlumit vysoká konga (vysoký buben, na který se hraje dlanÄ›mi) Open Hi Conga Otevřít vysoká konga (vysoký buben, na který se hraje dlanÄ›mi) Low Conga Nízká konga (nízký buben, na který se hraje dlanÄ›mi) High Timbale Vysoké timbale Low Timbale Nízké timbale High Agogo Vysoké agogo Low Agogo Nízké agogo Cabasa Cabasa Maracas Rumba koule Short Whistle Krátké hvízdnutí Long Whistle Dlouhé hvízdnutí Short Guiro Krátké guiro (perkusní nástroj latinskoamerického původu) Long Guiro Dlouhé guiro (perkusní nástroj latinskoamerického původu) Claves Claves Hi Wood Block Vysoký dÅ™evÄ›ný Å¡palíÄek (Äínský dÅ™evÄ›ný bicí nástroj v podobÄ› dutého Å¡palíku - Å¡tÄ›rbinový buben) Low Wood Block Nízký dÅ™evÄ›ný Å¡palíÄek (Äínský dÅ™evÄ›ný bicí nástroj v podobÄ› dutého Å¡palíku - Å¡tÄ›rbinový buben) Mute Cuica OnÄ›mÄ›lá cuica Open Cuica OtevÅ™ená cuica Mute Triangle OnÄ›mÄ›lý triangl Open Triangle OtevÅ™ený triangl Bank Select (coarse) VýbÄ›r banky (hrubý) Modulation Wheel (coarse) ModulaÄní kolo (hrubé) Breath Controller (coarse) Ovládací spínaÄ dechu (hrubý) Foot Pedal (coarse) Nožní pedál (hrubý) Portamento Time (coarse) Délka trvání portamenta (hrubá) (v nástrojové hÅ™e způsob pÅ™ednesu mezi legátem a stakkátem) Data Entry (coarse) Záznam údajů (hrubý) Volume (coarse) Hlasitost (hrubá) Balance (coarse) Vyvážení (hrubé) Pan Position (coarse) Pozice panorámy (hrubá) Expression (coarse) UmÄ›lecká stránka (hrubá) Effect Control 1 (coarse) Ovládání efektu 1 (hrubé) Effect Control 2 (coarse) Ovládání efektu 2 (hrubé) General Purpose Slider 1 Táhlo sloužící vÅ¡eobecnému úÄelu 1 General Purpose Slider 2 Táhlo sloužící vÅ¡eobecnému úÄelu 2 General Purpose Slider 3 Táhlo sloužící vÅ¡eobecnému úÄelu 3 General Purpose Slider 4 Táhlo sloužící vÅ¡eobecnému úÄelu 4 Bank Select (fine) VýbÄ›r banky (citlivý) Modulation Wheel (fine) ModulaÄní kolo (citlivé) Breath Controller (fine) Dechový ovládací spínaÄ (citlivý) Foot Pedal (fine) Nožní pedál citlivý) Portamento Time (fine) Délka trvání portamenta (citlivá) (v nástrojové hÅ™e způsob pÅ™ednesu mezi legátem a stakkátem) Data Entry (fine) Záznam údajů (citlivý) Volume (fine) Hlasitost (citlivá) Balance (fine) Vyvážení (citlivé) Pan Position (fine) Pozice panorámy (citlivá) Expression (fine) UmÄ›lecká stránka (citlivá) Effect Control 1 (fine) Ovládání efektu 1 (citlivé) Effect Control 2 (fine) Ovládání efektu 2 (citlivé) Hold Pedal (on/off) Držení pedálu (zapnuto/vypnuto) Portamento (on/off) Portamento (zapnuto/vypnuto) Sustenuto Pedal (on/off) Zdrženlivý pedál (sostenuto) (zapnuto/vypnuto) Soft Pedal (on/off) Jemný pedál (zapnuto/vypnuto) Legato Pedal (on/off) Vázaný (legáto) pedál (zapnuto/vypnuto) Hold 2 Pedal (on/off) Držení pedálu 2 (zapnuto/vypnuto) Sound Variation Zvuková variace Sound Timbre Zvukové zabarvení hlasu (témbr) Sound Release Time Doba vyloudÄ›ní zvuku Sound Attack Time Doba zaznÄ›ní zvuku Sound Brightness Jasnost zvuku Sound Control 6 Ovládání zvuku 6 Sound Control 7 Ovládání zvuku 7 Sound Control 8 Ovládání zvuku 8 Sound Control 9 Ovládání zvuku 9 Sound Control 10 Ovládání zvuku 10 General Purpose Button 1 (on/off) TlaÄítko sloužící vÅ¡eobecnému úÄelu 1 (zapnuto/vypnuto) General Purpose Button 2 (on/off) TlaÄítko sloužící vÅ¡eobecnému úÄelu 2 (zapnuto/vypnuto) General Purpose Button 3 (on/off) TlaÄítko sloužící vÅ¡eobecnému úÄelu 3 (zapnuto/vypnuto) General Purpose Button 4 (on/off) TlaÄítko sloužící vÅ¡eobecnému úÄelu 4 (zapnuto/vypnuto) Effects Level Úroveň efektu Tremulo Level Úroveň chvÄ›ní (tremolo) Chorus Level Úroveň refrénu Celeste Level Úroveň celesty (nástroj ponÄ›kud podobný klavíru) Phaser Level Úroveň fáze Data Button Increment Datové tlaÄítko - zvýšení (inkrement) Data Button Decrement Datové tlaÄítko - úbytek (dekrement útlumu) Non-Registered Parameter (fine) Nezapsaná pomocná promÄ›nná (citlivá) Non-Registered Parameter (coarse) Nezapsaná pomocná promÄ›nná (hrubá) Registered Parameter (fine) Zapsaná pomocná promÄ›nná (citlivá) Registered Parameter (coarse) Zapsaná pomocná promÄ›nná (hrubá) All Sound Off VÅ¡echny zvuky vypnuty All Controllers Off VÅ¡echny ovládací spínaÄe vypnuty Local Keyboard (on/off) Místní klávesnice (zapnuta/vypnuta) All Notes Off VÅ¡echny tóny (noty) vypnuty Omni Mode Off Celkový režim: vypnuto Omni Mode On Celkový režim: zapnuto Mono Operation Monofonní operace Poly Operation Polyfonní operace add clip PÅ™idat ukázku clip %1 Ukázka %1 fade-in Postupné zesílení signálu fade-out Postupné slábnutí signálu clip stretch Natáhnout ukázku clip resize ZmÄ›nit velikost ukázky %1 clip %1 ukázka cut Vyjmout delete Smazat move clip PÅ™esunout ukázku paste clip Vložit ukázku QObject Audio: %1 channels, %2 Hz Audio: %1 kanály, %2 Hz (%1 dB) (%1 dB) (%1% time stretch) (%1% natažení Äasu) (%1 semitones pitch shift) (posunutí výšky tónu v půltónech %1) (%1% pitch shift) (%1% posunutí výšky tónu) %1 In %1 Vstup %1 Out %1 Výstup Audio files (%1) Zvukové soubory (%1) All files (*.*) VÅ¡echny soubory (*.*) %1 (%2) %3 channels, %4 frames, %5 Hz %6 %1 (%2) %3 kanály, %4 snímky, %5 Hz %6 Name: %1 Název: %1 Start / End: %1 / %2 Offset / Length: %3 / %4 ZaÄátek/Konec: %1 / %2 Posun/Délka: %3 / %4 (take %1) (zábÄ›r %1) Start / End: %1 / %2 Offs. / Len.: %3 / %4 ZaÄátek/Konec: %1 / %2 Posun/Délka: %3 / %4 Start / End: %1 / %2 Offs. / Length: %3 / %4 ZaÄátek/Konec: %1 / %2 Posun/Délka: %3 / %4 Start/End: %1 / %2 Offs/Length: %3 / %4 ZaÄátek/Konec: %1 / %2 Posun/Délka: %3 / %4 Start: %1 End: %2 Offset: %3 Length: %4 ZaÄátek: %1 Konec: %2 Vyrovnání: %3 Délka: %4 File: %1 Soubor: %1 create bus VytvoÅ™it sbÄ›rnici update bus Zaktualizovat sbÄ›rnici delete bus Smazat sbÄ›rnici bus pass-through Průchodnost sbÄ›rnice bus gain Zesílení sbÄ›rnice bus pan Vyvážení sbÄ›rnice Cakewalk Instrument Definition File Soubor s Cakewalk definicí nástroje File Soubor Date Datum %1 Bank %2 %1 Banka %2 %1 - Bank %2 %1 - Banka %2 (format %1) MIDI: (formát %1) MIDI: Channel %1 Kanál %1 Track %1 Stopa %1 , %1 tracks, %2 tpqn , %1 stopy, %2 tpqn , %1 tracks, %2 tpb , %1 stopy, %2 tpb (%1% vol) (%1% hlasitost) %1 (format %2) %3 tracks, %4 tpb %5 %1 (formát %2) %3 stop, %4 tpb %5 %1 (format %2) %3 tracks, %4 tpqn %5 %1 (formát %2) %3 stop, %4 tpqn %5 %1 (format %2) %3 %1 (formát %2) %3 Usage: %1 [options] [session-file] Užití: %1 [volby] [soubor sezení] Usage: %1 [options] [session-file] Užití: %1 [volby] [soubor sezení] Options: Volby: Set session identification (uuid) Nastavit oznaÄení sezení (uuid) Show help about command line options Ukázat nápovÄ›du k volbám příkazového řádku Show version information Ukázat informaci o verzi Option -s requires an argument (session-id). Volba -s vyžaduje argument (ID sezení). Qt: %1 Qt: %1 (Any) (Jakýkoli) add plugin PÅ™idat přídavný modul add insert PÅ™idat vložku add aux-send PÅ™idat aux-send aux-send bus SbÄ›rnice aux-send remove plugin Odstranit přídavný modul move plugin PÅ™esunout přídavný modul activate plugin Zapnout přídavný modul preset plugin PÅ™ednastavit přídavný modul reset plugin Znovu spustit přídavný modul dedicated audio outputs JednoúÄelové zvukové výstupy direct access param Parametr pro přímý přístup session tempo Tempo sezení session loop SmyÄka sezení session punch ZaÄátek nahrávání sezení session properties Vlastnosti sezení Duplex Duplexní režim Output Výstup Input Vstup None Žádný Beat Rytmus add track PÅ™idat stopu remove track Odstratit stopu move track PÅ™esunout stopu resize track ZmÄ›nit velikost stopy import track Zavést stopu track properties Vlastnosti stopy Track assignment failed: Track: "%1" Input: "%2" Output: "%3" Selhalo pÅ™iÅ™azení k stopÄ›: Stopa: "%1" Vstup: "%2" Výstup: "%3" track record Nahrání stopy track mute Ztlumení stopy track solo Sólo pro stopu track monitor Sledování stopy track gain Zesílení stopy track pan Vyváženost stopy Automation (%1) Automatizace (%1) none Žádná Automation Automatizace Audio Zvuk MIDI MIDI Unknown Neznámý %1 (*.%2) %1 (*.%2) (default) (výchozí) %1 Hz %1 Hz slave Řízený %1 (%2) %1 (%2) add tempo node PÅ™idat uzel s tempem update tempo node Obnovit uzel s tempem remove tempo node Odstranit uzel s tempem move tempo node PÅ™esunout uzel s tempem add marker PÅ™idat znaÄku update marker Obnovit znaÄku remove marker Odstranit znaÄku move marker PÅ™esunout znaÄku %1 Monitor %1 Sledovat Send Gain Poslat zesílení Dry / Wet ZkuÅ¡ební/Ostrý set controller Nastavit ovladaÄ reset controller Nastavit ovladaÄ znovu %1 Record %1 Nahrát %1 Mute %1 Ztlumit %1 Solo %1 Sólo %1 Volume %1 Hlasitost %1 Gain %1 Zesílení %1 Pan %1 Vyvážení (Pan) automation select Automatizace Vybrat automation mode Automatizace Režim automation play Automatizace PÅ™ehrát automation record Automatizace Nahrát automation logarithmic Automatizace Logaritmická automation color Automatizace Barva automation play all Automatizace PÅ™ehrát vÅ¡e automation record all Automatizace Nahrát vÅ¡e automation edit Automatizace Upravit automation clear Automatizace Smazat automation clear all Automatizace Smazat vÅ¡e automation edit list Automatizace Upravit seznam take %1 ZábÄ›r %1 reset takes Nastavit zábÄ›ry znovu insert range Vložit rozsah insert track range Vložit rozsah stopy qtractorAudioListView Name Název Ch Kanál Frames Snímky Rate Frekvence Time ÄŒas Path Cesta Open Audio Files Otevřít zvukové soubory qtractorAudioMeter Gain (dB) Zesílení (dB) dB dB Pan: %1 Vyvážení (Pan): %1 Gain: %1 dB Zesílení: %1 dB qtractorBusForm Audio Zvuk MIDI MIDI Bus SbÄ›rnice Warning UpozornÄ›ní Some settings have been changed. Do you want to apply the changes? NÄ›která nastavení byla zmÄ›nÄ›na. Chcete použít tyto zmÄ›ny? (No instrument) (Žádný nástroj) (none) (Žádný) (1 item) (1 položka) (%1 items) (%1 položky) Apply Použít Discard Vyhodit Cancel ZruÅ¡it About to remove bus: "%1" (%2) Are you sure? Chystáte se odstranit sbÄ›rnici: "%1" (%2) Jste si jistý? OK OK Some settings have been changed. Do you want to discard the changes? NÄ›která nastavení byla zmÄ›nÄ›na. Chcete zahodit tyto zmÄ›ny? &Create &VytvoÅ™it &Update &Zaktualizovat &Remove &Odstranit &Refresh &Obnovit Buses - Qtractor SbÄ›rnice - Qtractor Bus list Seznam sbÄ›rnic Buses SbÄ›rnice Ch Kanál Mode Režim Properties Vlastnosti &Name: &Název: Bus name Název sbÄ›rnice &Mode: &Režim: Bus mode Režim sbÄ›rnice Input Vstup Output Výstup Duplex Duplexní režim Bus monitor (pass-through) Sledování sbÄ›rnice (průchodnost) M&onitor (pass-through) &Pass-through (monitor) &Sledování (průchodnost) Alt+O Alt+P Alt+O Cha&nnels: Ka&nály: Audio channels Zvukové kanály Audio auto-connect Automatické pÅ™ipojení zvuku &Auto connect &PÅ™ipojit automaticky Alt+A Alt+A MIDI Instrument name Název nástroje MIDI MIDI SysEx setup Nastavení MIDI SysEx SysE&x... SysE&x... Input Plugins Vstupní přídavné moduly Input bus plugins Vstupní sbÄ›rnicové přídavné moduly Add input plugin PÅ™idat vstupní přídavný modul &Add... &PÅ™idat... Remove input plugin Odstranit vstupní přídavný modul Alt+R Alt+R Move input plugin up PÅ™esunout vstupní přídavný modul nahoru &Up &Nahoru Alt+U Alt+U Move input plugin down PÅ™esunout vstupní přídavný modul dolů &Down &Dolů Alt+D Alt+D Output Plugins Výstupní přídavné moduly Output bus plugins Výstupní sbÄ›rnicové přídavné moduly Add output plugin PÅ™idat výstupní přídavný modul Remove output plugin Odstranit výstupní přídavný modul Move output plugin up PÅ™esunout výstupní přídavný modul nahoru Move output plugin down PÅ™esunout výstupní přídavný modul dolů Refresh bus list view Obnovit náhled na seznam sbÄ›rnic Create bus VytvoÅ™it sbÄ›rnici Alt+C Alt+C Update bus Zaktualizovat sbÄ›rnici Delete bus Smazat sbÄ›rnici &Delete &Smazat Close this dialog Zavřít tento dialog Close Zavřít qtractorClientListView Readable Clients / Output Ports ÄŒitelní klienti/Výstupní přípojky Writable Clients / Input Ports Zapisovatelní klienti/Vstupní přípojky qtractorClipForm &Gain: &Zesílení: dB dB &Volume: &Hlasitost: % % new clip Nový záznam edit clip Upravit záznam Warning UpozornÄ›ní Some settings have been changed. Do you want to apply the changes? NÄ›která nastavení byla zmÄ›nÄ›na. Chcete použít tyto zmÄ›ny? Apply Použít Discard Vyhodit Cancel ZruÅ¡it Audio Zvuk MIDI MIDI MIDI files (*.%1 *.smf *.midi) Soubory MIDI (*.%1 *.smf *.midi) %1 Clip File %1 Soubor se záznamem Clip - Qtractor Záznam - Qtractor &Name: &Název: Clip name Název záznamu &File: &Soubor: Clip filename Název souboru se záznamem Browse for clip file Procházet pro soubor se záznamem Track/&Channel: Stopa/&Kanál: Clip track/channel Stopa se záznamem/Kanál &Gain/Volume: &Zesílení/Hlasitost: Clip gain/volume Zesílení záznamu/hlasitost Parameters Parametry Clip start ZaÄátek záznamu Clip offset Posun záznamu Clip length Délka záznamu Offs&et: Pos&un: &Length: &Délka: &Start: &ZaÄátek: Gain/Volume Zesílení/Hlasitost Format Formát Time display format Formát zobrazení Äasu Frames Snímky Time ÄŒas BBT TDT (takty-doby-tiky) Fra&mes Sní&mky Time (hh:mm:ss.zzz) ÄŒas (hh:mm:ss.zzz) &Time ÄŒ&as BBT (bars.beats.ticks) TÚT (takty-doby-tiky) &BBT &TDT Fade In/Out Postupné zesílení/zeslabení signálu Fade &In: Postupné &zesílení signálu: Clip fade-in length Délka postupného zesílení signálu záznamu Clip fade-in type Druh postupného zesílení signálu záznamu Linear Lineární Quadratic ÄŒtvercové Cubic Krychlové Fade &Out: Postupné &zeslabení signálu: Clip fade-out length Délka postupného zeslabení signálu záznamu Clip fade-out type Druh postupného zeslabení signálu záznamu Time St&retch: Natažení Äa&su: Clip time-stretch percentage Procentní podíl natažení Äasu záznamu Pitch S&hift: Posunutí výš&ky tónu: Clip pitch-shift in semitones Posunutí výšky tónu záznamu v půltónech semitones Půltóny OK OK qtractorConnect Connect PÅ™ipojit Disconnect Odpojit Disconnect All Odpojit vÅ¡e Refresh Obnovit qtractorConnectForm (All) (vÅ¡e) qtractorConnectTest QTractor - test pÅ™ipojení Audio Zvuk Select output client/ports Vybrat výstupní klienty/přípojky Select input client/ports Vybrat vstupní klienty/přípojky Connect currently selected ports PÅ™ipojit nyní vybrané přípojky &Connect &PÅ™ipojit Alt+C Alt+C Disconnect currently selected ports Odpojit nyní vybrané přípojky &Disconnect &Odpojit Alt+D Alt+D Disconnect all currently connected ports Odpojit vÅ¡echny nyní vybrané přípojky Disconnect &All Odpojit &vÅ¡e Alt+A Alt+A Refresh current connections view Obnovit náhled na nynÄ›jší pÅ™ipojení &Refresh &Obnovit Alt+R Alt+R MIDI MIDI qtractorConnections Connections PÅ™ipojení qtractorCurveButton Automation (%1) Automatizace (%1) none Žádná qtractorEditRangeForm Range - Qtractor Rozsah - Qtractor Range Rozsah Selection range Rozsah výbÄ›ru &Selection &VýbÄ›r Loop range Rozsah smyÄky &Loop &SmyÄka Punch range Rozsah pÅ™epsání &Punch &PÅ™epsání Edit range Rozsah úprav &Edit Ú&pravy Custom range Vlastní rozsah &Custom &Vlastní St&art: Za&Äátek: Clip start ZaÄátek záznamu En&d: Ko&nec: Clip offset Posun záznamu Apply to Loop points in range Použít na body smyÄky v rozsahu L&oop &SmyÄka Apply to Punch In/Out points in range Použít na body zaÄátku/konce pÅ™epsání v rozsahu Pu&nch &PÅ™epsání Mar&kers &ZnaÄky Te&mpo Map &Zobrazení tempa &Format &Formát Time display format Formát zobrazení Äasu Time ÄŒas BBT TDT (takty-doby-tiky) Format Formát Frames Snímky &Frames &Snímky Time (hh:mm:ss.zzz) ÄŒas (hh:mm:ss.zzz) &Time ÄŒ&as &BBT &TDT Options Volby Apply to clips in range Použít na záznamy v rozsahu Cl&ips &Záznamy A&utomation A&utomatizace Apply to Automation nodes in range Použít na uzly automatizace v rozsahu &Automation &Automatizace Apply to Tempo Map nodes in range Použít na uzly zobrazení tempa v rozsahu Apply to location Markers in range Použít na znaÄky umístÄ›ní v rozsahu qtractorExportForm Audio Zvuk MIDI MIDI Export %1 Vyvést %1 Warning UpozornÄ›ní The file already exists: "%1" Do you want to replace it? Soubor již existuje: "%1" Chcete jej nahradit? Replace Nahradit Cancel ZruÅ¡it Audio file export: "%1" started... Vyvedení zvukového souboru: "%1" právÄ› zaÄalo... Audio file export: "%1" complete. Vyvedení zvukového souboru: "%1" je hotovo. Audio file export: "%1" failed. Vyvedení zvukového souboru: "%1" selhalo. MIDI file export: "%1" started... Vyvedení souboru MIDI: "%1" právÄ› zaÄalo... MIDI file export: "%1" complete. Vyvedení souboru MIDI: "%1" je hotovo. MIDI file export: "%1" failed. Vyvedení souboru MIDI: "%1" selhalo. Export %1 File Vyvést %1 soubor %1 files (*.%1) %1 soborů (*.%1) Export - Qtractor Vyvedení - Qtractor &File: &Soubor: Export file name Vyvést název souboru Browse export file name Procházet vyvedeným názvem souboru Range Rozsah Session range Rozsah sezení &Session &Sezení Loop range Rozsah smyÄky &Loop &SmyÄka Punch range Rozsah pÅ™epsání &Punch &PÅ™epsání Edit range Rozsah úprav &Edit &Úprava Custom range Vlastní rozsah &Custom &Vlastní St&art: Za&Äátek: Clip start ZaÄátek záznamu En&d: Ko&nec: Clip offset Posun záznamu Output Výstup Output bus name Název výstupní sbÄ›rnice Time ÄŒas BBT TDT (takty-doby-tiky) Ouput bus name Název výstupní sbÄ›rnice Format Formát Time display format Formát zobrazení Äasu Frames Snímky &Frames &Snímky Time (hh:mm:ss.zzz) ÄŒas (hh:mm:ss.zzz) &Time ÄŒ&as BBT (bars.beats.ticks) TDT (takty-doby-tiky) &BBT &TDT OK OK qtractorFileListView New Group Nová skupina Warning UpozornÄ›ní About to remove %1 file items. Are you sure? Chystáte se odstranit %1 položek souborů: Jste si jistý? OK OK Cancel ZruÅ¡it About to remove %1 file item(s). Are you sure? Chystáte se odstranit %1 položek souborů: Jste si jistý? About to remove %1 item: "%2" Are you sure? Chystáte se odstranit %1 položku: "%2" Jste si jistý? group Skupina file Soubor qtractorFiles Audio Zvuk MIDI MIDI Play file PÅ™ehrát soubor New &Group Nová &skupina Add &Files... PÅ™idat &soubory... Cu&t Vyj&mout &Copy &Kopírovat P&aste V&ložit R&ename P&Å™ejmenovat &Delete &Smazat Play PÅ™ehrát Ctrl+G Ctrl+G Ctrl+F Ctrl+F Ctrl+X Ctrl+X Ctrl+C Ctrl+C Ctrl+V Ctrl+V Ctrl+E Ctrl+E New &Group... Nová &skupina... &Paste &Vložit Re&name &PÅ™ejmenovat &Remove &Odstranit Pla&y PÅ™e&hrát Cl&eanup UdÄ›lat pořá&dek Del Smazat Files Soubory MIDI Files Soubory MIDI Audio Files Zvukové soubory qtractorInstrumentForm Import Instrument Files Zavést soubory s nástroji Instrument files (*.%1 *.sf2 *.midnam) Soubory nástrojů (*.%1 *.sf2 *.midnam)) Instrument files (*.%1) Soubory s nástroji (*.%1) Export Instrument File Vyvést soubor s nástrojem Instrument files (*.%1 *.sf2) Soubory nástrojů (*.%1 *.sf2) Warning UpozornÄ›ní The instrument file already exists: "%1" Do you want to replace it? Soubor nástroje již existuje: "%1" PÅ™ejete si jej nahradit? Replace Nahradit Cancel ZruÅ¡it Instrument settings have been changed. Nastavení nástrojů bylo zmÄ›nÄ›no. Do you want to apply the changes? PÅ™ejete si použít zmÄ›ny? Apply Použít Discard Vyhodit Instrument settings have been changed. Do you want to apply the changes? Nastavení nástrojů byla zmÄ›nÄ›na. Chcete použít tyto zmÄ›ny? Patch Names for Banks Názvy políÄek pro Banky Controller Names = %1 Názvy ovladaÄů = %1 RPN Names = %1 RPN Názvy = %1 NRPN Names = %1 NRPN Názvy = %1 Bank Select Method = %1 Metoda výbÄ›ru zvukové banky = %1 Patch Names Názvy políÄek Note Names Názvy not Controller Names Názvy ovladaÄů RPN Names Názvy RPN NRPN Names Názvy NRPN Bank Select Methods Metody výbÄ›ru zvukové banky %1 = %2 %1 = %2 Based On = %1 Založeno na = %1 Normal Normální Bank MSB Banka MSB Bank LSB Banka LSB Patch PolíÄko Unknown Neznámý Instruments - Qtractor Nástroje - Qtractor Instruments Nástroje Files Soubory Path Cesta Names Názvy Import from instrument file Zavést ze souboru s nástrojem &Import... &Zavést... Alt+I Alt+I Remove instrument file Odstranit soubor s nástrojem &Remove &Odstranit Alt+R Alt+R Move instrument file up on list order Posunout soubor s nástrojem nahoru v seznamu &Up &Nahoru Alt+U Alt+U Move instrument file down on list order PÅ™esunout soubor s nástrojem dolů na seznamu příkazů &Down &Dolů Alt+D Alt+D Reload all instrument files Znovu nahrát vÅ¡echny soubory s nástroji Relo&ad Na&hrát znovu Alt+A Alt+A E&xport... V&yvést... Alt+X Alt+X R&eload Z&novu nahrát Alt+E Alt+E Export to instrument file Vyvést do souboru s nástrojem &Export... &Exportovat... Close this dialog Zavřít tento dialog Close Zavřít qtractorMainForm Current transport time (playhead) NynÄ›jší Äas pÅ™esunu (hrací hlava) Tempo (BPM) Tempo (BPM - doby za minutu) Current time (playhead) NynÄ›jší Äas (hrací hlava) Current tempo (BPM) NynÄ›jší tempo (ÚZM) Snap/beat Zapadnout/doba Track Stopa Current track name Název nynÄ›jší stopy MOD MOD Session modification state Stav úprav bÄ›hem sezení REC NAHRÃT Session record state Stav nahrávání bÄ›hem sezení MUTE ZTLUMIT Session muting state Stav ztlumení bÄ›hem sezení SOLO SÓLO Session soloing state Stav sóla bÄ›hem sezení LOOP SMYÄŒKA Session looping state Stav smyÄky bÄ›hem sezení Session total time Celkový Äas sezení Session sample rate Vzorkovací kmitoÄet bÄ›hem sezení Could not set default session directory: %1 Sorry. Nemohla být nastavena výchozí složka sezení: %1 Promiňte. Ready PÅ™ipraven Session files (*.%1 *.%2 *.%3) Soubory se sezením (*.%1 *.%2 *.%3) Archive files (*.%1) Soubory s archivy (*.%1) Backup session: "%1" as "%2". Zazálohovat sezení: "%1" jako "%2". Could not backup existing session: %1 as %2 Sorry. NepodaÅ™ilo se zazálohovat stávající sezení: %1 jako %2 Promiňte. About to remove archive directory: "%1" Are you sure? Chystáte se odstranit soubor s archivem: "%1") Jste si jistý? The directory already exists: "%1" Do you want to replace it? Adresář již existuje: "%1" Chcete jej nahradit? Opening "%1"... Otevírá se "%1"... Saving "%1"... Ukládá se "%1"... About to clear automation: "%1" Are you sure? Chystáte se odstranit automatizaci: "%1" Jste si jistý? About to clear all automation: "%1" Are you sure? Chystáte se odstranit vÅ¡echnu automatizaci: "%1" Jste si jistý? VeSTige header support enabled. Povolena podpora hlaviÄek VeSTige. LV2 Plug-in UI support disabled. Podpora pro obrazové uživatelské rozhraní přídavných modulů LV2 byla zakázána. LV2 Plug-in UI support (libsuil) disabled. Podpora pro obrazové uživatelské rozhraní přídavných modulů LV2 (libsuil) byla zakázána. LV2 Plug-in MIDI/Atom support disabled. Podpora pro MIDI/Atom přídavných modulů LV2 byla zakázána. LV2 Plug-in Worker/Schedule support disabled. Podpora pro pracovník/rozvrh přídavných modulů LV2 byla zakázána. LV2 Plug-in State support disabled. Podpora pro stav přídavných modulů LV2 byla zakázána. LV2 Plug-in State Files support disabled. Podpora pro soubory stavu přídavných modulů LV2 byla zakázána. LV2 Plug-in Options support disabled. Podpora pro volby přídavných modulů LV2 byla zakázána. LV2 Plug-in Buf-size support disabled. Podpora pro velikost vyrovnávací pamÄ›ti přídavných modulů LV2 byla zakázána. LV2 Plug-in State Files support enabled. (FUBAR) Podpora pro přídavných modulů LV2 stav souborů byla povolena. LV2 Plug-in Programs support disabled. Podpora pro programy přídavných modulů LV2 byla zakázána. LV2 Plug-in Presets support disabled. Podpora pro pÅ™ednastavení přídavných modulů LV2 byla zakázána. LV2 Plug-in Time/position support disabled. Podpora pro Äas/poloha přídavných modulů LV2 byla zakázána. LV2 Plug-in support (libslv2) enabled. (OLD) Podpora pro přídavný modul LV2 (llibslv2) byla povolena. (STARÉ) LV2 Plug-in support (liblilv) enabled. (NEW) Podpora pro přídavný modul LV2 (liblilv) byla povolena. (NOVÉ) LV2 Plug-in UI instantiation support (libsuil) enabled. (NEW) Podpora pro doložení příkladem obrazové uživatelské rozhraní přídavný modul LV2 (libsuil) byla povolena. (NOVÉ) LV2 Plug-in QT4 UI support disabled. Podpora pro obrazové uživatelské rozhraní Qt4 přídavných modulů LV2 byla zakázána. LV2 Plug-in GTK UI support disabled. Podpora pro obrazové uživatelské rozhraní přídavných modulů GTK LV2 byla zakázána. LV2 Plug-in Persist support disabled. Podpora pro pÅ™etrvávání přídavných modulů LV2 byla zakázána. JACK Latency support disabled. Podpora pro prodlevu JACK byla zakázána. NSM support disabled. Podpora pro NSM byla zakázána. &Hold &Držet &Linear &Přímka &Spline &KÅ™ivka Take %1 ZábÄ›r %1 None Žádný The audio engine has been shutdown. Make sure the JACK audio server (jackd) is up and running and then restart session. Provoz zvukového stroje byl zastaven. UjistÄ›te se, že je zvukový server Jack (jackd) spuÅ¡tÄ›n a běží, a potom sezení zaÄnÄ›te znovu. STOP ZASTAVIT PLAY PŘEHRÃT FFWD RYCHLE DOPŘEDU REW PŘETOÄŒIT REC ON NAHRÃVÃNà ZAPNUTO REC OFF NAHRÃVÃNà VYPNUTO RESET NASTAVIT ZNOVU LOCATE %1 NAJÃT %1 SHUTTLE %1 JEZDIT TAM A ZPÄšT %1 STEP %1 INTERVAL %1 TRACK RECORD %1 %2 NAHRÃVAT STOPU %1 %2 TRACK MUTE %1 %2 ZTLUMIT STOPU %1 %2 TRACK SOLO %1 %2 SÓLO PRO STOPU %1 %2 Unknown sub-command Neznámý pod-příkaz Not implemented Neprovedeno MIDI CTL: %1, Channel %2, Param %3, Value %4 MIDI CTL %1, Kanál %2, Parametr %3, Hodnota %4 %1 BPM %1 ÚZM MIDI channel %1, Controller %2, Value %3 MIDI kanál %1, OvladaÄ %2, Hodnota %3 (track %1, gain %2) (stopa %1, zesílení %2) (track %1, panning %2) (stopa %1, vyvažování %2) START SPUSTIT CONTINUE POKRAÄŒOVAT SONGPOS %1 POLOHA V PÃSNI %1 Untitled%1 Bez názvu %1 Untitled Bez názvu New session: "%1". Nové sezení: "%1". Session files (*.%1 *.%2) Soubory se sezeními (*.%1 *.%2) Template files (*.%1) Sobory s pÅ™edlohami (*.%1) Open Session Otevřít sezení Save Session Uložit sezení Warning UpozornÄ›ní The file already exists: "%1" Do you want to replace it? Soubor již existuje: "%1" Chcete jej nahradit? Replace Nahradit Cancel ZruÅ¡it The current session has been changed: "%1" Do you want to save the changes? NynÄ›jší sezení bylo zmÄ›nÄ›no: "%1" Chcete uložit zmÄ›ny? Save Uložit Discard Vyhodit Session closed. Sezení uzavÅ™eno. Session could not be loaded from "%1". Sorry. Sezení nemohlo být nahráno z "%1". Promiňte. Open session: "%1". Otevřít sezení: "%1". Session could not be saved to "%1". Sorry. Sezení nemohlo být uloženo do "%1". Promiňte. Save session: "%1". Uložit sezení: "%1". take range Rozsah zábÄ›ru session Sezení or nebo program programová Information informace Some settings may be only effective next time you start this %1. NÄ›která nastavení mohou být úÄinná teprve, až pÅ™i příštím spuÅ¡tÄ›ní %1. OK OK Version Verze Build Sestavení Debugging option enabled. Povolena volba umožňující hlášení chyb. Set current snap to %1 Nastavit nynÄ›jší zapadnutí na %1 Current time (play-head) NynÄ›jší Äas (hrací hlava) Ogg Vorbis (libvorbis) file support disabled. Podpora pro soubory Ogg Vorbis (libvorbis) byla zakázána. MPEG-1 Audio Layer 3 (libmad) file support disabled. Podpora pro soubory MPEG-1 Audio Layer 3 (libmad) byla zakázána. Sample-rate conversion (libsamplerate) disabled. PÅ™evod vzorkovacího kmitoÄtu (libsamplerate) byl zakázán. Pitch-shifting support (librubberband) disabled. Podpora pro posunutí výšky tónu (librubberband) byla zakázána. OSC service support (liblo) disabled. Podpora pro službu OSC (liblo) byla zakázána. LADSPA Plug-in support disabled. Podpora pro přídavné moduly LADSPA byla zakázána. DSSI Plug-in support disabled. Podpora pro přídavné moduly DSSI byla zakázána. VST Plug-in support disabled. Podpora pro přídavné moduly VST byla zakázána. LV2 Plug-in support disabled. Podpora pro přídavné moduly LV2 byla zakázána. LV2 Plug-in support (libslv2) enabled. (DEPRECATED) Podpora pro přídavný modul LV2 (libslv2) byla povolena. (ODMÃTNUTÉ) LV2 Plug-in support (liblilv) disabled. Podpora přídavných modulů LV2 (liblilv) byla zakázána. LV2 Plug-in UI instantiation support (libsuil) disabled. Podpora pro instanciaci rozhraní přídavných modulů LV2 (libsuil) byla zakázána. LV2 Plug-in MIDI/Event support disabled. Podpora pro MIDI/Události přídavných modulů LV2 byla zakázána. LV2 Plug-in External UI support disabled. Podpora pro obrazové uživatelské rozhraní přídavných modulů LV2 byla zakázána. LV2 Plug-in Save/Restore support disabled. Podpora pro funkci uložit/obnovit přídavných modulů LV2 byla zakázána. JACK Session support disabled. Podpora pro sezení JACK byla zakázána. Website Webová stránka This program is free software; you can redistribute it and/or modify it Tento program je svobodným programovým vybavením. Můžete jej šířit a /nebo upravovat under the terms of the GNU General Public License version 2 or later. za podmínek GNU General Public License verze 2 nebo pozdÄ›jší. About O record clip Nahrát záznam [modified] (upraveno) %1 Hz %1 Hz Session started. Sezení zaÄalo. The original session sample rate (%1 Hz) is not the same of the current audio engine (%2 Hz). Saving and reloading from a new session file is highly recommended. Původní vzorkovací kmitoÄet sezení (%1 Hz) není stejný jako je vzorkovací kmitoÄet nynÄ›jšího zvukového stroje (%2 Hz). Velmi se doporuÄuje uložit sezení a znovu nahrát z nového souboru sezení. The audio/MIDI engine could not be started. Make sure the JACK audio server (jackd) and/or the ALSA Sequencer kernel module (snd-seq-midi) are up and running and then restart the session. Zvukový/MIDI stroj nebyl spuÅ¡tÄ›n. UjistÄ›te se, že jsou zvukový server Jack (jackd) a/nebo spuÅ¡tÄ›ny a běží, a potom sezení zaÄnÄ›te znovu. Error Chyba XRUN(%1 skipped) XRUN(%1 pÅ™eskoÄeno) XRUN(%1): some frames might have been lost. XRUN(%1): nÄ›které snímky mohly být ztraceny. Audio connections change. ZmÄ›na zvukových pÅ™ipojení. MIDI connections change. ZmÄ›na MIDI pÅ™ipojení. Playing ended. PÅ™ehrávání ukonÄeno. Tracks closed. Stopy zavÅ™eny. Playing "%1"... PÅ™ehrává "%1"... &Frames &Snímky &Time ÄŒ&as &BBT &TDT Qtractor Qtractor &Track &Stopa &State &Stav &Navigate &NavádÄ›ní &Move &PÅ™esunout Impor&t Tracks Zavés&t stopy E&xport Tracks Vy&vést stopy &View &Pohled &Toolbars &Nástrojové liÅ¡ty &Windows &Okna &Zoom &PÅ™iblížit S&nap PÅ™i&chytit T&ransport PÅ™e&sun &Help &NápovÄ›da &Edit &Úpravy Select &Mode Vybrat &režim &Select &Vybrat Mo&ve &PÅ™esunout &Height &Výška M&ode Reži&m A&utomation A&utomatizace T&ools &Nástroje Cl&ip Záznam &File &Soubor Open &Recent Otevřít &nedávné &New &Nový New Nový New session Nové sezení New session file Nový soubor se sezením Ctrl+N Ctrl+N &Open... &Otevřít... Open Otevřít Open session Otevřít sezení Open session from file Otevřít sezení ze souboru Ctrl+O Ctrl+O &Save &Uložit Save session Uložit sezení Save session to file Uložit sezení do souboru Ctrl+S Ctrl+S Save &As... Uložit &jako... Save As Uložit jako Save as Uložit jako Save current session with another file name Uložit nynÄ›jší sezení pod jiným názvem souboru &Properties... Vlastnosti&... Session Properties Vlastnosti sezení Session properties Vlastnosti sezení Edit current session properties Upravit nynÄ›jší vlastnosti sezení F2 F2 E&xit U&konÄit Exit UkonÄit Exit this application program UkonÄit tento program &Undo &Vrátit zpÄ›t Undo Vrátit zpÄ›t Undo last action Vrátit zpÄ›t poslední krok Ctrl+Z Ctrl+Z &Redo &UdÄ›lat znovu Redo UdÄ›lat znovu Redo last action UdÄ›lat znovu poslední krok Ctrl+Shift+Z Ctrl+Shift+Z Cu&t Vyjmou&t Cut Vyjmout Cut selection to clipboard Vyjmout výbÄ›r do schránky Ctrl+X Ctrl+X &Copy &Kopírovat Copy Kopírovat Copy selection to clipboard Kopírovat výbÄ›r do schránky Ctrl+C Ctrl+C &Paste &Vložit Paste Vložit Paste clipboard contents Vložit obsah schránky Ctrl+V Ctrl+V Past&e Repeat... Opakovat krok vlo&žit... Paste Repeat Opakovat krok vložit Paste repeat Opakovat krok vložit Paste/repeat clipboard contents Vložit/opakovat obsah schránky Ctrl+Shift+V Ctrl+Shift+V &Delete &Smazat Delete Smazat Delete selection Smazat výbÄ›r Del Smazat &Clip &Záznam Clip Záznam Select clip Vybrat záznam Clip selection mode Režim výbÄ›ru záznamu &Range &Rozsah Range Rozsah Select range Vybrat rozsah Range selection mode Režim rozsahu výbÄ›ru R&ectangle O&bdélníkový Rect Obdélníkový Select rectangle Vybrat obdélník Rectangular selection mode Režim obdélníkového výbÄ›ru &Automation &Automatizace Automation Automatizace Automation edit mode Režim úprav automatizace &None &Žádný Select None Žádný výbÄ›r Select none Žádný výbÄ›r Mark all as unselected OznaÄit vÅ¡e jako nevybrané Ctrl+Shift+A Ctrl+Shift+A &Invert &Obrátit Select Invert Obrátit výbÄ›r Select invert Obrátit výbÄ›r Invert selection Obrátit výbÄ›r Ctrl+I Ctrl+I Select Range Vybrat rozsah Mark range as selected OznaÄit rozsah jako vybraný Ctrl+R Ctrl+R Select Track Vybrat stopu Select track Vybrat stopu Mark track as selected OznaÄit stopu jako vybranou Ctrl+T Ctrl+T Trac&k Range Rozsah &stopy Select Track Range Vybrat rozsah stopy Select track range Vybrat rozsah stopy Mark track range as selected OznaÄit rozsah stopy jako vybraný Ctrl+Shift+R Ctrl+Shift+R &All &VÅ¡e Select All Vybrat vÅ¡e Select all Vybrat vÅ¡e Mark all as selected OznaÄit vÅ¡e jako vybrané Ctrl+A Ctrl+A &New... &Nový... New Clip Nový záznam New clip Nový záznam Create new clip VytvoÅ™it nový záznam &Edit... &Upravit... Edit Clip Upravit záznam Edit clip Upravit záznam Edit current clip Upravit nynÄ›jší záznam F4 F4 &Split &RozdÄ›lit Split Clip RozdÄ›lit záznam Split clip RozdÄ›lit záznam Split current clip at playhead RozdÄ›lit nynÄ›jší záznam v místÄ› hrací hlavy Nor&malize No&rmalizovat &Merge... &SlouÄit... Merge Clips SlouÄit záznamy Merge clips SlouÄit záznamy Merge selected clips SlouÄit vybrané záznamy N&ormalize &Normalizovat Normalize Clip Normalizovat záznam Normalize clip Normalizovat záznam Normalize current clip (gain/volume) Normalizovat nynÄ›jší záznam (zesílení/hlasitost) &Quantize &Kvantizovat Quantize Clip Kvantizovat záznam Quantize clip Kvantizovat ukázku Quantize current MIDI clip (snap to beat) Kvantizovat nynÄ›jší MIDI ukázku (zapadnout do doby) &Quantize... &Kvantizovat... Quantize clip events Kvantizovat události záznamu Quantize current MIDI clip events Kvantizovat události nynÄ›jšího záznamu MIDI &Transpose... &PÅ™evést... Transpose Clip PÅ™evést záznam Transpose clip events PÅ™evést události záznamu Transpose current MIDI clip events PÅ™evést události nynÄ›jšího záznamu MIDI &Normalize... &Normalizovat... Normalize clip events Normalizovat události záznamu Normalize current MIDI clip events Normalizovat události nynÄ›jšího záznamu MIDI &Randomize... &NáhodnÄ› vybrat... Randomize Clip NáhodnÄ› vybrat záznam Randomize clip events NáhodnÄ› vybrat události záznamu Randomize current MIDI clip events NáhodnÄ› vybrat události nynÄ›jšího záznamu MIDI Resi&ze... ZmÄ›&nit velikost... Resize Clip ZmÄ›nit velikost záznamu Resize clip events ZmÄ›nit velikost událostí záznamu Resize current MIDI clip events ZmÄ›nit velikost událostí nynÄ›jšího záznamu MIDI Re&scale... ZmÄ›nit &měřítko... Rescale Clip ZmÄ›nit měřítko záznamu Rescale clip events ZmÄ›nit měřítko událostí záznamu Rescale current MIDI clip events ZmÄ›nit měřítko událostí nynÄ›jšího záznamu MIDI T&imeshift... ÄŒa&sovÄ› posunout... Timeshift Clip ÄŒasovÄ› posunout záznam Timeshift clip events ÄŒasovÄ› posunout události záznamu Timeshift current MIDI clip events ÄŒasovÄ› posunout události nynÄ›jšího záznamu MIDI &Tempo... &Tempo... Tempo Adjust Úprava tempa Adjust session tempo from current clip selection Upravit tempo sezení podle nynÄ›jšího výbÄ›ru záznamu F7 F7 &Range Set Nastavení &rozsahu Clip Range Rozsah záznamu Clip range Rozsah záznamu Set edit-range from current clip extents Nastavit rozsah úprav z rozsahu nynÄ›jšího záznamu &Loop Set Nastavení &smyÄky Clip Loop SmyÄka záznamu Clip loop SmyÄka záznamu Set loop-range from current clip extents Nastavit rozsah smyÄky z rozsahu nynÄ›jšího záznamu &Import... &Zavést... Import Clip Zavést záznam Import clip Zavést záznam Import clip from file(s) Zavést záznam ze souboru(ů) E&xport... V&yvést... Export Clip Vyvést záznam Export clip Vyvést záznam Export current clip to file Vyvést nynÄ›jší záznam do souboru &Add Track... &PÅ™idat stopu... Add Track PÅ™idat stopu Add track PÅ™idat stopu Add a new track to session PÅ™idat novou stopu do sezení Shift+Ins Shift+Ins &Remove Track &Odstranit stopu Remove Track Odstranit stopu Remove track Odstranit stopu Remove current track from session Odstranit nynÄ›jší stopu ze sezení Shift+Del Shift+Del Track &Properties... Vlastnosti &stopy... Track Properties Vlastnosti stopy Track properties Vlastnosti stopy Edit current track properties Upravit vlastnosti nynÄ›jší stopy Shift+F2 Shift+F2 &Inputs &Vstupy Track Inputs Vstupy stop Track inputs Vstupy stop Show current track input bus connections Ukázat pÅ™ipojení vstupní sbÄ›rnice nynÄ›jší stopy &Outputs &Výstupy Track Outputs Výstupy stop Track outputs Výstupy stop Show current track output bus connections Ukázat pÅ™ipojení výstupní sbÄ›rnice nynÄ›jší stopy &Record &Nahrávat Record Track Nahrávat stopu Record track Nahrávat stopu Arm current track for recording Zapnout nynÄ›jší stopu pro nahrávání &Mute &Ztlumit Mute Track Ztlumit stopu Mute track Ztlumit stopu Mute current track Ztlumit nynÄ›jší stopu &Solo &Sólo Solo Track Sólo stopy Solo track Sólo stopy Solo current track Sólo nynÄ›jší stopy M&onitor S&ledovat Monitor Track Sledovat stopu Monitor track Sledovat stopu Monitor current track Sledovat nynÄ›jší stopu &First &První First Track První stopa First track První stopa Make current the first track UdÄ›lat z nynÄ›jší stopy první stopu &Previous &PÅ™edchozí Previous Track PÅ™edchozí stopa Previous track PÅ™edchozí stopa Make current the previous track UdÄ›lat z nynÄ›jší stopy pÅ™edchozí stopu &Next &Další Next Track Další stopa Next track Další stopa Make current the next track UdÄ›lat z nynÄ›jší stopy další stopu &Last &Poslední Last Track Poslední stopa Last track Poslední stopa Make current the last track UdÄ›lat z nynÄ›jší stopy poslední stopu N&one Žá&dná None Track Žádná stopa None track Žádná stopa None current track Žádná nynÄ›jší stopa &Top &Ç“plnÄ› nahoru Move Top PÅ™esunout úplnÄ› nahoru Move top PÅ™esunout úplnÄ› nahoru Move current track to top PÅ™esunout nynÄ›jší stopu úplnÄ› nahoru &Up &Nahoru Move Up Posunout nahoru Move up Posunout nahoru Move current track up PÅ™esunout nynÄ›jší stopu nahoru &Down &Dolů Move Down Posunout dolů Move down Posunout dolů Move current track down PÅ™esunout nynÄ›jší stopu dolů &Bottom &Ç“plnÄ› dolů Move Bottom PÅ™esunout úplnÄ› dolů Move bottom PÅ™esunout úplnÄ› dolů Move current track to bottom PÅ™esunout nynÄ›jší stopu úplnÄ› dolů A&uto Monitor A&utomaticky sledovat Auto Monitor Automaticky sledovat Auto monitor Automaticky sledovat Auto-monitor current track Automaticky sledovat nynÄ›jší stopu F6 F6 &Audio... &Zvuk... Inport Audio File Zavést zvukový soubor Import Audio file Zavést zvukový soubor Import tracks from Audio file Zavést stopy ze zvukového souboru &MIDI... &MIDI... Import MIDI File Zavést soubor MIDI Import MIDI file Zavést soubor MIDI Import tracks from MIDI file Zavést stopy z MIDI souboru Export Audio File Vyvést zvukový soubor Export Audio file Vyvést zvukový soubor Export tracks to Audio file Vyvést stopy do zvukového souboru Export MIDI File Vyvést jako soubor MIDI Export MIDI file Vyvést jako soubor MIDI Export tracks to MIDI file Vyvést stopy do souboru MIDI First Take První zábÄ›r First take První zábÄ›r Select current clip first take Vybrat první zábÄ›r nynÄ›jšího záznamu Previous Take PÅ™edchozí zábÄ›r Previous take PÅ™edchozí zábÄ›r Select current clip previous take Vybrat pÅ™edchozí zábÄ›r nynÄ›jšího záznamu Next Take Další zábÄ›r Next take Další zábÄ›r Select current clip next take Vybrat další zábÄ›r nynÄ›jšího záznamu Last Take Poslední zábÄ›r Last take Poslední zábÄ›r Select current clip last take Vybrat poslední zábÄ›r nynÄ›jšího záznamu Reset Takes Nastavit zábÄ›ry znovu Reset takes Nastavit zábÄ›ry znovu Reset (unfold) current clip takes Nastavit znovu (zruÅ¡it složení) zábÄ›ry nynÄ›jšího záznamu Range (fold) current clip into takes Řadit (složit) nynÄ›jší záznam do zábÄ›rů &Menubar &Hlavní nabídka Menubar Hlavní nabídka Show/hide the main program window menubar Ukázat/Skrýt pruh se seznamy nabídek v hlavním oknÄ› programu Ctrl+M Ctrl+M &Statusbar &Stavový řádek Statusbar Stavový řádek Show/hide the main program window statusbar Ukázat/Skrýt stavový řádek v hlavním oknÄ› programu File Toolbar Nástrojový pruh pro soubor File toolbar Nástrojový pruh pro soubor Show/hide main program window file toolbar Ukázat/Skrýt nástrojový pruh pro soubor v hlavním oknÄ› programu Edit Toolbar Nástrojový pruh pro úpravy Edit toolbar Nástrojový pruh pro úpravy Show/hide main program window edit toolbar UkázatSkrýt nástrojový pruh pro úpravy v hlavním oknÄ› programu Track Toolbar Nástrojový pruh pro stopy Track toolbar Nástrojový pruh pro stopy Show/hide main program window track toolbar Ukázat/Skrýt nástrojový pruh pro stopy v hlavním oknÄ› programu View Toolbar Nástrojový pruh pro pohled View toolbar Nástrojový pruh pro pohled Show/hide main program window view toolbar Ukázat/Skrýt nástrojový pruh pro pohled v hlavním oknÄ› programu &Options &Volby Options Toolbar Nástrojový pruh pro volby Options toolbar Nástrojový pruh pro volby Show/hide main program window options toolbar Ukázat/Skrýt nástrojový pruh pro volby v hlavním oknÄ› programu Transport Toolbar Nástrojový pruh pro pÅ™esuny Transport toolbar Nástrojový pruh pro pÅ™esuny Show/hide main program window transport toolbar Ukázat/Skrýt nástrojový pruh pro pÅ™esuny v hlavním oknÄ› programu T&ime ÄŒ&as Time Toolbar Nástrojový pruh pro Äas Time toolbar Nástrojový pruh pro Äas Show/hide main program window time toolbar Ukázat/Skrýt nástrojový pruh pro Äas v hlavním oknÄ› programu Thum&b Ná&hled Thumb Toolbar Nástrojový pruh pro náhled Thumb toolbar Nástrojový pruh pro náhled Show/hide main program window thumb toolbar Ukázat/Skrýt nástrojový pruh pro náhled v hlavním oknÄ› programu &Files &Soubory Files Soubory Show/hide the files window Ukázat/Skrýt okno se soubory M&essages Z&právy Messages Zprávy Show/hide the messages window Ukázat/Skrýt okno se vzkazy &Connections &PÅ™ipojení Connections PÅ™ipojení Show/hide the connections window Ukázat/Skrýt okno s pÅ™ipojením F8 F8 Mi&xer Mix&ážní pult Mixer Mixážní pult Show/hide the mixer window Ukázat/Skrýt okno s mixážním pultem F9 F9 &In &PÅ™iblížit Zoom In PÅ™iblížit Zoom in PÅ™iblížit Ctrl++ Ctrl++ &Out &Oddálit Zoom Out Oddálit Zoom out Oddálit Ctrl+- Ctrl+- &Reset &Nastavit znovu &Unlink &ZruÅ¡it odkaz Unlink Clip Odpojit záznam Unlink clip Odpojit záznam Unlink current clip Odpojit nynÄ›jší záznam &Increase &Zvýšit I&nsert &Vložit Remo&ve &Odstranit Ta&ke Zá&bÄ›r &Range... &Rozsah... Remove Range Odstranit rozsah Remove range Odstranit rozsah Remove range as selected Odstranit rozsah jako vybraný Ctrl+Del Ctrl+Delete Remove Track Range Odstranit rozsah stopy Remove track range Odstranit rozsah stopy Remove track range as selected Odstranit rozsah stopy jako vybraný Ctrl+Shift+Del Ctrl+Shift+Del Insert Range Vložit rozsah Insert range Vložit rozsah Insert range as selected Vložit rozsah jako vybraný Ctrl+Ins Ctrl+Ins Insert Track Range Vložit rozsah stopy Insert track range Vložit rozsah stopy Insert track range as selected Vložit rozsah stopy jako vybraný Ctrl+Shift+Ins Ctrl+Shift+Ins Sp&lit &RozdÄ›lit Split Selection RozdÄ›lit výbÄ›r Split selection RozdÄ›lit výbÄ›r Split current selection RozdÄ›lit nynÄ›jší výbÄ›r Ctrl+Y Ctrl+Y Increase Height Zvýšit výšku Increase height Zvýšit výšku Increase track height Zvýšit výšku stopy Ctrl+Shift++ Ctrl+Shift++ &Decrease &Snížit Decrease Height Snížit výšku Decrease height Snížit výšku Decrease track height Snížit výšku stopy Ctrl+Shift+- Ctrl+Shift+- Height Reset Nastavení výšky znovu Height reset Nastavení výšky znovu Reset track height Nastavit znovu výšku stopy Ctrl+Shift+1 Ctrl+Shift+1 Auto &Monitor Automatické sledování Log&arithmic &Logaritmický Automation logarithmic Automatizace Logaritmická Automation curve logarithmic scale Logaritmická stupnice kÅ™ivky automatizace C&olor... Ba&rva... Automation color Barva automatizace Automation curve color Barva kÅ™ivky automatizace &Lock &Zamknout Automation lock Automatizace zamknout Lock automation curve Zamknout kÅ™ivku automatizace Automation playback Automatizace pÅ™ehrát Playback automation curve PÅ™ehrát kÅ™ivku automatizace Automation record Automatizace nahrát Record automation curve Nahrát kÅ™ivku automatizace &Clear &Smazat Automation clear Automatizace smazat Clear automation curve Smazat kÅ™ivku automatizace Loc&k All Zam&knout vÅ¡e Automation lock all Automatizace zamknout vÅ¡e Lock all automation curves Zamknout vÅ¡echny kÅ™ivky automatizace Play &All PÅ™ehrát &vÅ¡e Automation playback all Automatizace pÅ™ehrát vÅ¡e Playback all automation curves PÅ™ehrát vÅ¡echny kÅ™ivky automatizace Rec&ord All Nah&rát vÅ¡e Automation record all Automatizace nahrát vÅ¡e Record all automation curves Nahrát vÅ¡echny kÅ™ivky automatizace C&lear All S&mazat vÅ¡e Automation clear all Automatizace smazat vÅ¡e Clear all automation curves Smazat vÅ¡echny kÅ™ivky automatizace Shift+T Shift+T R&ange... &Rozsah... Take Range Rozsah zábÄ›ru Take range Rozsah zábÄ›ru Zoom Reset Nastavit znovu zvÄ›tÅ¡ení Zoom reset Nastavit znovu zvÄ›tÅ¡ení Ctrl+1 Ctrl+1 &Horizontal &Vodorovné Horizontal Zoom Vodorovné zvÄ›tÅ¡ení Horizontal zoom Vodorovné zvÄ›tÅ¡ení Horizontal zoom mode Režim vodorovného zvÄ›tÅ¡ení &Vertical &Svislé Vertical Zoom Svislé zvÄ›tÅ¡ení Vertical zoom Svislé zvÄ›tÅ¡ení Vertical zoom mode Režim svislého zvÄ›tÅ¡ení All Zoom ZvÄ›tÅ¡it vÅ¡e All zoom ZvÄ›tÅ¡it vÅ¡e All zoom mode Režim zvÄ›tÅ¡ení vÅ¡eho &Grid &Mřížka Grid Mřížka Snap grid view mode Pohledový režim se zapadáváním do mřížky &Zebra &Zebra Zebra Zebra Bar zebra view mode Pohledový režim se zebrovými pruhy Too&l Tips Rady k &nástrojům Tool tips Rady k nástrojům Floating tool tips view mode Pohledový režim s plovoucími radami k nástrojům &Refresh &Obnovit Refresh Obnovit Refresh views Obnovit náhledy F5 F5 &Instruments... &Nástroje... Instruments Nástroje Change instrument definitions and files ZmÄ›nit vymezení nástrojů a souborů &Controllers... &OvladaÄe... Controllers OvladaÄe Change MIDI controllers configuration ZmÄ›nit nastavení ovladaÄů MIDI &Buses... &SbÄ›rnice... Buses SbÄ›rnice Change session bus definitions ZmÄ›nit vymezení sbÄ›rnice sezení Tempo M&ap... &Zobrazení tempa... Tempo Map Zobrazení tempa Tempo map Zobrazení tempa Change session tempo map ZmÄ›nit zobrazení tempa sezení &Options... &Volby... Options Volby Change general application program options ZmÄ›nit vÅ¡eobecné programové volby aplikace F12 F12 &Backward &ZpÄ›t Backward ZpÄ›t Transport backward PÅ™ehrávat zpÄ›t Backspace Posunout o znak zpÄ›t Re&wind PÅ™e&toÄit Rewind PÅ™etoÄit Transport rewind PÅ™ehrávat pÅ™etoÄení F&ast Forward R&ychle dopÅ™edu Fast Forward Rychle dopÅ™edu Fast forward Rychle dopÅ™edu Transport fast forward PÅ™ehrávat rychle dopÅ™edu &Forward &DopÅ™edu Forward DopÅ™edu Transport forward PÅ™ehrávat dopÅ™edu &Loop &SmyÄka Loop SmyÄka Transport loop SmyÄka pÅ™ehrávání Ctrl+Shift+L Ctrl+Shift+L Ctrl+Shift+P Ctrl+Shift+P Pa&nic &Nouzové zastavení Shift+Ctrl+L Shift+Ctrl+L Loop &Set Nastavení &smyÄky Loop Set Nastavení smyÄky Loop set Nastavení smyÄky Transport loop set Nastavení smyÄky pÅ™ehrávání Ctrl+L Ctrl+L &Stop &Zastavit Stop Zastavit Transport stop Zastavení pÅ™ehrávání &Play &PÅ™ehrát Tempo M&ap / Markers... &Rozvržení tempa/ZnaÄky... Tempo Map / Markers Rozvržení tempa/ZnaÄky Tempo map / markers Rozvržení tempa/ZnaÄky Change session tempo map / markers ZmÄ›nit rozvržení tempa sezení/znaÄky Play PÅ™ehrát Transport play/pause PÅ™ehrávání/pozastavení pÅ™ehrávání Space Mezerník Record Nahrát Transport record Náhrávání pÅ™ehrávání &Punch &PÅ™epsat Punch PÅ™epsat Punch in/out ZaÄátek/Konec pÅ™episu Transport punch in/out ZaÄátek/Konec pÅ™episu pÅ™ehrávání Shift+Ctrl+P Shift+Ctrl+P Punch Se&t Nastavení &pÅ™episu Punch Set Nastavení pÅ™episu Punch in/out set Nastavení zaÄátku/konce pÅ™episu Transport punch in/out set Nastavení zaÄátku/konce pÅ™episu pÅ™ehrávání Ctrl+P Ctrl+P &Metronome &Metronom Metronome Metronom F&ollow Playhead N&ásledovat hrací hlavu Follow Playhead Následovat hrací hlavu Follow playhead Následovat hrací hlavu A&uto Backward A&utomaticky zpÄ›t Auto Backward Automaticky zpÄ›t Auto backward Automaticky zpÄ›t &Continue Past End &PokraÄovat po konec Continue Past End PokraÄovat po konec Continue past end PokraÄovat po konec Panic Nouzové zastavení All MIDI tracks shut off (panic) Vypnout vÅ¡echny stopy MIDI (nouzové zastavení) &Shortcuts... &Zkratky... Shortcuts Zkratky Keyboard shortcuts Klávesové zkratky &About... &O... Show information about this application program Ukázat informaci o tomto programu About &Qt... O &Qt... About Qt O Qt Show information about the Qt toolkit Ukázat informaci o sadÄ› softwarových nástrojů Qt qtractorMessages Messages Vzkazy Logging stopped --- %1 --- Zapisování vzkazů bylo zastaveno --- %1 --- Logging started --- %1 --- Zapisování vzkazů zaÄalo --- %1 --- qtractorMeter Pan Vyvážení Gain Zesílení MIDI Controller... OvladaÄ MIDI... qtractorMidiControlButton MIDI Controller... OvladaÄ MIDI... qtractorMidiControlForm Controllers - Qtractor OvladaÄe - Qtractor Controller files Soubory s ovladaÄi Files Soubory Path Cesta Import controller files Zavést soubory s ovladaÄi &Import... &Zavést... Alt+I Alt+I Remove controller file Odstranit soubor s ovladaÄem &Remove &Odstranit Alt+R Alt+R Move controller file up on list order Posunout soubor s ovladaÄem nahoru v seznamu &Up &Nahoru Alt+U Alt+U Move controller file down on list order Posunout soubor s ovladaÄem dolů v seznamu &Down &Dolů Alt+D Alt+D C&hannel &Kanál &Controller &OvladaÄ C&ommand Pří&kaz &Parameter &Parametr MIDI Channel Kanál MIDI MIDI Controller OvladaÄ MIDI Command action Krok příkazu Command parameter Parametr příkazu Command feedback ZpÄ›tná vazba příkazu &Feedback &ZpÄ›tná vazba Map/update controller command PÅ™iÅ™adit/Obnovit příkaz pro ovladaÄ &Map &PÅ™iÅ™adit Alt+M Alt+M Controller map Zobrazení ovladaÄe Channel Kanál Controller OvladaÄ Command Příkaz Parameter Parametr &Type &Typ &Channel &Kanál Trac&k Offset Posun &stopy MIDI Event type Typ události MIDI MIDI Controller (parameter) OvladaÄ MIDI (parametr) MIDI parameter (track offset) Parameter MIDI (posun stopy) + + Track offset Posun stopy Type Typ Track Stopa Feedback ZpÄ›tná vazba Unmap/remove controller command ZruÅ¡it pÅ™iÅ™azení/Odstranit příkaz pro ovladaÄ U&nmap Zr&uÅ¡it pÅ™iÅ™azení Alt+N Alt+N Reload/apply all controller files Nahrát znovu/Použít vÅ¡echny soubory s ovladaÄi Relo&ad Na&hrát znovu Alt+A Alt+A Export to controller file Vyvést do souboru s ovladaÄem E&xport... V&yvést... Alt+X Alt+X Close this dialog Zavřít tento dialog Close Zavřít Import Controller Files Zavést soubory s ovladaÄi Controller files (*.%1) Soubory s ovladaÄi (*.%1) Warning UpozornÄ›ní About to remove controller file: "%1" Are you sure? Chystáte se odstranit soubor s ovladaÄem: "%1" Jste si jistý? Export Controller File Vyvést do souboru s ovladaÄem The controller file already exists: "%1" Do you want to replace it? Soubor s ovladaÄem již existuje: "%1" PÅ™ejete si jej nahradit? Saved controller mappings may not be effective the next time you start this program. "%1" Do you want to apply to controller files? Uložená pÅ™iÅ™azení ovladaÄů nezaÄnou působit, dokud znovu program nespustíte. "%1" Chcete použít soubory s ovladaÄi? Controller mappings have been changed. PÅ™iÅ™azení ovladaÄů byla zmÄ›nÄ›na. Do you want to save the changes? Chcete uložit zmÄ›ny? Yes Ano No Ne qtractorMidiControlObserverForm MIDI Controller - Qtractor OvladaÄ MIDI - Qtractor &Type: &Typ: MIDI event type Typ události MIDI Cha&nnel: &Kanál: MIDI channel Kanál MIDI In&vert &Obrátit &Hook &Hák Control input connections Ovládat spojení vstupů &Inputs &Vstupy Control output connections Ovládat spojení výstupů &Outputs &Výstupy (Any) (Jakýkoli) &Parameter: &Parametr: MIDI parameter Parametr MIDI &Logarithmic &Logaritmický &Feedback &ZpÄ›tná vazba MIDI Controller OvladaÄ MIDI MIDI controller is already assigned. Do you want to replace the mapping? OvladaÄ MIDI je již pÅ™iÅ™azen. Chcete nahradit pÅ™iÅ™azení? Some settings have been changed. Do you want to apply the changes? NÄ›která nastavení byla zmÄ›nÄ›na. Chcete použít tyto zmÄ›ny? &MIDI Controller... OvladaÄ &MIDI... &Automation &Automatizace &Lock &Zamknout &Play &PÅ™ehrát &Record &Nahrávat &Clear &Smazat qtractorMidiEditEvent Zoom in (horizontal) PÅ™iblížit (vodorovnÄ›) Zoom out (horizontal) Oddálit (vodorovnÄ›) Zoom reset (horizontal) Nastavit pÅ™ibližování (vodorovné) znovu qtractorMidiEditList C%1 C%1 qtractorMidiEditTime Play-head ZaÄátek pÅ™ehrávání Edit-head ZaÄátek úprav Edit-tail Konec úprav Loop-start ZaÄátek smyÄky Loop-end Konec smyÄky Punch-in ZaÄátek pÅ™episu Punch-out Konec pÅ™episu Start: %1 End: %2 Length: %3 ZaÄátek: %1 Konec: %2 Délka: %3 qtractorMidiEditView Zoom in (vertical) PÅ™iblížit (svisle) Zoom out (vertical) Oddálit (svisle) Zoom reset (vertical) Nastavit zvÄ›tÅ¡ení (svislé) znovu qtractorMidiEditor MIDI Editor MIDI Editor cut Vyjmout delete Smazat insert range Vložit rozsah remove range Odstranit rozsah move PÅ™esunout edit Upravit resize ZmÄ›nit velikost rescale ZmÄ›nit měřítko paste Vložit Time: %1 Type: ÄŒas: %1 Typ: Note On (%1) %2 Velocity: %3 Duration: %4 Nota zapnuta (%1) %2 Rychlost: %3 Doba trvání: %4 Key Press (%1) %2 Value: %3 ZmáÄknout klávesu (%1) %2 Hodnota: %3 Controller (%1) Name: %2 Value: %3 OvladaÄ (%1) Název: %2 Hodnota: %3 Pgm Change (%1) ZmÄ›nit Pgm (%1) Chan Press (%1) Stisknout kanál (%1) Pitch Bend (%1) ZmÄ›na výšky tónu (%1) Pich Bend (%d) Ohyb výšky tónu (%d) SysEx (%1 bytes) Data: SysEx (%1 bajtů) Data: Unknown (%1) Neznámý (%1) Start: %1 End: %2 Length: %3 ZaÄátek: %1 Konec: %2 Délka: %3 qtractorMidiEditorForm Snap/beat Klapnout/doba Note On Tóny (noty) zapnuty Set current snap to %1 Nastavit nynÄ›jší zapadnutí na %1 Key Press Stisk klávesy Note Velocity Rychlost noty Key Pressure Stisknutí klávesy Controller OvladaÄ Program Change ZmÄ›na programu Channel Pressure Stisknutí kanálu Pitch Bend ZmÄ›na výšky tónu System Exclusive Exkluzivní zpráva systému Pgm Change ZmÄ›na Pgm Chan Press Stisknutí kanálu Sys Ex SysEx Note type Typ noty Value type Typ hodnoty Controller type Typ ovladaÄe Scale key KlÃ­Ä měřítka Scale type Typ měřítka MIDI clip name Název záznamu MIDI MIDI file name Název MIDI souboru MIDI track/channel Stopa s MIDI/Kanál MOD REŽIM MIDI modification state Stav MIDI úprav 00:00:00.000 00:00:00.000 MIDI clip duration Doba trvání záznamu MIDI Warning UpozornÄ›ní The current MIDI clip has been changed: "%1" Do you want to save the changes? NynÄ›jší záznam MIDI byl zmÄ›nÄ›n: "%1" Chcete uložit zmÄ›ny? Save Uložit Discard Vyhodit Cancel ZruÅ¡it Save MIDI Clip Uložit záznam MIDI MIDI files (*.%1 *.smf *.midi) Soubory MIDI (*.%1 *.smf *.midi) MIDI file save: "%1", track-channel: %2. Uložit soubor MIDI: "%1", stopa-kanál: %2. MIDI Editor MIDI Editor Channel %1 Kanál %1 Track %1 Stopa %1 [modified] (upraveno) &Track &Stopa &File &Soubor Select &Mode Režim &výbÄ›ru &Select &Vybrat &Tools &Nástroje &Edit &Upravit &View &Zobrazit &Toolbars &Nástrojové liÅ¡ty &Zoom &PÅ™iblížit S&nap PÅ™&ichytit T&ransport PÅ™e&sunout &Help &NápovÄ›da &Context &Souvislosti &Save &Uložit Save current MIDI clip to existing file name Uložit nynÄ›jší záznam MIDI pod již existujícím názvem souboru Save &As... Uložit &jako... Save As Uložit jako Save as Uložit jako Save current MIDI clip with another file name Uložit nynÄ›jší záznam MIDI pod jiným názvem souboru &Inputs &Vstupy Track Inputs Vstupy stop Track inputs Vstupy stop Show current MIDI clip/track input bus connections Ukázat pÅ™ipojení vstupní sbÄ›rnice nynÄ›jšího záznamu/stopy MIDI &Outputs &Výstupy Track Outputs Výstupy stop Track outputs Výstupy stop Show current MIDI clip/track output bus connections Ukázat pÅ™ipojení výstupní sbÄ›rnice nynÄ›jšího záznamu/stopy MIDI &Properties... Vlastnosti&... Track Properties Vlastnosti stopy Track properties Vlastnosti stopy Edit current MIDI clip/track properties Upravit vlastnosti nynÄ›jšího záznamu/stopy MIDI Shift+F2 Shift+F2 Properties Vlastnosti Edit current MIDI clip properties Upravit vlastnosti nynÄ›jšího záznamu MIDI F4 F4 &Close &Zavřít Close Zavřít Close this MIDI clip editor Zavřít tento editor záznamů MIDI Edit Of&f Úpravy &vypnuty Edit Off Úpravy vypnuty Edit off Úpravy vypnuty Set edit mode off Nastavit režim úprav na: vypnuto Edit &On Úpravy &zapnuty Edit On Úpravy zapnuty Edit on Úpravy zapnuty Set edit mode on Nastavit režim úprav na: zapnuto Edit &Draw &Kreslení úprav Edit draw mode Režim kreslení úprav Edit draw mode (notes) Režim kreslení úprav (noty) &Undo &ZpÄ›t Undo ZpÄ›t Undo last edit operation Vrátit zpÄ›t poslední úpravu Ctrl+Z Ctrl+Z &Redo &Znovu Redo Znovu Redo last edit operation UdÄ›lat znovu poslední úpravu Ctrl+Shift+Z Ctrl+Shift+Z Cu&t Vyjmou&t Cut Vyjmout Cut current selection into the local clipboard Vyjmout nynÄ›jší výbÄ›r do místní schránky Ctrl+X Ctrl+X &Copy &Kopírovat Copy Kopírovat Copy current selection to the local clipboard Kopírovat nynÄ›jší výbÄ›r do místní schránky Ctrl+C Ctrl+C &Paste &Vložit Paste Vložit Paste local clipboard contents into the current MIDI clip Vložit obsah místní schránky do nynÄ›jší MIDI ukázky Ctrl+V Ctrl+V Past&e Repeat... Opakovat v&ložení... Paste Repeat Opakovat vložení Paste repeat Opakovat vložení Paste/repeat local clipboard contents into the current MIDI clip Vložit/Opakovat obsah místní schránky do nynÄ›jšího záznamu MIDI Ctrl+Shift+V Ctrl+Shift+V &Delete &Smazat Delete Smazat Delete current selection Smazat nynÄ›jší výbÄ›r Del Smazat Select &None Žádný &výbÄ›r Select None Žádný výbÄ›r Select none Žádný výbÄ›r Ctrl+Shift+A Ctrl+Shift+A Select &Invert &Obrátit výbÄ›r Select Invert Obrátit výbÄ›r Select invert Obrátit výbÄ›r Ctrl+I Ctrl+I Select &All Vybrat &vÅ¡e Select All Vybrat vÅ¡e Select all Vybrat vÅ¡e Ctrl+A Ctrl+A &Range &Rozsah Select Range Vybrat rozsah Select range Vybrat rozsah Mark range as selected OznaÄit rozsah jako vybraný Ctrl+R Ctrl+R &Quantize... &Kvantizovat... Quantize Kvantizovat Quantize selection Kvantizovat výbÄ›r &Transpose... &PÅ™evést... Transpose PÅ™evést Transpose selection PÅ™evést výbÄ›r &Normalize... &Normalizovat... Normalize Normalizovat Normalize selection Normalizovat výbÄ›r &Randomize... &NáhodnÄ› vybrat... Randomize NáhodnÄ› vybrat Randomize selection NáhodnÄ› vybrat výbÄ›r Snap grid view mode Pohledový režim se zapadáváním do mřížky Too&l Tips Rady k &nástrojům Tool tips Rady k nástrojům Floating tool tips view mode Pohledový režim s plovoucími radami k nástrojům &Windows &Okna I&nsert &Vložka Remo&ve &Odstranit Sc&ale &Měřítko &Unlink &ZruÅ¡it odkaz Unlink ZruÅ¡it odkaz Unlink current MIDI clip ZruÅ¡it odkaz na nynÄ›jší záznam MIDI &Range Set Nastavení &rozsahu Clip Range Rozsah záznamu Clip range Rozsah záznamu Set edit-range from clip extents Nastavit rozsah úprav z rozsahu nynÄ›jšího záznamu &Loop Set Nastavení &smyÄky Clip Loop SmyÄka záznamu Clip loop SmyÄka záznamu Set loop-range from clip extents Nastavit rozsah smyÄky z rozsahu nynÄ›jšího záznamu &None &Žádný &Invert &Obrátit Insert Range Vložit rozsah Insert range Vložit rozsah Insert range as selected Vložit rozsah jako vybraný Ctrl+Ins Ctrl+Ins Remove Range Odstranit rozsah Remove range Odstranit rozsah Remove range as selected Odstranit rozsah jako vybraný Ctrl+Del Ctrl+Delete Resi&ze... ZmÄ›&nit velikost... Resize ZmÄ›nit velikost Resize selection ZmÄ›nit velikost výbÄ›ru Re&scale... ZmÄ›nit &měřítko... Rescale ZmÄ›nit měřítko Rescale selection ZmÄ›nit měřítko výbÄ›ru T&imeshift... ÄŒa&sový posun... Timeshift ÄŒasový posun Timeshift selection VýbÄ›r Äasového posunu &Menubar &Hlavní nabídka Menubar &Hlavní nabídka Show/hide the menubar Ukázat/Skrýt nabídkový pruh Ctrl+M Ctrl+M &Statusbar &Stavový řádek Statusbar Stavový řádek Show/hide the statusbar Ukázat/Skrýt stavový řádek File Toolbar Nástrojový pruh pro soubor File toolbar Nástrojový pruh pro soubor Show/hide the file toolbar Ukázat/Skrýt nástrojový pruh k souboru Edit Toolbar Nástrojový pruh pro úpravy Edit toolbar Nástrojový pruh pro úpravy Show/hide the edit toolbar Ukázat/Skrýt nástrojový pruh pro úpravy View Toolbar Nástrojový pruh pro zobrazení View toolbar Nástrojový pruh pro zobrazení Show/hide the view toolbar Ukázat/Skrýt nástrojový pruh pro zobrazování &Transport &PÅ™esun Transport Toolbar Nástrojový pruh pro pÅ™esun Transport toolbar Nástrojový pruh pro pÅ™esun Show/hide the transport toolbar Ukázat/Skrýt nástrojový pruh pro pÅ™esun &Scale &Měřítko Scale Toolbar Nástrojový pruh pro měřítko Scale toolbar Nástrojový pruh pro měřítko Show/hide the scale toolbar Ukázat/Skrýt nástrojový pruh pro měřítko Note &Duration &Doba trvání noty Note Duration Doba trvání noty Note duration Doba trvání noty Whether note events are shown proportional to duration Zda události vztahující se k notÄ› jsou ukazovány úmÄ›rnÄ› k jejich trvání Note &Color Barva &noty Note Color Barva noty Note color Barva noty Whether note events are colored according to pitch Zda jsou události vztahující se k notÄ› zbarveny podle podle výšky tónu noty &Value Color Barva &hodnoty Value Color Barva hodnoty Value color Barva hodnoty Whether note events are colored according to value (velocity) Zda jsou události vztahující se k notÄ› zbarveny podle hodnoty (rychlost) &Events &Události View events Zobrazit události Show/hide the events list Ukázat/Skrýt seznam s událostmi &Preview Notes &Náhled na noty Preview Notes Náhled na noty Preview notes Náhled na noty Preview notes while editing (scrub) Náhled na noty pÅ™i úpravách F&ollow Playhead N&ásledovat hrací hlavu Follow Playhead Následovat hrací hlavu Follow playhead Následovat hrací hlavu &In &PÅ™iblížit Zoom In PÅ™iblížit Zoom in PÅ™iblížit Ctrl++ Ctrl++ &Out &Oddálit Zoom Out Oddálit Zoom out Oddálit Ctrl+- Ctrl+- &Reset &Nastavit znovu Zoom Reset Nastavit znovu zvÄ›tÅ¡ení Zoom reset Nastavit znovu zvÄ›tÅ¡ení Ctrl+1 Ctrl+1 &Horizontal &Vodorovné Horizontal Zoom Vodorovné zvÄ›tÅ¡ení Horizontal zoom Vodorovné zvÄ›tÅ¡ení Horizontal zoom mode Režim vodorovného zvÄ›tÅ¡ení &Vertical &Svislé Vertical Zoom Svislé zvÄ›tÅ¡ení Vertical zoom Svislé zvÄ›tÅ¡ení Vertical zoom mode Režim svislého zvÄ›tÅ¡ení &Zebra &Zebra Zebra Zebra Bar zebra view mode Pohledový režim se zebrovými pruhy Ctrl+Shift+L Ctrl+Shift+L Ctrl+Shift+P Ctrl+Shift+P &All &VÅ¡e All Zoom ZvÄ›tÅ¡it vÅ¡e All zoom ZvÄ›tÅ¡it vÅ¡e All zoom mode Režim zvÄ›tÅ¡ení vÅ¡eho &Grid &Mřížka Grid Mřížka Snap grid mode Režim zapadávání do mřížky &Refresh &Obnovit Refresh Obnovit Refresh views Obnovit zobrazení F5 F5 &Backward &ZpÄ›t Backward ZpÄ›t Transport backward PÅ™esunout se zpÄ›t Backspace Posunout se o znak zpÄ›t Re&wind PÅ™e&toÄit Rewind PÅ™etoÄit Transport rewind PÅ™esunout pÅ™etoÄení F&ast Forward R&ychle dopÅ™edu Fast Forward Rychle dopÅ™edu Fast forward Rychle dopÅ™edu Transport fast forward PÅ™esunout se rychle dopÅ™edu &Forward &DopÅ™edu Forward DopÅ™edu Transport forward PÅ™esunout se dopÅ™edu &Loop &SmyÄka Loop SmyÄka Transport loop PÅ™esunout smyÄku Shift+Ctrl+L Shift+Ctrl+L Loop &Set Umístit &smyÄku Loop Set Umístit smyÄku Loop set Umístit smyÄku Transport loop set PÅ™esunout umístÄ›ní smyÄky Ctrl+L Ctrl+L &Stop &Zastavit Stop Zastavit Transport stop PÅ™esunout zastavení &Play &PÅ™ehrát Play PÅ™ehrát Transport play/pause PÅ™esunout pÅ™ehrát/pozastavit Space Mezera &Record &Nahrát Record Nahrát Transport record PÅ™esunout náhrávání &Punch &Důraz Punch Důraz Punch in/out Důraz: zapnutý/vypnutý Transport punch in/out PÅ™esunout důraz: zapnutý/vypnutý Shift+Ctrl+P Shift+Ctrl+P Punch Se&t Nastavit dů&raz Punch Set Nastavit důraz Punch in/out set Nastavit důraz: zapnutý/vypnutý Transport punch in/out set PÅ™esunout nastavit důraz: zapnutý/vypnutý Ctrl+P Ctrl+P Pa&nic No&uzové zastavení Panic Nouzové zastavení All MIDI tracks shut off (panic) Vypnout vÅ¡echny stopy MIDI (nouzové zastavení) &Shortcuts... &Zkratky... Shortcuts Zkratky Keyboard shortcuts Klávesové zkratky &About... &O... About O Show information about this application program Ukázat informaci o tomto programu About &Qt... O &Qt... About Qt O Qt Show information about the Qt toolkit Ukázat informaci o sadÄ› softwarových nástrojů Qt qtractorMidiEventItemDelegate edit %1 Upravit %1 qtractorMidiEventList Events Události qtractorMidiEventListModel Time ÄŒas Type Typ Name Název Value Hodnota Duration/Data Doba trvání/Data Frame Snímek BBT TDT (takty-doby-tiky) Note On (%1) Nota zapnuta (%1) Note Off (%1) Nota vypnuta (%1) Key Press (%1) Stisknutí klávesy (%1) Controller (%1) OvladaÄ (%1) Pgm Change ZmÄ›na Pgm Chan Press Stisknutí kanálu Pitch Bend ZmÄ›na výšky tónu Pich Bend Ohyb výšky tónu SysEx SysEx Meta (%1) Meta (%1) Unknown (%1) Neznámý (%1) qtractorMidiListView Name Název Fmt Fmt Tracks Stopy tpqn tpqn tpb tpb Path Cesta Open MIDI Files Otevřít soubory MIDI MIDI files (*.%1 *.smf *.midi) Soubory MIDI (*.%1 *.smf *.midi) qtractorMidiMeter Volume (%) Hlasitost (%) % % Pan: %1 Vyvážení (Pan): %1 Volume: %1% Hlasitost: %1% qtractorMidiSysexForm MIDI SysEx - Qtractor MIDI SysEx - Qtractor Name Název Size Velikost Data (hex) Data (hex) Import from SysEx file Zavést ze souboru SysEx &Import... &Zavést... Alt+I Alt+I Export to SysEx file Vyvést do souboru SysEx E&xport... V&yvést... Alt+X Alt+X Move SysEx item up on list order Posunout položku SysEx nahoru v seznamu &Up &Nahoru Alt+U Alt+U Move SysEx item down on list order Posunout položku SysEx dolů v seznamu &Down &Dolů Alt+D Alt+D Open SysEx Otevřít SysEx Sysex name Název SysEx Save SysEx Uložit SysEx Delete SysEx Smazat SysEx Create SysEx item VytvoÅ™it položku SysEx &Add &PÅ™idat Alt+A Alt+A Update SysEx item Obnovit položku SysEx Upda&te Obnovi&t Alt+T Alt+T Remove SysEx item Odstranit položku SysEx &Remove &Odstranit Alt+R Alt+R Clear all SysEx items Smazat vÅ¡echny položky SysEx Clear Smazat OK OK Cancel ZruÅ¡it SysEx files (*.%1) Soubory SysEx (*.%1) MIDI files (*.mid *.smf *.midi) Soubory MIDI (*.mid *.smf *.midi) All files (*.*) VÅ¡echny soubory (*.*) Import SysEx Files Zavést soubory SysEx Export SysEx File Vyvést do souboru SysEx Warning UpozornÄ›ní The SysEx file already exists: "%1" Do you want to replace it? Soubor SysEx již existuje: "%1" Chcete jej nahradit? Sysex files (*.%1) Soubory SysEx (*.%1) About to replace SysEx: "%1" Are you sure? Chystáte se nahradit SysEx: "%1" Jste si jistý? About to delete SysEx: "%1" Are you sure? Chystáte se smazat SysEx: "%1" Jste si jistý? SysEx settings have been changed. Do you want to apply the changes? Nastavení SysEx byla zmÄ›nÄ›na. Chcete použít tyto zmÄ›ny? Error Chyba SysEx could not be loaded: "%1". Sorry. NepodaÅ™ilo se nahrát SysEx: "%1". Promiňte. qtractorMidiToolsForm (default) (výchozí) Warning UpozornÄ›ní About to delete preset: "%1" Are you sure? Chystáte se smazat pÅ™ednastavení: "%1" Jste si jistý? OK OK Cancel ZruÅ¡it none Žádný quantize Kvantizovat transpose PÅ™evést normalize Normalizovat randomize NáhodnÄ› vybrat resize ZmÄ›nit velikost rescale ZmÄ›nit měřítko timeshift ÄŒasový posun MIDI Tools Nástroje MIDI Preset name Název pÅ™ednastavení Save preset Uložit pÅ™ednastavení Delete preset Smazat pÅ™ednastavení &Quantize &Kvantizovat Quantize selected events Kvantizovat výbrané události &Time: ÄŒ&as: Quantize time Kvantizovat Äas Quantize time percent Kvantizovat procento Äasu &Duration: &Doba trvání: Quantize duration Kvantizovat dobu trvání Quantize duration percent Kvantizovat procento doby trvání &Swing: &Výkyv: Swing-quantize time ÄŒas výkyvu-kvantizování Swing-quantize percent Procento výkyvu-kvantizování Swing-quantize type Typ výkyvu-kvantizování Linear Lineární Quadratic ÄŒtvercový Cubic Krychlový &Scale: &Měřítko: Scale-quantize key KlÃ­Ä měřítka-kvantizace Scale-quantize type Typ měřítka-kvantizace &Transpose &PÅ™evést Transpose selected events PÅ™evést výbrané události &Note: &Nota: Transpose note PÅ™evést noty Transpose time PÅ™esunout Äas Transpose time format PÅ™esunout formát Äasu Frames Snímky Time ÄŒas BBT TDT (takty-doby-tiky) &Normalize &Normalizovat Normalize selected events Normalizovat výbrané události &Percent: &Procento: Normalize percent Normalizovat procento Resi&ze &ZmÄ›nit velikost Resize value mode Režim zmÄ›ny velikosti hodnoty Flat Rovný Ramp Nájezd Resize final value ZmÄ›nit koneÄnou velikost Re&scale ZmÄ›nit &měřítko Rescale selected events ZmÄ›nit měřítko vybraných událostí Rescale time ZmÄ›nit měřítko Äasu Rescale duration ZmÄ›nit měřítko doby trvání Rescale value ZmÄ›nit měřítko hodnoty T&imeshift ÄŒa&sový posun Timeshift selected events ÄŒasovÄ› posunout vybrané události Timeshift ÄŒasovÄ› posunout P: P: Timeshift parameter Parametr pro Äasový posun Timeshift parameter (log) Parametr pro Äasový posun (log) Timeshift curve KÅ™ivka Äasového posunu P = 0 : no change. P > 0 : accelerating shift. P < 0 : slowing down shift. Edit head/tail (blue) markers define the shift range. P = 0 : žádná zmÄ›na. P > 0 : zrychlení posunu. P < 0 : zpomalení posunu. (Modré) znaÄky pro úpravy zaÄátku/konce vymezují rozsah posunu. Timeshift duration Doba trvání posunu % % S&wing: &Výkyv: &Value: &Délka trvání: Normalize value Normalizovat délku trvání &Randomize &NáhodnÄ› vybrat Randomize selected events NáhodnÄ› vybrat výbrané události Randomize note/pitch NáhodnÄ› vybrat notu/výšku tónu Randomize time NáhodnÄ› vybrat Äas Randomize duration NáhodnÄ› vybrat dobu trvání Randomize value NáhodnÄ› vybrat délku trvání tónu Re&size ZmÄ›&nit velikost Resize selected events ZmÄ›nit velikost výbraných událostí Resize duration ZmÄ›nit velikost doby trvání Resize duration format ZmÄ›nit velikost formátu doby trvání Percentage Procento Resize value ZmÄ›nit velikost hodnoty qtractorMixer Inputs Vstupy Tracks Stopy Outputs Výstupy Mixer Mixážní pult qtractorMixerRack &Inputs &Vstupy &Outputs &Výstupy &Monitor &Sledování &Pass-through &Průchodnost &Buses... &SbÄ›rnice... qtractorMixerStrip monitor Sledovat Monitor (rec) Sledovat (nahrávání) inputs Vstupy outputs Výstupy Connect %1 PÅ™ipojit %1 Monitor (thru) Sledovat (skrz: "thru") %1 In %1 Vstup %1 Out %1 Výstup (Audio) (Zvuk) Gain Zesílení (MIDI) (MIDI) Volume Hlasitost (None) (Žádný) Pan Vyvážení qtractorMonitorButton monitor Sledovat Monitor (rec) Sledovat (nahrávání) Monitor (thru) Sledovat (skrz: "thru") qtractorOptionsForm Signed 16-Bit OznaÄený znaménkem 16-Bit Signed 24-Bit OznaÄený znaménkem 24-Bit Signed 32-Bit OznaÄený znaménkem 32-Bit Float 32-Bit Plovoucí 32-Bit Float 64-Bit Plovoucí 64-Bit SMF Format 0 SMF Format 0 SMF Format 1 SMF Format 1 (Any) (Jakýkoli) Warning UpozornÄ›ní Some settings have been changed. Do you want to apply the changes? NÄ›která nastavení byla zmÄ›nÄ›na. Chcete použít tyto zmÄ›ny? Apply Použít Discard Vyhodit Cancel ZruÅ¡it Metronome Bar Audio File Zvukový soubor s taktem pro přístroj sloužící k stanovení tempa v hudbÄ› (metronom) Metronome Beat Audio File Zvukový soubor s dobou pro přístroj sloužící k stanovení tempa v hudbÄ› (metronom) Plug-in Directory Adresář s přídavnými moduly LV2 Presets Directory Adresář s pÅ™ednastaveními LV2 Messages Log Záznam se sdÄ›leními Log files (*.%1) Soubory se záznamy (*.%1) Session Template PÅ™edloha pro sezení Session template files (*.qtr *.qts *.%1) Soubory pÅ™edloh (*.qtr *.qts *.%1) pro sezení Options - Qtractor Volby - Qtractor Which mode to rename existing session files Který režim pro pÅ™ejmenování stávajících souborů sezení &Audio &Zvuk Capture / Export Zachytávání/Vyvedení Audio compression quality to use on capture (record) and export Kvalitu zvukové komprese k použití na zachytávání (nahrávání) a pro vyvedení Audio sample format to use on capture (record) and export Formát zvukového vzorku použít na zachytávání (nahrávání) a pro vyvedení Audio file type to use on capture (record) and export Druh zvukového souboru k použití na zachytávání (nahrávání) a pro vyvedení File &type: Druh &souboru: Sample &format: Formát &vzorku: &Quality: &Kvalita: Playback PÅ™ehrávání Sample-&rate converter type: Druh pÅ™evodníku vzorkovacího &kmitoÄtu: Sample-rate converter quality Kvalita pÅ™evodníku vzorkovacího kmitoÄtu Sinc (Best Quality) Sinc (nejlepší kvalita) Sinc (Medium Quality) Sinc (stÅ™ední kvalita) Sinc (Fastest) Sinc (nejrychlejší) Zero Order Hold Držení nulového pořádku Linear Lineární Tran&sport mode: Režim pÅ™e&sunu: Transport control mode (JACK) Režim ovládání pÅ™esunu (JACK) None Žádný Slave Řízený Master Řídící Full Úplný Whether to apply time-stretching when tempo changes Zda se má použít natahování Äasu, když se zmÄ›ní tempo Aut&omatic time-stretching Auto&matické natahování Äasu Alt+O Alt+O Whether to use WSOLA time-stretching Zda se má použít WSOLA natahování Äasu &WSOLA time-stretching &WSOLA natahování Äasu Alt+W Alt+W Whether to apply WSOLA quick seek time-stretching Zda se má použít WSOLA rychlé vyhledání natahování Äasu WSOLA quic&k seek WSOLA rych&lé vyhledání Alt+K Alt+K Whether to have separate audition/pre-listening player output ports Zda mít oddÄ›lené poslechové/pÅ™ed-poslechové výstupní přípojky pÅ™ehrávacího zařízení Dedicated au&dition/pre-listening player outputs JednoúÄelové po&slechové/pÅ™ed-poslechové výstupní přípojky pÅ™ehrávacího zařízení Alt+D Alt+D Metronome Metronom Whether to enable the audio metronome Zda povolit zvukový metronom &Enable audio metronome &Povolit zvukový metronom Alt+E Alt+E &File (bar): &Soubor (takt): Metronome Audio filename (bar) Název zvukového souboru metronomu (takt) Browse for sample audio file (bar) Procházet kvůli zvukovému souboru se vzorkem (takt) Metronome gain (bar) Zesílení metronomu (takt) dB dB &File (beat): &Soubor (doba): Metronome Audio filename (beat) Název zvukového souboru metronomu (doba) Browse for sample audio file (beat) Procházet kvůli zvukovému souboru se vzorkem (doba) &Gain (beat): &Zesílení (doba): Metronome gain (beat) Zesílení metronomu (doba) Whether to have separate audio metronome output ports Zda mít pro metronom oddÄ›lené zvukové výstupní přípojky Dedicated a&udio metronome outputs JednoúÄelové zv&ukové výstupy metronomu Alt+U Alt+U &MIDI &MIDI MIDI capture (record) quantization MIDI zachytávací (nahrávací) kvantování &Quantize: &Kvantizovat: MIDI file format to use on capture (record) and export Druh MIDI souboru k použití na zachytávání (nahrávání) a pro vyvedení File &format: Formát &souboru: Queue &timer (resolution): ÄŒa&sovaÄ Å™ady (rozliÅ¡ení): Queue timer (resolution) ÄŒasovaÄ Å™ady (rozliÅ¡ení) Control Kontrola &MMC: &OSM: MIDI Machine Control (MMC) mode Režim ovládání stroje MIDI (OSM) Input Vstup Output Výstup Duplex Duplexní režim &Device: &Zařízení: MIDI Machine Control (MMC) device id. ID zařízení na ovládání stroje MIDI (OSM). &SPP: &UPP: MIDI Song Position pointer (SPP) control mode Režim ovládání ukazovátka polohy písnÄ› MIDI (UPP) Cloc&k: &Hodiny: MIDI Clock control mode Ovládací režim &hodin MIDI: Whether to have separate MIDI control ports Zda mít oddÄ›lené ovládací přípojky MIDI Dedicated MIDI &control input/output &JednoúÄelový ovládací vstup/výstup pro MIDI Alt+C Alt+C &General &Obecné Number of &recent files: PoÄet &naposledy otevÅ™ených souborů: S&how complete path of session files Ukázat úplnou &cestu souborů se sezením Keep tool &windows always on top Držet vÅ¡echna nástrojová &okna vždy navrchu &Drop multiple audio files into the same track &Upustit mnohonásobné zvukové soubory do stejné stopy Default session &file format: Výchozí formát &souboru se sezením: Default session file format (suffix) Výchozí formát souboru se sezením (přípona) &New session template: PÅ™edloha pro &nové sezení: Save &backup versions of existing sessions: Uložit &zálohovací verze stávajících sezení: Increment previous version (default) Zvýšení pÅ™edchozí verze (výchozí) Increment current version Zvýšení nynÄ›jší verze Whether to reverse mouse middle-button role on keyboard modifiers (Shift/Ctrl) Zda zmÄ›nit úlohu prostÅ™edního tlaÄítka myÅ¡i na modifikátory klávesnice (Shift/Ctrl) Re&verse middle-button modifier role (Shift/Ctrl) &ZmÄ›nit úlohu prostÅ™ední tlaÄítka myÅ¡i na modifikátor (Shift/Ctrl) Transport PÅ™esun Transport &mode: &Režim pÅ™esunu: &Loop recording mode (takes): Režim nahrávání &smyÄky (zábÄ›ry): Dedicated au&dition/pre-listening player outputs: JednoúÄelové po&slechové/pÅ™ed-poslechové výstupy pÅ™ehrávaÄe: Whether to auto-connect dedicated audio player outputs Zda pÅ™ipojit automaticky jednoúÄelové zvukové výstupy pÅ™ehrávaÄe Auto-&connect &PÅ™ipojit automaticky &Gain (bar): &Zesílení (takt): Dedicated a&udio metronome outputs: JednoúÄelové zv&ukové výstupy metronomu: Whether to auto-connect dedicated audio metronome outputs Zda pÅ™ipojit automaticky jednoúÄelové zvukové výstupy metronomu Auto-co&nnect PÅ™ip&ojit automaticky Alt+N Alt+N Whether to have separate MIDI player output ports Zda mít oddÄ›lené výstupní přípojky pÅ™ehrávaÄe MIDI Dedicated MIDI p&layer outputs JednoúÄelové výstupy pÅ™e&hrávaÄe MIDI Alt+L Alt+L Whether to have separate MIDI metronome output port Zda mít oddÄ›lenou výstupní přípojku metronomu pro MIDI Dedicated M&IDI metronome output JenoúÄelový výstup metronomu pro M&IDI Alt+I Alt+I &Note (beat): &Nota (doba): Metronome MIDI note (beat) Nota (doba) MIDI pro metronom Metronome MIDI velocity (beat) Rychlost (doba) MIDI pro metronom &Duration (beat): &Doba trvání (doba): &Velocity (beat): &Rychlost (doba): Metronome MIDI velocity (bar) Rychlost (takt) MIDI pro metronom &Duration (bar): &Doba trvání (takt): &Velocity (bar): &Rychlost (takt): Metronome MIDI note (bar) Nota MIDI pro metronom (takt) &Note (bar): &Nota (takt): &Channel: &Kanál: Metronome MIDI channel Kanál MIDI metronomu Whether to enable the MIDI metronome Zda se má povolit MIDI metronom &Enable MIDI metronome &Povolit MIDI metronom &Display &Zobrazit M&essages limit: Nejvyšší poÄet &zpráv: Options Volby Whether to ask for confirmation on removal Zda se má požádat o potvrzení pÅ™i odstranÄ›ní &Confirm removals &Potvrdit odstranÄ›ní &Number of recent files: &PoÄet naposledy otevÅ™ených souborů: The maximum number of recent files to keep in menu Nejvyšší poÄet naposledy otevÅ™ených souborů, které mají být podrženy v seznamu nabídek Whether to capture standard output (stdout/stderr) into messages window Zda se má zachytit obvyklý výstup (stdout/stderr) do okna se zprávami Capture standard &output Zachytit obvyklý &výstup Whether to show the complete directory path of loaded session files Zda se má ukázat úplnou adresářovou cestu nahraných souborů se sezením Show complete &path of session files Ukázat úplnou adresářovou &cestu nahraných souborů se sezením Alt+P Alt+P Loop recording mode (takes) Režim nahrávání &smyÄky (zábÄ›ry) First První Last Poslední Whether to remove audio peak files on session close Zda se mají na závÄ›r sezení odstranit nejvyšší zvukové soubory Auto-remove audio pea&k files Automatické odstranÄ›ní nej&vyšších zvukových souborů Whether to keep all tool windows on top of the main window Zda se mají držet vÅ¡echna nástrojová okna navrchu hlavního okna &Keep tool windows always on top &Držet vÅ¡echna nástrojová okna vždy navrchu Time display &format: &Formát zobrazení Äasu: Time display format Formát zobrazení Äasu Frames Snímky Time ÄŒas BBT TDT Whether to try dropping multiple audio files into the same track Zda se má zkusit upustit mnohonásobné zvukové soubory do stejné stopy Drop multiple audio files into the &same track Upustit mnohonásobné zvukové soubory do &stejné stopy Alt+S Alt+S &Base font size: &Základní velikost fontu: Base application font size (pt.) Základní velikost fontu aplikace (v bodech) (default) (výchozí) 6 6 7 7 8 8 9 9 10 10 11 11 12 12 Session Sezení Whether to create new sessions based on template Zda se mají vytvoÅ™it nová sezení založená na pÅ™edlohách New session &template: &PÅ™edloha pro nové sezení: New session template PÅ™edloha pro nové sezení Browse for new session template Procházet kvůli pÅ™edloze pro nové sezení Whether to save backup versions of existing sessions Zda se mají uložit zálohovací verze stávajících sezení Save &backup versions of existing sessions Uložit &zálohovací verze stávajících sezení Defaults Výchozí &Time display format: Formát zobrazení Ä&asu: Meters Měřidla &Audio: &Zvuk: Audio meter level Úroveň měřiÄe zvuku Over Nad 0 dB 0 dB 3 dB 3 dB 6 dB 6 dB 10 dB 10 dB Audio meter color Barva měřiÄe zvuku Select custom audio meter color Vybrat vlastní barvu měřiÄe zvuku ... ... &MIDI: &MIDI: MIDI meter level Úroveň měřiÄe MIDI Peak Vrchol MIDI meter color Barva měřiÄe MIDI Select custom MIDI meter color Vybrat vlastní barvu měřiÄe MIDI Reset meter colors to default Nastavit barvy měřiÄů Nastavit znovu na výchozí &Reset &Nastavit znovu Alt+R Alt+R Messages SdÄ›lení Sample messages text font display Font zobrazení textu u ukázkových sdÄ›lení Select font for the messages text display Vybrat font pro zobrazení textu u sdÄ›lení &Font... &Font... Alt+F Alt+F Whether to keep a maximum number of lines in the messages window Zda se má podržet nejvyšší poÄet řádků ve sdÄ›lovacím oknÄ› &Messages limit: &Nejvyšší poÄet sdÄ›lení: Alt+M Alt+M The maximum number of message lines to keep in view Nejvyšší poÄet řádků u sdÄ›lení, který se ponechá v náhledu lines Řádky Logging Zaznamenávání Messages log file Soubor se záznamy sdÄ›lení Browse for the messages log file location Procházet kvůli umístÄ›ní souboru se záznamy sdÄ›lení Whether to activate a messages logging to file. Zda se má zapnout zaznamenávání sdÄ›lení do souboru. Messages &log file: Soubor se &záznamy sdÄ›lení: &Plugins &Přídavné moduly Paths Cesty Plugin type Druh přídavného modulu Plugin path Cesta k přídavnému modulu Browse plugin path Procházet cestu k přídavnému modulu Add plugin path PÅ™idat cestu k přídavnému modulu &Add &PÅ™idat Plugin paths Cesty k přídavnému modulu Remove plugin path Odstranit cestu k přídavnému modulu &Remove &Odstranit Move up path PÅ™esunout cestu nahoru &Up &Nahoru &Down &Dolů &LV2 Presets directory: Adresář s pÅ™ednastaveními &LV2: LV2 Presets directory (default: ~/.lv2) Adresář s pÅ™ednastaveními LV2 (výchozí: ~/.lv2) Browse LV2 Presets directory Procházet adresář s pÅ™ednastaveními LV2 Instruments Nástroje Whether to have separate audio output ports Zda mít oddÄ›lené zvukové výstupní přípojky Dedicated audi&o outputs: JednoúÄelové zvuk&ové výstupy: Whether to auto-connect dedicated audio output ports Zda pÅ™ipojit automaticky jednoúÄelové zvukové výstupní přípojky Au&to-connect PÅ™ipoji&t automaticky Alt+T Alt+T Editor Editor Whether to open plugin's editor (GUI) by default Zda ve výchozím nastavení otevřít editor (rozhraní) přídavného modulu Open plugin's &editor (GUI) by default Otevřít editor (rozhraní) přídavného modulu Alt+G Alt+G Dedicated audi&o outputs JednoúÄelové zvuk&ové výstupy Experimental Pokusný Whether to use a dummy plugin type when scanning for VST plugins Zda se má použít umÄ›lý druh přídavného modulu pÅ™i hledání VST přídavných modulů Dummy &VST plugin scan (RECOMMENDED) UmÄ›lý &VST přídavný modul pÅ™i hledání (DOPORUÄŒENO) Alt+V Alt+V OK OK qtractorPasteRepeatForm Warning UpozornÄ›ní Some settings have been changed. Do you want to apply the changes? NÄ›která nastavení byla zmÄ›nÄ›na. Chcete použít tyto zmÄ›ny? Apply Použít Discard Vyhodit Cancel ZruÅ¡it Paste Repeat - Qtractor Vložit opakování (repetici) - Qtractor Repeat Opakovat &Count: &PoÄet: Repeat count PoÄet opakování (repetic) &Period: &Perioda (doba): Repeat period Doba opakování (repetice) Repeat period format Formát doby opakování (repetice) Frames Snímky Time ÄŒas BBT TDT OK OK qtractorPluginForm (default) (výchozí) Page %1 Strana %1 (none) (Žádné) Open Preset Otevřít pÅ™ednastavení Preset files (*.%1) Soubory s pÅ™ednastaveními (*.%1) Error Chyba Preset could not be loaded from "%1". Sorry. PÅ™ednastavení nemohlo být nahráno z "%1". Promiňte. &None &Žádné MIDI Controller... OvladaÄ MIDI... Cancel ZruÅ¡it Save Preset Uložit pÅ™ednastavení Warning UpozornÄ›ní About to delete preset: "%1" (%2) Are you sure? Chystáte se smazat pÅ™ednastavení: "%1" (%2) Jste si jistý? OK OK qtractorPluginForm Formulář přídavných modulů QTractor Open preset Otevřít pÅ™ednastavení Preset name Název pÅ™ednastavení Save preset Uložit pÅ™ednastavení Delete preset Smazat pÅ™ednastavení Plugin parameters Parametry přídavného modulu Params Parametry Edit plugin Upravit přídavný modul Edit upravit Outputs (Sends) Výstupy (Poslání) Sends Poslání Inputs (Returns) Vstupy (Navrácení) Returns Navrácení Aux Send Bus: SbÄ›rnice aux-send: Manage buses Spravovat sbÄ›rnice ... ... Direct Access Parameter Parametr pro přímý přístup Direct Access Přímý přístup Activate plugin Zapnout přídavný modul Active Aktivní qtractorPluginListView copy plugin Kopírovat přídavný modul activate all plugins Zapnout vÅ¡echny přídavné moduly deactivate all plugins Vypnout vÅ¡echny přídavné moduly remove all plugins Odstranit vÅ¡echny přídavné moduly &Move Here &PÅ™esunout na toto místo &Copy Here &Kopírovat na toto místo C&ancel Z&ruÅ¡it &Add Plugin... &PÅ™idat přídavný modul... Add &Insert PÅ™idat &vložku Add &Aux Send PÅ™idat &aux-send &Sends &Poslání &Returns &Navrácení Ac&tivate &Zapnout &Remove &Odstranit &None &Žádný &Properties... Vlastnosti&... &Edit &Upravit &Auto-connect &PÅ™ipojit automaticky Act&ivate Za&pnout Acti&vate All Z&apnout vÅ¡e Deactivate Al&l Vypnout v&Å¡e Re&move All Od&stranit vÅ¡e Move &Up Posunout &nahoru Move &Down Posunout &dolů &Edit Plugin... &Upravit přídavný modul... &Outputs &Výstupy &Dedicated &JednoúÄelové qtractorPluginSelectForm GUI GUI EXT EXT RT RT Plugins - Qtractor Přídavné moduly - Qtractor Reset filter Nastavit filtr znovu X X Plugin search string (regular expression) Vyhledávací Å™etÄ›zec pro přídavný modul (řádný výraz) Plugin type Druh přídavného modulu Available plugins Dostupné přídavné moduly Name Název Audio Zvuk MIDI MIDI Control Kontrola Modes Mode Režimy Path Cesta Index Rejstřík Instances Příklady Type Druh &Activate &Zapnout Activate plugin on insert Zapnout přídavný modul pÅ™i vložení Alt+A Alt+A Plugin scanning in progress... Běží hledání přídavných modulů... OK OK Cancel ZruÅ¡it qtractorSessionForm Warning UpozornÄ›ní Session directory does not exist: "%1" Do you want to create it? Adresář se sezením neexistuje: "%1" Chcete jej vytvoÅ™it? Some settings have been changed. Do you want to apply the changes? NÄ›která nastavení byla zmÄ›nÄ›na. Chcete použít tyto zmÄ›ny? Apply Použít Discard Vyhodit Cancel ZruÅ¡it Session Directory Adresář sezení Session - Qtractor Sezení - Qtractor Session Sezení &Name: &Název: Session name Název sezení &Directory: &Adresář: Session directory Adresář sezení Browse for session directory Procházet kvůli adresáři sezení ... ... &Description: &Popis: Session description Popis sezení Properties Vlastnosti Time ÄŒas Sample &Rate: Vzorkovací &kmitoÄet: Sample rate (Hz) Vzorkovací kmitoÄet (Hz) 44100 44100 48000 48000 96000 96000 192000 192000 &Tempo: &Tempo: Tempo (BPM) / Signature Tempo (ÚZM)/Taktové oznaÄení Resolution (ticks/beat; tpqn) RozliÅ¡ení (tiky/doby; tpqn) Tempo (BPM) Tempo (poÄet úderů za minutu) &Beats/Bar: &Doby/takty: Time signature (beats/bar) Taktové oznaÄení (doby/takty) / 4 / 4 T&icks/Beat: T&iky/doby: Resolution (ticks/beat; TPQN) Rozvedení (akordu) (tiky/doby; TPQN) View Zobrazit &Snap/Beat: &Zapadnout/doba: Snap/beat Zapadnout/doba &Pixels/Beat: &Obrazové body/doba: Pixels/beat Obrazové body/doba &Horizontal Zoom: &Vodorovné pÅ™iblížení: Horizontal Zoom (%) Vodorovné pÅ™iblížení (%) % % &Vertical Zoom: &Svislé pÅ™iblížení: Vertical Zoom (%) Svislé pÅ™iblížení (%) OK OK qtractorShortcutForm Warning UpozornÄ›ní Keyboard shortcut (%1) already assigned. Klávesová zkratka (%1) již pÅ™iÅ™azena. Keyboard shortcuts have been changed. Do you want to apply the changes? Klávesové zkratky byly zmÄ›nÄ›ny. Chcete použít tyto zmÄ›ny? Keyboard shortcuts have been changed. Klávesové zkratky byly zmÄ›nÄ›ny. Do you want to apply the changes? PÅ™ejete si použít zmÄ›ny? Apply Použít Discard Vyhodit Cancel ZruÅ¡it Keyboard Shortcuts Klávesové zkratky Action ÄŒin Description Popis Shortcut Zkratka OK OK qtractorTakeRangeForm Take - Qtractor ZábÄ›r - Qtractor Range Rozsah Selection range Rozsah výbÄ›ru &Selection &VýbÄ›r Loop range Rozsah smyÄky &Loop &SmyÄka Punch range Rozsah pÅ™epsání &Punch &PÅ™epsání Time ÄŒas BBT TDT (takty-doby-tiky) Edit range Rozsah úprav &Edit &Úpravy Custom range Vlastní rozsah &Custom &Vlastní St&art: Za&Äátek: Clip start ZaÄátek záznamu En&d: Ko&nec: Clip offset Posun záznamu Select Vybrat Current take NynÄ›jší zábÄ›r Format Formát Time display format Formát zobrazení Äasu Frames Snímky &Frames &Snímky Time (hh:mm:ss.zzz) ÄŒas (hh:mm:ss.zzz) &Time ÄŒ&as BBT (bars.beats.ticks) TDT (takty-doby-tiky) &BBT &TDT Take %1 ZábÄ›r %1 qtractorTempoAdjustForm Tempo - Qtractor Tempo - Qtractor Metronome Metronom Temp&o: &Tempo: Tempo/Time signature Tempo/Taktové oznaÄení T&ap ZaÅ¥u&kání Range Rozsah &Start: &ZaÄátek: Range start ZaÄátek rozsahu Time ÄŒas BBT TDT (takty-doby-tiky) &Length: &Délka: Range length Délka rozsahu B&eats: &Doby: Range beats Doby rozsahu A&djust &Upravit Format Formát Time display format Formát zobrazení Äasu Frames Snímky Fra&mes Sní&mky Time (hh:mm:ss.zzz) ÄŒas (hh:mm:ss.zzz) &Time ÄŒ&as BBT (bars.beats.ticks) TDT (takty.doby.tiky) &BBT &TDT Warning Varování Some settings have been changed. Do you want to apply the changes? NÄ›která nastavení byla zmÄ›nÄ›na. Chcete použít tyto zmÄ›ny? qtractorThumbView Thumb view Zobrazit náhled qtractorTimeScaleForm Tempo Map - Qtractor Zobrazení tempa - Qtractor Tempo map Zobrazení tempa Bar Takt Time ÄŒas Tempo Tempo Signature Taktové oznaÄení Node Uzel &Bar: &Takt: Tempo Map / Markers - Qtractor Rozvržení tempa/ZnaÄky - Qtractor Tempo map / Markers Rozvržení tempa/ZnaÄky Marker ZnaÄka Location UmístÄ›ní Bar location UmístÄ›ní taktu T&ime: ÄŒ&as: Bar/Time node Takt/ÄŒasový uzel Time/frame location UmístÄ›ní Äasu/snímku &Tempo: &Tempo: Tempo (BPM) / Signature Tempo (ÚZM)/Taktové oznaÄení T&ap ZaÅ¥u&kání Marker text Text znaÄky ... ... Marker color Barva znaÄky Refresh tempo map Obnovit rozvržení tempa Re&fresh &Obnovit Alt+F Alt+F Add node PÅ™idat uzel &Add &PÅ™idat Alt+A Alt+A Update node Obnovit uzel &Update &Obnovit Alt+U Alt+U Remove node Odstranit uzel &Remove &Odstranit Alt+R Alt+R Close this dialog Zavřít tento dialog Close Zavřít Warning UpozornÄ›ní Some settings have been changed. Do you want to apply the changes? NÄ›která nastavení byla zmÄ›nÄ›na. Chcete použít tyto zmÄ›ny? About to remove tempo node: %1 (%2) %3 %4/%5 Are you sure? Chystáte se odstranit uzel s tempem: %1 (%2) %3 %4/%5 Jste si jistý? Some settings have been changed. Do you want to discard the changes? NÄ›která nastavení byla zmÄ›nÄ›na. Chcete zahodit tyto zmÄ›ny? &Refresh &Obnovit qtractorTimeSpinBox &Frames &Snímky &Time ÄŒ&as &BBT &TDT qtractorTrackButton Record Nahrát Mute Ztlumit Solo Sólo qtractorTrackForm Normal Normální Bank MSB Banka MSB Bank LSB Banka LSB Patch PolíÄko Warning UpozornÄ›ní Some settings have been changed. Do you want to apply the changes? NÄ›která nastavení byla zmÄ›nÄ›na. Chcete použít tyto zmÄ›ny? (No instrument) (Žádný nástroj) Apply Použít Discard Vyhodit Cancel ZruÅ¡it (None) (Žádný) Track - Qtractor Stopa - Qtractor Track Stopa &Name: &Název: Track name description Popis názvu stopy Type Druh Audio track type Druh zvukové stopy &Audio &Zvuk Alt+A Alt+A MIDI track type Druh MIDI stopy &MIDI &MIDI Alt+M Alt+M Input / Output Vstup/Výstup Input bus name Název vstupní sbÄ›rnice Ouput bus name Název výstupní sbÄ›rnice Output bus name Název výstupní sbÄ›rnice Manage buses Spravovat sbÄ›rnice ... ... MIDI / Instrument MIDI/nástroj &Program: &Program: &Bank: &Banka: Bank &Select Method: Metoda &výbÄ›ru zvukové banky: &Omni &Omni MIDI Omni: Capture All Channels MIDI Omni: zachytávání vÅ¡ech kanálů Alt+O Alt+O &Channel: &Kanál: MIDI Channel (1-16) MIDI kanál (1-16) MIDI Patch: Instrument MIDI políÄko: nástroj MIDI Patch: Bank Select Method MIDI políÄko: metoda výbÄ›ru zvukové banky MIDI Patch: Bank MIDI políÄko: zvuková banka MIDI Patch: Program MIDI políÄko: program(ovat) View / Colors Pohled/barvy &Foreground: &PopÅ™edí: Foreground color Barva popÅ™edí Select custom track foreground color Vybrat vlastní barvu popÅ™edí stopy Bac&kground: Po&zadí: Background color Barva pozadí Select custom track background color Vybrat vlastní barvu pozadí stopy Plugins Přídavné moduly Track plugins Přídavné moduly stopy Add plugin PÅ™idat přídavný modul &Add... &PÅ™idat... Remove plugin Odstranit přídavný modul &Remove &Odstranit Alt+R Alt+R Move plugin up PÅ™esunout přídavný modul nahoru &Up &Nahoru Alt+U Alt+U Move plugin down PÅ™esunout přídavný modul dolů &Down &Dolů Alt+D Alt+D OK OK qtractorTrackItemWidget Automation Automatizace qtractorTrackListHeaderModel Nr Číslo Track Name Název stopy Bus SbÄ›rnice Ch Kanál Patch PolíÄko Instrument Nástroj qtractorTrackTime Play-head ZaÄátek pÅ™ehrávání Edit-head ZaÄátek úprav Edit-tail Konec úprav Loop-start ZaÄátek smyÄky Loop-end Konec smyÄky Punch-in ZaÄátek pÅ™episu Punch-out Konec pÅ™episu Start: %1 End: %2 Length: %3 ZaÄátek: %1 Konec: %2 Délka: %3 qtractorTrackView Zoom in (horizontal) PÅ™iblížit (vodorovnÄ›) Zoom out (horizontal) Oddálit (vodorovnÄ›) Zoom in (vertical) PÅ™iblížit (svisle) Zoom out (vertical) Oddálit (svisle) Zoom reset Nastavit zvÄ›tÅ¡ení znovu add clip PÅ™idat záznam Start: %1 End: %2 Length: %3 ZaÄátek: %1 Konec: %2 Délka: %3 clip %1 Záznam %1 fade-in Postupné zesílení signálu fade-out Postupné zeslabení signálu clip stretch Natáhnout záznam clip resize ZmÄ›nit velikost záznamu %1 automation %1 automatizace %1 clip %1 záznam move automation PÅ™esunout automatizaci paste automation Vložit automatizaci cut Vyjmout delete Smazat split RozdÄ›lit move clip PÅ™esunout záznam paste clip Vložit záznam qtractorTracks Tracks Stopy new clip Nový záznam split clip RozdÄ›lení záznamu clip normalize Normalizace záznamu clip quantize Kvantizace ukázky clip import Zavedení záznamu Export Audio Clip Exportovat zvukovou ukázku Audio files (*.%1) Zvukové soubory (*.%1) Audio clip export: "%1" started... Export zvukové ukázky: "%1" právÄ› zaÄal... Audio clip export: "%1" complete. Export zvukové ukázky: "%1" je hotový. Audio clip export: "%1" failed. Export zvukové ukázky: "%1" selhal. Export MIDI Clip Exportovat MIDI ukázku MIDI files (*.%1 *.smf *.midi) Soubory MIDI (*.%1 *.smf *.midi) MIDI clip export: "%1" started... Export ukázky MIDI: "%1" právÄ› zaÄal... MIDI clip export: "%1" complete. Export ukázky MIDI: "%1" je hotový. MIDI clip export: "%1" failed. Export ukázky MIDI: "%1" selhal. Warning UpozornÄ›ní About to remove track: "%1" Are you sure? Chystáte se odstranit stopu: "%1" Jste si jistý? OK OK Cancel ZruÅ¡it quantize Kvantizovat transpose PÅ™evést normalize Normalizovat randomize Vybrat náhodnÄ› resize ZmÄ›nit velikost rescale ZmÄ›nit měřítko timeshift ÄŒasový posun clip tool %1 Nástroj na záznamy %1 Audio file import "%1" on %2 %3. Zavedení zvukového souboru "%1" do %2 %3. Audio file import: "%1". Zavedení zvukového souboru: "%1". MIDI file import "%1" track-channel %2 on %3 %4. Zavedení MIDI souboru: "%1", stopa-kanál %2 %3 %4. clip merge SlouÄení záznamu Merge/Export Audio Clip SlouÄit/Vyvést zvukový záznam Audio clip merge/export: "%1" started... SlouÄení/Vyvedení zvukového záznamu: "%1" právÄ› zaÄalo... Audio clip merge/export: "%1" complete. SlouÄení/Vyvedení zvukového záznamu: "%1" je hotovo. Merge/Export MIDI Clip SlouÄit/Vyvést záznam MIDI MIDI clip merge/export: "%1" started... SlouÄení/Vyvedení záznamu MIDI: "%1" právÄ› zaÄalo... MIDI clip merge/export: "%1" complete. SlouÄení/Vyvedení záznamu MIDI: "%1" je hotovo. Insert Range Vložit rozsah insert track range Vložit rozsah stopy Remove Range Odstranit rozsah insert range Vložit rozsah remove range Odstranit rozsah remove track range Odstranit rozsah stopy MIDI file import "%1" on %2 %3. Zavedení MIDI souboru "%1" do %2 %3. MIDI file import: "%1". Zavedení MIDI souboru: "%1". MIDI file import: "%1", track-channel: %2. Zavedení MIDI souboru: "%1", stopa-kanál: %2. qtractorVstPlugin::EditorWidget %1 - Editor %1 - Editor qtractor-0.5.11/src/translations/PaxHeaders.10084/qtractor_ru.ts0000644000175000001440000000012312223511102022666 xustar000000000000000027 mtime=1380880962.062114 26 atime=1381134669.24408 30 ctime=1381134669.346080086 qtractor-0.5.11/src/translations/qtractor_ru.ts0000644000175000001440000177421312223511102022174 0ustar00rncbcusers00000000000000 C C C# C# D D D# D# F F F# F# G G G# G# A A A# A# B B Acoustic Bass Drum Acoustic Bass Drum Bass Drum 1 Bass Drum 1 Side Stick Side Stick Acoustic Snare Acoustic Snare Hand Clap Hand Clap Electric Snare Electric Snare Low Floor Tom Low Floor Tom Closed Hi-Hat Closed Hi-Hat High Floor Tom High Floor Tom Pedal Hi-Hat Pedal Hi-Hat Low Tom Low Tom Open Hi-Hat Open Hi-Hat Low-Mid Tom Low-Mid Tom Hi-Mid Tom Hi-Mid Tom Crash Cymbal 1 Crash Cymbal 1 High Tom High Tom Ride Cymbal 1 Ride Cymbal 1 Chinese Cymbal Chinese Cymbal Ride Bell Ride Bell Tambourine Tambourine Splash Cymbal Splash Cymbal Cowbell Cowbell Crash Cymbal 2 Crash Cymbal 2 Vibraslap Vibraslap Ride Cymbal 2 Ride Cymbal 2 Hi Bongo Hi Bongo Low Bongo Low Bongo Mute Hi Conga Mute Hi Conga Open Hi Conga Open Hi Conga Low Conga Low Conga High Timbale High Timbale Low Timbale Low Timbale High Agogo High Agogo Low Agogo Low Agogo Cabasa Cabasa Maracas Maracas Short Whistle Short Whistle Long Whistle Long Whistle Short Guiro Short Guiro Long Guiro Long Guiro Claves Claves Hi Wood Block Hi Wood Block Low Wood Block Low Wood Block Mute Cuica Mute Cuica Open Cuica Open Cuica Mute Triangle Mute Triangle Open Triangle Open Triangle Effects Level Уровень Ñффектов Tremulo Level Уровень тремоло Chorus Level Уровень хора add clip добавление клипа clip %1 клип %1 fade-in нараÑтание fade-out угаÑание clip stretch раÑÑ‚Ñгивание клипа clip resize Ñмена размера клипа cut вырезание delete удаление move clip перемещение клипа paste clip вÑтавка клипа Track Gain УÑиление дорожки Track Panning Панорамирование дорожки Track Monitor Мониторинг дорожки Track Record ЗапиÑÑŒ дорожки Track Mute Приглушение дорожки Track Solo Солирование дорожки QObject Audio: %1 channels, %2 Hz Звук: каналов: %1, %2 Гц (%1 dB) (%1 Дб) (%1% time stretch) (%1 semitones pitch shift) %1 In Вход %1 %1 Out Выход %1 Audio files (%1) Звуковые файлы (%1) All files (*.*) Ð’Ñе файлы (*.*) %1 (%2) %3 channels, %4 frames, %5 Hz %6 %1 (%2) %3 каналов, %4 выборок, %5 Гц %6 (take %1) Name: %1 Ðазвание: %1 Start / End: %1 / %2 Offset / Length: %3 / %4 File: %1 Файл: %1 create bus Ñоздание шины update bus обновление шины delete bus удаление шины bus pass-through ÑÐºÐ²Ð¾Ð·Ð½Ð°Ñ ÑˆÐ¸Ð½Ð° bus gain уÑиление шины bus pan панорама шины Cakewalk Instrument Definition File Файл определений инÑтрументов Cakewalk File Файл Date Дата %1 Bank %2 %1 - Bank %2 %1 - Банк %2 (format %1) MIDI: (формат %1) MIDI: Channel %1 Канал %1 Track %1 Дорожка %1 , %1 tracks, %2 tpqn , %1 дорожек, %2 tpqn (%1% vol) (%1% громк) %1 (format %2) %3 tracks, %4 tpqn %5 %1 (формат %2) %3 дорожек, %4 tpqn %5 %1 (format %2) %3 %1 (формат %2) %3 Usage: %1 [options] [session-file] ИÑпользование: %1 [ключи] [файл-ÑеанÑа] Usage: %1 [options] [session-file] Options: Set session identification (uuid) Show help about command line options Show version information Option -s requires an argument (session-id). Qt: %1 Qt: %1 (Any) (Любой) add plugin добавление Ñффекта add insert add aux-send aux-send bus remove plugin удаление Ñффекта move plugin перемещение Ñффекта activate plugin Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ñ Ñффекта preset plugin reset plugin dedicated audio outputs ÑобÑтвенный выход Ñффекта direct access param session tempo Ñмена темпа ÑеанÑа session loop Ð¿ÐµÑ‚Ð»Ñ ÑеанÑа session properties ÑвойÑтва ÑеанÑа Duplex Ð”ÑƒÐ¿Ð»ÐµÐºÑ Output Выход Input Вход None Ðет Beat Такт add track добавление дорожки remove track удаление дорожки move track перемещение дорожки resize track Ñмена размера дорожки import track импорт дорожки track properties ÑвойÑтва дорожки Track assignment failed: Track: "%1" Input: "%2" Output: "%3" track record запиÑÑŒ дорожки track mute приглушение дорожки track solo Ñолирование дорожки track monitor мониторинг дорожки track gain уÑиление дорожки track pan панорама дорожки Automation (%1) none нет Automation Audio Звук MIDI MIDI Unknown ÐеизвеÑтно %1 (*.%2) %1 (*.%2) add tempo node update tempo node remove tempo node move tempo node add marker update marker remove marker move marker session punch врезка в ÑеÑÑии Start/End: %1 / %2 Offs/Length: %3 / %4 Ðачало/Конец: %1 / %2 Смещение/ДлительноÑть: %3 / %4 %1 Monitor Send Gain Dry / Wet До / ПоÑле обработки set controller reset controller (default) (по умолчанию) %1 Hz %1 Гц slave %1 (%2) %1 (%2) %1 Record %1 Mute %1 Solo %1 Volume %1 Gain %1 Pan take %1 reset takes automation select automation mode automation play automation record automation logarithmic automation color automation play all automation record all automation edit automation clear automation clear all automation edit list qtractorAudioListView Name Ðазвание Ch К Frames Выборок Rate ЧаÑтота Time Ð’Ñ€ÐµÐ¼Ñ Path Путь Open Audio Files Открыть звуковые файлы qtractorAudioMeter Gain (dB) УÑиление (Дб) dB Дб Pan: %1 Пан: %1 Gain: %1 dB УÑиление: %1 Дб qtractorBusForm Audio Звук MIDI MIDI Bus Шина Warning Предупреждение Some settings have been changed. Do you want to apply the changes? Ðекоторые параметры изменилиÑÑŒ. Ð’Ñ‹ хотите применить изменениÑ? About to remove bus: "%1" (%2) Are you sure? Будет удалена шина: "%1" (%2) Ð’Ñ‹ уверены? Some settings have been changed. Do you want to discard the changes? Ðекоторые параметры изменилиÑÑŒ. Ð’Ñ‹ хотите применить изменениÑ? (No instrument) (none) (1 item) (%1 items) &Create &Создать &Update О&бновить &Delete &Удалить &Refresh О&бновить Buses - Qtractor Шины - Qtractor Bus list СпиÑок шин Buses Шины Ch К Mode Режим Properties СвойÑтва &Name: Ð&азвание: Bus name Ðазвание шины &Mode: &Режим: Bus mode Режим работы шины Input Вход Output Выход Duplex Ð”ÑƒÐ¿Ð»ÐµÐºÑ &Pass-through (monitor) &Ð¡ÐºÐ²Ð¾Ð·Ð½Ð°Ñ (мониторинг) Alt+P Alt+Ñ Bus monitor (pass-through) M&onitor (pass-through) &Мониторинг (pass-through) Alt+O Alt+м Cha&nnels: &Каналов: Audio channels КоличеÑтво звуковых каналов Audio auto-connect &Auto connect &ÐвтоÑоединение Alt+A Alt+а MIDI Instrument name MIDI SysEx setup SysE&x... SysE&x... Input Plugins Эффекты на входе Input bus plugins Эффекты шины на входе Add input plugin Добавить Ñффект на вход &Add... &Добавить Remove input plugin Удалить Ñффект на входе &Remove &Удалить Alt+R Alt+у Move input plugin up ПоднÑть Ñффект в ÑпиÑке &Up &Выше Alt+U Alt+в Move input plugin down ОпуÑтить Ñффект в ÑпиÑке &Down &Ðиже Alt+D Alt+н Output Plugins Эффекты на выходе Output bus plugins Эффекты шины на выходе Add output plugin Добавить Ñффект на выход Remove output plugin Удалить Ñффект на выходе Move output plugin up ПоднÑть Ñффект в ÑпиÑке Move output plugin down ОпуÑтить Ñффект в ÑпиÑке Refresh bus list view Обновить ÑпиÑок шин Create bus Создать шину Alt+C Alt+Ñ Update bus Обновить шину Delete bus Удалить шину Close this dialog Закрыть Ñтот диалог Close Закрыть qtractorClientListView Readable Clients / Output Ports Порты выхода Writable Clients / Input Ports Порты входа qtractorClipForm &Gain: &УÑиление: dB Дб &Volume: &ГромкоÑть: % % new clip Ñоздание клипа edit clip правка клипа Warning Предупреждение Some settings have been changed. Do you want to apply the changes? Ðекоторые параметры изменилиÑÑŒ. Ð’Ñ‹ хотите применить изменениÑ? Cancel Отменить Audio Звук MIDI MIDI MIDI files (*.%1 *.smf *.midi) Файлы MIDI (*.%1 *.smf *.midi) %1 Clip File Clip - Qtractor Клип — Qtractor &Name: &Ðазвание: Clip name Ðазвание клипа &File: &Файл Clip filename Ð˜Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° клипа Browse for clip file Указать файл клипа Track/&Channel: Дорожка/&Канал: Clip track/channel Дорожка/канал клипа &Gain/Volume: &УÑиление/ГромкоÑть: Clip gain/volume УÑиление/громкоÑть клипа Parameters Параметры Clip start Ðачало клипа Clip offset Смещение клипа Clip length ДлительноÑть клипа Offs&et: С&мещение: &Length: &ДлительноÑть: &Start: &Ðачало: Gain/Volume Format Формат Time display format Формат Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸: Frames Выборки Time Ð’Ñ€ÐµÐ¼Ñ BBT BBT Fra&mes Ð’Ñ‹&борки Time (hh:mm:ss.zzz) Ð’Ñ€ÐµÐ¼Ñ (чч:мм:ÑÑ.мÑ) &Time &Ð’Ñ€ÐµÐ¼Ñ BBT (bars.beats.ticks) BBT (bars.beats.ticks) &BBT &BBT Fade In/Out Плавное нараÑтание и затухание Ñигнала Fade &In: &ÐараÑтание: Clip fade-in length ДлительноÑть нараÑÑ‚Ð°Ð½Ð¸Ñ Ñигнала клипа Clip fade-in type Тип нараÑÑ‚Ð°Ð½Ð¸Ñ Ñигнала клипа Linear Линейное Quadratic Квадратичное Cubic КубичеÑкое Fade &Out: &Затухание: Clip fade-out length ДлительноÑть Ð·Ð°Ñ‚ÑƒÑ…Ð°Ð½Ð¸Ñ Ñигнала клипа Clip fade-out type Тип Ð·Ð°Ñ‚ÑƒÑ…Ð°Ð½Ð¸Ñ Ñигнала клипа Time St&retch: &РаÑÑ‚Ñгивание: Clip time-stretch percentage РаÑÑ‚Ñгивание клипа во времени в процентах Pitch S&hift: Ð’&Ñ‹Ñота тона: Clip pitch-shift in semitones Ð’Ñ‹Ñота тона клипа в полутонах semitones полутонов OK ОК qtractorConnect Connect Соединить Disconnect Разъединить Disconnect All Разъединить вÑе Refresh Обновить qtractorConnectForm (All) (Ð’Ñе) qtractorConnectTest qtractorConnectTest Audio Звук Select output client/ports Выберите порты клиента наружу Select input client/ports Выберите порты клиента внутрь Connect currently selected ports Соединить выбранные ÑÐµÐ¹Ñ‡Ð°Ñ Ð¿Ð¾Ñ€Ñ‚Ñ‹ &Connect &Соединить Alt+C Alt+c Disconnect currently selected ports РаÑÑоединить выбранные ÑÐµÐ¹Ñ‡Ð°Ñ Ð¿Ð¾Ñ€Ñ‚Ñ‹ &Disconnect &РаÑÑоединить Alt+D Alt+Ñ€ Disconnect all currently connected ports РаÑÑоединить вÑе Ñоединённые ÑÐµÐ¹Ñ‡Ð°Ñ Ð¿Ð¾Ñ€Ñ‚Ñ‹ Disconnect &All РаÑÑоединить &вÑе Alt+A Alt+в Refresh current connections view Обновить отображение текущих Ñоединений &Refresh О&бновить Alt+R Alt+б MIDI MIDI qtractorConnections Connections Ð¡Ð¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ qtractorEditRangeForm Range - Qtractor Range ОблаÑть Selection range &Selection Loop range Ð’ÑÑŽ петлю &Loop &ÐŸÐµÑ‚Ð»Ñ Punch range Ð’ÑÑŽ врезку &Punch &Врезка Edit range ОблаÑть Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ &Edit Custom range Другую облаÑть &Custom &Ð”Ñ€ÑƒÐ³Ð°Ñ St&art: &Ðачало: Clip start Ðачало клипа En&d: &Конец: Clip offset Te&mpo Map &Format Time display format Формат Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸: Time Ð’Ñ€ÐµÐ¼Ñ BBT BBT Format Формат Frames &Frames Ð’Ñ‹&борки Time (hh:mm:ss.zzz) Ð’Ñ€ÐµÐ¼Ñ (чч:мм:ÑÑ.мÑ) &Time &Ð’Ñ€ÐµÐ¼Ñ BBT (bars.beats.ticks) BBT (bars.beats.ticks) &BBT &BBT Options Параметры Apply to clips in range Cl&ips A&utomation Apply to Automation nodes in range Apply to Loop points in range L&oop Apply to Punch In/Out points in range Pu&nch Mar&kers Apply to Tempo Map nodes in range Apply to location Markers in range qtractorExportForm Audio звуковых данных MIDI MIDI Export %1 ЭкÑпорт %1 Warning Предупреждение The file already exists: "%1" Do you want to replace it? Такой файл уже ÑущеÑтвует: "%1" Ð’Ñ‹ хотите его заменить? Cancel Отменить Audio file export: "%1" started... ЭкÑпорт звукового файла: "%1" начат... Audio file export: "%1" complete. ЭкÑпорт звукового файла: "%1" завершен... Audio file export: "%1" failed. ЭкÑпорт звукового файла: не удалоÑÑŒ ÑкÑпортировать "%1" MIDI file export: "%1" started... ЭкÑпорт файла MIDI: "%1" начат... MIDI file export: "%1" complete. ЭкÑпорт файла MIDI: "%1" завершен... MIDI file export: "%1" failed. ЭкÑпорт файла MIDI: не удалоÑÑŒ ÑкÑпортировать "%1" Export %1 File ЭкÑпорт %1 файла %1 files (*.%1) %1 файлов (*.%1) Export - Qtractor ЭкÑпорт — Qtractor &File: &Файл: Export file name Ð˜Ð¼Ñ ÑкÑпортируемого файла Browse export file name Указать Ð¸Ð¼Ñ ÐºÐ¾Ð½ÐµÑ‡Ð½Ð¾Ð³Ð¾ файла Range ОблаÑть Session range ВеÑÑŒ ÑÐµÐ°Ð½Ñ &Session &Ð¡ÐµÐ°Ð½Ñ Loop range Ð’ÑÑŽ петлю &Loop &ÐŸÐµÑ‚Ð»Ñ Punch range Ð’ÑÑŽ врезку &Punch &Врезка Edit range ОблаÑть Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ &Edit &Изменить Custom range Другую облаÑть &Custom &Ð”Ñ€ÑƒÐ³Ð°Ñ St&art: &Ðачало: Clip start Ðачало клипа En&d: &Конец: Clip offset Конец клипа Output Выход Output bus name Time Ð’Ñ€ÐµÐ¼Ñ BBT BBT Ouput bus name Ðазвание шины на выходе Format Формат Time display format Формат Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸: Frames Выборки &Frames Ð’Ñ‹&борки Time (hh:mm:ss.zzz) Ð’Ñ€ÐµÐ¼Ñ (чч:мм:ÑÑ.мÑ) &Time &Ð’Ñ€ÐµÐ¼Ñ BBT (bars.beats.ticks) BBT (bars.beats.ticks) &BBT &BBT OK &ОК qtractorFileListView New Group ÐÐ¾Ð²Ð°Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð° Warning Предупреждение About to remove %1 file items. Are you sure? Будет удалено файлов: %1. Ð’Ñ‹ уверены? About to remove %1 file item(s). Are you sure? About to remove %1 item: "%2" Are you sure? Будет удален %1 файл: "%2" Ð’Ñ‹ уверены? group группа file файл qtractorFiles Audio Звук MIDI MIDI Play file ВоÑпроизвеÑти файл New &Group &Создать группу Add &Files... &Добавить файлы... Cu&t &Вырезать &Copy &Копировать P&aste Ð’ÑÑ‚&авить R&ename &Переименовать &Delete &Удалить Play Ð’&оÑпроизвеÑти Ctrl+G Ctrl+G Ctrl+F Ctrl+F Ctrl+X Ctrl+X Ctrl+C Ctrl+C Ctrl+V Ctrl+V Ctrl+E Ctrl+E New &Group... &Paste Ð’ÑÑ‚&авить Re&name &Remove &Удалить Pla&y Cl&eanup Del Del Files Файлы MIDI Files Audio Files qtractorInstrumentForm Import Instrument Files Импортировать файлы инÑтрументов Instrument files (*.%1 *.sf2 *.midnam) Instrument files (*.%1) Файлы инÑтрументов (*.%1) Export Instrument File ЭкÑпортировать файлы инÑтрументов Warning Предупреждение The instrument file already exists: "%1" Do you want to replace it? Такой файл инÑтрументов уже ÑущеÑтвует: "%1" Ð’Ñ‹ хотите его заменить? Instrument settings have been changed. Параметры инÑтрумента изменилиÑÑŒ. Do you want to apply the changes? Применить внеÑенные изменениÑ? Instrument settings have been changed. Do you want to apply the changes? Patch Names for Banks ÐÐ°Ð·Ð²Ð°Ð½Ð¸Ñ Ð¿Ð°Ñ‚Ñ‡ÐµÐ¹ Ð´Ð»Ñ Ð±Ð°Ð½ÐºÐ¾Ð² Controller Names = %1 ÐÐ°Ð·Ð²Ð°Ð½Ð¸Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»Ð»ÐµÑ€Ð¾Ð² = %1 RPN Names = %1 ÐÐ°Ð·Ð²Ð°Ð½Ð¸Ñ RPN = %1 NRPN Names = %1 ÐÐ°Ð·Ð²Ð°Ð½Ð¸Ñ NRPN = %1 Bank Select Method = %1 СпоÑоб выбора банка = %1 Patch Names ÐÐ°Ð·Ð²Ð°Ð½Ð¸Ñ Ð¿Ð°Ñ‚Ñ‡ÐµÐ¹ Note Names ÐÐ°Ð·Ð²Ð°Ð½Ð¸Ñ Ð½Ð¾Ñ‚ Controller Names ÐÐ°Ð·Ð²Ð°Ð½Ð¸Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»Ð»ÐµÑ€Ð¾Ð² RPN Names ÐÐ°Ð·Ð²Ð°Ð½Ð¸Ñ RPN NRPN Names ÐÐ°Ð·Ð²Ð°Ð½Ð¸Ñ NRPN Bank Select Methods СпоÑобы выбора банка %1 = %2 %1 = %2 Based On = %1 ОÑновано на = %1 Normal Обычный Bank MSB Банк MSB Bank LSB Банк LSB Patch Патч Unknown ÐеизвеÑтно Instruments - Qtractor ИнÑтрументы — Qtractor Instruments ИнÑтрументы Files Файлы Path РаÑположение Names ÐÐ°Ð·Ð²Ð°Ð½Ð¸Ñ Import from instrument file Импортировать из файла инÑтрументов &Import... &Импортировать... Alt+I Alt+и Remove instrument file Удалить файл инÑтрумента &Remove &Удалить Alt+R Alt+у Move instrument file up on list order ПеремеÑтить файл инÑтрумента вверх по ÑпиÑку &Up &Выше Alt+U Alt+в Move instrument file down on list order ПеремеÑтить файл инÑтрумента вниз по ÑпиÑку &Down &Ðиже Alt+D Alt+н Reload all instrument files Перезагрузить вÑе файлы инÑтрументов R&eload Пере&загрузить Alt+E Alt+з Export to instrument file ЭкÑпортировать в файл инÑтрументов &Export... &ЭкÑпортировать... Close this dialog Закрыть Ñтот диалог Close Закрыть Relo&ad Пере&загрузить Alt+A Alt+з E&xport... &ЭкÑпортировать... Alt+X Alt+Ñ qtractorMainForm Snap/beat Прилипание к долÑм Track Дорожка Current track name Ðазвание текущей дорожки MOD ИЗМ Session modification state СоÑтоÑние измененноÑти ÑеанÑа REC ЗÐП Session record state СоÑтоÑние запиÑываемоÑти ÑеанÑа MUTE ТИХО Session muting state СоÑтоÑние приглушенноÑти ÑеанÑа SOLO СОЛО Session soloing state СоÑтоÑние ÑÐ¾Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² ÑеанÑе LOOP ПЕТЛЯ Session looping state СоÑтоÑние Ð·Ð°Ñ†Ð¸ÐºÐ»Ð¸Ð²Ð°Ð½Ð¸Ñ Ð² ÑеанÑе Session total time ÐžÐ±Ñ‰Ð°Ñ Ð´Ð»Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñть ÑеанÑа Session sample rate ЧаÑтота ÑÑÐ¼Ð¿Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÑеанÑа Could not set default session directory: %1 Sorry. Ðе удалоÑÑŒ уÑтановить каталог Ñ ÑеÑÑией по умолчанию: %1 Извините. Ready Готово Untitled%1 Session files (*.%1 *.%2 *.%3) Archive files (*.%1) About to remove archive directory: "%1" Are you sure? The directory already exists: "%1" Do you want to replace it? Opening "%1"... Saving "%1"... About to clear automation: "%1" Are you sure? About to clear all automation: "%1" Are you sure? take range VeSTige header support enabled. LV2 Plug-in support disabled. LV2 Plug-in UI support disabled. LV2 Plug-in UI support (libsuil) disabled. LV2 Plug-in MIDI/Event support disabled. LV2 Plug-in support (liblilv) disabled. Current time (play-head) Backup session: "%1" as "%2". Could not backup existing session: %1 as %2 Sorry. LV2 Plug-in External UI support disabled. LV2 Plug-in MIDI/Atom support disabled. LV2 Plug-in Worker/Schedule support disabled. LV2 Plug-in State support disabled. LV2 Plug-in Programs support disabled. LV2 Plug-in Presets support disabled. LV2 Plug-in Time/position support disabled. LV2 Plug-in Options support disabled. LV2 Plug-in Buf-size support disabled. JACK Session support disabled. JACK Latency support disabled. NSM support disabled. &Hold &Linear &Spline Take %1 None Ðет The audio engine has been shutdown. Make sure the JACK audio server (jackd) is up and running and then restart session. Звуковой движок выключен. УбедитеÑÑŒ в том, что звуковой Ñервер JACK (jackd) запущен и функционирует, а затем начните ÑÐµÐ°Ð½Ñ Ð·Ð°Ð½Ð¾Ð²Ð¾. STOP СТОП PLAY FFWD REW REC ON ЗÐП ВКЛ REC OFF ЗÐП ВЫКЛ RESET СБРОС LOCATE %1 SHUTTLE %1 STEP %1 ШÐГ %1 TRACK RECORD %1 %2 TRACK MUTE %1 %2 TRACK SOLO %1 %2 Unknown sub-command Not implemented Ðе реализовано MIDI CTL: %1, Channel %2, Param %3, Value %4 %1 BPM MIDI channel %1, Controller %2, Value %3 Канал MIDI %1, контроллер %2, значение %3 (track %1, gain %2) (дорожка %1, уÑиление %2) (track %1, panning %2) (дорожка %1, панорамирование %2) START CONTINUE ПРОДОЛЖИТЬ SONGPOS %1 Untitled Без Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ New session: "%1". Ðовый ÑеанÑ: "%1". Session files (*.%1 *.%2) Файлы ÑеанÑов (*.%1 *.%2) Template files (*.%1) Файлы шаблонов (*.%1) Open Session Открыть ÑÐµÐ°Ð½Ñ Save Session Сохранить ÑÐµÐ°Ð½Ñ Warning Предупреждение The file already exists: "%1" Do you want to replace it? Такой файл уже ÑущеÑтвует: "%1" Ð’Ñ‹ хотите его заменить? The current session has been changed: "%1" Do you want to save the changes? Ðктивный ÑÐµÐ°Ð½Ñ Ð±Ñ‹Ð» изменен: "%1" Ð’Ñ‹ хотите Ñохранить изменениÑ? Save Сохранить Session closed. Ð¡ÐµÐ°Ð½Ñ Ð·Ð°ÐºÑ€Ñ‹Ñ‚. Session could not be loaded from "%1". Sorry. Ðе удалоÑÑŒ загрузить ÑÐµÐ°Ð½Ñ Ð¸Ð· "%1". Извините! Open session: "%1". Открыть ÑеанÑ: "%1". Session could not be saved to "%1". Sorry. Ðе удалоÑÑŒ Ñохранить ÑÐµÐ°Ð½Ñ Ð² файл "%1". Извините. Save session: "%1". Сохранить ÑеанÑ: "%1". session ÑÐµÐ°Ð½Ñ or или program программа Information Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Some settings may be only effective next time you start this %1. Ðекоторые Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð²Ð¾Ð·Ñ‹Ð¼ÐµÑŽÑ‚ Ñилу только при Ñледующем запуÑке %1. Version ВерÑÐ¸Ñ Build Сборка Debugging option enabled. Отладка включена Set current snap to %1 Ogg Vorbis (libvorbis) file support disabled. Поддержка файлов Ogg Vorbis (libvorbis) отключена MPEG-1 Audio Layer 3 (libmad) file support disabled. Поддержка MPEG-1 Audio Layer 3 (libmad) отключена Sample-rate conversion (libsamplerate) disabled. Поддержка Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ‡Ð°Ñтоты ÑÑÐ¼Ð¿Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ (libsamplerate) отключена Pitch-shifting support (librubberband) disabled. Поддержка Ñмена выÑоты тона (librubberband) отключена OSC service support (liblo) disabled. Поддержка Ñлужбы OSC (liblo) отключена LADSPA Plug-in support disabled. Поддержка Ñффектов LADSPA отключена DSSI Plug-in support disabled. Поддержка Ñффектов DSSI отключена VST Plug-in support disabled. Поддержка Ñффектов VST отключена LV2 Plug-in State Files support disabled. Website Веб-Ñайт This program is free software; you can redistribute it and/or modify it Эта программа ÑвлÑетÑÑ Ñвободной; вы можете раÑпроÑтранÑть и/или under the terms of the GNU General Public License version 2 or later. изменÑть ее на уÑловиÑÑ… GNU GPL верÑии 2 или новее. About О программе record clip запиÑÑŒ клипа [modified] [изменен] %1 Hz %1 Гц Session started. Ð¡ÐµÐ°Ð½Ñ Ð½Ð°Ñ‡Ð°Ñ‚. The original session sample rate (%1 Hz) is not the same of the current audio engine (%2 Hz). Saving and reloading from a new session file is highly recommended. ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ñ‡Ð°Ñтота ÑÑÐ¼Ð¿Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÑеанÑа (%1 Гц) не Ñовпадает Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ чаÑтотой звукового движка (%2 Гц). ÐаÑтоÑтельно рекомендуетÑÑ Ñохранить ÑÐµÐ°Ð½Ñ Ð¸ заново открыть его из нового файла. The audio/MIDI engine could not be started. Make sure the JACK audio server (jackd) and/or the ALSA Sequencer kernel module (snd-seq-midi) are up and running and then restart the session. Ðе удалоÑÑŒ запуÑтить движок аудио/MIDI. УбедитеÑÑŒ в том, что звуковой Ñервер JACK и/или модуль ÑеквенÑера ALSA (snd-seq-midi) запущены и работают, затем перезапуÑтите ÑеанÑ. Error Ошибка XRUN(%1 skipped) XRUN(%1): some frames might have been lost. Audio connections change. Смена звуковых Ñоединений MIDI connections change. Смена Ñоединений MIDI Playing ended. ВоÑпроизведение завершено Tracks closed. Дорожки закрыты. Playing "%1"... ВоÑпроизводитÑÑ "%1"... &Frames Ð’Ñ‹&борки &Time &Ð’Ñ€ÐµÐ¼Ñ &BBT &BBT Qtractor Qtractor &Track &Дорожка &State &СоÑтоÑние &Navigate &ÐÐ°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ &Move &ПеремеÑтить Impor&t Tracks &Импортировать дорожки E&xport Tracks &ЭкÑпортировать дорожки &View &Вид &Toolbars &Панели инÑтрументов &Windows &Zoom МаÑш&таб S&nap При&липание T&ransport &ТранÑпорт &Help &Справка &Edit &Правка Select &Mode &Режим Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ &Select Ð’Ñ‹&делить T&ools Cl&ip К&лип &File &Файл Open &Recent Открыть &недавние I&nsert Remo&ve Mo&ve &Height M&ode A&utomation Ta&ke &New &Создать New Создать New session Создать ÑеÑÑию New session file Создать файл новой ÑеÑÑии Ctrl+N Ctrl+N &Open... &Открыть... Open Открыть Open session Открыть ÑÐµÐ°Ð½Ñ Open session from file Открыть ÑÐµÐ°Ð½Ñ Ð¸Ð· файла Ctrl+O Ctrl+O &Save &Сохранить Save session Сохранить ÑÐµÐ°Ð½Ñ Save session to file Сохранить ÑÐµÐ°Ð½Ñ Ð² файл Ctrl+S Ctrl+S Save &As... Сохранить &как Save As Сохранить как Save as Сохранить как Save current session with another file name Сохранить активный ÑÐµÐ°Ð½Ñ Ð¿Ð¾Ð´ другим названием &Properties... С&войÑтва... Session Properties СвойÑтва ÑеанÑа Session properties СвойÑтва ÑеанÑа Edit current session properties Изменить ÑвойÑтва активного ÑеанÑа F2 F2 E&xit Ð’&ыход Exit Выход Exit this application program Завершить работу Ñ Ñтой программой &Undo &Отменить Undo Отменить Undo last action Отменить поÑледнее дейÑтвие Ctrl+Z Ctrl+Z &Redo Ве&рнуть Redo Вернуть Redo last action Вернуть отмененное дейÑтвие Ctrl+Shift+Z Ctrl+Shift+Z Cu&t &Вырезать Cut Вырезать Cut selection to clipboard Вырезать выделение в буфер обмена Ctrl+X Ctrl+X &Copy &Копировать Copy Копировать Copy selection to clipboard Скопировать выделение в буфер обмена Ctrl+C Ctrl+C &Paste Ð’ÑÑ‚&авить Paste Ð’Ñтавить Paste clipboard contents Ð’Ñтавить Ñодержимое буфера обмена Ctrl+V Ctrl+V Past&e Repeat... Ð’Ñтав&ить Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð¾Ð¼ Paste Repeat Ð’Ñтавить Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð¾Ð¼ Paste repeat Ð’Ñтавить Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð¾Ð¼ Paste/repeat clipboard contents Ð’Ñтавить Ñодержимое буфера обмена Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð¾Ð¼ Ctrl+Shift+V Ctrl+Shift+V &Delete &Удалить Delete Удалить Delete selection Удалить выделение Del Del &Clip &Клип Clip Клип Select clip Clip selection mode режим Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ»Ð¸Ð¿Ð¾Ð² &Range &ОблаÑть Range ОблаÑть Select range Выделить облаÑть Range selection mode Режим Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¾Ð±Ð»Ð°Ñти R&ectangle &ПрÑмоугольник Rect Select rectangle Rectangular selection mode ПрÑмоугольный режим Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ &Automation Automation Automation edit mode &None &СнÑть выделение Select None СнÑть выделение Select none СнÑть выделение Mark all as unselected СнÑть выделение Ñо вÑех Ñлементов Ctrl+Shift+A Ctrl+Shift+A &Invert Select Invert Инвертировать выделение Select invert Инвертировать выделение Invert selection Ctrl+I Ctrl+I Select Range Выделить облаÑть Mark range as selected Пометить облаÑть выделенной Ctrl+R Ctrl+R Select Track Выделить дорожку Select track Выделить дорожку Mark track as selected Пометить дорожку выделенной Ctrl+T Ctrl+T Trac&k Range Select Track Range Select track range Mark track range as selected Ctrl+Shift+R &All &Ð’ÑÑ‘ Select All Выделить вÑÑ‘ Select all Выбрать вÑÑ‘ Mark all as selected Пометить вÑÑ‘ выделенным Ctrl+A Ctrl+A &New... &Создать... New Clip Создать клип New clip Создать клип Create new clip Создать новый клип &Edit... &Изменить... Edit Clip Изменить клип Edit clip Изменить клип Edit current clip Изменить текущий клип F4 F4 &Split &Разделить Split Clip Разделить клип Split clip Разделить клип Split current clip at playhead Разделить клип по курÑору воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Normalize Clip Ðормализовать клип Normalize clip Ðормализовать клип Normalize current clip (gain/volume) ВыровнÑть уÑиление/громкоÑть выбранного клипа &Quantize От&квантовать Quantize Clip Отквантовать клип Quantize clip Отквантовать клип Quantize current MIDI clip (snap to beat) ВыровнÑть ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð² выбранном MIDI-клипе по Ñетке E&xport... &ЭкÑпортировать... Export Clip ЭкÑпортировать клип Export clip ЭкÑпортировать клип Export current clip to file ЭкÑпортировать клип в файл &Add Track... &Добавить дорожку... &Range... Remove Range Remove range Remove range as selected Ctrl+Del Remove Track Range Remove track range Remove track range as selected Ctrl+Shift+Del Sp&lit Split Selection Split selection Split current selection Ctrl+Y Add Track Добавить дорожку Add track Добавить дорожку Add a new track to session Добавить в ÑÐµÐ°Ð½Ñ Ð½Ð¾Ð²ÑƒÑŽ дорожку Shift+Ins Shift+Ins &Remove Track &Удалить дорожку Remove Track Удалить дорожку Remove track Удалить дорожку Remove current track from session Удалить текущую дорожку из ÑеанÑа Shift+Del Shift+Del Track &Properties... С&войÑтва дорожки... Track Properties СвойÑтва дорожки Track properties СвойÑтва дорожки Edit current track properties Изменить ÑвойÑтва текущей дорожки Shift+F2 Shift+F2 &Inputs &Входы Track Inputs Входы дорожки Track inputs Входы дорожки Show current track input bus connections Показать активные ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ ÑˆÐ¸Ð½Ð¾Ð¹ входа &Outputs Ð’&ыходы Track Outputs Выходы дорожки Track outputs Выходы дорожки Show current track output bus connections Показать активные ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ ÑˆÐ¸Ð½Ð¾Ð¹ выхода &Record &ЗапиÑÑŒ Record Track ЗапиÑать дорожку Record track ЗапиÑать дорожку Arm current track for recording Включить режим запиÑи Ð´Ð»Ñ Ñтой дорожки &Mute &Приглушение Mute Track Приглушить дорожку Mute track Приглушить дорожку Mute current track Приглушить текущую дорожку &Solo &Солирование Solo Track Сделать дорожку Ñолирующей Solo track Сделать дорожку Ñолирующей Solo current track Сделать текущую дорожку Ñолирующей M&onitor &Мониторинг Monitor Track Включить мониторинг дорожки Monitor track Включить мониторинг дорожки Monitor current track Включить мониторинг текущей дорожки &First П&ÐµÑ€Ð²Ð°Ñ First Track К первой дорожке First track К первой дорожке Make current the first track Перейти к первой в ÑпиÑке дорожке &Previous &ÐŸÑ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ Previous Track К предыдущей дорожке Previous track К предыдущей дорожке Make current the previous track Перейти к предыдущей в ÑпиÑке дорожке &Next &Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Next Track К Ñледующей дорожке Next track К Ñледующей дорожке Make current the next track Перейти к Ñледующей в ÑпиÑке дорожке &Last П&оÑледнÑÑ Last Track К поÑледней дорожке Last track К поÑледней дорожке Make current the last track Перейти к поÑледней в ÑпиÑке дорожке N&one None Track None track None current track &Top Ð’ Ñамый &верх Move Top ПеремеÑтить в Ñамый верх Move top ПеремеÑтить в Ñамый верх Move current track to top ПеремеÑтить текущую дорожку в Ñамый верх &Up &Выше Move Up ПеремеÑтить выше Move up ПеремеÑтить выше Move current track up ПеремеÑтить текущую дорожку выше &Down &Ðиже Move Down ПеремеÑтить ниже Move down ПеремеÑтить ниже Move current track down ПеремеÑтить текущую дорожку ниже &Bottom Ð’ Ñ&амый низ Move Bottom ПеремеÑтить в Ñамый низ Move bottom ПеремеÑтить в Ñамый низ Move current track to bottom ПеремеÑтить текущую дорожку в Ñамый низ A&uto Monitor &Ðвтомониторинг Auto Monitor Ðвтомониторинг Auto monitor Ðвтомониторинг Auto-monitor current track Ðвтомониторинг текущей дорожки F6 F6 &Audio... &Звук... Inport Audio File Импортировать звуковой файл Import Audio file Импортировать звуковой файл Import tracks from Audio file Импортировать дорожки из звукового файла &MIDI... &MIDI... Import MIDI File Импортировать файл MIDI Import MIDI file Импортировать файл MIDI Import tracks from MIDI file Импортировать дорожки из файла MIDI Export Audio File ЭкÑпортировать звуковой файл Export Audio file ЭкÑпортировать звуковой файл Export tracks to Audio file ЭкÑпортировать дорожки в звуковой файл Export MIDI File ЭкÑпортировать файл MIDI Export MIDI file ЭкÑпортировать файл MIDI Export tracks to MIDI file ЭкÑпортировать дорожки в файл MIDI Log&arithmic Automation logarithmic Automation curve logarithmic scale C&olor... Automation color Automation curve color &Lock Automation lock Lock automation curve Automation playback Playback automation curve Automation record Record automation curve &Clear Automation clear Clear automation curve Loc&k All Automation lock all Lock all automation curves Play &All Automation playback all Playback all automation curves Rec&ord All Automation record all Record all automation curves C&lear All Automation clear all Clear all automation curves &Unlink Unlink Clip Unlink clip Unlink current clip &Range Set Clip Range Clip range Set edit-range from current clip extents &Loop Set Clip Loop Clip loop Set loop-range from current clip extents First Take First take Select current clip first take Previous Take Previous take Select current clip previous take Next Take Next take Select current clip next take Shift+T Last Take Last take Select current clip last take Reset Takes Reset takes Reset (unfold) current clip takes R&ange... Take Range Take range Range (fold) current clip into takes &Menubar Строка &меню Menubar Строка меню Show/hide the main program window menubar Показать или Ñкрыть меню оÑновного окна программы Ctrl+M Ctrl+M &Statusbar &Строка ÑоÑтоÑÐ½Ð¸Ñ Statusbar Строка ÑоÑтоÑÐ½Ð¸Ñ Show/hide the main program window statusbar Показать или Ñкрыть Ñтроку ÑоÑтоÑÐ½Ð¸Ñ Ð¾Ñновного окна программы File Toolbar Панель файлов File toolbar Панель файлов Show/hide main program window file toolbar Показать или Ñкрыть панель файлов в оÑновном окне программы Edit Toolbar Панель правки Edit toolbar Панель правки Show/hide main program window edit toolbar Показать или Ñкрыть панель правки в оÑновном окне программы Track Toolbar Панель дорожек Track toolbar Панель дорожек Show/hide main program window track toolbar Показать или Ñкрыть панель параметров в оÑновном окне программы View Toolbar Панель вида View toolbar Панель вида Show/hide main program window view toolbar Показать или Ñкрыть панель вида в оÑновном окне программы &Options &Параметры Options Toolbar Панель параметров Options toolbar Панель параметров Show/hide main program window options toolbar Показать или Ñкрыть панель параметров в оÑновном окне программы Transport Toolbar Панель транÑпорта Transport toolbar Панель транÑпорта Show/hide main program window transport toolbar Показать или Ñкрыть панель транÑпорта в оÑновном окне программы T&ime Сч&етчик времени Time Toolbar Панель Ñчетчика времени Time toolbar Панель Ñчетчика времени Show/hide main program window time toolbar Показать или Ñкрыть Ñчетчик времени в оÑновном окне программы Thum&b О&бзор проекта Thumb Toolbar Панель обзора проекта Thumb toolbar Панель обзора проекта Show/hide main program window thumb toolbar Показать или Ñкрыть панель обзора проекта в оÑновном окне программы &Files &Файлы Files Файлы Show/hide the files window Показать или Ñкрыть панель доÑтупа к файлам M&essages Соо&Ð±Ñ‰ÐµÐ½Ð¸Ñ Messages Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Show/hide the messages window Показать или Ñкрыть панель Ñообщений &Connections &Ð¡Ð¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Connections Ð¡Ð¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Show/hide the connections window Показать или Ñкрыть диалог ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÑоединениÑми F8 F8 Mi&xer Микш&ер Mixer Микшер Show/hide the mixer window Показать или Ñкрыть диалог микшера F9 F9 &In &Приблизить Zoom In Приблизить отображение Zoom in Приблизить отображение дорожек Ctrl++ Ctrl++ &Out &Отдалить Zoom Out Отдалить отображение Zoom out Отдалить отображение дорожек Ctrl+- Ctrl+- &Reset &СброÑить Insert Range Insert range Insert range as selected Ctrl+Ins Insert Track Range Insert track range Insert track range as selected Ctrl+Shift+Ins &Increase Increase Height Increase height Increase track height Ctrl+Shift++ &Decrease Decrease Height Decrease height Decrease track height Ctrl+Shift+- Height Reset Height reset Reset track height Ctrl+Shift+1 Auto &Monitor Zoom Reset Обычный маÑштаб Zoom reset СброÑить вÑе Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¼Ð°Ñштаба Ctrl+1 &Horizontal По &горизонтали Horizontal Zoom МаÑштабирование по горизонтали Horizontal zoom МаÑштабирование по горизонтали Horizontal zoom mode Включить или выключить режим маÑÑˆÑ‚Ð°Ð±Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ горизонтали &Vertical По &вертикали Vertical Zoom МаÑштабирование по вертикали Vertical zoom МаÑштабирование по вертикали Vertical zoom mode Включить или выключить режим маÑÑˆÑ‚Ð°Ð±Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ вертикали All Zoom МаÑштабирование во вÑех направлениÑÑ… All zoom МаÑштабирование во вÑех направлениÑÑ… All zoom mode Включить или выключить режим маÑÑˆÑ‚Ð°Ð±Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ð¾ вÑех направлениÑÑ… &Grid К &Ñетке Grid Сетка Snap grid view mode &Zebra Zebra Bar zebra view mode Too&l Tips Tool tips Floating tool tips view mode &Refresh О&бновить Refresh Обновить Refresh views Обновить вид проекта F5 F5 &Instruments... &ИнÑтрументы... Instruments ИнÑтрументы Change instrument definitions and files Изменить Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¸ файлы инÑтрументов &Buses... &Шины... Buses Шины Change session bus definitions Изменить Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÑˆÐ¸Ð½Ñ‹ ÑеанÑа Tempo M&ap... &Карта темпа... Tempo Map Карта темпа Tempo map Карта темпа Change session tempo map Изменить карту темпа ÑеанÑа &Options... &Параметры... Options Параметры Change general application program options Изменить общие параметры работы программы F12 F12 &Backward Ð’ &начало Backward Ð’ начало Transport backward Перемотать в начало Backspace Backspace Re&wind Ð&азад Rewind Ðазад Transport rewind Перемотать назад F&ast Forward &Вперед Fast Forward Вперед Fast forward Вперед Transport fast forward Перемотать вперед &Forward Ð’ &конец Forward Ð’ конец Transport forward Перемотать в конец &Loop &ÐŸÐµÑ‚Ð»Ñ Loop ÐŸÐµÑ‚Ð»Ñ Transport loop ÐŸÐµÑ‚Ð»Ñ Ñ‚Ñ€Ð°Ð½Ñпорта Ctrl+Shift+L Ctrl+Shift+P Shift+Ctrl+L Shift+Ctrl+L Loop &Set УÑтановить п&етлю Loop Set УÑтановить петлю Loop set УÑтановить петлю Transport loop set УÑтановить петлю Ctrl+L Ctrl+L &Stop &Стоп Stop Стоп Transport stop ОÑтановить транÑпорт &Play Ð’&оÑпроизведение Tempo M&ap / Markers... Tempo Map / Markers Tempo map / markers Change session tempo map / markers Play ВоÑпроизведение Transport play/pause ВоÑпроизведение/пауза Space Пробел Record ЗапиÑÑŒ Transport record ЗапиÑÑŒ &Punch &Врезка Punch Врезка Punch in/out Ðачало/конец врезки Transport punch in/out Ðачало/конец врезки транÑпорта Shift+Ctrl+P Shift+Ctrl+P Punch Se&t УÑтановить &врезку Punch Set УÑтановить врезку Punch in/out set УÑтановить начало/конец врезки Transport punch in/out set УÑтановить начало/конец врезки Ctrl+P Ctrl+P &Metronome М&етроном Metronome Метроном F&ollow Playhead С&ледовать за курÑором воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Follow Playhead Следовать за курÑором воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Follow playhead Следовать за курÑором воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ A&uto Backward Ðв&товозврат Auto Backward Ðвтовозврат Auto backward Ðвтовозврат &Continue Past End &Играть поÑле конца Continue Past End Играть поÑле конца Continue past end Играть поÑле конца Pa&nic Panic All MIDI tracks shut off (panic) &Shortcuts... &Клавиатурные комбинации... Shortcuts Клавиатурные комбинации Keyboard shortcuts Клавиатурные комбинации &About... &О программе... Show information about this application program Показать информацию об Ñтом приложении About &Qt... О &Qt... About Qt О Qt Show information about the Qt toolkit Показать ифнормацию об инÑтрументарии Qt Current time (playhead) Текущее Ð²Ñ€ÐµÐ¼Ñ (по курÑору воÑпроизведениÑ) Current tempo (BPM) Текущий темп (BPM) &Merge... &Объединить... Merge Clips Объединить клипы Merge clips Объединить клипы Merge selected clips Объединить выделенные клипы N&ormalize &Ðормализовать &Quantize... &Отквантовать... Quantize clip events Quantize current MIDI clip events &Transpose... &ТранÑпонировать... Transpose Clip Transpose clip events Transpose current MIDI clip events &Normalize... &Ðормализовать... Normalize clip events Normalize current MIDI clip events &Randomize... &Случайные значениÑ... Randomize Clip Randomize clip events Randomize current MIDI clip events Resi&ze... Resize Clip Resize clip events Resize current MIDI clip events Re&scale... Rescale Clip Rescale clip events Rescale current MIDI clip events T&imeshift... Timeshift Clip Timeshift clip events Timeshift current MIDI clip events &Tempo... Tempo Adjust Adjust session tempo from current clip selection F7 F7 &Import... &Импортировать... Import Clip Import clip Import clip from file(s) &Controllers... К&онтроллеры... Controllers Контроллеры Change MIDI controllers configuration Изменить конфигурацию контроллеров MIDI qtractorMessages Messages Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Logging stopped --- %1 --- Ведение журнала оÑтановлено --- %1 --- Logging started --- %1 --- Ведение журнала начато --- %1 --- qtractorMeter Pan Панорама Gain УÑиление qtractorMidiControlButton MIDI Controller... MIDI-контроллер... qtractorMidiControlForm Warning Предупреждение Controller mappings have been changed. Карта ÑвÑзанных каналов/контроллеров изменилаÑÑŒ. Do you want to save the changes? Ð’Ñ‹ хотите Ñохранить Ñти изменениÑ? Controller settings have been changed. Параметры контроллеров изменилиÑÑŒ. Do you want to apply the changes? Применить внеÑенные изменениÑ? Import Controller Files Импорт конфигурации контроллеров Controller files (*.%1) Файлы Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸ÐµÐ¹ контроллеров (*.%1) Export Controller File ЭкÑпорт конфигурации контроллеров The controller file already exists: "%1" Do you want to replace it? Этот файл Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸ÐµÐ¹ уже добавлен: "%1" Ð’Ñ‹ хотите заменить его? Yes Да No Ðет Controllers - Qtractor Контроллеры - Qtractor Controller files Файлы контроллеров Files Файлы Path РаÑположение Import controllers file Импортировать файл Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸ÐµÐ¹ контроллеров &Import... &Импортировать... Alt+I Alt+и Remove controller file Удалить файл Ñ Ð¾Ð¿Ð¸Ñанием контроллеров &Remove &Удалить Alt+R Alt+у Move controller file up on list order ПеремеÑтить файл конфигурации вверх по ÑпиÑку &Up &Выше Alt+U Alt+в Move controller file down on list order ПеремеÑтить файл конфигурации вниз по ÑпиÑку &Down &Ðиже Alt+D Alt+н C&hannel К&анал &Controller &Контроллер C&ommand Ко&манда &Parameter &Параметр MIDI Channel Канал MIDI MIDI Controller Контроллер MIDI Command type Тип команды Command parameter Параметр команды Commend feedback Отклик команды &Feedback Отк&лик Map channel/controller command Команда ÑвÑÐ·Ñ‹Ð²Ð°Ð½Ð¸Ñ ÐºÐ°Ð½Ð°Ð»Ð°/контроллера &Map &СвÑзать Alt+M Alt+Ñ Unmap channel/controller command Убрать ÑвÑзывание канала/контроллера U&nmap &Удалить Alt+N Alt+у Controller map Карта контроллеров Channel Канал Controller Контроллер Command Команда Parameter Параметр &Type Т&ип &Channel &Канал Trac&k Offset MIDI Event type MIDI Controller (parameter) MIDI parameter (track offset) + Track offset Type Тип Track Дорожка Feedback Отклик Reload/apply all controller files Потоврно загрузить и применить конфигурации контроллеров Relo&ad Пере&загрузить Alt+A Alt+з Export to controller file ЭкÑпортировать в файл конфигурации контроллеров E&xport... &ЭкÑпортировать... Alt+X Alt+Ñ Close this dialog Закрыть Ñтот диалог Close Закрыть Saved controller mappings may not be effective the next time you start this program. "%1" Do you want to apply to controller files? Import controller files Импорт файлов конфигурации контроллеров Command action ДейÑтвие команды Command feedback Отклик команды Map/update controller command СвÑзать/обновить команду контроллера Unmap/remove controller command Убрать ÑвÑзывание команды контроллера About to remove controller file: "%1" Are you sure? qtractorMidiControlObserverForm MIDI Controller - Qtractor &Type: MIDI event type Cha&nnel: MIDI channel In&vert &Hook Control input connections &Inputs &Входы Control output connections &Outputs Ð’&ыходы (Any) (Любой) &Parameter: MIDI parameter &Logarithmic &Feedback Отк&лик MIDI Controller Контроллер MIDI MIDI controller is already assigned. Do you want to replace the mapping? Some settings have been changed. Do you want to apply the changes? Ðекоторые параметры изменилиÑÑŒ. Ð’Ñ‹ хотите применить изменениÑ? &MIDI Controller... &Automation &Lock &Play Ð’&оÑпроизведение &Record &ЗапиÑÑŒ &Clear qtractorMidiEditEvent Zoom in (horizontal) Приблизить по горизонтали Zoom out (horizontal) Отдалить по горизонтали Zoom reset (horizontal) ИÑходный маÑштаб по горизонтали qtractorMidiEditList C%1 C%1 qtractorMidiEditTime Play-head Edit-head Edit-tail Loop-start Loop-end Punch-in Punch-out Start: %1 End: %2 Length: %3 qtractorMidiEditView Zoom in (vertical) Приблизить по вертикали Zoom out (vertical) Отдалить по вертикали Zoom reset (vertical) ИÑходный маÑштаб по вертикали qtractorMidiEditor MIDI Editor Редактор MIDI cut вырезание delete удаление insert range remove range move перемещение edit правка resize Ñмена размера rescale paste вÑтавка Time: %1 Type: ВремÑ: %1 Тип: Note On (%1) %2 Velocity: %3 Duration: %4 Ðота (%1) %2 Сила нажатиÑ: %3 ДлительноÑть: %4 Key Press (%1) %2 Value: %3 Controller (%1) Name: %2 Value: %3 Контроллер (%1) Ðазвание: %2 Значение: %3 Pgm Change (%1) Chan Press (%1) Pitch Bend (%1) Start: %1 End: %2 Length: %3 SysEx (%1 bytes) Data: SysEx (%1 байтов) Данные: Unknown (%1) ÐеизвеÑтно (%1) qtractorMidiEditorForm Snap/beat Прилипание к долÑм Note On Set current snap to %1 Key Press Note Velocity Controller Контроллер Pitch Bend System Exclusive System Exclusive Pgm Change Chan Press Sys Ex Note type Value type Controller type Scale key Scale type MIDI clip name Ð˜Ð¼Ñ ÐºÐ»Ð¸Ð¿Ð° MIDI MIDI file name Ð˜Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° MIDI MIDI track/channel Дорожка/канал MIDI MOD РЕЖ MIDI modification state СоÑтоÑние измененноÑти MIDI 00:00:00.000 00:00:00.000 MIDI clip duration ДлительноÑть клипа MIDI Warning Предупреждение The current MIDI clip has been changed: "%1" Do you want to save the changes? Открытый клип был изменен: "%1" Ð’Ñ‹ хотите Ñохранить изменениÑ? Save Сохранить Save MIDI Clip Сохранить клип MIDI MIDI files (*.%1 *.smf *.midi) Файлы MIDI (*.%1 *.smf *.midi) MIDI file save: "%1", track-channel: %2. Сохранение файла MIDI: "%1", дорожка-канал: %2. MIDI Editor Редактор MIDI Channel %1 Канал %1 Track %1 Дорожка %1 [modified] [изменен] &Track &Дорожка &File &Файл Select &Mode &Режим Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ &Select Ð’Ñ‹&деление &Tools &ИнÑтрументы &Edit &Правка &View &Вид &Toolbars &Панели инÑтрументов &Windows &Zoom МаÑш&таб S&nap При&липание T&ransport &ТранÑпорт &Help &Справка &Context &КонтекÑÑ‚ &Save &Сохранить Save current MIDI clip to existing file name Сохранить активный клип MIDI в уже ÑущеÑтвующий файл Save &As... Сохранить &как... Save As Сохранить как Save as Сохранить как Save current MIDI clip with another file name Сохранить активный клип MIDI в файл Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼ именем &Unlink Unlink Unlink current MIDI clip &Inputs &Входы Track Inputs Входы дорожки Track inputs Входы дорожки Show current MIDI clip/track input bus connections Показать активные ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ ÑˆÐ¸Ð½Ð¾Ð¹ входа MIDI-клипа или дорожки &Outputs Ð’&ыходы Track Outputs Выходы дорожки Track outputs Выходы дорожки Show current MIDI clip/track output bus connections Показать активные ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ ÑˆÐ¸Ð½Ð¾Ð¹ выхода MIDI-клипа или дорожки &Properties... С&войÑтва... Track Properties СвойÑтва дорожки Track properties СвойÑтва дорожки Edit current MIDI clip/track properties Изменить ÑвойÑтва активного клипа/дорожки MIDI Shift+F2 Shift+F2 Properties СвойÑтва Edit current MIDI clip properties Изменить ÑвойÑтва активного клипа MIDI F4 F4 &Range Set Clip Range Clip range Set edit-range from clip extents &Loop Set Clip Loop Clip loop Set loop-range from clip extents &Close &Закрыть Close Закрыть Close this MIDI clip editor Закрыть Ñтот диалог Edit Of&f Edit Off Edit off Set edit mode off Edit &On Edit On Edit on Set edit mode on Edit &Draw Edit draw mode Edit draw mode (notes) &Undo &Отменить Sc&ale Undo Отменить Undo last edit operation Отменить поÑледнее дейÑтвие Ctrl+Z Ctrl+Z &Redo Ве&рнуть Redo Вернуть Redo last edit operation Вернуть отмененное дейÑтвие Ctrl+Shift+Z Ctrl+Shift+Z Cu&t &Вырезать Cut Вырезать Cut current selection into the local clipboard Вырезать активное выделение в буфер обмена Ctrl+X Ctrl+X &Copy &Копировать Copy Копировать Copy current selection to the local clipboard Скопировать активное выделение в буфер обмена Ctrl+C Ctrl+C &Paste Ð’ÑÑ‚&авить Paste Ð’Ñтавить Paste local clipboard contents into the current MIDI clip Ð’Ñтавить Ñодержимое буфера обмена Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð¾Ð¼ в текущий клип MIDI Ctrl+V Ctrl+V Past&e Repeat... Ð’Ñтав&ить Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð¾Ð¼... Paste Repeat Ð’Ñтавить Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð¾Ð¼ Paste repeat Ð’Ñтавить Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð¾Ð¼ Paste/repeat local clipboard contents into the current MIDI clip Ð’Ñтавить Ñодержимое буфера обмена Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð¾Ð¼ в текущий клип MIDI Ctrl+Shift+V Ctrl+Shift+V &Delete &Удалить Delete Удалить Delete current selection Удалить активное выделение Del Del Select &None Сн&Ñть выделение Select None СнÑть выделение Select none СнÑть выделение Ctrl+Shift+A Ctrl+Shift+A Select &Invert &Инвертировать выделение Select Invert Инвертировать выделение Select invert Инвертировать выделение Ctrl+I Ctrl+I Select &All Ð’&ыделить вÑÑ‘ Select All Выделить вÑÑ‘ Select all Выбрать вÑÑ‘ Ctrl+A Ctrl+A &Range &ОблаÑть Select Range Выделить облаÑть Select range Выделить облаÑть Mark range as selected Пометить облаÑть выделенной Ctrl+R Ctrl+R &Quantize... &Отквантовать... Quantize Отквантовать Quantize selection Отквантовать выделение &Transpose... &ТранÑпонировать... Transpose ТранÑпонировать Transpose selection ТранÑпонировать выделение &Normalize... &Ðормализовать... Normalize Ðормализовать Normalize selection Ðормализовать выделение &Randomize... &Случайные значениÑ... Randomize Применить Ñлучайные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Randomize selection Применить к выделению Ñлучайные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Re&size... &Изменить размер... Resize Изменить размер Resize selection Изменить размер Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Re&scale... Rescale Rescale selection T&imeshift... Timeshift Timeshift selection &Menubar Строка &меню Menubar Строка меню Show/hide the menubar Показать или Ñкрыть Ñтроку меню Ctrl+M Ctrl+M &Statusbar &Строка ÑоÑтоÑÐ½Ð¸Ñ Statusbar Строка ÑоÑтоÑÐ½Ð¸Ñ Show/hide the statusbar Показать или Ñкрыть Ñтроку ÑоÑтоÑÐ½Ð¸Ñ File Toolbar Панель файлов File toolbar Панель файлов Show/hide the file toolbar Показать или Ñкрыть панель доÑтупа к файлам Edit Toolbar Панель правки Edit toolbar Панель правки Show/hide the edit toolbar Показать или Ñкрыть панель доÑтупа к файлам View Toolbar Панель вида View toolbar Панель вида Show/hide the view toolbar Показать или Ñкрыть панель вида &Transport Transport Toolbar Панель транÑпорта Transport toolbar Панель транÑпорта Show/hide the transport toolbar Показать или Ñкрыть панель транÑпорта &Scale Scale Toolbar Scale toolbar Show/hide the scale toolbar Note &Duration &ДлительноÑть нот Note Duration ДлительноÑть нот Note duration ДлительноÑть нот Whether note events are shown proportional to duration Отображать ли ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð¿Ñ€Ð¾Ð¿Ð¾Ñ€Ñ†Ð¸Ð¾Ð½Ð°Ð»ÑŒÐ½Ð¾ длительноÑти нот Note &Color &Цвет выÑоты тона Note Color Цветные ноты Note color Цветные ноты Whether note events are colored according to pitch РаÑкрашивать ли ноты ÑоглаÑно их выÑоте тона &Value Color Цвет Ñилы &Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ Value Color Цвет Ñилы Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ Value color Цвет Ñилы Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ Whether note events are colored according to value (velocity) РаÑкрашивать ли ноты ÑоглаÑно их Ñиле Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ &Events View events Show/hide the events list &Preview Notes &ВоÑпроизводить при правке Preview Notes ВоÑпроизводить при правке Preview notes ВоÑпроизводить ноты при правке Preview notes while editing (scrub) ВоÑпроизводить ноты при редактировании F&ollow Playhead С&ледовать за курÑором воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Follow Playhead Следовать за курÑором воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Follow playhead Следовать за курÑором воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ &In &Приблизить Zoom In Приблизить отображение Zoom in Приблизить отображение Ctrl++ Ctrl++ &Out &Отдалить Zoom Out Отдалить отображение Zoom out Отдалить отображение Ctrl+- Ctrl+- &Reset &СброÑить Zoom Reset Обычный маÑштаб Zoom reset Обычный маÑштаб Ctrl+1 &Horizontal По &горизонтали Horizontal Zoom МаÑштабирование по горизонтали Horizontal zoom МаÑштабирование по горизонтали Horizontal zoom mode Включить или выключить режим маÑÑˆÑ‚Ð°Ð±Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ горизонтали &Vertical По &вертикали Vertical Zoom МаÑштабирование по вертикали Vertical zoom МаÑштабирование по вертикали Vertical zoom mode Включить или выключить режим маÑÑˆÑ‚Ð°Ð±Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ вертикали &Zebra Zebra Bar zebra view mode Ctrl+Shift+L Ctrl+Shift+P &All &Во вÑех направлениÑÑ… I&nsert Remo&ve &None &СнÑть выделение &Invert Insert Range Insert range Insert range as selected Ctrl+Ins Remove Range Remove range Remove range as selected Ctrl+Del All Zoom МаÑштабирование во вÑех направлениÑÑ… All zoom МаÑштабирование во вÑех направлениÑÑ… All zoom mode Включить или выключить режим маÑÑˆÑ‚Ð°Ð±Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ð¾ вÑех направлениÑÑ… Snap grid view mode Too&l Tips Tool tips Floating tool tips view mode &Refresh О&бновить Refresh Обновить Refresh views Обновить вид клипа F5 F5 &Backward Ð’ &начало Backward Ð’ начало Transport backward Перемотать в начало Backspace Backspace Re&wind Ð&азад Rewind Ðазад Transport rewind Перемотать назад F&ast Forward &Вперед Fast Forward Вперед Fast forward Вперед Transport fast forward Перемотать вперед &Forward Ð’ &конец Forward Ð’ конец Transport forward Перемотать в конец &Loop &ÐŸÐµÑ‚Ð»Ñ Loop ÐŸÐµÑ‚Ð»Ñ Transport loop ÐŸÐµÑ‚Ð»Ñ Ñ‚Ñ€Ð°Ð½Ñпорта Shift+Ctrl+L Shift+Ctrl+L Loop &Set УÑтановить п&етлю Loop Set УÑтановить петлю Loop set УÑтановить петлю Transport loop set УÑтановить петлю Ctrl+L Ctrl+L &Stop &Стоп Stop Стоп Transport stop ОÑтановить транÑпорт &Play Ð’&оÑпроизведение Play ВоÑпроизведение Transport play/pause ВоÑпроизведение/пауза Space Пробел &Record &ЗапиÑÑŒ Record ЗапиÑÑŒ Transport record ЗапиÑÑŒ &Punch &Врезка Punch Врезка Punch in/out Ðачало/конец врезки Transport punch in/out Ðачало/конец врезки транÑпорта Shift+Ctrl+P Shift+Ctrl+P Punch Se&t УÑтановить &врезку Punch Set УÑтановить врезку Punch in/out set УÑтановить начало/конец врезки Transport punch in/out set УÑтановить начало/конец врезки Ctrl+P Ctrl+P Pa&nic Panic All MIDI tracks shut off (panic) &Shortcuts... &Клавиатурные комбинации... Shortcuts Клавиатурные комбинации Keyboard shortcuts Клавиатурные комбинации &About... &О программе... About О программе Show information about this application program Показать информацию об Ñтом приложении About &Qt... О &Qt... About Qt О Qt Show information about the Qt toolkit Показать ифнормацию об инÑтрументарии Qt &Grid К &Ñетке Resi&ze... Grid Сетка Snap grid mode Прилипание к Ñетке qtractorMidiEventItemDelegate edit %1 qtractorMidiEventList Events qtractorMidiEventListModel Time Ð’Ñ€ÐµÐ¼Ñ Type Тип Name Ðазвание Value Duration/Data Frame BBT BBT Note On (%1) Note Off (%1) Key Press (%1) Controller (%1) Pgm Change Chan Press Pitch Bend SysEx Meta (%1) Unknown (%1) ÐеизвеÑтно (%1) qtractorMidiListView Name Ðазвание Fmt Фмт Tracks Дорожки tpqn Path РаÑположение Open MIDI Files Открыть файлы MIDI MIDI files (*.%1 *.smf *.midi) Файлы MIDI (*.%1 *.smf *.midi) qtractorMidiMeter Volume (%) ГромкоÑть (%) % % Pan: %1 Панорама: %1 Volume: %1% ГромкоÑть: %1% qtractorMidiSysexForm MIDI SysEx - Qtractor MIDI SysEx Name Ðазвание Size Размер Data (hex) Import from SysEx file ЭкÑпортировать из файла SysEx &Import... &Импортировать... Alt+I Alt+и Export to SysEx file ЭкÑпортировать в файл SysEx E&xport... &ЭкÑпортировать... Alt+X Alt+Ñ Move SysEx item up on list order &Up &Выше Alt+U Move SysEx item down on list order &Down &Ðиже Alt+D Open SysEx Sysex name Save SysEx Delete SysEx Create SysEx item &Add &Добавить Alt+A Update SysEx item Upda&te О&бновить Alt+T Alt+б Remove SysEx item &Remove &Удалить Alt+R Alt+у SysEx files (*.%1) Файлы SysEx (*.%1) MIDI files (*.mid *.smf *.midi) Файлы MIDI (*.mid *.smf *.midi) All files (*.*) Ð’Ñе файлы (*.*) Import SysEx Files Импортировать файлы SysEx Export SysEx File ЭкÑпортировать файлы SysEx Warning Предупреждение The SysEx file already exists: "%1" Do you want to replace it? Sysex files (*.%1) Файлы SysEx (*.%1) About to replace SysEx: "%1" Are you sure? About to delete SysEx: "%1" Are you sure? SysEx settings have been changed. Do you want to apply the changes? Error Ошибка SysEx could not be loaded: "%1". Sorry. qtractorMidiToolsForm (default) (по умолчанию) Warning Предупреждение About to delete preset: "%1" Are you sure? Эта предуÑтановка будет удалена: "%1" Ð’Ñ‹ уверены? OK &ОК Cancel О&тменить none нет quantize квантование transpose транÑпонирование normalize Ð½Ð¾Ñ€Ð¼Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ randomize Ñлучайные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ resize Ñмена размера rescale timeshift MIDI Tools ИнÑтрументы MIDI Preset name Ðазвание предуÑтановки Save preset Сохранить предуÑтановку Delete preset Удалить предуÑтановку &Quantize &Квантование Quantize selected events Квантование выделенных Ñобытий &Time: &ВремÑ: Quantize time Ð’Ñ€ÐµÐ¼Ñ ÐºÐ²Ð°Ð½Ñ‚Ð¾Ð²Ð°Ð½Ð¸Ñ Quantize time percent &Duration: &ДлительноÑть: Quantize duration ДлительноÑть ÐºÐ²Ð°Ð½Ñ‚Ð¾Ð²Ð°Ð½Ð¸Ñ Quantize duration percent Swing-quantize time Swing-quantize percent Swing-quantize type Linear Линейное Quadratic Квадратичное Cubic КубичеÑкое &Scale: Scale-quantize key Scale-quantize type &Transpose Т&ранÑпонирование Transpose selected events ТранÑпонирование выделенных Ñобытий &Note: &Ðота: Transpose note Величина транÑÐ¿Ð¾Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² нотах Transpose time Ð’Ñ€ÐµÐ¼Ñ Ñ‚Ñ€Ð°Ð½ÑÐ¿Ð¾Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Transpose time format Формат времени транÑÐ¿Ð¾Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Frames Выборки Time Ð’Ñ€ÐµÐ¼Ñ BBT BBT &Normalize &ÐÐ¾Ñ€Ð¼Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Normalize selected events ÐÐ¾Ñ€Ð¼Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð½Ñ‹Ñ… Ñобытий &Percent: &Процент: Normalize percent Процент нормализации Resi&ze Resize value mode Flat Ramp Resize final value Re&scale Rescale selected events Rescale time Rescale duration Rescale value T&imeshift Timeshift selected events Timeshift P: Timeshift parameter Timeshift parameter (log) Timeshift curve P = 0 : no change. P > 0 : accelerating shift. P < 0 : slowing down shift. Edit head/tail (blue) markers define the shift range. Timeshift duration % % S&wing: &Value: &Сила нажатиÑ: Normalize value Значение нормализации &Randomize &Случайные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Randomize selected events Применение Ñлучайных значений к выделению Randomize note/pitch Случайные ноты Randomize time Случайное Ð²Ñ€ÐµÐ¼Ñ Randomize duration Ð¡Ð»ÑƒÑ‡Ð°Ð¹Ð½Ð°Ñ Ð´Ð»Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñть Randomize value Ð¡Ð»ÑƒÑ‡Ð°Ð¹Ð½Ð°Ñ Ñила Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ Re&size &Размер Resize selected events Смена размера выделенных Ñобытий Resize duration Смена длительноÑти Resize duration format Формат значений Percentage Resize value Множитель qtractorMixer Inputs Входы Tracks Дорожки Outputs Выходы Mixer Микшер qtractorMixerRack &Inputs &Входы &Outputs Ð’&ыходы &Monitor &Мониторинг &Buses... &Шины... qtractorMixerStrip monitor монитор Monitor (rec) Мониторинг (запиÑÑŒ) inputs входы outputs выходы Connect %1 Соединить %1 Monitor (thru) Мониторинг (Ñквозной) %1 In Вход %1 %1 Out Выход %1 (Audio) (аудио) Gain УÑиление (MIDI) (MIDI) Volume ГромкоÑть (None) (нет) Pan Панорама qtractorMonitorButton monitor монитор Monitor (rec) Мониторинг (запиÑÑŒ) Monitor (thru) Мониторинг (Ñквозной) qtractorOptionsForm Signed 16-Bit Signed 16-Bit Signed 24-Bit Signed 24-Bit Signed 32-Bit Signed 32-Bit Float 32-Bit Float 32-Bit Float 64-Bit Float 64-Bit SMF Format 0 SMF Format 0 SMF Format 1 SMF Format 1 (Any) (Любой) Warning Предупреждение Some settings have been changed. Do you want to apply the changes? Ðекоторые параметры изменилиÑÑŒ. Ð’Ñ‹ хотите применить изменениÑ? Cancel Отменить Metronome Bar Audio File Звуковой файл такта Ð´Ð»Ñ Ð¼ÐµÑ‚Ñ€Ð¾Ð½Ð¾Ð¼Ð° Metronome Beat Audio File Звуковой файл доли Ð´Ð»Ñ Ð¼ÐµÑ‚Ñ€Ð¾Ð½Ð¾Ð¼Ð° Plug-in Directory Каталог Ñ Ñффектами LV2 Presets Directory Messages Log Журнал Ñообщений Log files (*.%1) Файлы журнала (*.%1) Session Template Шаблон ÑеанÑа Session template files (*.qtr *.qts *.%1) Файлы шаблонов ÑеанÑа (*.qtr *.qts *.%1) Options - Qtractor Параметры - Qtractor &General Default session &file format: Default session file format (suffix) &New session template: Save &backup versions of existing sessions: Increment previous version (default) Increment current version &Audio &Звук Capture / Export Захват/ЭкÑпорт Audio compression quality to use on capture (record) and export Сжатие звуковых данных при запиÑи и ÑкÑпорте Audio sample format to use on capture (record) and export Формат ÑÑмплов при запиÑи и ÑкÑпорте Audio file type to use on capture (record) and export Формат файлов, иÑпользуемый при запиÑи и ÑкÑпорте File &type: Т&ип файла: Sample &format: &Формат ÑÑмпла: &Quality: &КачеÑтво: Playback ВоÑпроизведение Sample-&rate converter type: Преобразование &чаÑтоты ÑÑмплированиÑ: Sample-rate converter quality КачеÑтво Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ‡Ð°Ñтоты ÑÑÐ¼Ð¿Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Sinc (Best Quality) Sinc (наилучшее качеÑтво) Sinc (Medium Quality) Sinc (Ñреднее качеÑтво) Sinc (Fastest) Sinc (ÑÐ°Ð¼Ð°Ñ Ð±Ñ‹ÑÑ‚Ñ€Ð°Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ°) Zero Order Hold Linear Линейное Transport control mode (JACK) None Ðет Slave Master Full Whether to apply time-stretching when tempo changes РаÑÑ‚Ñгивать ли во времени при Ñмене темпа Aut&omatic time-stretching &ÐвтоматичеÑки раÑÑ‚Ñгивать во времени Alt+O Alt+а Whether to use WSOLA time-stretching ИÑпользовать ли WSOLA Ð´Ð»Ñ Ñ€Ð°ÑÑ‚ÑÐ³Ð¸Ð²Ð°Ð½Ð¸Ñ Ð²Ð¾ времени &WSOLA time-stretching &РаÑÑ‚Ñгивание во времени при помощи WSOLA Alt+W Alt+Ñ€ Whether to apply WSOLA quick seek time-stretching WSOLA quic&k seek Alt+K Whether to have separate audition/pre-listening player output ports Alt+D Alt+н Metronome Метроном Whether to enable the audio metronome ИÑпользовать ли звуковой метроном &Enable audio metronome &Включить звуковой метроном Alt+E Alt+в &File (bar): Фай&л (такт): Metronome Audio filename (bar) Звуковой файл такта Ð´Ð»Ñ Ð¼ÐµÑ‚Ñ€Ð¾Ð½Ð¾Ð¼Ð° Browse for sample audio file (bar) Указать звуковой файл Ð´Ð»Ñ Ð¾Ð±Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñ‚Ð°ÐºÑ‚Ð° &Gain (bar): Metronome gain (bar) dB Дб &File (beat): Фай&л (&долÑ): Metronome Audio filename (beat) Звуковой файл доли Ð´Ð»Ñ Ð¼ÐµÑ‚Ñ€Ð¾Ð½Ð¾Ð¼Ð° Browse for sample audio file (beat) Указать звуковой файл Ð´Ð»Ñ Ð¾Ð±Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¸ &Gain (beat): Metronome gain (beat) Whether to have separate audio metronome output ports Создавать ли раздельные звуковые порты выхода Ð´Ð»Ñ Ð¼ÐµÑ‚Ñ€Ð¾Ð½Ð¾Ð¼Ð° Dedicated a&udio metronome outputs Раздельные звуковые выходы Ð´Ð»Ñ &метронома Alt+U Alt+м &MIDI &MIDI MIDI capture (record) quantization &Quantize: &Квантование: MIDI file format to use on capture (record) and export File &format: &Формат файлов: Queue &timer (resolution): Queue timer (resolution) Control Управление &MMC: MIDI Machine Control (MMC) mode Input Вход Output Выход Duplex Ð”ÑƒÐ¿Ð»ÐµÐºÑ &Device: MIDI Machine Control (MMC) device id. &SPP: MIDI Song Position pointer (SPP) control mode Cloc&k: MIDI Clock control mode Whether to have separate MIDI control ports Создавать ли раздельные порты ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ MIDI Dedicated MIDI &control input/output &Раздельные порты ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ MIDI Alt+C Alt+Ñ€ Whether to have separate MIDI metronome output port Dedicated M&IDI metronome output Раздельный выход Ð´Ð»Ñ MIDI-&метронома Alt+I Alt+м &Note (beat): &Ðота (долÑ): Metronome MIDI note (beat) Metronome MIDI velocity (beat) &Duration (beat): &ДлительноÑть (beat): &Velocity (beat): &Сила Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ (beat): Metronome MIDI velocity (bar) &Duration (bar): &ДлительноÑть (такт): &Velocity (bar): &Сила Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ (такт): Metronome MIDI note (bar) &Note (bar): Ðота (Ñ‚&акт): &Channel: Кана&л: Metronome MIDI channel MIDI-канал метронома Whether to enable the MIDI metronome ИÑпользовать ли MIDI-метроном &Enable MIDI metronome &Включить MIDI-метроном &Display &Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Options Параметры Whether to ask for confirmation on removal Запрашивать ли подтверждение на удаление &Confirm removals Спрашивать подтверждение на &удаление &Number of recent files: &Запоминаемых недавних ÑеанÑов: The maximum number of recent files to keep in menu Whether to capture standard output (stdout/stderr) into messages window Capture standard &output За&хватывать оÑновной порт вывода Whether to show the complete directory path of loaded session files Show complete &path of session files &Показывать раÑположение файлов ÑеанÑов полноÑтью Alt+P Alt+п Whether to remove audio peak files on session close Auto-remove audio pea&k files &ÐвтоматичеÑки удалÑть пиковые звуковые файлы Whether to keep all tool windows on top of the main window &Keep tool windows always on top &Дочерние окна программы вÑегда наверху Time display &format: &Формат Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸: Time display format Формат Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸: Frames Выборки Time Ð’Ñ€ÐµÐ¼Ñ BBT BBT Whether to try dropping multiple audio files into the same track Drop multiple audio files into the &same track По&мещать неÑкоклько звуковых файлов в одну дорожку Alt+S Alt+м &Base font size: &Кегль шрифта в окнах: Base application font size (pt.) Кегль шрифта в окнах Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ (pt) (default) (по умолчанию) 6 6 7 7 8 8 9 9 10 10 11 11 12 12 Session Ð¡ÐµÐ°Ð½Ñ Whether to create new sessions based on template Создавать ли новые ÑеанÑÑ‹ на оÑнове шаблона New session &template: &Шаблон новых ÑеанÑов: New session template Шаблон новых ÑеанÑов Browse for new session template Указать шаблон новых ÑеанÑов Whether to save backup versions of existing sessions Which mode to rename existing session files Number of &recent files: S&how complete path of session files Keep tool &windows always on top &Drop multiple audio files into the same track Whether to reverse mouse middle-button role on keyboard modifiers (Shift/Ctrl) Re&verse middle-button modifier role (Shift/Ctrl) Transport Transport &mode: &Loop recording mode (takes): Loop recording mode (takes) First Last Dedicated au&dition/pre-listening player outputs: Whether to auto-connect dedicated audio player outputs Auto-&connect Dedicated a&udio metronome outputs: Whether to auto-connect dedicated audio metronome outputs Auto-co&nnect Alt+N Alt+у Whether to have separate MIDI player output ports Dedicated MIDI p&layer outputs Alt+L Defaults &Time display format: Meters Счетчики &Audio: &Звуковой: Audio meter level Уровень звукового Ñчетчика Over 0 dB 0 Дб 3 dB 3 Дб 6 dB 6 Дб 10 dB 10 Дб Audio meter color Цвет звукового Ñчетчика Select custom audio meter color Указать иной цвет Ð´Ð»Ñ Ð·Ð²ÑƒÐºÐ¾Ð²Ð¾Ð³Ð¾ Ñчетчика ... ... &MIDI: &MIDI: MIDI meter level Уровень Ñчетчика MIDI Peak Пик MIDI meter color Цвет Ñчетчика MIDI Select custom MIDI meter color Указать иной цвет Ð´Ð»Ñ Ñчетчика MIDI Reset meter colors to default СброÑить цвета Ñчетчиков до иÑходных значений &Reset &СброÑить Alt+R Alt+Ñ Messages Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Sample messages text font display Пример текÑта Ñообщений Select font for the messages text display Указать шрифт Ð´Ð»Ñ Ñообщений &Font... &Шрифт... Alt+F Alt+ш Whether to keep a maximum number of lines in the messages window УÑтанавливать ли предел хранимых Ñообщений M&essages limit: &LV2 Presets directory: LV2 Presets directory (default: ~/.lv2) Browse LV2 Presets directory Dedicated audi&o outputs: Whether to auto-connect dedicated audio output ports Au&to-connect Alt+T Alt+б Editor Whether to open plugin's editor (GUI) by default Open plugin's &editor (GUI) by default Alt+G &Messages limit: Предел Ñооб&щений: Alt+M Alt+щ The maximum number of message lines to keep in view МакÑимальное чиÑло хранимых Ñтрок Ñообщений lines Ñтрок Logging Ведение журнала Messages log file Файл ждурнала Ñообщений Browse for the messages log file location Указать раÑположение файла журнала Ñообщений Whether to activate a messages logging to file. ВеÑти ли журнал Ñообщений в файле Messages &log file: Файл &журнала Ñообщений: &Plugins &Эффекты Paths РаÑположение Plugin type Тип Ñффекта Plugin path РаÑположение Ñффектов Browse plugin path Указать раÑположение Ñффектов Add plugin path Добавить путь к раÑширениÑм &Add &Добавить Plugin paths РаÑположение Ñффектов Remove plugin path Удалить указатель раÑÐ¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñффектов &Remove &Удалить Move up path ПоднÑть указатель в ÑпиÑке &Up &Выше &Down &Ðиже Instruments ИнÑтрументы Whether to have separate audio output ports Создавать ли порты выхода Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ инÑтрумента Dedicated audi&o outputs Раздельные &звуковые выходы Experimental ЭкÑпериментально Whether to use a dummy plugin type when scanning for VST plugins Dummy &VST plugin scan (RECOMMENDED) Alt+V OK ОК qtractorPasteRepeatForm Warning Предупреждение Some settings have been changed. Do you want to apply the changes? Ðекоторые параметры изменилиÑÑŒ. Ð’Ñ‹ хотите применить изменениÑ? Cancel О&тменить Paste Repeat - Qtractor Ð’Ñтавка Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð¾Ð¼ Repeat Повторы &Count: &КоличеÑтво: Repeat count КоличеÑтво повторов &Period: &Период: Repeat period ПериодичноÑть повторов Repeat period format Формат периода повторов Frames Выборки Time Ð’Ñ€ÐµÐ¼Ñ BBT BBT OK &ОК qtractorPluginForm (default) (по умолчанию) Page %1 (none) Open Preset Открыть предуÑтановку Preset files (*.%1) Файлы предуÑтановок (*.%1) Error Ошибка Preset could not be loaded from "%1". Sorry. Ðе удалоÑÑŒ загрузить предуÑтановку из "%1". Извините. Save Preset Сохранить предуÑтановку Warning Предупреждение About to delete preset: "%1" (%2) Are you sure? Эта предуÑтановка будет удалена: "%1" (%2) Ð’Ñ‹ уверены? &None &СнÑть выделение qtractorPluginForm qtractorPluginForm Open preset Открыть предуÑтановку Preset name Ðазвание предуÑтановки Save preset Сохранить предуÑтановку Delete preset Удалить предуÑтановку Plugin parameters Параметры Ñффекта Params Параметры Edit plugin Изменить параметры Ñффекта Edit Изменить Activate plugin Ðктивировать Ñффект Active Ðктивен Outputs (Sends) Sends Inputs (Returns) Returns Aux Send Bus: Manage buses ÐаÑтроить шины ... ... Direct Access Parameter Direct Access qtractorPluginListView copy plugin копирование Ñффекта activate all plugins Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ñ Ð²Ñех Ñффектов deactivate all plugins Ð´ÐµÐ°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ñ Ð²Ñех Ñффектов remove all plugins удаление вÑех Ñффектов &Move Here &ПеремеÑтить Ñюда &Copy Here &Скопировать Ñюда C&ancel О&тменить &Add Plugin... &Добавить Ñффект... Add &Insert Add &Aux Send &Sends &Returns Ac&tivate &Remove &Удалить &None &СнÑть выделение &Properties... С&войÑтва... &Edit &Auto-connect Act&ivate &Ðктивировать Acti&vate All Ðктивировать &вÑе Deactivate Al&l Д&еактивировать вÑе Re&move All Уда&лить вÑе Move &Up ПеремеÑтить &выше Move &Down ПеремеÑтить &ниже &Edit Plugin... &Параметры Ñффекта... &Outputs Ð’&ыходы &Dedicated &СобÑтвенный выход qtractorPluginSelectForm GUI EXT RT Plugins - Qtractor Эффекты - Qtractor Reset filter СброÑить фильтр X Plugin search string (regular expression) Строка поиÑка Ñффектов (поддерживает регулÑрные выражениÑ) Plugin type Тип Ñффекта Available plugins ДоÑтупные Ñффекты Name Ðазвание Audio Звук MIDI MIDI Control Управление Modes Mode Режим Path РаÑположение Index Instances Копий Type Тип &Activate &Ðктивировать Activate plugin on insert Ðктивировать Ñффект на вÑтавке Alt+A Alt+а Plugin scanning in progress... ВыполнÑетÑÑ Ñканирование Ñффектов OK ОК Cancel Отменить qtractorSessionForm Warning Предупреждение Session directory does not exist: "%1" Do you want to create it? Some settings have been changed. Do you want to apply the changes? Ðекоторые параметры изменилиÑÑŒ. Ð’Ñ‹ хотите применить изменениÑ? Cancel Отменить Session Directory Каталог файлов ÑеанÑа Session - Qtractor Ð¡ÐµÐ°Ð½Ñ - Qtractor Session Ð¡ÐµÐ°Ð½Ñ &Name: &Ðазвание: Session name Ðазвание ÑеанÑа &Directory: &Каталог: Session directory Каталог файлов ÑеанÑа Browse for session directory Указать каталог Ñ Ñ„Ð°Ð¹Ð»Ð°Ð¼Ð¸ ÑеанÑа ... ... &Description: О&пиÑание: Session description ОпиÑание ÑеанÑа Properties СвойÑтва Time Ð’Ñ€ÐµÐ¼Ñ Sample &Rate: &ЧаÑтота ÑÑмплированиÑ: Sample rate (Hz) ЧаÑтота ÑÑÐ¼Ð¿Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ (Гц) 44100 44100 48000 48000 96000 96000 192000 192000 &Tempo: Т&емп: T&icks/Beat: &Тиков на долю: Resolution (ticks/beat; tpqn) Resolution (ticks/beat; TPQN) Разрешение (тиков на долю; TPQN) View Вид &Snap/Beat: Прилипание к &долÑм: Snap/beat Прилипание к долÑм &Pixels/Beat: П&икÑелов на долю: Pixels/beat ПикÑелов на долю &Horizontal Zoom: МаÑштаб по &горизонтали: Horizontal Zoom (%) МаÑштаб по горизонтали (%) % % &Vertical Zoom: МаÑштаб по &вертикали: Vertical Zoom (%) МаÑштаб по вертикали (%) OK ОК Tempo (BPM) / Signature Темп (BPM) / Размер qtractorShortcutForm Warning Предупреждение Keyboard shortcut (%1) already assigned. Keyboard shortcuts have been changed. Do you want to apply the changes? Keyboard shortcuts have been changed. Клавиатурные комбинации изменилиÑÑŒ Do you want to apply the changes? Применить внеÑенные изменениÑ? Cancel О&тменить Keyboard Shortcuts Клавиатурные комбинации Action ДейÑтвие Description ОпиÑание Shortcut ÐšÐ¾Ð¼Ð±Ð¸Ð½Ð°Ñ†Ð¸Ñ OK &ОК qtractorTakeRangeForm Take - Qtractor Range ОблаÑть Selection range &Selection Loop range Ð’ÑÑŽ петлю &Loop &ÐŸÐµÑ‚Ð»Ñ Punch range Ð’ÑÑŽ врезку &Punch &Врезка Time Ð’Ñ€ÐµÐ¼Ñ BBT BBT Edit range ОблаÑть Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ &Edit Custom range Другую облаÑть &Custom &Ð”Ñ€ÑƒÐ³Ð°Ñ St&art: &Ðачало: Clip start Ðачало клипа En&d: &Конец: Clip offset Select Current take Format Формат Time display format Формат Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸: Frames &Frames Ð’Ñ‹&борки Time (hh:mm:ss.zzz) Ð’Ñ€ÐµÐ¼Ñ (чч:мм:ÑÑ.мÑ) &Time &Ð’Ñ€ÐµÐ¼Ñ BBT (bars.beats.ticks) BBT (bars.beats.ticks) &BBT &BBT Take %1 qtractorTempoAdjustForm Tempo - Qtractor Metronome Метроном Temp&o: Tempo/Time signature T&ap Range ОблаÑть &Start: &Ðачало: Range start Time Ð’Ñ€ÐµÐ¼Ñ BBT BBT &Length: &ДлительноÑть: Range length B&eats: Range beats A&djust Format Формат Time display format Формат Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸: Frames Fra&mes Ð’Ñ‹&борки Time (hh:mm:ss.zzz) Ð’Ñ€ÐµÐ¼Ñ (чч:мм:ÑÑ.мÑ) &Time &Ð’Ñ€ÐµÐ¼Ñ BBT (bars.beats.ticks) BBT (bars.beats.ticks) &BBT &BBT Warning Предупреждение Some settings have been changed. Do you want to apply the changes? Ðекоторые параметры изменилиÑÑŒ. Ð’Ñ‹ хотите применить изменениÑ? qtractorThumbView Thumb view Панель обзора проекта qtractorTimeScaleForm Warning Предупреждение Some settings have been changed. Do you want to apply the changes? Ðекоторые параметры изменилиÑÑŒ. Ð’Ñ‹ хотите применить изменениÑ? About to remove tempo node: %1 (%2) %3 %4/%5 Are you sure? Some settings have been changed. Do you want to discard the changes? Ðекоторые параметры изменилиÑÑŒ. Ð’Ñ‹ хотите применить изменениÑ? &Add &Добавить &Update Об&новить ноду &Remove &Удалить &Refresh О&бновить Tempo Map - Qtractor Карта темпа Tempo map Карта темпа Bar Такт Time Ð’Ñ€ÐµÐ¼Ñ Tempo Темп Signature Размер &Tempo: Т&емп: T&ap Marker text ... ... Marker color Refresh tempo map Обновить карту темпа Re&fresh О&бновить Alt+F Alt+б Add node Alt+A Alt+д Update node Alt+U Alt+н Remove node Alt+R Alt+у Close this dialog Закрыть Ñтот диалог Close Закрыть Node Tempo Map / Markers - Qtractor Tempo map / Markers Marker Location &Bar: &Такт: Bar location T&ime: Ð’Ñ€&ÐµÐ¼Ñ Time/frame location Tempo (BPM) / Signature Темп (BPM) / Размер qtractorTimeSpinBox &Frames Ð’Ñ‹&борки &Time &Ð’Ñ€ÐµÐ¼Ñ &BBT &BBT qtractorTrackButton Record Включить режим запиÑи Mute Приглушить Solo Сделать Ñолирующей qtractorTrackForm Normal Обычный Bank MSB Банк MSB Bank LSB Банк LSB Patch Патч Warning Предупреждение Some settings have been changed. Do you want to apply the changes? Ðекоторые параметры изменилиÑÑŒ. Ð’Ñ‹ хотите применить изменениÑ? (No instrument) Cancel Отменить (None) (нет) Track - Qtractor Дорожка - Qtractor Track Дорожка &Name: Ð&азвание: Track name description ОпиÑание дорожки Type Тип Audio track type Ð—Ð²ÑƒÐºÐ¾Ð²Ð°Ñ Ð´Ð¾Ñ€Ð¾Ð¶ÐºÐ° &Audio &Ð—Ð²ÑƒÐºÐ¾Ð²Ð°Ñ Alt+A Alt+з MIDI track type MIDI-дорожка &MIDI &MIDI Alt+M Alt+M Input / Output Вход / выход Input bus name Ðазвание шины на входе Ouput bus name Ðазвание шины на выходе Output bus name Manage buses ÐаÑтроить шины ... ... MIDI / Instrument MIDI / инÑтрумент &Program: &Программа: &Bank: &Банк: Bank &Select Method: СпоÑоб &выбора банка: &Omni Ом&ни MIDI Omni: Capture All Channels MIDI-омни: захватить вÑе каналы Alt+O Alt+н &Channel: &Канал: MIDI Channel (1-16) Канал MIDI (1-16) MIDI Patch: Instrument Патч MIDI: инÑтрумент MIDI Patch: Bank Select Method Патч MIDI: ÑпоÑоб выбора банка MIDI Patch: Bank Патч MIDI: банк MIDI Patch: Program Патч MIDI: прогромма View / Colors Вид / цвета &Foreground: П&ередний план: Foreground color Цвет переднего плана Select custom track foreground color Укажите другой цвет переднего плана дорожки Bac&kground: &Фон: Background color Цвет фона Select custom track background color Укажите другой цвет фона дорожки Plugins Эффекты Track plugins Эффекты дорожки Add plugin Добавить Ñффект &Add... &Добавить Remove plugin Удалить Ñффект &Remove &Удалить Alt+R Alt+у Move plugin up ПеремеÑтить Ñффект на одно положение вверх &Up &Выше Alt+U Alt+в Move plugin down ПеремеÑтить Ñффект на одно положение вниз &Down &Ðиже Alt+D Alt+н OK &ОК qtractorTrackListHeaderModel Nr â„– Track Name Ðазвание Bus Шина Ch К Patch Патч Instrument ИнÑтрумент qtractorTrackTime Play-head Edit-head Edit-tail Loop-start Loop-end Punch-in Punch-out Start: %1 End: %2 Length: %3 qtractorTrackView Zoom in (horizontal) Приблизить по горизонтали Zoom out (horizontal) Отдалить по горизонтали Zoom in (vertical) Приблизить по вертикали Zoom out (vertical) Отдалить по вертикали Zoom reset ИÑходный маÑштаб add clip добавление клипа Start: %1 End: %2 Length: %3 clip %1 клип %1 fade-in нараÑтание fade-out угаÑание clip stretch раÑÑ‚Ñгивание клипа clip resize Ñмена размера клипа %1 automation %1 clip move automation paste automation cut вырезание delete удаление split move clip перемещение клипа paste clip вÑтавка клипа qtractorTracks Tracks Дорожки new clip Ñоздание клипа split clip разделение клипа clip normalize Ð½Ð¾Ñ€Ð¼Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÐºÐ»Ð¸Ð¿Ð° clip quantize квантование клипа Export Audio Clip ЭкÑпорт звукового клипа Audio files (*.%1) Звуковые файлы (*.%1) Audio clip export: "%1" started... ЭкÑпорта звукового клипа: "%1" начат... Audio clip export: "%1" complete. ЭкÑпорт звукового клипа: "%1" ÑкÑпортирован... Audio clip export: "%1" failed. ЭкÑпорт звукового клипа: не удалоÑÑŒ ÑкÑпортировать "%1" Export MIDI Clip ЭкÑпорт клипа MIDI MIDI files (*.%1 *.smf *.midi) Файлы MIDI (*.%1 *.smf *.midi) MIDI clip export: "%1" started... ЭкÑпорта клипа MIDI: "%1" начат... MIDI clip export: "%1" complete. ЭкÑпорт файла MIDI: "%1" ÑкÑпортирован... MIDI clip export: "%1" failed. ЭкÑпорт клипа MIDI: не удалоÑÑŒ ÑкÑпортировать "%1" Warning Предупреждение About to remove track: "%1" Are you sure? Будет удалена дорожка: "%1" Ð’Ñ‹ уверены? Audio file import "%1" on %2 %3. Импорт звукового файла "%1" в %2 %3. quantize квантование transpose транÑпонирование normalize Ð½Ð¾Ñ€Ð¼Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ randomize Ñлучайные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ resize Ñмена размера rescale timeshift clip tool %1 clip import Audio file import: "%1". Импорт звукового файла: "%1". MIDI file import "%1" track-channel %2 on %3 %4. Insert Range insert range insert track range Remove Range remove range remove track range MIDI file import "%1" on %2 %3. Импорт файла MIDI "%1" в %2 %3. MIDI file import: "%1". Импорт файла MIDI: "%1". MIDI file import: "%1", track-channel: %2. Импорт файла MIDI "%1", дорожка-канал: %2. Merge Audio Clip Объединить звуковые клипы clip merge объединение клипов Audio clip merge: "%1" complete. Объединение звуковых клипов: "%1" завершено. Merge MIDI Clip Объединить MIDI-клипы MIDI clip merge: "%1" started... Объединение MIDI-клипов: "%1" начато... MIDI clip merge: "%1" complete. Объединение MIDI-клипов: "%1" завершено. Merge/Export Audio Clip Объединить/ÑкÑпортировать звуковые клипы Audio clip merge/export: "%1" started... Объединение/ÑкÑпорт звукового клипа: "%1" начат... Audio clip merge/export: "%1" complete. Объединение/ÑкÑпорт звукового клипа: "%1" завершен... Merge/Export MIDI Clip Объединить/ÑкÑпортировать клипы MIDI MIDI clip merge/export: "%1" started... Объединение/ÑкÑпорт клипа MIDI: "%1" начат... MIDI clip merge/export: "%1" complete. Объединение/ÑкÑпорт клипа MIDI: "%1" завершен... qtractorVstPlugin::EditorWidget %1 - Editor %1 - Редактор qtractor-0.5.11/src/translations/PaxHeaders.10084/qtractor_de.ts0000644000175000001440000000012312223511102022630 xustar000000000000000027 mtime=1380880962.062114 26 atime=1381134669.44508 30 ctime=1381134669.480080088 qtractor-0.5.11/src/translations/qtractor_de.ts0000644000175000001440000161112312223511102022124 0ustar00rncbcusers00000000000000 QObject Audio: %1 channels, %2 Hz Audio: %1 Kanäle, %2 Hz (%1 dB) (%1 dB) (%1% time stretch) (%1% Zeitdehnung) (%1 semitones pitch shift) %1 In %1 Ein %1 Out %1 Aus Audio files (%1) Audiodateien (%1) All files (*.*) Alle Dateien (*.*) %1 (%2) %3 channels, %4 frames, %5 Hz %6 %1 (%2) %3 Kanäle, %4 Frames, %5 Hz %6 Duplex Duplex Output Ausgang Input Eingang None Keine (take %1) Name: %1 Name: %1 Start / End: %1 / %2 Offset / Length: %3 / %4 Start / Ende: %1 / %2 Versatz / Länge: %3 / %4 File: %1 Datei: %1 take %1 reset takes automation select automation mode automation play automation record automation logarithmic automation color automation play all automation record all automation edit automation clear automation clear all automation edit list %1 Monitor create bus update bus delete bus bus pass-through bus gain bus pan Send Gain Dry / Wet Cakewalk Instrument Definition File File Datei Date Datum %1 Bank %2 %1 - Bank %2 (format %1) MIDI: (Format %1) MIDI: Channel %1 Kanal %1 Track %1 Spur %1 , %1 tracks, %2 tpqn (%1% vol) set controller reset controller %1 (format %2) %3 tracks, %4 tpqn %5 %1 (format %2) %3 %1 (Format %2) %3 (default) (voreingestellt) %1 Hz %1 Hz slave %1 (%2) Usage: %1 [options] [session-file] Benutzung: %1 [Optionen] [Sitzungsdatei] Options: Optionen: Set session identification (uuid) Setze Sitzungsidentifikation (uuid) Show help about command line options Zeige Hilfe zu Kommandozeilenargumenten an Show version information Zeige Versionsinformation an Option -s requires an argument (session-id). Option -s benötigt ein Argument (session-id). Qt: %1 Qt: %1 (Any) add plugin add insert add aux-send aux-send bus remove plugin move plugin activate plugin preset plugin reset plugin dedicated audio outputs direct access param session loop session punch session properties Beat add tempo node update tempo node remove tempo node move tempo node add marker update marker remove marker move marker %1 Record %1 Aufnahme %1 Mute %1 Stumm %1 Solo %1 Volume %1 Gain %1 Pan add track remove track move track resize track import track track properties Track assignment failed: Track: "%1" Input: "%2" Output: "%3" Spurzuweisung schlug fehl: Spur: "%1" Eingang: "%2" Ausgang: "%3" track record track mute track solo track monitor track gain track pan Automation (%1) Automatisierung (%1) none keiner Automation Automatisierung Audio Audio MIDI Unknown Unbenannt %1 (*.%2) qtractorAudioListView Name Name Ch Kanal Frames Rate Rate Time Zeit Path Pfad Open Audio Files Audiodateien öffnen qtractorAudioMeter Gain (dB) Verstärkung (dB) dB dB Pan: %1 Gain: %1 dB Verstärkung: %1 dB qtractorBusForm Buses - Qtractor Busse - Qtractor Bus list Busliste Buses Busse Ch Kanal Mode Modus Bus Bus Properties Eigenschaften &Name: &Name: Bus name Busname &Mode: &Modus: Bus mode Busmodus Input Eingang Output Ausgang Duplex Duplex Bus monitor (pass-through) M&onitor (pass-through) Alt+O Alt+Ü Audio Audio Cha&nnels: Ka&näle: Audio channels Audiokanäle Audio auto-connect &Auto connect &Automatisch verbinden Alt+A Alt+A MIDI MIDI Instrument name MIDI-Instrumentname MIDI SysEx setup SysE&x... Input Plugins Input bus plugins Add input plugin &Add... &Hinzufügen... Remove input plugin &Remove En&tfernen Alt+R Alt+F Move input plugin up &Up Au&f Alt+U Alt+K Move input plugin down &Down A&b Alt+D Alt+T Output Plugins Output bus plugins Add output plugin Remove output plugin Move output plugin up Move output plugin down Refresh bus list view Ansicht der Busliste auffrischen &Refresh &Auffrischen Create bus Bus erzeugen &Create &Erzeugen Alt+C Alt+S Update bus Bus aktualisieren &Update A&ktualisieren Delete bus Bus löschen &Delete &Löschen Close this dialog Diesen Dialog schließen Close Schließen Warning Warnung Some settings have been changed. Do you want to apply the changes? Einige Einstellungen wurden verändert. Wollen Sie diese übernehmen? About to remove bus: "%1" (%2) Are you sure? Bus soll entfernt werden: "%1" (%2) Sind Sie sicher? Some settings have been changed. Do you want to discard the changes? Einige Einstellungen wurden verändert. Wollen Sie diese verwerfen? (No instrument) (Kein Instrument) (none) (1 item) (%1 items) qtractorClientListView Readable Clients / Output Ports Lesbare Clients/Ausgänge Writable Clients / Input Ports Beschreibbare Clients/Eingänge qtractorClipForm Clip - Qtractor Ausschnitt - Qtractor &Name: &Name: Clip name &File: &Datei: Clip filename Browse for clip file Track/&Channel: Spur/&Kanal: Clip track/channel &Gain/Volume: &Verstärkung/Lautstärke: Clip gain/volume Parameters Parameter Clip start Clip offset Clip length Offs&et: Vers&atz: &Length: &Länge: &Start: &Start: Gain/Volume Format Format Time display format Frames Time (hh:mm:ss.zzz) Zeit (hh:mm:ss.zzz) &Time &Zeit Time Zeit BBT Fade In/Out Ein-/Ausblenden Fade &In: &Einblenden: Clip fade-in length Clip fade-in type Fade &Out: &Ausblenden: Clip fade-out length Clip fade-out type Audio Audio Time St&retch: Zeitde&hnung: Clip time-stretch percentage % Pitch S&hift: &Tonhöhenverschiebung: Clip pitch-shift in semitones Tonhöhenverschiebung in Halbtönen semitones Halbtöne &Gain: &Verstärkung: dB dB &Volume: &Lautstärke: new clip edit clip Warning Warnung Some settings have been changed. Do you want to apply the changes? Einige Einstellungen wurden verändert. Wollen Sie diese übernehmen? MIDI MIDI files (*.%1 *.smf *.midi) MIDI-Dateien (*.%1 *.smf *.midi) %1 Clip File qtractorConnect Connect Verbinden Disconnect Trennen Disconnect All Alle trennen Refresh Auffrischen qtractorConnectForm qtractorConnectTest Audio Audio Select output client/ports Ausgang Client/Anschluß wählen Select input client/ports Eingang Client/Anschluß wählen Connect currently selected ports Ausgewählte Anschlüsse verbinden &Connect &Verbinden Alt+C Alt+S Disconnect currently selected ports Ausgewählte Anschlüsse trennen &Disconnect &Trennen Alt+D Alt+T Disconnect all currently connected ports Alle verbundenen Anschlüsse trennen Disconnect &All &Alle trennen Alt+A Alt+A Refresh current connections view Ansicht der bestehenden Verbindungen erneuern &Refresh Auf&frischen Alt+R Alt+F MIDI (All) qtractorConnections Connections Verbindungen qtractorEditRangeForm Range - Qtractor Range Bereich Selection range &Selection Loop range &Loop &Endlosschleife Punch range &Punch Edit range &Edit Custom range &Custom St&art: Clip start En&d: En&de: Clip offset Apply to Loop points in range L&oop Apply to Punch In/Out points in range Pu&nch Mar&kers Te&mpo Map &Format Time display format Time Zeit BBT Format Format Frames Time (hh:mm:ss.zzz) Zeit (hh:mm:ss.zzz) &Time &Zeit Options Optionen Apply to clips in range Cl&ips A&utomation A&utomatisierung Apply to Automation nodes in range &Automation &Automatisierung Apply to Tempo Map nodes in range Apply to location Markers in range qtractorExportForm Export - Qtractor Export - Qtractor &File: &Datei: Export file name Dateiname für Export Browse export file name Range Bereich Session range &Session S&itzung Loop range &Loop &Endlosschleife Punch range &Punch Edit range &Edit Bea&rbeiten Custom range &Custom St&art: &Start: Clip start En&d: En&de: Clip offset Output Ausgang Output bus name Format Format Time display format Frames Time Zeit BBT Time (hh:mm:ss.zzz) Zeit (hh:mm:ss.zzz) &Time &Zeit Audio Audio MIDI Export %1 Export %1 Warning Warnung The file already exists: "%1" Do you want to replace it? Die Datei existiert bereits: "%1" Ersetzen? Audio file export: "%1" started... Audiodateiexport: "%1" gestartet... Audio file export: "%1" complete. Audiodateiexport: "%1" vollständig. Audio file export: "%1" failed. Audiodateiexport: "%1" gescheitert. MIDI file export: "%1" started... MIDI-Dateiexport: "%1" gestartet... MIDI file export: "%1" complete. MIDI-Dateiexport: "%1" vollständig. MIDI file export: "%1" failed. MIDI-Dateiexport: "%1" gescheitert. Export %1 File Exportiere %1-Datei %1 files (*.%1) %1 Dateien (*.%1) qtractorFileListView New Group Neue Gruppe Warning Warnung About to remove %1 file item(s). Are you sure? About to remove %1 item: "%2" Are you sure? group file qtractorFiles Audio Audio MIDI Play file Datei abspielen New &Group... Neue &Gruppe... Add &Files... Dateien hinzu&fügen... Cu&t &Ausschneiden &Copy &Kopieren &Paste &Einfügen Re&name &Umbenennen &Remove En&tfernen Pla&y Abs&pielen Cl&eanup Auf&räumen Ctrl+X Ctrl+X Ctrl+C Ctrl+C Ctrl+V Ctrl+V Del Entf Files Dateien MIDI Files MIDI-Dateien Audio Files Audiodateien qtractorInstrumentForm Instruments - Qtractor Instrumente - Qtractor Instruments Instrumente Files Dateien Path Pfad Names Namen Import from instrument file Aus Instrumentendatei importieren &Import... &Importieren... Alt+I Alt+I Remove instrument file Instrumentendatei löschen &Remove En&tfernen Alt+R Alt+F Move instrument file up on list order &Up A&uf Alt+U Alt+K Move instrument file down on list order &Down A&b Alt+D Alt+T Reload all instrument files Alle Instrumentendateien neu laden Relo&ad Neu &laden Alt+A Alt+A Export to instrument file E&xport... E&xportieren... Alt+X Alt+K Close this dialog Diesen Dialog schließen Close Schließen Import Instrument Files Instrumentendatei importieren Instrument files (*.%1 *.sf2 *.midnam) Instrumentendateien (*.%1 *.sf2 *.midnam) Export Instrument File Exportiere Instrumentendatei Instrument files (*.%1) Instrumentendateien (*.%1) Warning Warnung The instrument file already exists: "%1" Do you want to replace it? Die Instrumentendatei existiert bereits: "%1" Ersetzen? Instrument settings have been changed. Do you want to apply the changes? Die Einstellungen für die Instrumente wurden geändert. Sollen die Änderungen übernommen werden? Patch Names for Banks Controller Names = %1 RPN Names = %1 NRPN Names = %1 Bank Select Method = %1 Patch Names Note Names Controller Names RPN Names NRPN Names Bank Select Methods %1 = %2 Based On = %1 Normal Bank MSB Bank LSB Patch Unknown Unbenannt qtractorMainForm Qtractor Qtractor &File &Datei Open &Recent &Zuletzt geöffnet &Edit Bea&rbeiten Select &Mode Auswahl&modus &Select Au&swahl I&nsert &Einfügen Remo&ve &Track &Spur &State &Status &Navigate &Navigieren Mo&ve &Verschieben &Height &Höhe Impor&t Tracks Spur impor&tieren E&xport Tracks Spur e&xportieren M&ode M&odus A&utomation A&utomatisierung Cl&ip Ausschn&itt T&ools Werk&zeuge Ta&ke &View &Ansicht &Toolbars &Werkzeugleisten &Windows &Fenster &Zoom S&nap T&ransport T&ransport &Help &Hilfe &New &Neu New Neu New session Neue Sitzung New session file Sitzungsdatei Ctrl+N &Open... &Öffnen... Open Öffnen Open session Sitzung öffnen Open session from file Sitzung aus Datei laden Ctrl+O &Save &Speichern Save Speichern Save session Sitzung speichern Save session to file Sitzung in Datei speichern Ctrl+S Save &As... Speichern &unter... Save As Speichern unter Save as Speichern unter Save current session with another file name Aktuelle Sitzung unter anderem Dateinamen speichern &Properties... Ei&genschaften... Session Properties Sitzungseigenschaften Session properties Sitzungseigenschaften Edit current session properties Bearbeite Eigenschaften der aktuellen Sitzung F2 E&xit B&eenden Exit Beenden Exit this application program Dieses Programm beenden &Undo &Rückgängig Undo Rückgängig Undo last action Letzte Aktion rückgängig machen Ctrl+Z &Redo &Wiederherstellen Redo Wiederherstellen Redo last action Letzte Aktion wiederherstellen Ctrl+Shift+Z Cu&t &Ausschneiden Cut Ausschneiden Cut selection to clipboard Auswahl in Zwischenablage ausschneiden Ctrl+X Ctrl+X &Copy &Kopieren Copy Kopieren Copy selection to clipboard Auswahl in Zwischenablage kopieren Ctrl+C Ctrl+C &Paste &Einfügen Paste Einfügen Paste clipboard contents Inhalt der Zwischenablage einfügen Ctrl+V Ctrl+V Past&e Repeat... Wiederhol&t einfügen... Paste Repeat Paste repeat Wiederholt einfügen Paste/repeat clipboard contents Füge Inhalt der Zwischenablage wiederholt ein Ctrl+Shift+V &Delete &Löschen Delete Löschen Delete selection Auswahl löschen Del Entf &Clip Au&sschnitt Clip Ausschnitt Select clip Ausschnittwählen Clip selection mode Ausschnittwahlmodus &Range &Bereich Range Bereich Select range Bereich auswählen Range selection mode Bereichsauswahlmodus R&ectangle R&echteck Rect Select rectangle Rechteck auswählen Rectangular selection mode Rechteckauswahlmodus &Automation &Automatisierung Automation Automatisierung Automation edit mode &All &Alles Select All Alles auswählen Select all Alles auswählen Mark all as selected Alles als ausgewählt markieren Ctrl+A &None &Nichts Select None Nichts auswählen Select none Nichts auswählen Mark all as unselected Alles als nicht ausgewählt markieren Ctrl+Shift+A &Invert &Invertieren Select Invert Invertieren auswählen Select invert Invertieren auswählen Invert selection Auswahl invertieren Ctrl+I Select Track Spur auswählen Select track Spur auswählen Mark track as selected Markiere Spur als ausgewählt Ctrl+T Trac&k Range Sp&urbereich Select Track Range Select track range Mark track range as selected Spur als auswewählt markieren Ctrl+Shift+R Select Range Bereich auswählen Mark range as selected Bereich als ausgewählt markieren Ctrl+R &Range... Remove Range Remove range Remove range as selected Ctrl+Del Remove Track Range Remove track range Remove track range as selected Ctrl+Shift+Del Insert Range Bereich einfügen Insert range Bereich einfügen Insert range as selected Bereich wie ausgewählt einfügen Ctrl+Ins Insert Track Range Spurbereich einfügen Insert track range Spurbereich einfügen Insert track range as selected Spurbereich wie ausgewählt einfügen Ctrl+Shift+Ins Sp&lit Tei&len Split Selection Auswahl teilen Split selection Auswahl teilen Split current selection Aktuelle Auswahl teilen Ctrl+Y &Add Track... Spur &hinzufügen... Add Track Spur hinzufügen Add track Spur hinzufügen Add a new track to session Neue Spur zur Sitzung hinzufügen Shift+Ins &Remove Track Spur &löschen Remove Track Spur löschen Remove track Spur löschen Remove current track from session Aktuelle Spur von Sitzung entfernen Shift+Del Track &Properties... Spurein&geschaften... Track Properties Spureingeschaften Track properties Spureingeschaften Edit current track properties Bearbeite Eigenschaften der aktuellen Spur Shift+F2 &Inputs &Eingänge Track Inputs Spureingänge Track inputs Spureingänge Show current track input bus connections &Outputs &Ausgänge Track Outputs Spurausgänge Track outputs Spurausgänge Show current track output bus connections &Record &Aufnehmen Record Track Spur aufnehmen Record track Spur aufnehmen Arm current track for recording &Mute &Stumm Mute Track Spurr stumm schalten Mute track Spurr stumm schalten Mute current track Aktuelle Spur stumm schalten &Solo Solo Track Solo track Solo current track M&onitor Monitor Track Monitor track Monitor current track &First &Erste First Track Erste Spur First track Erste Spur Make current the first track &Previous &Vorherige Previous Track Vorherige Spur Previous track Vorherige Spur Make current the previous track &Next &Nächste Next Track Nächste Spur Next track Nächste Spur Make current the next track &Last &Letzte Last Track Letzte Spur Last track Letzte Spur Make current the last track N&one &Keine None Track Keine Spur None track Keine Spur None current track Keine aktuelle Spur &Top &Anfang Move Top Zum Anfang verschieben Move top Zum Anfang verschieben Move current track to top &Up A&uf Move Up Nach oben verschieben Move up Nach oben verschieben Move current track up &Down A&b Move Down Nach unten verschieben Move down Nach unten verschieben Move current track down &Bottom &Ende Move Bottom Zum Ende verschieben Move bottom Zum Ende verschieben Move current track to bottom &Increase &Vergrößern Increase Height Höhe vergrößern Increase height Spurhöhe vergrößern Increase track height Ctrl+Shift++ &Decrease &Reduzieren Decrease Height Decrease height Decrease track height Ctrl+Shift+- &Reset &Zurücksetzen Height Reset Höhe zurücksetzen Height reset Höhe zurücksetzen Reset track height Setze Spurhöhe zurück Ctrl+Shift+1 Auto &Monitor Auto Monitor Auto monitor Auto-monitor current track F6 &Audio... Inport Audio File Audiodatei importieren Import Audio file Audiodatei importieren Import tracks from Audio file Spur aus Audiodatei importieren &MIDI... Import MIDI File MIDI-Datei importieren Import MIDI file MIDI-Datei importieren Import tracks from MIDI file Importiere Spur aus MIDI-Datei Export Audio File Exportiere Audiodatei Export Audio file Exportiere Audiodatei Export tracks to Audio file Spuren in Audiodatei exportieren Export MIDI File MIDI-Datei exportieren Export MIDI file MIDI-Datei exportieren Export tracks to MIDI file Log&arithmic Log&arithmisch Automation logarithmic Automation curve logarithmic scale C&olor... &Farbe... Automation color Automation curve color &Lock &Sperren Automation lock Lock automation curve &Play &Abspielen Automation playback Playback automation curve Automation record Record automation curve &Clear &Löschen Automation clear Clear automation curve Loc&k All Alles s&perren Automation lock all Lock all automation curves Play &All All&es abspielen Automation playback all Playback all automation curves Rec&ord All Alles a&ufnehmen Automation record all Record all automation curves C&lear All Alles lösc&hen Automation clear all Clear all automation curves Alle Automatisierungskurven löschen &New... &Neu... New Clip New clip Create new clip &Edit... &Bearbeiten... Edit Clip Edit clip Edit current clip F4 &Unlink Unlink Clip Unlink clip Unlink current clip &Split Tei&len Split Clip Split clip Split current clip at playhead &Merge... &Zusammenfügen... Merge Clips Merge clips Merge selected clips N&ormalize N&ormalisieren Normalize Clip Normalize clip Normalize current clip (gain/volume) &Quantize... &Quantisieren... Quantize Clip Quantize clip events Quantize current MIDI clip events &Transpose... &Transponieren... Transpose Clip Transpose clip events Transpose current MIDI clip events &Normalize... N&ormalisieren... Normalize clip events Normalize current MIDI clip events &Randomize... &Zufällig anordnen... Randomize Clip Randomize clip events Randomize current MIDI clip events Resi&ze... Größe &anpassen... Resize Clip Resize clip events Resize current MIDI clip events Re&scale... &Umskalieren... Rescale Clip Rescale clip events Rescale current MIDI clip events T&imeshift... Timeshift Clip Timeshift clip events Timeshift current MIDI clip events &Tempo... Tempo Adjust Adjust session tempo from current clip selection F7 &Range Set Clip Range Clip range Set edit-range from current clip extents &Loop Set Clip Loop Clip loop Set loop-range from current clip extents &Import... &Importieren... Import Clip Import clip Import clip from file(s) E&xport... E&xportieren... Export Clip Export clip Export current clip to file First Take First take Select current clip first take Previous Take Previous take Select current clip previous take Next Take Next take Select current clip next take Shift+T Last Take Last take Select current clip last take Reset Takes Reset takes Reset (unfold) current clip takes R&ange... &Bereich... Take Range Take range Range (fold) current clip into takes &Menubar &Menüzeile Menubar Menüzeile Show/hide the main program window menubar Ctrl+M &Statusbar &Statuszeile Statusbar Statuszeile Show/hide the main program window statusbar File Toolbar File toolbar Show/hide main program window file toolbar Edit Toolbar Edit toolbar Show/hide main program window edit toolbar Track Toolbar Track toolbar Show/hide main program window track toolbar View Toolbar View toolbar Show/hide main program window view toolbar &Options &Optionen Options Toolbar Options toolbar Show/hide main program window options toolbar Transport Toolbar Transport toolbar Show/hide main program window transport toolbar T&ime &Zeit Time Toolbar Time toolbar Show/hide main program window time toolbar Thum&b Thumb Toolbar Thumb toolbar Show/hide main program window thumb toolbar &Files &Dateien Files Dateien Show/hide the files window M&essages &Meldungen Messages Meldungen Show/hide the messages window Zeige/Verberge Meldungsfenster &Connections &Verbindungen Connections Verbindungen Show/hide the connections window Zeige/Verberge Verbindungsübersicht F8 Mi&xer Mi&scher Mixer Mischer Show/hide the mixer window Zeige/Verberge Mischerfenster F9 &In &Ein Zoom In Zoom in Ctrl++ &Out &Aus Zoom Out Zoom out Ctrl+- Zoom Reset Zoom reset Ctrl+1 &Horizontal &Horizontal Horizontal Zoom Horizontal zoom Horizontal zoom mode &Vertical &Vertikal Vertical Zoom Vertical zoom Vertical zoom mode All Zoom All zoom All zoom mode &Grid &Gitter Grid Snap grid view mode &Zebra &Zebra Zebra Bar zebra view mode Too&l Tips Tool tips Floating tool tips view mode &Refresh Auf&frischen Refresh Auffrischen Refresh views Ansichten auffrischen F5 &Instruments... &Instrumente... Instruments Instrumente Change instrument definitions and files &Controllers... Controllers Change MIDI controllers configuration &Buses... &Busse... Buses Busse Change session bus definitions Tempo M&ap / Markers... Tempo Map / Markers Tempo map / markers Change session tempo map / markers &Options... &Optionen... Options Optionen Change general application program options Allgemeine Programmoptionen ändern F12 &Backward &Rückwärts Backward Rückwärts Transport backward Transport rückwärts Backspace Re&wind &Zurückspulen Rewind Zurückspulen Transport rewind Transport zurückspulen F&ast Forward Vorspu&len Fast Forward Vorspulen Fast forward Vorspulen Transport fast forward Transport vorspulen &Forward &Vorwärts Forward Vorwärts Transport forward Transport vorwärts &Loop &Endlosschleife Loop Endlosschleife Transport loop Ctrl+Shift+L Loop &Set Loop Set Loop set Transport loop set Ctrl+L &Stop &Stopp Stop Stopp Transport stop Play Abspielen Transport play/pause Space Leertaste Record Transport record &Punch Punch Punch in/out Transport punch in/out Ctrl+Shift+P Punch Se&t Punch Set Punch in/out set Transport punch in/out set Ctrl+P &Metronome &Metronom Metronome Metronom F&ollow Playhead Follow Playhead Follow playhead A&uto Backward Auto Backward Auto backward &Continue Past End Continue Past End Continue past end Pa&nic Pa&nik Panic Panik All MIDI tracks shut off (panic) Alle MIDI-Spuren ausschalten (Panik) &Shortcuts... &Tastaturkürzel... Shortcuts Tastaturkürzel Keyboard shortcuts Tastaturkürzel &About... &Über... About Über Show information about this application program About &Qt... Über &Qt... About Qt Über Qt Show information about the Qt toolkit Set current snap to %1 Current time (play-head) Current tempo (BPM) Snap/beat Track Spur Current track name MOD Session modification state REC Session record state MUTE Session muting state SOLO Session soloing state LOOP Session looping state Session total time Session sample rate Could not set default session directory: %1 Sorry. Ready Untitled%1 Unbenannt%1 New session: "%1". Session files (*.%1 *.%2 *.%3) Session files (*.%1 *.%2) Template files (*.%1) Archive files (*.%1) Open Session Sitzung öffnen Save Session Sitzung speichern Warning Warnung The file already exists: "%1" Do you want to replace it? Die Datei existiert bereits: "%1" Ersetzen? Backup session: "%1" as "%2". Could not backup existing session: %1 as %2 Sorry. The current session has been changed: "%1" Do you want to save the changes? About to remove archive directory: "%1" Are you sure? Session closed. Sitzung geschlossen. The directory already exists: "%1" Do you want to replace it? Opening "%1"... Öffne "%1"... Session could not be loaded from "%1". Sorry. Open session: "%1". Sitzung öffnen: "%1". Saving "%1"... Speichere "%1"... Session could not be saved to "%1". Sorry. Save session: "%1". About to clear automation: "%1" Are you sure? About to clear all automation: "%1" Are you sure? take range session or program Information Information Some settings may be only effective next time you start this %1. Einige Einstellungen sind möglicherweise erst aktiv, wenn sie %1 das nächste Mal starten. Debugging option enabled. Debugging-Option aktiviert. Ogg Vorbis (libvorbis) file support disabled. MPEG-1 Audio Layer 3 (libmad) file support disabled. Sample-rate conversion (libsamplerate) disabled. Pitch-shifting support (librubberband) disabled. OSC service support (liblo) disabled. LADSPA Plug-in support disabled. DSSI Plug-in support disabled. VST Plug-in support disabled. VeSTige header support enabled. LV2 Plug-in support disabled. LV2 Plug-in support (liblilv) disabled. LV2 Plug-in UI support disabled. LV2 Plug-in UI support (libsuil) disabled. LV2 Plug-in External UI support disabled. LV2 Plug-in MIDI/Event support disabled. LV2 Plug-in MIDI/Atom support disabled. LV2 Plug-in Worker/Schedule support disabled. LV2 Plug-in State support disabled. LV2 Plug-in State Files support disabled. LV2 Plug-in Programs support disabled. LV2 Plug-in Presets support disabled. LV2 Plug-in Time/position support disabled. LV2 Plug-in Options support disabled. LV2 Plug-in Buf-size support disabled. JACK Session support disabled. JACK Session nicht unterstützt. JACK Latency support disabled. NSM support disabled. Version Version Build Build Website Webseite This program is free software; you can redistribute it and/or modify it Dieses Programm ist freie Software; Sie können es gemäß der under the terms of the GNU General Public License version 2 or later. GNU General Public License weiterverteilen und/oder modifizieren. record clip [modified] %1 Hz %1 Hz Session started. Sitzung gestartet. The audio/MIDI engine could not be started. Make sure the JACK audio server (jackd) and/or the ALSA Sequencer kernel module (snd-seq-midi) are up and running and then restart the session. The original session sample rate (%1 Hz) is not the same of the current audio engine (%2 Hz). Saving and reloading from a new session file is highly recommended. &Hold &Linear &Linear &Spline Take %1 None Keiner Error Fehler XRUN(%1 skipped) XRUN(%1 übersprungen) XRUN(%1): some frames might have been lost. Audio connections change. MIDI connections change. Playing ended. The audio engine has been shutdown. Make sure the JACK audio server (jackd) is up and running and then restart session. STOP PLAY FFWD REW REC ON REC OFF RESET LOCATE %1 SHUTTLE %1 STEP %1 TRACK RECORD %1 %2 TRACK MUTE %1 %2 TRACK SOLO %1 %2 Unknown sub-command Unbekanntes Unterkommando Not implemented Nicht implementiert MIDI CTL: %1, Channel %2, Param %3, Value %4 (track %1, gain %2) (track %1, panning %2) START CONTINUE SONGPOS %1 %1 BPM Playing "%1"... Spiele "%1" ab... &Time &Zeit qtractorMessages Messages Meldungen Logging stopped --- %1 --- Aufzeichung angehalten --- %1 --- Logging started --- %1 --- Aufzeichnung gestartet --- %1 --- qtractorMeter Pan Gain Verstärkung qtractorMidiControlForm Controllers - Qtractor Controller files Files Dateien Path Pfad Import controller files &Import... &Importieren... Alt+I Alt+I Remove controller file &Remove En&tfernen Alt+R Alt+F Move controller file up on list order &Up A&uf Alt+U Alt+K Move controller file down on list order &Down A&b Alt+D Alt+T &Type T&yp &Channel &Kanal &Parameter &Parameter Trac&k Offset Spur&versatz C&ommand K&ommando MIDI Event type MIDI Channel MIDI-Kanal MIDI Controller (parameter) MIDI parameter (track offset) + Track offset Command action Command feedback &Feedback &Rückmeldung Map/update controller command &Map Alt+M Alt+M Controller map Type Typ Channel Kanal Parameter Parameter Track Spur Command Kommando Feedback Unmap/remove controller command U&nmap Alt+N Alt+U Reload/apply all controller files Relo&ad Neu &laden Alt+A Alt+A Export to controller file E&xport... E&xportieren... Alt+X Alt+K Close this dialog Diesen Dialog schließen Close Schließen Import Controller Files Controller files (*.%1) Warning Warnung About to remove controller file: "%1" Are you sure? Export Controller File The controller file already exists: "%1" Do you want to replace it? Saved controller mappings may not be effective the next time you start this program. "%1" Do you want to apply to controller files? Controller mappings have been changed. Do you want to save the changes? Wollen sie die Änderungen speichern? Yes Ja No Nein qtractorMidiControlObserverForm MIDI Controller - Qtractor &Type: T&yp MIDI event type Cha&nnel: Ka&nal: MIDI channel &Parameter: &Parameter: MIDI parameter &Logarithmic &Logarithmisch &Feedback &Rückmeldung In&vert &Invertieren &Hook Control input connections &Inputs &Eingänge Control output connections &Outputs &Ausgänge MIDI Controller MIDI controller is already assigned. Do you want to replace the mapping? Some settings have been changed. Do you want to apply the changes? Einige Einstellungen wurden verändert. Wollen Sie diese übernehmen? &MIDI Controller... &Automation &Automatisierung &Lock &Sperren &Play &Abspielen &Record Auf&nehmen &Clear &Löschen qtractorMidiEditEvent Zoom in (horizontal) Zoom out (horizontal) Zoom reset (horizontal) qtractorMidiEditList C%1 qtractorMidiEditTime Play-head Edit-head Edit-tail Loop-start Loop-end Punch-in Punch-out Start: %1 End: %2 Length: %3 Start: %1 Ende: %2 Länge: %3 qtractorMidiEditView Zoom in (vertical) Zoom out (vertical) Zoom reset (vertical) qtractorMidiEditor MIDI Editor cut delete insert range remove range move edit resize rescale paste Time: %1 Type: Note On (%1) %2 Velocity: %3 Duration: %4 Key Press (%1) %2 Value: %3 Controller (%1) Name: %2 Value: %3 Pgm Change (%1) Chan Press (%1) Pitch Bend (%1) SysEx (%1 bytes) Data: Unknown (%1) Start: %1 End: %2 Length: %3 Start: %1 Ende: %2 Länge: %3 qtractorMidiEditorForm MIDI Editor &Track &Spur &File &Datei Select &Mode Auswahl&modus &Select Au&swahl I&nsert &Einfügen Remo&ve &Tools &Edit &Bearbeiten &View &Ansicht &Toolbars &Werkzeugleisten &Windows &Fenster &Zoom S&nap Sc&ale T&ransport T&ransport &Help &Hilfe &Save &Speichern Save Speichern Save current MIDI clip to existing file name Save &As... Speichern &unter... Save As Speichern unter Save as Speichern unter Save current MIDI clip with another file name &Unlink Unlink Unlink current MIDI clip &Inputs &Eingänge Track Inputs Spureingänge Track inputs Spureingänge Show current MIDI clip/track input bus connections &Outputs &Ausgänge Track Outputs Spurausgänge Track outputs Spurausgänge Show current MIDI clip/track output bus connections &Properties... Ei&genschaften... Track Properties Spureingeschaften Track properties Spureingeschaften Edit current MIDI clip/track properties Shift+F2 Properties Eigenschaften Edit current MIDI clip properties F4 &Range Set Clip Range Clip range Set edit-range from clip extents &Loop Set Clip Loop Clip loop Set loop-range from clip extents &Close &Schließen Close Schließen Close this MIDI clip editor &Undo &Rückgängig Undo Rückgängig Undo last edit operation Ctrl+Z &Redo &Wiederherstellen Redo Wiederherstellen Redo last edit operation Ctrl+Shift+Z Cu&t &Ausschneiden Cut Ausschneiden Cut current selection into the local clipboard Ctrl+X Ctrl+X &Copy &Kopieren Copy Kopieren Copy current selection to the local clipboard Ctrl+C Ctrl+C &Paste &Einfügen Paste Einfügen Paste local clipboard contents into the current MIDI clip Ctrl+V Ctrl+V Past&e Repeat... Wiederhol&t einfügen... Paste Repeat Paste repeat Wiederholt einfügen Paste/repeat local clipboard contents into the current MIDI clip Ctrl+Shift+V &Delete &Löschen Delete Löschen Delete current selection Del Entf Edit Of&f Edit Off Edit off Set edit mode off Edit &On Edit On Edit on Set edit mode on Edit &Draw Edit draw mode Edit draw mode (notes) &All &Alles Select All Alles auswählen Select all Alles auswählen Ctrl+A &None &Nichts Select None Nichts auswählen Select none Nichts auswählen Ctrl+Shift+A &Invert &Invertieren Select Invert Invertieren auswählen Select invert Invertieren auswählen Ctrl+I &Range &Bereich Select Range Bereich auswählen Select range Bereich auswählen Mark range as selected Bereich als ausgewählt markieren Ctrl+R Insert Range Bereich einfügen Insert range Bereich einfügen Insert range as selected Bereich wie ausgewählt einfügen Ctrl+Ins Remove Range Remove range Remove range as selected Ctrl+Del &Quantize... &Quantisieren... Quantize Quantisieren Quantize selection &Transpose... &Transponieren... Transpose Transponieren Transpose selection &Normalize... N&ormalisieren... Normalize Normalisieren Normalize selection &Randomize... &Zufällig anordnen... Randomize Zufällig anordnen Randomize selection Resi&ze... Größe &anpassen... Resize Größe anpassen Resize selection Re&scale... &Umskalieren... Rescale Umskalieren Rescale selection T&imeshift... Timeshift Timeshift selection &Menubar &Menüzeile Menubar Menüzeile Show/hide the menubar Ctrl+M &Statusbar &Statuszeile Statusbar Statuszeile Show/hide the statusbar File Toolbar File toolbar Show/hide the file toolbar Edit Toolbar Edit toolbar Show/hide the edit toolbar View Toolbar View toolbar Show/hide the view toolbar &Transport &Transport Transport Toolbar Transport toolbar Show/hide the transport toolbar &Scale &Skalieren Scale Toolbar Scale toolbar Show/hide the scale toolbar Note &Duration Note Duration Note duration Whether note events are shown proportional to duration Note &Color Note Color Note color Whether note events are colored according to pitch &Value Color Value Color Value color Whether note events are colored according to value (velocity) &Events View events Show/hide the events list &Preview Notes Preview Notes Preview notes Preview notes while editing (scrub) F&ollow Playhead Follow Playhead Follow playhead &In &Ein Zoom In Zoom in Ctrl++ &Out &Aus Zoom Out Zoom out Ctrl+- &Reset &Zurücksetzen Zoom Reset Zoom reset Ctrl+1 &Horizontal &Horizontal Horizontal Zoom Horizontal zoom Horizontal zoom mode &Vertical &Vertikal Vertical Zoom Vertical zoom Vertical zoom mode All Zoom All zoom All zoom mode &Zebra &Zebra Zebra Bar zebra view mode &Grid &Gitter Grid Snap grid view mode Too&l Tips Tool tips Floating tool tips view mode &Refresh Au&ffrischen Refresh Erneuern Refresh views Ansichten auffrischen F5 &Backward &Rückwärts Backward Rückwärts Transport backward Transport rückwärts Backspace Re&wind &Zurückspulen Rewind Zurückspulen Transport rewind Transport zurückspulen F&ast Forward Vorspu&len Fast Forward Vorspulen Fast forward Vorspulen Transport fast forward Transport vorspulen &Forward &Vorwärts Forward Weiterleiten Transport forward Transport vorwärts &Loop &Endlosschleife Loop Endlosschleife Transport loop Ctrl+Shift+L Loop &Set Loop Set Loop set Transport loop set Ctrl+L &Stop &Stopp Stop Stopp Transport stop &Play &Abspielen Play Abspielen Transport play/pause Space Leertaste &Record &Aufnehmen Record Transport record &Punch Punch Punch in/out Transport punch in/out Ctrl+Shift+P Punch Se&t Punch Set Punch in/out set Transport punch in/out set Ctrl+P Pa&nic Pa&nik Panic Panik All MIDI tracks shut off (panic) Alle MIDI-Spuren ausschalten (Panik) &Shortcuts... &Tastaturkürzel... Shortcuts Tastaturkürzel Keyboard shortcuts Tastaturkürzel &About... &Über... About Über Show information about this application program About &Qt... Über &Qt... About Qt Über Qt Show information about the Qt toolkit Set current snap to %1 Note On Key Press Note Velocity Controller Pgm Change Chan Press Pitch Bend Sys Ex Snap/beat Note type Value type Controller type Scale key Scale type MIDI clip name MIDI file name MIDI track/channel MOD MIDI modification state 00:00:00.000 00:00:00.000 MIDI clip duration Warning Warnung The current MIDI clip has been changed: "%1" Do you want to save the changes? Save MIDI Clip MIDI files (*.%1 *.smf *.midi) MIDI-Dateien (*.%1 *.smf *.midi) MIDI file save: "%1", track-channel: %2. Channel %1 Kanal %1 Track %1 Spur %1 [modified] qtractorMidiEventItemDelegate edit %1 qtractorMidiEventList Events qtractorMidiEventListModel Time Zeit Type Typ Name Name Value Wert Duration/Data Frame BBT Note On (%1) Note Off (%1) Key Press (%1) Controller (%1) Pgm Change Chan Press Pitch Bend SysEx Meta (%1) Unknown (%1) qtractorMidiListView Name Name Fmt Tracks Spuren tpqn Path Pfad Open MIDI Files MIDI files (*.%1 *.smf *.midi) MIDI-Dateien (*.%1 *.smf *.midi) qtractorMidiMeter Volume (%) Lautstärke (%) % Pan: %1 Volume: %1% Lautstärke: %1% qtractorMidiSysexForm MIDI SysEx - Qtractor Name Name Size Größe Data (hex) Import from SysEx file &Import... &Importieren... Alt+I Alt+I Export to SysEx file E&xport... E&xportieren... Alt+X Alt+K Move SysEx item up on list order &Up A&uf Alt+U Alt+K Move SysEx item down on list order &Down A&b Alt+D Alt+T Open SysEx Sysex name Save SysEx Delete SysEx Create SysEx item &Add &Hinzufügen Alt+A Alt+A Update SysEx item Upda&te A&ktualisieren Alt+T Alt+T Remove SysEx item &Remove En&tfernen Alt+R Alt+F SysEx files (*.%1) MIDI files (*.mid *.smf *.midi) MIDI-Dateien (*.mid *.smf *.midi) All files (*.*) Alle Dateien (*.*) Import SysEx Files Export SysEx File Warning Warnung The SysEx file already exists: "%1" Do you want to replace it? Sysex files (*.%1) About to replace SysEx: "%1" Are you sure? About to delete SysEx: "%1" Are you sure? SysEx settings have been changed. Do you want to apply the changes? Error Fehler SysEx could not be loaded: "%1". Sorry. qtractorMidiToolsForm MIDI Tools Preset name Save preset Delete preset &Quantize &Quantisieren Quantize selected events &Time: &Zeit: Quantize time Quantize time percent % &Duration: &Dauer: Quantize duration Quantize duration percent S&wing: Swing-quantize time Swing-quantize percent Swing-quantize type Linear Linear Quadratic Quadratisch Cubic Kubisch &Scale: Scale-quantize key Scale-quantize type &Transpose &Transponieren Transpose selected events &Note: Transpose note Transpose time Transpose time format Frames Time Zeit BBT &Normalize &Normalisieren Normalize selected events &Percent: &Prozent: Normalize percent &Value: &Wert: Normalize value &Randomize &Zufällig anordnen Randomize selected events Randomize note/pitch Randomize time Randomize duration Randomize value Resi&ze Größe &anpassen Resize selected events Resize duration Resize duration format Percentage Resize value Resize value mode Flat Ramp Resize final value Re&scale &Umskalieren Rescale selected events Rescale time Rescale duration Rescale value T&imeshift Timeshift selected events Timeshift P: Timeshift parameter Timeshift parameter (log) Timeshift curve P = 0 : no change. P > 0 : accelerating shift. P < 0 : slowing down shift. Edit head/tail (blue) markers define the shift range. Timeshift duration (default) (voreingestellt) Warning Warnung About to delete preset: "%1" Are you sure? none keiner quantize transpose normalize randomize resize rescale timeshift qtractorMixer Inputs Eingänge Tracks Spuren Outputs Ausgänge Mixer Mischer qtractorMixerRack &Inputs &Eingänge &Outputs &Ausgänge &Monitor &Überwachung &Buses... &Busse... qtractorMixerStrip inputs outputs Connect %1 %1 In %1 Ein %1 Out %1 Aus (Audio) Gain Verstärkung (MIDI) (None) (Keine) qtractorMonitorButton monitor Monitor (rec) Monitor (thru) qtractorOptionsForm Options - Qtractor Optionen - Qtractor &General &Allgemeines Session Sitzung Default session &file format: Default session file format (suffix) Whether to create new sessions based on template &New session template: New session template Browse for new session template Whether to save backup versions of existing sessions Save &backup versions of existing sessions: Which mode to rename existing session files Increment previous version (default) Increment current version Options Optionen Whether to ask for confirmation on removal &Confirm removals Alt+C Alt+S Number of &recent files: The maximum number of recent files to keep in menu Whether to capture standard output (stdout/stderr) into messages window Standardausgabe (stdout/stderr) in Meldungsfenster umleiten Capture standard &output Standardausgabe &umleiten Alt+O Alt+Ü Whether to show the complete directory path of loaded session files S&how complete path of session files Alt+P Alt+P Whether to remove audio peak files on session close Auto-remove audio pea&k files Alt+K Alt+C Whether to keep all tool windows on top of the main window Keep tool &windows always on top Whether to try dropping multiple audio files into the same track &Drop multiple audio files into the same track Alt+S Alt+S Whether to reverse mouse middle-button role on keyboard modifiers (Shift/Ctrl) Re&verse middle-button modifier role (Shift/Ctrl) Transport Transport &mode: Transport control mode (JACK) None Keiner Slave Master Ausgang Full &Loop recording mode (takes): Loop recording mode (takes) First Erster Last &Audio Capture / Export Audio compression quality to use on capture (record) and export Audio sample format to use on capture (record) and export Audio file type to use on capture (record) and export File &type: Sample &format: &Quality: Playback Whether to apply time-stretching when tempo changes Aut&omatic time-stretching Sample-&rate converter type: Sample-rate converter quality Sinc (Best Quality) Sinc (Medium Quality) Sinc (Fastest) Zero Order Hold Linear Linear Whether to use WSOLA time-stretching &WSOLA time-stretching Alt+W Alt+M Whether to apply WSOLA quick seek time-stretching WSOLA quic&k seek Whether to have separate audition/pre-listening player output ports Dedicated au&dition/pre-listening player outputs: Alt+D Alt+T Whether to auto-connect dedicated audio player outputs Auto-&connect Metronome Metronom Whether to enable the audio metronome &Enable audio metronome Alt+E Alt+I &File (bar): Metronome Audio filename (bar) Browse for sample audio file (bar) &Gain (bar): Metronome gain (bar) dB dB &File (beat): Metronome Audio filename (beat) Browse for sample audio file (beat) &Gain (beat): Metronome gain (beat) Whether to have separate audio metronome output ports Dedicated a&udio metronome outputs: Alt+U Alt+K Whether to auto-connect dedicated audio metronome outputs Auto-co&nnect Alt+N Alt+U &MIDI File &format: MIDI file format to use on capture (record) and export &Quantize: MIDI capture (record) quantization Queue &timer (resolution): Queue timer (resolution) Whether to have separate MIDI player output ports Dedicated MIDI p&layer outputs Alt+L Alt+L Control &MMC: MIDI Machine Control (MMC) mode Input Eingang Output Ausgang Duplex Duplex &Device: MIDI Machine Control (MMC) device id. &SPP: MIDI Song Position pointer (SPP) control mode Cloc&k: MIDI Clock control mode Whether to have separate MIDI control ports Dedicated MIDI &control input/output Whether to enable the MIDI metronome &Enable MIDI metronome &Channel: &Kanal: Metronome MIDI channel &Note (bar): Metronome MIDI note (bar) &Velocity (bar): Metronome MIDI velocity (bar) &Duration (bar): &Note (beat): Metronome MIDI note (beat) &Velocity (beat): Metronome MIDI velocity (beat) &Duration (beat): Whether to have separate MIDI metronome output port Dedicated M&IDI metronome output Alt+I Alt+I &Display Defaults Voreinstellungen &Time display format: Time display format Frames Time Zeit BBT &Base font size: &Basisschriftgröße: Base application font size (pt.) Generelle Schriftgröße (pt.) für die Anwendung festlegen (default) (voreingestellt) 6 6 7 7 8 8 9 9 10 10 11 11 12 12 Meters &Audio: &Audio: Audio meter level Over 0 dB 3 dB 6 dB 10 dB Audio meter color Select custom audio meter color ... &MIDI: &MIDI: MIDI meter level Peak MIDI meter color Select custom MIDI meter color Reset meter colors to default &Reset &Zurücksetzen Alt+R Alt+F Messages Meldungen Sample messages text font display Beispielhafte Darstellung des Textes im Meldungsfenster Select font for the messages text display Schriftart für Text im Meldungsfenster wählen &Font... &Schriftart... Alt+F Alt+V Whether to keep a maximum number of lines in the messages window Maximale Anzahl der im Meldungsfenster angezeigten Zeilen festlegen M&essages limit: Alt+M Alt+M The maximum number of message lines to keep in view Maximale Anzahl der Nachrichten im Meldungsfenster lines Logging Protokollierung Messages log file Protokolldatei für Meldungen Browse for the messages log file location Speicherort für Protokolldatei wählen Whether to activate a messages logging to file. Protokollierung der Meldungen in eine Datei festlegen. Messages &log file: Protokoll&datei: &Plugins Paths Pfade Plugin type Plugin path Browse plugin path Add plugin path &Add &Hinzufügen Plugin paths Remove plugin path &Remove En&tfernen Move up path &Up Au&f &Down A&b &LV2 Presets directory: LV2 Presets directory (default: ~/.lv2) Browse LV2 Presets directory Instruments Instrumente Whether to have separate audio output ports Dedicated audi&o outputs: Whether to auto-connect dedicated audio output ports Au&to-connect Alt+T Alt+T Editor Editor Whether to open plugin's editor (GUI) by default Open plugin's &editor (GUI) by default Alt+G Experimental Experimentell Whether to use a dummy plugin type when scanning for VST plugins Dummy &VST plugin scan (RECOMMENDED) Alt+V Alt+V Signed 16-Bit Signed 24-Bit Signed 32-Bit Float 32-Bit Float 64-Bit SMF Format 0 SMF Format 1 (Any) Warning Warnung Some settings have been changed. Do you want to apply the changes? Einige Einstellungen wurden verändert. Wollen Sie diese übernehmen? Metronome Bar Audio File Metronome Beat Audio File Plug-in Directory LV2 Presets Directory Messages Log Meldungsprotokoll Log files (*.%1) Session Template Session template files (*.qtr *.qts *.%1) qtractorPasteRepeatForm Paste Repeat - Qtractor Repeat &Count: Repeat count &Period: Repeat period Repeat period format Frames Time Zeit BBT Warning Warnung Some settings have been changed. Do you want to apply the changes? Einige Einstellungen wurden verändert. Wollen Sie diese übernehmen? qtractorPluginForm qtractorPluginForm Open preset Preset name Save preset Delete preset Plugin parameters Params Edit plugin Edit Bearbeiten Activate plugin Active Aktiv Outputs (Sends) Sends Inputs (Returns) Returns Aux Send Bus: Manage buses ... Direct Access Parameter Direct Access (default) (voreingestellt) Page %1 (none) Open Preset Preset files (*.%1) Error Fehler Preset could not be loaded from "%1". Sorry. Save Preset Warning Warnung About to delete preset: "%1" (%2) Are you sure? &None &Nichts qtractorPluginListView copy plugin activate all plugins deactivate all plugins remove all plugins &Move Here &Copy Here C&ancel &Add Plugin... Add &Insert Add &Aux Send &Sends &Returns Ac&tivate Acti&vate All Deactivate Al&l &Remove En&tfernen Re&move All Move &Up Move &Down &None &Nichts &Properties... &Eigenschaften &Edit &Bearbeiten &Outputs &Ausgänge &Dedicated &Auto-connect qtractorPluginSelectForm Plugins - Qtractor Reset filter X Plugin search string (regular expression) Plugin type Available plugins Name Name Audio Audio MIDI Control Modes Path Pfad Index Instances Type Typ &Activate Activate plugin on insert Alt+A Alt+A Plugin scanning in progress... GUI EXT RT RT qtractorSessionForm Session - Qtractor Session Sitzung &Name: &Name: Session name &Directory: Session directory Sitzungsverzeichnis Browse for session directory ... &Description: Session description Properties Eigenschaften Time Zeit Sample &Rate: Abtast&rate: Sample rate (Hz) 44100 44100 48000 48000 96000 96000 192000 192000 &Tempo: Tempo (BPM) / Signature T&icks/Beat: Resolution (ticks/beat; tpqn) View &Snap/Beat: Snap/beat &Pixels/Beat: Pixels/beat &Horizontal Zoom: Horizontal Zoom (%) % &Vertical Zoom: Vertical Zoom (%) Warning Warnung Session directory does not exist: "%1" Do you want to create it? Some settings have been changed. Do you want to apply the changes? Einige Einstellungen wurden verändert. Wollen Sie diese übernehmen? Session Directory qtractorShortcutForm Keyboard Shortcuts Tastaturkürzel Action Aktion Description Beschreibung Shortcut Kürzel Warning Warnung Keyboard shortcut (%1) already assigned. Tastaturkürzel (%1) bereits zugewiesen. Keyboard shortcuts have been changed. Do you want to apply the changes? Tastaturkürzel wurden verändert. Wollen Sie diese übernehmen? qtractorTakeRangeForm Take - Qtractor Range Bereich Selection range &Selection Loop range &Loop &Endlosschleife Punch range &Punch Time Zeit BBT Edit range &Edit &Bearbeiten Custom range &Custom St&art: St&art: Clip start En&d: En&de: Clip offset Select Current take Format Format Time display format Frames Time (hh:mm:ss.zzz) Zeit (hh:mm:ss.zzz) &Time &Zeit Take %1 qtractorTempoAdjustForm Tempo - Qtractor Metronome Metronom Temp&o: Tempo/Time signature T&ap Range Bereich &Start: &Start: Range start Time Zeit BBT &Length: &Länge: Range length B&eats: Range beats A&djust An&passen Format Format Time display format Frames Time (hh:mm:ss.zzz) Zeit (hh:mm:ss.zzz) &Time &Zeit Warning Warnung Some settings have been changed. Do you want to apply the changes? Einige Einstellungen wurden verändert. Wollen Sie diese übernehmen? qtractorThumbView Thumb view qtractorTimeScaleForm Tempo Map / Markers - Qtractor Tempo map / Markers Bar Time Zeit Tempo Marker Markierung Location &Bar: Bar location T&ime: &Zeit: Time/frame location Node &Tempo: Tempo (BPM) / Signature T&ap Marker text ... Marker color Refresh tempo map Re&fresh Au&ffrischen Alt+F Alt+V Add node &Add &Hinzufügen Alt+A Alt+A Update node &Update A&ktualisieren Alt+U Alt+K Remove node &Remove En&tfernen Alt+R Alt+F Close this dialog Diesen Dialog schließen Close Schließen Warning Warnung Some settings have been changed. Do you want to apply the changes? Einige Einstellungen wurden verändert. Wollen Sie diese übernehmen? About to remove tempo node: %1 (%2) %3 %4/%5 Are you sure? Some settings have been changed. Do you want to discard the changes? Einige Einstellungen wurden verändert. Wollen Sie diese verwerfen? &Refresh Au&ffrischen qtractorTimeSpinBox &Frames &Time &Zeit &BBT qtractorTrackButton Record Mute Solo qtractorTrackForm Track - Qtractor Track Spur &Name: &Name: Track name description Type Typ Audio track type &Audio Alt+A Alt+A MIDI track type &MIDI Alt+M Alt+M Input / Output Input bus name Output bus name Manage buses ... MIDI / Instrument &Program: &Bank: Bank &Select Method: &Omni MIDI Omni: Capture All Channels Alt+O Alt+Ü &Channel: &Kanal: MIDI Channel (1-16) MIDI Patch: Instrument MIDI Patch: Bank Select Method MIDI Patch: Bank MIDI Patch: Program View / Colors &Foreground: Foreground color Select custom track foreground color Bac&kground: Hin&tergrund: Background color Select custom track background color Plugins Track plugins Add plugin &Add... &Hinzufügen... Remove plugin &Remove En&tfernen Alt+R Alt+F Move plugin up &Up Au&f Alt+U Alt+K Move plugin down &Down A&b Alt+D Alt+T Normal Bank MSB Bank LSB Patch Warning Warnung Some settings have been changed. Do you want to apply the changes? Einige Einstellungen wurden verändert. Wollen Sie diese übernehmen? (No instrument) (Kein Instrument) (None) (Keine) qtractorTrackListHeaderModel Nr Nr Track Name Spurname Bus Bus Ch Kanal Patch Instrument Instrument qtractorTrackTime Play-head Edit-head Edit-tail Loop-start Loop-end Punch-in Punch-out Start: %1 End: %2 Length: %3 Start: %1 Ende: %2 Länge: %3 qtractorTrackView Zoom in (horizontal) Zoom out (horizontal) Zoom in (vertical) Zoom out (vertical) Zoom reset add clip Start: %1 End: %2 Length: %3 Start: %1 Ende: %2 Länge: %3 clip %1 fade-in fade-out clip stretch clip resize %1 automation %1 clip move automation paste automation cut delete split move clip paste clip qtractorTracks Tracks Spuren new clip split clip clip normalize quantize transpose normalize randomize resize rescale timeshift clip tool %1 clip import Audio file import "%1" on %2 %3. Audio file import: "%1". MIDI file import "%1" track-channel %2 on %3 %4. MIDI file import: "%1", track-channel: %2. clip merge Merge/Export Audio Clip Audio files (*.%1) Audio clip merge/export: "%1" started... Audio clip merge/export: "%1" complete. Merge/Export MIDI Clip MIDI files (*.%1 *.smf *.midi) MIDI-Dateien (*.%1 *.smf *.midi) MIDI clip merge/export: "%1" started... MIDI clip merge/export: "%1" complete. Insert Range Bereich einfügen insert range insert track range Remove Range remove range remove track range Warning Warnung About to remove track: "%1" Are you sure? MIDI file import "%1" on %2 %3. MIDI file import: "%1". qtractor-0.5.11/src/PaxHeaders.10084/qtractorConnections.h0000644000175000001440000000012311354101152021447 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134666.35608 30 ctime=1381134666.357080039 qtractor-0.5.11/src/qtractorConnections.h0000644000175000001440000000426611354101152020746 0ustar00rncbcusers00000000000000// qtractorConnections.h // /**************************************************************************** Copyright (C) 2005-2010, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorConnections_h #define __qtractorConnections_h #include "qtractorEngine.h" #include // Forward declarations. class qtractorConnectForm; //------------------------------------------------------------------------- // qtractorConnections - Connections dockable window. // class qtractorConnections : public QWidget { Q_OBJECT public: // Constructor. qtractorConnections(QWidget *pParent, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorConnections(); // Connect form accessor. qtractorConnectForm *connectForm() const; // Main bus mode switching. void showBus(qtractorBus *pBus, qtractorBus::BusMode busMode); // Complete connections refreshment. void refresh(); // Complete connections recycle. void clear(); // Conditional connections recycle. void reset(); protected: // Notify the main application widget that we're closing. void showEvent(QShowEvent *); void hideEvent(QHideEvent *); // Just about to notify main-window that we're closing. void closeEvent(QCloseEvent *); // Keyboard event handler. void keyPressEvent(QKeyEvent *); private: // Instance variables. qtractorConnectForm *m_pConnectForm; }; #endif // __qtractorConnections_h // end of qtractorConnections.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEngine.h0000644000175000001440000000012312070655741021213 xustar000000000000000027 mtime=1357077473.388373 26 atime=1381134666.49108 30 ctime=1381134666.491080041 qtractor-0.5.11/src/qtractorMidiEngine.h0000644000175000001440000003473712070655741020520 0ustar00rncbcusers00000000000000// qtractorMidiEngine.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiEngine_h #define __qtractorMidiEngine_h #include "qtractorEngine.h" #include "qtractorTimeScale.h" #include "qtractorMmcEvent.h" #include "qtractorCtlEvent.h" #include #include // Forward declarations. class qtractorMidiBus; class qtractorMidiEvent; class qtractorMidiSequence; class qtractorMidiInputThread; class qtractorMidiOutputThread; class qtractorMidiMonitor; class qtractorMidiSysexList; class qtractorMidiPlayer; class qtractorPluginList; class qtractorCurveList; class QSocketNotifier; //---------------------------------------------------------------------- // class qtractorMidiEngineProxy -- MIDI engine event proxy object. // class qtractorMidiEngineProxy : public QObject { Q_OBJECT public: // Constructor. qtractorMidiEngineProxy(QObject *pParent = NULL) : QObject(pParent) {} // Event notifications. void notifyMmcEvent(const qtractorMmcEvent& mmce) { emit mmcEvent(mmce); } void notifyCtlEvent(const qtractorCtlEvent& ctle) { emit ctlEvent(ctle); } void notifySppEvent(int iSppCmd, unsigned short iSongPos) { emit sppEvent(iSppCmd, iSongPos); } void notifyClkEvent(float fTempo) { emit clkEvent(fTempo); } signals: // Event signals. void mmcEvent(const qtractorMmcEvent& mmce); void ctlEvent(const qtractorCtlEvent& ctle); void sppEvent(int iSppCmd, unsigned short iSongPos); void clkEvent(float fTempo); }; //---------------------------------------------------------------------- // class qtractorMidiEngine -- ALSA sequencer client instance (singleton). // class qtractorMidiEngine : public qtractorEngine { public: // Constructor. qtractorMidiEngine(qtractorSession *pSession); // Engine initialization. bool init(); // Special event notifier proxy object. const qtractorMidiEngineProxy *proxy() const; // ALSA client descriptor accessor. snd_seq_t *alsaSeq() const; int alsaClient() const; int alsaQueue() const; // ALSA subscription port notifier. QSocketNotifier *alsaNotifier() const; void alsaNotifyAck(); // Special slave sync method. void sync(); // Read ahead frames configuration. void setReadAhead(unsigned int iReadAhead); unsigned int readAhead() const; // Reset queue tempo. void resetTempo(); // Reset all MIDI monitoring... void resetAllMonitors(); // Reset all MIDI controllers... void resetAllControllers(bool bForceImmediate); bool isResetAllControllers() const; // Shut-off all MIDI tracks (panic)... void shutOffAllTracks() const; // MIDI event capture method. void capture(snd_seq_event_t *pEv); // MIDI event enqueue method. void enqueue(qtractorTrack *pTrack, qtractorMidiEvent *pEvent, unsigned long iTime, float fGain = 1.0f); // Do ouput queue drift stats (audio vs. MIDI)... void drift(); // Flush ouput queue (if necessary)... void flush(); // Special rewind method, on queue loop. void restartLoop(); // The delta-time/frame accessors. long timeStart() const; long frameStart() const; // Special track-immediate methods. void trackMute(qtractorTrack *pTrack, bool bMute); // Special metronome-immediate methods. void metroMute(bool bMute); // Metronome switching. void setMetronome(bool bMetronome); bool isMetronome() const; // Metronome enabled accessors. void setMetroEnabled(bool bMetroEnabled); bool isMetroEnabled() const; // Metronome bus accessors. void setMetroBus(bool bMetroBus); bool isMetroBus() const; void resetMetroBus(); // Metronome parameters. void setMetroChannel (unsigned short iChannel); unsigned short metroChannel() const; void setMetroBar(int iNote, int iVelocity, unsigned long iDuration); int metroBarNote() const; int metroBarVelocity() const; unsigned long metroBarDuration() const; void setMetroBeat(int iNote, int iVelocity, unsigned long iDuration); int metroBeatNote() const; int metroBeatVelocity() const; unsigned long metroBeatDuration() const; // Process metronome clicks. void processMetro(unsigned long iFrameStart, unsigned long iFrameEnd); // Access to current tempo/time-signature cursor. qtractorTimeScale::Cursor *metroCursor() const; // Control bus accessors. void setControlBus(bool bControlBus); bool isControlBus() const; void resetControlBus(); // Control buses accessors. qtractorMidiBus *controlBus_in() const; qtractorMidiBus *controlBus_out() const; // Audition/pre-listening bus mode accessors. void setPlayerBus(bool bPlayerBus); bool isPlayerBus() const; bool isPlayerOpen() const; bool openPlayer(const QString& sFilename, int iTrackChannel = -1); void closePlayer(); // MMC dispatch special commands. void sendMmcLocate(unsigned long iLocate) const; void sendMmcMaskedWrite(qtractorMmcEvent::SubCommand scmd, int iTrack, bool bOn) const; void sendMmcCommand(qtractorMmcEvent::Command cmd, unsigned char *pMmcData = NULL, unsigned short iMmcData = 0) const; // SPP dispatch special command. void sendSppCommand(int iCmdType, unsigned short iSongPos = 0) const; // Document element methods. bool loadElement(qtractorDocument *pDocument, QDomElement *pElement); bool saveElement(qtractorDocument *pDocument, QDomElement *pElement) const; // MIDI-export method. bool fileExport(const QString& sExportPath, unsigned long iExportStart = 0, unsigned long iExportEnd = 0, qtractorMidiBus *pExportBus = NULL); // Retrieve/restore all connections, on all buses; // return the effective number of connection attempts. int updateConnects(); // Capture (record) quantization accessors. void setCaptureQuantize(unsigned short iCaptureQuantize); unsigned short captureQuantize() const; // ALSA device queue timer. void setAlsaTimer(int iAlsaTimer); int alsaTimer() const; // MMC device-id accessors. void setMmcDevice(unsigned char mmcDevice); unsigned char mmcDevice() const; // MMC mode accessors. void setMmcMode(qtractorBus::BusMode mmcMode); qtractorBus::BusMode mmcMode() const; // SPP mode accessors. void setSppMode(qtractorBus::BusMode sppMode); qtractorBus::BusMode sppMode() const; // MIDI Clock mode accessors. void setClockMode(qtractorBus::BusMode clockMode); qtractorBus::BusMode clockMode() const; // Free overriden SysEx queued events. void clearSysexCache(); protected: // Concrete device (de)activation methods. bool activate(); bool start(); void stop(); void deactivate(); void clean(); // Reset ouput queue drift stats (audio vs. MIDI)... void resetDrift(); // Metronome (de)activation methods. void createMetroBus(); bool openMetroBus(); void closeMetroBus(); void deleteMetroBus(); // Control (de)activation methods. void createControlBus(); bool openControlBus(); void closeControlBus(); void deleteControlBus(); // Player (de)activation methods. void createPlayerBus(); bool openPlayerBus(); void closePlayerBus(); void deletePlayerBus(); private: // Special event notifier proxy object. qtractorMidiEngineProxy m_proxy; // Device instance variables. snd_seq_t *m_pAlsaSeq; int m_iAlsaClient; int m_iAlsaQueue; int m_iAlsaTimer; // Subscription notification stuff. snd_seq_t *m_pAlsaSubsSeq; int m_iAlsaSubsPort; QSocketNotifier *m_pAlsaNotifier; // Name says it all. qtractorMidiInputThread *m_pInputThread; qtractorMidiOutputThread *m_pOutputThread; // The number of times we check for time drift. unsigned int m_iDriftCheck; // The delta-time/frame when playback started . long m_iTimeStart; long m_iTimeDrift; long m_iFrameStart; long m_iFrameTime; // The assigned control buses. bool m_bControlBus; qtractorMidiBus *m_pIControlBus; qtractorMidiBus *m_pOControlBus; // Metronome enablement. bool m_bMetronome; bool m_bMetroBus; qtractorMidiBus *m_pMetroBus; unsigned short m_iMetroChannel; int m_iMetroBarNote; int m_iMetroBarVelocity; unsigned long m_iMetroBarDuration; int m_iMetroBeatNote; int m_iMetroBeatVelocity; unsigned long m_iMetroBeatDuration; bool m_bMetroEnabled; // Time-scale cursor (tempo/time-signature map) qtractorTimeScale::Cursor *m_pMetroCursor; // Track down tempo changes. float m_fMetroTempo; // SMF player enablement. bool m_bPlayerBus; qtractorMidiBus *m_pPlayerBus; qtractorMidiPlayer *m_pPlayer; // Input quantization (aka. record snap-per-beat). unsigned short m_iCaptureQuantize; // Controller update pending flagger. int m_iResetAllControllers; // MMC Device ID. unsigned char m_mmcDevice; // MMC/SPP modes. qtractorBus::BusMode m_mmcMode; qtractorBus::BusMode m_sppMode; // MIDI Clock mode. qtractorBus::BusMode m_clockMode; // MIDI Clock tempo tracking. unsigned short m_iClockCount; float m_fClockTempo; // Overriden SysEx queued events. QList m_sysexCache; }; //---------------------------------------------------------------------- // class qtractorMidiBus -- Managed ALSA sequencer port set // class qtractorMidiBus : public qtractorBus { public: // Constructor. qtractorMidiBus(qtractorMidiEngine *pMidiEngine, const QString& sBusName, BusMode busMode, bool bMonitor = false); // Destructor. ~qtractorMidiBus(); // ALSA sequencer port accessor. int alsaPort() const; // Activation methods. bool open(); void close(); // Shut-off everything out there. void shutOff(bool bClose = false) const; // SysEx setup list accessors. qtractorMidiSysexList *sysexList() const; // Default instrument name accessors. void setInstrumentName(const QString& sInstrumentName); const QString& instrumentName() const; // Channel map payload. struct Patch { // Default payload constructor. Patch() : bankSelMethod(-1), bank(-1), prog(-1) {} // Payload members. QString instrumentName; int bankSelMethod; int bank; int prog; }; // Channel patch map accessor. Patch& patch(unsigned short iChannel) { return m_patches[iChannel & 0x0f]; } // Direct MIDI bank/program selection helper. void setPatch(unsigned short iChannel, const QString& sInstrumentName, int iBankSelMethod, int iBank, int iProg, qtractorTrack *pTrack); // Direct MIDI controller helpers. void setController(qtractorTrack *pTrack, int iController, int iValue = 0) const; void setController(unsigned short iChannel, int iController, int iValue = 0) const; // Direct MIDI channel event helper. void sendEvent(qtractorMidiEvent::EventType etype, unsigned short iChannel, unsigned short iParam, unsigned short iValue) const; // Direct MIDI note helper. void sendNote(qtractorTrack *pTrack, int iNote, int iVelocity = 0) const; // Direct SysEx helpers. void sendSysex(unsigned char *pSysex, unsigned int iSysex) const; void sendSysexList() const; // Import/export SysEx setup from/into event sequence. bool importSysexList(qtractorMidiSequence *pSeq); bool exportSysexList(qtractorMidiSequence *pSeq); // Virtual I/O bus-monitor accessors. qtractorMonitor *monitor_in() const; qtractorMonitor *monitor_out() const; // MIDI I/O bus-monitor accessors. qtractorMidiMonitor *midiMonitor_in() const; qtractorMidiMonitor *midiMonitor_out() const; // Plugin-chain accessors. qtractorPluginList *pluginList_in() const; qtractorPluginList *pluginList_out() const; // Automation curve list accessors. qtractorCurveList *curveList_in() const; qtractorCurveList *curveList_out() const; // Automation curve serializer accessors. qtractorCurveFile *curveFile_in() const; qtractorCurveFile *curveFile_out() const; // Retrieve/restore client:port connections. // return the effective number of connection attempts. int updateConnects(BusMode busMode, ConnectList& connects, bool bConnect = false) const; // MIDI master volume. void setMasterVolume(float fVolume); // MIDI master panning (balance). void setMasterPanning(float fPanning); // MIDI channel volume. void setVolume(qtractorTrack *pTrack, float fVolume); // MIDI channel stereo panning. void setPanning(qtractorTrack *pTrack, float fPanning); // Document element methods. bool loadElement(qtractorDocument *pDocument, QDomElement *pElement); bool saveElement(qtractorDocument *pDocument, QDomElement *pElement) const; protected: // Direct MIDI controller common helper. void setControllerEx(unsigned short iChannel, int iController, int iValue = 0, qtractorTrack *pTrack = NULL) const; // Bus mode change event. void updateBusMode(); // Create plugin-list properly. qtractorPluginList *createPluginList(int iFlags) const; // Set plugin-list title name properly. void updatePluginListName( qtractorPluginList *pPluginList, int iFlags) const; // Set plugin-list buffers properly. void updatePluginList(qtractorPluginList *pPluginList, int iFlags); // Document instrument map methods. bool loadMidiMap(qtractorDocument *pDocument, QDomElement *pElement); bool saveMidiMap(qtractorDocument *pDocument, QDomElement *pElement) const; // Document SysEx setup list methods. bool loadSysexList(qtractorDocument *pDocument, QDomElement *pElement); bool saveSysexList(qtractorDocument *pDocument, QDomElement *pElement) const; private: // Instance variables. int m_iAlsaPort; // Specific monitor instances. qtractorMidiMonitor *m_pIMidiMonitor; qtractorMidiMonitor *m_pOMidiMonitor; // Plugin-chain instances. qtractorPluginList *m_pIPluginList; qtractorPluginList *m_pOPluginList; // Automation curve serializer instances. qtractorCurveFile *m_pICurveFile; qtractorCurveFile *m_pOCurveFile; // SysEx setup list. qtractorMidiSysexList *m_pSysexList; // Default instrument name. QString m_sInstrumentName; // Channel patch mapper. QHash m_patches; }; #endif // __qtractorMidiEngine_h // end of qtractorMidiEngine.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorPlugin.cpp0000644000175000001440000000012312166526620020773 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134668.06708 30 ctime=1381134668.067080066 qtractor-0.5.11/src/qtractorPlugin.cpp0000644000175000001440000015226312166526620020273 0ustar00rncbcusers00000000000000// qtractorPlugin.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorPlugin.h" #include "qtractorPluginListView.h" #include "qtractorPluginCommand.h" #include "qtractorPluginForm.h" #include "qtractorAudioEngine.h" #include "qtractorMidiBuffer.h" #include "qtractorOptions.h" #include "qtractorSession.h" #include "qtractorDocument.h" #include "qtractorCurveFile.h" #ifdef CONFIG_LADSPA #include "qtractorLadspaPlugin.h" #endif #ifdef CONFIG_DSSI #include "qtractorDssiPlugin.h" #endif #ifdef CONFIG_VST #include "qtractorVstPlugin.h" #endif #ifdef CONFIG_LV2 #include "qtractorLv2Plugin.h" #endif #include "qtractorInsertPlugin.h" #include #include #include #include #include #if QT_VERSION < 0x040500 namespace Qt { const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000); } #endif // A common scheme for (a default) plugin serach paths... // #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) #define PATH_SEP ";" #else #define PATH_SEP ":" #endif static QString default_paths ( const QString& suffix ) { const QString& sep = QDir::separator(); const QString& home = QDir::homePath(); const QString& pre1 = QDir::rootPath() + "usr"; const QString& pre2 = pre1 + sep + "local"; const QString& lib0 = "lib"; const QString& lib1 = pre1 + sep + lib0; const QString& lib2 = pre2 + sep + lib0; #if defined(__x86_64__) const QString& x64 = "64"; const QString& lib3 = lib1 + x64; const QString& lib4 = lib2 + x64; #endif QStringList paths; paths << home + sep + '.' + suffix; #if defined(__x86_64__) // paths << home + sep + lib0 + x64 + sep + suffix; paths << lib4 + sep + suffix; paths << lib3 + sep + suffix; #endif // paths << home + sep + lib0 + sep + suffix; paths << lib2 + sep + suffix; paths << lib1 + sep + suffix; return paths.join(PATH_SEP); } // A common function for special platforms... // #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) typedef void (*qtractorPluginFile_Function)(void); #endif //---------------------------------------------------------------------------- // qtractorPluginPath -- Plugin path helper. // // Executive methods. bool qtractorPluginPath::open (void) { close(); // Get paths based on hints... QString sPaths; QStringList paths; QStringList path_list; #ifdef CONFIG_LADSPA // LADSPA default path... if (m_typeHint == qtractorPluginType::Any || m_typeHint == qtractorPluginType::Ladspa) { paths = m_paths.value(qtractorPluginType::Ladspa); if (paths.isEmpty()) { sPaths = ::getenv("LADSPA_PATH"); if (sPaths.isEmpty()) sPaths = default_paths("ladspa"); if (!sPaths.isEmpty()) { paths = sPaths.split(PATH_SEP); m_paths.insert(qtractorPluginType::Ladspa, paths); } } path_list.append(paths); } #endif #ifdef CONFIG_DSSI // DSSI default path... if (m_typeHint == qtractorPluginType::Any || m_typeHint == qtractorPluginType::Dssi) { paths = m_paths.value(qtractorPluginType::Dssi); if (paths.isEmpty()) { sPaths = ::getenv("DSSI_PATH"); if (sPaths.isEmpty()) sPaths = default_paths("dssi"); if (!sPaths.isEmpty()) { paths = sPaths.split(PATH_SEP); m_paths.insert(qtractorPluginType::Dssi, paths); } } path_list.append(paths); } #endif #ifdef CONFIG_VST // VST default path... if (m_typeHint == qtractorPluginType::Any || m_typeHint == qtractorPluginType::Vst) { paths = m_paths.value(qtractorPluginType::Vst); if (paths.isEmpty()) { sPaths = ::getenv("VST_PATH"); if (sPaths.isEmpty()) sPaths = default_paths("vst"); if (!sPaths.isEmpty()) { paths = sPaths.split(PATH_SEP); m_paths.insert(qtractorPluginType::Vst, paths); } } path_list.append(paths); } #endif #ifdef CONFIG_LV2 // LV2 default path... if (m_typeHint == qtractorPluginType::Any || m_typeHint == qtractorPluginType::Lv2) { paths = m_paths.value(qtractorPluginType::Lv2); if (paths.isEmpty()) { sPaths = ::getenv("LV2_PATH"); if (sPaths.isEmpty()) sPaths = default_paths("lv2"); if (!sPaths.isEmpty()) { paths = sPaths.split(PATH_SEP); m_paths.insert(qtractorPluginType::Lv2, paths); } } path_list.append(paths); #ifdef CONFIG_LV2_PRESETS QString sPresetDir; qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) sPresetDir = pOptions->sLv2PresetDir; if (sPresetDir.isEmpty()) sPresetDir = QDir::homePath() + QDir::separator() + ".lv2"; if (!paths.contains(sPresetDir)) paths.append(sPresetDir); #endif // HACK: set special environment for LV2... ::setenv("LV2_PATH", paths.join(PATH_SEP).toUtf8().constData(), 1); } #endif #ifdef CONFIG_DEBUG qDebug("qtractorPluginPath[%p]::open() paths=\"%s\" typeHint=%d", this, path_list.join(PATH_SEP).toUtf8().constData(), int(m_typeHint)); #endif QStringListIterator path_iter(path_list); while (path_iter.hasNext()) { const QDir dir(path_iter.next()); const QStringList& file_list = dir.entryList(QDir::Files); QStringListIterator file_iter(file_list); while (file_iter.hasNext()) { const QString& sPath = dir.absoluteFilePath(file_iter.next()); if (QLibrary::isLibrary(sPath)) m_files.append(new qtractorPluginFile(sPath)); } } return (m_files.count() > 0); } void qtractorPluginPath::close (void) { qDeleteAll(m_files); m_files.clear(); } // Helper methods. void qtractorPluginPath::setPaths ( qtractorPluginType::Hint typeHint, const QString& sPaths ) { m_paths.insert(typeHint, sPaths.split(PATH_SEP)); } //---------------------------------------------------------------------------- // qtractorPluginFile -- Plugin file library instance. // // Executive methods. bool qtractorPluginFile::open (void) { close(); // ATTN: Not really needed, as it would be // loaded automagically on resolve()... if (!QLibrary::load()) return false; // Do the openning dance... #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) qtractorPluginFile_Function pfnInit = (qtractorPluginFile_Function) QLibrary::resolve("_init"); if (pfnInit) (*pfnInit)(); #endif return true; } void qtractorPluginFile::close (void) { if (!QLibrary::isLoaded()) return; // Do the closing dance... #if 0 // defined(__WIN32__) || defined(_WIN32) || defined(WIN32) qtractorPluginFile_Function pfnFini = (qtractorPluginFile_Function) QLibrary::resolve("_fini"); if (pfnFini) (*pfnFini)(); #endif if (m_bAutoUnload) QLibrary::unload(); } // Plugin type listing. bool qtractorPluginFile::getTypes ( qtractorPluginPath& path, qtractorPluginType::Hint typeHint ) { // Try to fill the types list at this moment... qtractorPluginType *pType; unsigned long iIndex = 0; #ifdef CONFIG_DSSI // Try DSSI plugin types first... if (typeHint == qtractorPluginType::Any || typeHint == qtractorPluginType::Dssi) { while ((pType = qtractorDssiPluginType::createType(this, iIndex)) != NULL) { if (pType->open()) { path.addType(pType); pType->close(); ++iIndex; } else { delete pType; break; } } } // Have we found some, already? if (iIndex > 0) return true; #endif #ifdef CONFIG_LADSPA // Try LADSPA plugin types... if (typeHint == qtractorPluginType::Any || typeHint == qtractorPluginType::Ladspa) { while ((pType = qtractorLadspaPluginType::createType(this, iIndex)) != NULL) { if (pType->open()) { path.addType(pType); pType->close(); ++iIndex; } else { delete pType; break; } } } // Have we found some, already? if (iIndex > 0) return true; #endif #ifdef CONFIG_VST // Try VST plugin types... if (typeHint == qtractorPluginType::Any || typeHint == qtractorPluginType::Vst) { // Need to look at the options... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions && pOptions->bDummyVstScan) pType = qtractorDummyPluginType::createType(this); else pType = qtractorVstPluginType::createType(this); if (pType) { if (pType->open()) { path.addType(pType); pType->close(); ++iIndex; } else { delete pType; } } } #endif // Have we something? return (iIndex > 0); } // Plugin factory method (static). qtractorPlugin *qtractorPluginFile::createPlugin ( qtractorPluginList *pList, const QString& sFilename, unsigned long iIndex, qtractorPluginType::Hint typeHint ) { #ifdef CONFIG_DEBUG qDebug("qtractorPluginFile::createPlugin(%p, \"%s\", %lu, %d)", pList, sFilename.toUtf8().constData(), iIndex, int(typeHint)); #endif // Attend to insert pseudo-plugin hints... if (sFilename.isEmpty()) { if (typeHint == qtractorPluginType::Insert) { qtractorInsertPluginType *pInsertType = qtractorInsertPluginType::createType(iIndex); if (pInsertType) { if (pInsertType->open()) return new qtractorInsertPlugin(pList, pInsertType); delete pInsertType; } } else if (typeHint == qtractorPluginType::AuxSend) { qtractorAuxSendPluginType *pAuxSendType = qtractorAuxSendPluginType::createType(iIndex); if (pAuxSendType) { if (pAuxSendType->open()) return new qtractorAuxSendPlugin(pList, pAuxSendType); delete pAuxSendType; } } // Don't bother with anything else. return NULL; } #ifdef CONFIG_LV2 // Try LV2 plugins hints before anything else... if (typeHint == qtractorPluginType::Any || typeHint == qtractorPluginType::Lv2) { qtractorLv2PluginType *pLv2Type = qtractorLv2PluginType::createType(sFilename); if (pLv2Type) { if (pLv2Type->open()) return new qtractorLv2Plugin(pList, pLv2Type); delete pLv2Type; } } #endif // Try to fill the types list at this moment... qtractorPluginFile *pFile = new qtractorPluginFile(sFilename); if (!pFile->open()) { delete pFile; return NULL; } #ifdef CONFIG_DSSI // Try DSSI plugin types first... if (typeHint == qtractorPluginType::Any || typeHint == qtractorPluginType::Dssi) { qtractorDssiPluginType *pDssiType = qtractorDssiPluginType::createType(pFile, iIndex); if (pDssiType) { if (pDssiType->open()) return new qtractorDssiPlugin(pList, pDssiType); delete pDssiType; } } #endif #ifdef CONFIG_LADSPA // Try LADSPA plugin types... if (typeHint == qtractorPluginType::Any || typeHint == qtractorPluginType::Ladspa) { qtractorLadspaPluginType *pLadspaType = qtractorLadspaPluginType::createType(pFile, iIndex); if (pLadspaType) { if (pLadspaType->open()) return new qtractorLadspaPlugin(pList, pLadspaType); delete pLadspaType; } } #endif #ifdef CONFIG_LV2 // Try LV2 plugin types... if (typeHint == qtractorPluginType::Any || typeHint == qtractorPluginType::Lv2) { qtractorLv2PluginType *pLv2Type = qtractorLv2PluginType::createType(sFilename); if (pLv2Type) { if (pLv2Type->open()) return new qtractorLv2Plugin(pList, pLv2Type); delete pLv2Type; } } #endif #ifdef CONFIG_VST // Try VST plugin types... if (typeHint == qtractorPluginType::Any || typeHint == qtractorPluginType::Vst) { qtractorVstPluginType *pVstType = qtractorVstPluginType::createType(pFile); if (pVstType) { if (pVstType->open()) return new qtractorVstPlugin(pList, pVstType); delete pVstType; } } #endif // Bad luck, no valid plugin found... delete pFile; return NULL; } //---------------------------------------------------------------------------- // qtractorPluginType -- Plugin type instance. // // Plugin filename accessor (default virtual). QString qtractorPluginType::filename (void) const { return (m_pFile ? m_pFile->filename() : QString()); } // Compute the number of instances needed // for the given input/output audio channels. unsigned short qtractorPluginType::instances ( unsigned short iChannels, bool bMidi ) const { unsigned short iInstances = 0; if (iChannels > 0) { if (bMidi && m_iMidiOuts > 0) iInstances = 1; else if (iChannels >= m_iAudioIns && m_iAudioOuts > 0) iInstances = (m_iAudioOuts >= iChannels ? 1 : iChannels); else if (m_iAudioOuts >= iChannels) iInstances = (iChannels >= m_iAudioIns ? iChannels : 1); else if (bMidi && m_iMidiIns > 0) iInstances = 1; } return iInstances; } // Plugin type(hint) textual helpers (static). qtractorPluginType::Hint qtractorPluginType::hintFromText ( const QString& sText ) { #ifdef CONFIG_LADSPA if (sText == "LADSPA") return Ladspa; else #endif #ifdef CONFIG_DSSI if (sText == "DSSI") return Dssi; else #endif #ifdef CONFIG_VST if (sText == "VST") return Vst; else #endif #ifdef CONFIG_LV2 if (sText == "LV2") return Lv2; else #endif if (sText == "Insert") return Insert; else if (sText == "AuxSend") return AuxSend; else return Any; } QString qtractorPluginType::textFromHint ( qtractorPluginType::Hint typeHint ) { #ifdef CONFIG_LADSPA if (typeHint == Ladspa) return "LADSPA"; else #endif #ifdef CONFIG_DSSI if (typeHint == Dssi) return "DSSI"; else #endif #ifdef CONFIG_VST if (typeHint == Vst) return "VST"; else #endif #ifdef CONFIG_LV2 if (typeHint == Lv2) return "LV2"; else #endif if (typeHint == Insert) return "Insert"; else if (typeHint == AuxSend) return "AuxSend"; else return QObject::tr("(Any)"); } //---------------------------------------------------------------------------- // qtractorDummyPluginType -- Dummy plugin type instance. // // Constructor. qtractorDummyPluginType::qtractorDummyPluginType ( qtractorPluginFile *pFile, unsigned long iIndex, Hint typeHint) : qtractorPluginType(pFile, iIndex, typeHint) { } // Must be overriden methods. bool qtractorDummyPluginType::open (void) { m_sName = QFileInfo(filename()).baseName(); m_sLabel = m_sName.simplified().replace(QRegExp("[\\s|\\.|\\-]+"), "_"); m_iUniqueID = 0; for (int i = 0; i < m_sLabel.length(); ++i) m_iUniqueID += int(m_sLabel[i].toLatin1()); // Fake the rest... m_iAudioIns = 2; m_iAudioOuts = 2; m_iMidiIns = 1; return true; } void qtractorDummyPluginType::close (void) { } // Factory method (static) qtractorDummyPluginType *qtractorDummyPluginType::createType ( qtractorPluginFile *pFile, unsigned long iIndex, Hint typeHint ) { // Sanity check... if (pFile == NULL) return NULL; // Yep, most probably its a dummy plugin effect... return new qtractorDummyPluginType(pFile, iIndex, typeHint); } //---------------------------------------------------------------------------- // qtractorPlugin -- Plugin instance. // // Constructors. qtractorPlugin::qtractorPlugin ( qtractorPluginList *pList, qtractorPluginType *pType ) : m_pList(pList), m_pType(pType), m_iInstances(0), m_bActivated(false), m_pForm(NULL), m_iDirectAccessParamIndex(-1) { #if 0 // Open this... if (m_pType) { qtractorPluginFile *pFile = m_pType->file(); if (pFile && pFile->open()) m_pType->open(); } #endif } // Destructor. qtractorPlugin::~qtractorPlugin (void) { // Clear out all dependables... clearItems(); // Clear out all dependables... qDeleteAll(m_params); m_params.clear(); // Rest of stuff goes cleaned too... if (m_pType) { qtractorPluginFile *pFile = m_pType->file(); delete m_pType; if (pFile) delete pFile; } } // Chain helper ones. unsigned int qtractorPlugin::sampleRate (void) const { return (m_pList ? m_pList->sampleRate() : 0); } unsigned int qtractorPlugin::bufferSize (void) const { return (m_pList ? m_pList->bufferSize() : 0); } unsigned short qtractorPlugin::channels (void) const { return (m_pList ? m_pList->channels() : 0); } // Set the internal instance count... void qtractorPlugin::setInstances ( unsigned short iInstances ) { // Some sanity required here... if (iInstances < 1) { // We're sorry but dialogs must also go now... closeEditor(); if (m_pForm) { m_pForm->close(); delete m_pForm; m_pForm = NULL; } } m_iInstances = iInstances; } // Activation methods. void qtractorPlugin::setActivated ( bool bActivated ) { if (bActivated && !m_bActivated) { activate(); m_pList->updateActivated(true); } else if (!bActivated && m_bActivated) { deactivate(); m_pList->updateActivated(false); } m_bActivated = bActivated; QListIterator iter(m_items); while (iter.hasNext()) iter.next()->updateActivated(); if (m_pForm) m_pForm->updateActivated(); } // Plugin state serialization methods. void qtractorPlugin::setValueList ( const QStringList& vlist ) { // qSort(m_params); -- does not work with QHash... QMap params; Params::ConstIterator param = m_params.constBegin(); const Params::ConstIterator& param_end = m_params.constEnd(); for ( ; param != param_end; ++param) params.insert(param.key(), param.value()); // Split it up... clearValues(); QStringListIterator val(vlist); QMapIterator iter(params); while (val.hasNext() && iter.hasNext()) m_values.index[iter.next().key()] = val.next().toFloat(); } QStringList qtractorPlugin::valueList (void) const { // qSort(m_params); -- does not work with QHash... QMap params; Params::ConstIterator param = m_params.constBegin(); const Params::ConstIterator& param_end = m_params.constEnd(); for ( ; param != param_end; ++param) params.insert(param.key(), param.value()); // Join it up... QStringList vlist; QMapIterator iter(params); while (iter.hasNext()) vlist.append(QString::number(iter.next().value()->value())); return vlist; } // Reset-to-default method. void qtractorPlugin::reset (void) { Params::ConstIterator param = m_params.constBegin(); const Params::ConstIterator& param_end = m_params.constEnd(); for ( ; param != param_end; ++param) param.value()->reset(); } // Update editor title. void qtractorPlugin::updateEditorTitle (void) { QString sEditorTitle = m_pType->name(); if (m_pList && !m_pList->name().isEmpty()) sEditorTitle += " - " + m_pList->name(); setEditorTitle(sEditorTitle); if (m_pForm) m_pForm->setWindowTitle(sEditorTitle); } // List of observers management. void qtractorPlugin::addItem ( qtractorPluginListItem *pItem ) { m_items.append(pItem); } void qtractorPlugin::removeItem ( qtractorPluginListItem *pItem ) { int iItem = m_items.indexOf(pItem); if (iItem >= 0) m_items.removeAt(iItem); } void qtractorPlugin::clearItems (void) { qDeleteAll(m_items); m_items.clear(); } // Special plugin form accessors. bool qtractorPlugin::isFormVisible (void) const { return (m_pForm ? m_pForm->isVisible() : false); } qtractorPluginForm *qtractorPlugin::form (void) { // Take the change and create the form if it doesn't current exist. if (m_pForm == NULL) { // Build up the plugin form... // What style do we create tool childs? QWidget *pParent = NULL; Qt::WindowFlags wflags = Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint; qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions && pOptions->bKeepToolsOnTop) { // pParent = qtractorMainForm::getInstance(); wflags |= Qt::Tool; } // Do it... m_pForm = new qtractorPluginForm(pParent, wflags); m_pForm->setPlugin(this); } return m_pForm; } // Provisional preset accessors. QStringList qtractorPlugin::presetList (void) const { QStringList list; qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { pOptions->settings().beginGroup(presetGroup()); list.append(pOptions->settings().childKeys()); pOptions->settings().endGroup(); } return list; } // Plugin default preset name accessor (informational) void qtractorPlugin::setPreset ( const QString& sPreset ) { m_sPreset = sPreset; if (m_pForm) m_pForm->setPreset(sPreset); } const QString& qtractorPlugin::preset (void) const { return m_sPreset; } // Plugin preset group - common identification group/prefix. QString qtractorPlugin::presetGroup (void) const { return "/Plugin/" + presetPrefix(); } // Normalize plugin identification prefix... QString qtractorPlugin::presetPrefix (void) const { return m_pType->label() + '_' + QString::number(m_pType->uniqueID()); } // Load plugin preset from xml file. bool qtractorPlugin::loadPresetFile ( const QString& sFilename ) { // Open file... QFile file(sFilename); if (!file.open(QIODevice::ReadOnly)) return false; // Parse it a-la-DOM :-) QDomDocument doc("qtractorPlugin"); if (!doc.setContent(&file)) { file.close(); return false; } file.close(); // Get root element. QDomElement ePreset = doc.documentElement(); if (ePreset.tagName() != "preset") return false; // Check if it's on the correct plugin preset... if (ePreset.attribute("type") != presetPrefix()) return false; // Reset any old configs. clearConfigs(); clearValues(); // Now parse for children... for (QDomNode nChild = ePreset.firstChild(); !nChild.isNull(); nChild = nChild.nextSibling()) { // Convert node to element, if any. QDomElement eChild = nChild.toElement(); if (eChild.isNull()) continue; // Check for preset item... if (eChild.tagName() == "configs" || eChild.tagName() == "configure") { // Parse for config entries... qtractorPlugin::loadConfigs(&eChild, m_configs, m_ctypes); } else if (eChild.tagName() == "params") { // Parse for param entries... qtractorPlugin::loadValues(&eChild, m_values); } } // Make it real. realizeConfigs(); realizeValues(); releaseConfigs(); releaseValues(); return true; } // Save plugin preset to xml file. bool qtractorPlugin::savePresetFile ( const QString& sFilename ) { freezeConfigs(); QFileInfo fi(sFilename); QDomDocument doc("qtractorPlugin"); QDomElement ePreset = doc.createElement("preset"); ePreset.setAttribute("type", presetPrefix()); ePreset.setAttribute("name", fi.baseName()); ePreset.setAttribute("version", QTRACTOR_VERSION); // Save plugin configs... QDomElement eConfigs = doc.createElement("configs"); saveConfigs(&doc, &eConfigs); ePreset.appendChild(eConfigs); // Save plugin params... QDomElement eParams = doc.createElement("params"); saveValues(&doc, &eParams); ePreset.appendChild(eParams); doc.appendChild(ePreset); // Finally, we're ready to save to external file. QFile file(sFilename); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) return false; QTextStream ts(&file); ts << doc.toString() << endl; file.close(); releaseConfigs(); return true; } // Plugin parameter lookup. qtractorPluginParam *qtractorPlugin::findParam ( unsigned long iIndex ) const { return m_params.value(iIndex, NULL); } qtractorPluginParam *qtractorPlugin::findParamName ( const QString& sName ) const { return m_paramNames.value(sName); } // Direct access parameter qtractorPluginParam *qtractorPlugin::directAccessParam (void) const { if (isDirectAccessParam()) return findParam(m_iDirectAccessParamIndex); else return NULL; } void qtractorPlugin::setDirectAccessParamIndex ( long iDirectAccessParamIndex ) { m_iDirectAccessParamIndex = iDirectAccessParamIndex; updateDirectAccessParam(); } long qtractorPlugin::directAccessParamIndex (void) const { return m_iDirectAccessParamIndex; } bool qtractorPlugin::isDirectAccessParam (void) const { return (m_iDirectAccessParamIndex >= 0); } // Write the value to the display item. void qtractorPlugin::updateDirectAccessParam (void) { QListIterator iter(m_items); while (iter.hasNext()) iter.next()->updateActivated(); } // Plugin parameter/state snapshot. void qtractorPlugin::freezeValues (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorPlugin[%p]::freezeValues()", this); #endif clearValues(); Params::ConstIterator param = m_params.constBegin(); const Params::ConstIterator& param_end = m_params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); unsigned long iIndex = pParam->index(); m_values.names[iIndex] = pParam->name(); m_values.index[iIndex] = pParam->value(); } } void qtractorPlugin::releaseValues (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorPlugin[%p]::releaseValues()", this); #endif clearValues(); } // Plugin configure realization. void qtractorPlugin::realizeConfigs (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorPlugin[%p]::realizeConfigs()", this); #endif // Set configuration (CLOBs)... Configs::ConstIterator config = m_configs.constBegin(); const Configs::ConstIterator& config_end = m_configs.constEnd(); for ( ; config != config_end; ++config) configure(config.key(), config.value()); // Set proper bank/program selection... qtractorMidiManager *pMidiManager = m_pList->midiManager(); if (pMidiManager) selectProgram(pMidiManager->currentBank(), pMidiManager->currentProg()); } // Plugin parameter realization. void qtractorPlugin::realizeValues (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorPlugin[%p]::realizeValues()", this); #endif // (Re)set parameter values (initial)... ValueIndex::ConstIterator param = m_values.index.constBegin(); const ValueIndex::ConstIterator& param_end = m_values.index.constEnd(); for ( ; param != param_end; ++param) { unsigned long iIndex = param.key(); qtractorPluginParam *pParam = findParam(iIndex); if (pParam) { const QString& sName = m_values.names.value(iIndex); if (!sName.isEmpty() && sName != pParam->name()) pParam = findParamName(sName); if (pParam) pParam->setValue(param.value(), true); } } } // Load plugin configuration stuff (CLOB). void qtractorPlugin::loadConfigs ( QDomElement *pElement, Configs& configs, ConfigTypes& ctypes ) { for (QDomNode nConfig = pElement->firstChild(); !nConfig.isNull(); nConfig = nConfig.nextSibling()) { // Convert config node to element... QDomElement eConfig = nConfig.toElement(); if (eConfig.isNull()) continue; if (eConfig.tagName() == "config") { const QString& sKey = eConfig.attribute("key"); if (!sKey.isEmpty()) { configs[sKey] = eConfig.text(); const QString& sType = eConfig.attribute("type"); if (!sType.isEmpty()) ctypes[sKey] = sType; } } } } // Load plugin parameter values. void qtractorPlugin::loadValues ( QDomElement *pElement, Values& values ) { for (QDomNode nParam = pElement->firstChild(); !nParam.isNull(); nParam = nParam.nextSibling()) { // Convert node to element, if any. QDomElement eParam = nParam.toElement(); if (eParam.isNull()) continue; // Check for config item... if (eParam.tagName() == "param") { unsigned long iIndex = eParam.attribute("index").toULong(); const QString& sName = eParam.attribute("name"); if (!sName.isEmpty()) values.names.insert(iIndex, sName); values.index.insert(iIndex, eParam.text().toFloat()); } } } // Save plugin configuration stuff (CLOB)... void qtractorPlugin::saveConfigs ( QDomDocument *pDocument, QDomElement *pElement ) { // Save plugin configs... Configs::ConstIterator iter = m_configs.constBegin(); const Configs::ConstIterator& iter_end = m_configs.constEnd(); for ( ; iter != iter_end; ++iter) { QDomElement eConfig = pDocument->createElement("config"); eConfig.setAttribute("key", iter.key()); ConfigTypes::ConstIterator ctype = m_ctypes.find(iter.key()); if (ctype != m_ctypes.constEnd()) eConfig.setAttribute("type", ctype.value()); eConfig.appendChild( pDocument->createTextNode(iter.value())); pElement->appendChild(eConfig); } } // Save plugin parameter values. void qtractorPlugin::saveValues ( QDomDocument *pDocument, QDomElement *pElement ) { Params::ConstIterator param = m_params.constBegin(); const Params::ConstIterator param_end = m_params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); QDomElement eParam = pDocument->createElement("param"); eParam.setAttribute("name", pParam->name()); eParam.setAttribute("index", QString::number(pParam->index())); eParam.appendChild( pDocument->createTextNode(QString::number(pParam->value()))); pElement->appendChild(eParam); } } // Parameter update executive. void qtractorPlugin::updateParamValue ( unsigned long iIndex, float fValue, bool bUpdate ) { qtractorPluginParam *pParam = findParam(iIndex); if (pParam) pParam->updateValue(fValue, bUpdate); } //---------------------------------------------------------------------------- // qtractorPluginList -- Plugin chain list instance. // // Constructor. qtractorPluginList::qtractorPluginList ( unsigned short iChannels, unsigned int iBufferSize, unsigned int iSampleRate, unsigned int iFlags ) : m_iChannels(0), m_iBufferSize(0), m_iSampleRate(0), m_iFlags(0), m_iActivated(0), m_pMidiManager(NULL), m_iMidiBank(-1), m_iMidiProg(-1), m_pMidiProgramSubject(NULL) { setAutoDelete(true); m_pppBuffers[0] = NULL; m_pppBuffers[1] = NULL; m_pCurveList = new qtractorCurveList(); m_bAudioOutputBus = qtractorMidiManager::isDefaultAudioOutputBus(); m_bAudioOutputAutoConnect = qtractorMidiManager::isDefaultAudioOutputAutoConnect(); setBuffer(iChannels, iBufferSize, iSampleRate, iFlags); } // Destructor. qtractorPluginList::~qtractorPluginList (void) { // Reset allocated channel buffers. setBuffer(0, 0, 0, 0); // Clear out all dependables... m_views.clear(); delete m_pCurveList; } // The title to show up on plugin forms... void qtractorPluginList::setName ( const QString& sName ) { m_sName = sName; for (qtractorPlugin *pPlugin = first(); pPlugin; pPlugin = pPlugin->next()) { pPlugin->updateEditorTitle(); } if (m_pMidiManager) m_pMidiManager->resetAudioOutputBus(); } // Main-parameters accessor. void qtractorPluginList::setBuffer ( unsigned short iChannels, unsigned int iBufferSize, unsigned int iSampleRate, unsigned int iFlags ) { unsigned short i; // Delete old interim buffer... if (m_pppBuffers[1]) { for (i = 0; i < m_iChannels; ++i) delete [] m_pppBuffers[1][i]; delete [] m_pppBuffers[1]; m_pppBuffers[1] = NULL; } // Destroy any MIDI manager still there... if (m_pMidiManager) { m_bAudioOutputBus = m_pMidiManager->isAudioOutputBus(); m_bAudioOutputAutoConnect = m_pMidiManager->isAudioOutputAutoConnect(); qtractorMidiManager::deleteMidiManager(m_pMidiManager); m_pMidiManager = NULL; } if (m_pMidiProgramSubject) { delete m_pMidiProgramSubject; m_pMidiProgramSubject = NULL; } // Set proper sample-rate and flags at once. m_iSampleRate = iSampleRate; m_iFlags = iFlags; // Some sanity is in order, at least for now... if (iChannels == 0 || iBufferSize == 0) return; // Go, go, go... m_iChannels = iChannels; m_iBufferSize = iBufferSize; // Allocate new interim buffer... if (m_iChannels > 0 && m_iBufferSize > 0) { m_pppBuffers[1] = new float * [m_iChannels]; for (i = 0; i < m_iChannels; ++i) { m_pppBuffers[1][i] = new float [m_iBufferSize]; ::memset(m_pppBuffers[1][i], 0, m_iBufferSize * sizeof(float)); } } // Allocate new MIDI manager, if applicable... if (m_iFlags & Midi) { m_pMidiProgramSubject = new MidiProgramSubject(m_iMidiBank, m_iMidiProg); m_pMidiManager = qtractorMidiManager::createMidiManager(this); // Set loaded/cached properties properly... m_pMidiManager->setCurrentBank(m_iMidiBank); m_pMidiManager->setCurrentProg(m_iMidiProg); m_pMidiManager->setAudioOutputAutoConnect(m_bAudioOutputAutoConnect); m_pMidiManager->setAudioOutputBus(m_bAudioOutputBus); if (m_pMidiManager->isAudioOutputBus()) { qtractorAudioBus *pAudioOutputBus = m_pMidiManager->audioOutputBus(); if (pAudioOutputBus) pAudioOutputBus->outputs().copy(m_audioOutputs); } } // Reset all plugin chain channels... for (qtractorPlugin *pPlugin = first(); pPlugin; pPlugin = pPlugin->next()) pPlugin->setChannels(m_iChannels); // FIXME: This should be better managed... if (m_pMidiManager) m_pMidiManager->updateInstruments(); } // Reset and (re)activate all plugin chain. void qtractorPluginList::resetBuffer (void) { #if 0 // Save and reset activation count... int iActivated = m_iActivated; m_iActivated = 0; // Temporarily deactivate all activated plugins... for (qtractorPlugin *pPlugin = first(); pPlugin; pPlugin = pPlugin->next()) { if (pPlugin->isActivated()) pPlugin->deactivate(); } #endif // Reset interim buffer, if any... if (m_pppBuffers[1]) { for (unsigned short i = 0; i < m_iChannels; ++i) ::memset(m_pppBuffers[1][i], 0, m_iBufferSize * sizeof(float)); } #if 0 // Restore activation of all previously deactivated plugins... for (qtractorPlugin *pPlugin = first(); pPlugin; pPlugin = pPlugin->next()) { if (pPlugin->isActivated()) pPlugin->activate(); } // Restore activation count. m_iActivated = iActivated; #endif } // Special guard activation methods. bool qtractorPluginList::isActivatedAll (void) const { return (m_iActivated > 0 && m_iActivated >= (unsigned int) count()); } void qtractorPluginList::updateActivated ( bool bActivated ) { if (bActivated) { ++m_iActivated; } else { --m_iActivated; } } // Add-guarded plugin method. void qtractorPluginList::addPlugin ( qtractorPlugin *pPlugin ) { // Link the plugin into list... insertPlugin(pPlugin, pPlugin->next()); } // Insert-guarded plugin method. void qtractorPluginList::insertPlugin ( qtractorPlugin *pPlugin, qtractorPlugin *pNextPlugin ) { // We'll get prepared before plugging it in... pPlugin->setChannels(m_iChannels); if (pNextPlugin) insertBefore(pPlugin, pNextPlugin); else append(pPlugin); // Now update each observer list-view... QListIterator iter(m_views); while (iter.hasNext()) { qtractorPluginListView *pListView = iter.next(); int iNextItem = pListView->count(); if (pNextPlugin) iNextItem = pListView->pluginItem(pNextPlugin); qtractorPluginListItem *pNextItem = new qtractorPluginListItem(pPlugin); pListView->insertItem(iNextItem, pNextItem); pListView->setCurrentItem(pNextItem); } } // Move-guarded plugin method. void qtractorPluginList::movePlugin ( qtractorPlugin *pPlugin, qtractorPlugin *pNextPlugin ) { // Source sanity... if (pPlugin == NULL) return; qtractorPluginList *pPluginList = pPlugin->list(); if (pPluginList == NULL) return; // Remove and insert back again... pPluginList->unlink(pPlugin); if (pNextPlugin) { insertBefore(pPlugin, pNextPlugin); } else { append(pPlugin); } // DANGER: Gasp, we might be not the same... if (pPluginList != this) { pPlugin->setPluginList(this); pPlugin->setChannels(channels()); if (pPlugin->isActivated()) { pPluginList->updateActivated(false); updateActivated(true); } } // Now update each observer list-view: // - take all items... QListIterator item(pPlugin->items()); while (item.hasNext()) delete item.next(); // - give them back into the right position... QListIterator view(m_views); while (view.hasNext()) { qtractorPluginListView *pListView = view.next(); int iNextItem = pListView->count(); if (pNextPlugin) iNextItem = pListView->pluginItem(pNextPlugin); qtractorPluginListItem *pNextItem = new qtractorPluginListItem(pPlugin); pListView->insertItem(iNextItem, pNextItem); pListView->setCurrentItem(pNextItem); } } // Remove-guarded plugin method. void qtractorPluginList::removePlugin ( qtractorPlugin *pPlugin ) { // Just unlink the plugin from the list... unlink(pPlugin); if (pPlugin->isActivated()) updateActivated(false); pPlugin->setChannels(0); pPlugin->clearItems(); } // Clone/copy plugin method. qtractorPlugin *qtractorPluginList::copyPlugin ( qtractorPlugin *pPlugin ) { qtractorPluginType *pType = pPlugin->type(); if (pType == NULL) return NULL; // Clone the plugin instance... pPlugin->freezeValues(); pPlugin->freezeConfigs(); #if 0 // MIDI bank program whether necessary... int iBank = 0; int iProg = 0; if (m_pMidiManager && m_pMidiManager->currentBank() >= 0) iBank = m_pMidiManager->currentBank(); if (m_pMidiManager && m_pMidiManager->currentProg() >= 0) iProg = m_pMidiManager->currentProg(); #endif // Filename is empty for insert pseudo-plugins. QString sFilename = pType->filename(); qtractorPlugin *pNewPlugin = qtractorPluginFile::createPlugin(this, sFilename, pType->index(), pType->typeHint()); if (pNewPlugin) { pNewPlugin->setPreset(pPlugin->preset()); pNewPlugin->setConfigs(pPlugin->configs()); pNewPlugin->setConfigTypes(pPlugin->configTypes()); pNewPlugin->setValues(pPlugin->values()); pNewPlugin->realizeConfigs(); pNewPlugin->realizeValues(); pNewPlugin->releaseConfigs(); pNewPlugin->releaseValues(); pNewPlugin->setActivated(pPlugin->isActivated()); } pPlugin->releaseConfigs(); pPlugin->releaseValues(); return pNewPlugin; } // List of views management. void qtractorPluginList::addView ( qtractorPluginListView *pView ) { m_views.append(pView); } void qtractorPluginList::removeView ( qtractorPluginListView *pView ) { int iView = m_views.indexOf(pView); if (iView >= 0) m_views.removeAt(iView); } // The meta-main audio-processing plugin-chain procedure. void qtractorPluginList::process ( float **ppBuffer, unsigned int nframes ) { // Sanity checks... if (ppBuffer == NULL || *ppBuffer == NULL) return; if (nframes > m_iBufferSize || m_pppBuffers[1] == NULL) return; // Start from first input buffer... m_pppBuffers[0] = ppBuffer; // Buffer binary iterator... unsigned short iBuffer = 0; // For each plugin in chain (in order, of course...) for (qtractorPlugin *pPlugin = first(); pPlugin; pPlugin = pPlugin->next()) { // Must be properly activated... if (!pPlugin->isActivated()) continue; // Set proper buffers for this plugin... float **ppIBuffer = m_pppBuffers[ iBuffer & 1]; float **ppOBuffer = m_pppBuffers[++iBuffer & 1]; // Time for the real thing... pPlugin->process(ppIBuffer, ppOBuffer, nframes); } // Now for the output buffer commitment... if (iBuffer & 1) { for (unsigned short i = 0; i < m_iChannels; ++i) { ::memcpy(ppBuffer[i], m_pppBuffers[1][i], nframes * sizeof(float)); } } } // Document element methods. bool qtractorPluginList::loadElement ( qtractorDocument *pDocument, QDomElement *pElement ) { // Reset some MIDI manager elements... m_iMidiBank = -1; m_iMidiProg = -1; m_bAudioOutputBus = false; m_audioOutputs.clear(); // Load plugin-list children... for (QDomNode nPlugin = pElement->firstChild(); !nPlugin.isNull(); nPlugin = nPlugin.nextSibling()) { // Convert clip node to element... QDomElement ePlugin = nPlugin.toElement(); if (ePlugin.isNull()) continue; if (ePlugin.tagName() == "bank") setMidiBank(ePlugin.text().toInt()); else if (ePlugin.tagName() == "program") setMidiProg(ePlugin.text().toInt()); else if (ePlugin.tagName() == "plugin") { QString sFilename; unsigned long iIndex = 0; QString sLabel; QString sPreset; QStringList vlist; bool bActivated = false; long iDirectAccessParamIndex = -1; qtractorPlugin::Configs configs; qtractorPlugin::ConfigTypes ctypes; qtractorPlugin::Values values; qtractorMidiControl::Controllers controllers; qtractorCurveFile cfile(qtractorPluginList::curveList()); qtractorPluginType::Hint typeHint = qtractorPluginType::hintFromText( ePlugin.attribute("type")); for (QDomNode nParam = ePlugin.firstChild(); !nParam.isNull(); nParam = nParam.nextSibling()) { // Convert buses list node to element... QDomElement eParam = nParam.toElement(); if (eParam.isNull()) continue; if (eParam.tagName() == "filename") sFilename = eParam.text(); else if (eParam.tagName() == "index") iIndex = eParam.text().toULong(); else if (eParam.tagName() == "label") sLabel = eParam.text(); else if (eParam.tagName() == "preset") sPreset = eParam.text(); else if (eParam.tagName() == "values") vlist = eParam.text().split(','); else if (eParam.tagName() == "activated") bActivated = qtractorDocument::boolFromText(eParam.text()); else if (eParam.tagName() == "configs") { // Load plugin configuration stuff (CLOB)... qtractorPlugin::loadConfigs(&eParam, configs, ctypes); } else if (eParam.tagName() == "params") { // Load plugin parameter values... qtractorPlugin::loadValues(&eParam, values); } else if (eParam.tagName() == "controllers") { // Load plugin parameter controllers... qtractorPlugin::loadControllers(&eParam, controllers); } else if (eParam.tagName() == "direct-access-param") iDirectAccessParamIndex = eParam.text().toLong(); else if (eParam.tagName() == "curve-file") { // Load plugin automation curves... qtractorPlugin::loadCurveFile(&eParam, &cfile); } } qtractorPlugin *pPlugin = qtractorPluginFile::createPlugin(this, sFilename, iIndex, typeHint); if (!sFilename.isEmpty() && !sLabel.isEmpty() && ((pPlugin == NULL) || ((pPlugin->type())->label() != sLabel))) { iIndex = 0; do { pPlugin = qtractorPluginFile::createPlugin(this, sFilename, iIndex++, typeHint); } while (pPlugin && (pPlugin->type())->label() != sLabel); } if (pPlugin) { pPlugin->setPreset(sPreset); pPlugin->setConfigs(configs); pPlugin->setConfigTypes(ctypes); if (!vlist.isEmpty()) pPlugin->setValueList(vlist); if (!values.index.isEmpty()) pPlugin->setValues(values); append(pPlugin); pPlugin->mapControllers(controllers); pPlugin->applyCurveFile(&cfile); pPlugin->setDirectAccessParamIndex(iDirectAccessParamIndex); pPlugin->setActivated(bActivated); // Later's better! } // Cleanup. qDeleteAll(controllers); controllers.clear(); } else // Load audio output bus flag... if (ePlugin.tagName() == "audio-output-bus") { setAudioOutputBus(qtractorDocument::boolFromText(ePlugin.text())); } else // Load audio output auto-connect flag... if (ePlugin.tagName() == "audio-output-auto-connect") { setAudioOutputAutoConnect(qtractorDocument::boolFromText(ePlugin.text())); } else // Load audio output connections... if (ePlugin.tagName() == "audio-outputs") { qtractorBus::loadConnects(m_audioOutputs, pDocument, &ePlugin); } } return true; } bool qtractorPluginList::saveElement ( qtractorDocument *pDocument, QDomElement *pElement ) { // Save current MIDI bank/program setting... if (m_pMidiManager && m_pMidiManager->currentBank() >= 0) pDocument->saveTextElement("bank", QString::number(m_pMidiManager->currentBank()), pElement); if (m_pMidiManager && m_pMidiManager->currentProg() >= 0) pDocument->saveTextElement("program", QString::number(m_pMidiManager->currentProg()), pElement); // Save plugins... for (qtractorPlugin *pPlugin = qtractorPluginList::first(); pPlugin; pPlugin = pPlugin->next()) { // Do freeze plugin state... pPlugin->freezeConfigs(); // Create the new plugin element... QDomElement ePlugin = pDocument->document()->createElement("plugin"); qtractorPluginType *pType = pPlugin->type(); ePlugin.setAttribute("type", qtractorPluginType::textFromHint(pType->typeHint())); // Pseudo-plugins don't have a file... const QString& sFilename = pType->filename(); if (!sFilename.isEmpty()) { pDocument->saveTextElement("filename", sFilename, &ePlugin); } pDocument->saveTextElement("index", QString::number(pType->index()), &ePlugin); pDocument->saveTextElement("label", pType->label(), &ePlugin); pDocument->saveTextElement("preset", pPlugin->preset(), &ePlugin); pDocument->saveTextElement("direct-access-param", QString::number(pPlugin->directAccessParamIndex()), &ePlugin); // pDocument->saveTextElement("values", // pPlugin->valueList().join(","), &ePlugin); pDocument->saveTextElement("activated", qtractorDocument::textFromBool(pPlugin->isActivated()), &ePlugin); // Plugin configuration stuff (CLOB)... QDomElement eConfigs = pDocument->document()->createElement("configs"); pPlugin->saveConfigs(pDocument->document(), &eConfigs); ePlugin.appendChild(eConfigs); // Plugin parameter values... QDomElement eParams = pDocument->document()->createElement("params"); pPlugin->saveValues(pDocument->document(), &eParams); ePlugin.appendChild(eParams); // Plugin paramneter controllers... QDomElement eControllers = pDocument->document()->createElement("controllers"); pPlugin->saveControllers(pDocument, &eControllers); ePlugin.appendChild(eControllers); // Save plugin automation... qtractorCurveList *pCurveList = qtractorPluginList::curveList(); if (pCurveList && !pCurveList->isEmpty()) { qtractorCurveFile cfile(pCurveList); QDomElement eCurveFile = pDocument->document()->createElement("curve-file"); pPlugin->saveCurveFile(pDocument, &eCurveFile, &cfile); ePlugin.appendChild(eCurveFile); } // Add this plugin... pElement->appendChild(ePlugin); // May release plugin state... pPlugin->releaseConfigs(); } // Save audio output-bus connects... if (m_pMidiManager) { pDocument->saveTextElement("audio-output-bus", qtractorDocument::textFromBool( m_pMidiManager->isAudioOutputBus()), pElement); pDocument->saveTextElement("audio-output-auto-connect", qtractorDocument::textFromBool( m_pMidiManager->isAudioOutputAutoConnect()), pElement); if (m_pMidiManager->isAudioOutputBus()) { qtractorAudioBus *pAudioBus = m_pMidiManager->audioOutputBus(); if (pAudioBus) { QDomElement eOutputs = pDocument->document()->createElement("audio-outputs"); qtractorBus::ConnectList outputs; pAudioBus->updateConnects(qtractorBus::Output, outputs); pAudioBus->saveConnects(outputs, pDocument, &eOutputs); pElement->appendChild(eOutputs); } } } return true; } // Load plugin parameter controllers (MIDI). void qtractorPlugin::loadControllers ( QDomElement *pElement, qtractorMidiControl::Controllers& controllers ) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return; pMidiControl->loadControllers(pElement, controllers); } // Save plugin parameter controllers (MIDI). void qtractorPlugin::saveControllers ( qtractorDocument *pDocument, QDomElement *pElement ) const { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return; qtractorMidiControl::Controllers controllers; Params::ConstIterator param = m_params.constBegin(); const Params::ConstIterator param_end = m_params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); qtractorMidiControlObserver *pObserver = pParam->observer(); if (pMidiControl->isMidiObserverMapped(pObserver)) { qtractorMidiControl::Controller *pController = new qtractorMidiControl::Controller; pController->name = pParam->name(); pController->index = pParam->index(); pController->ctype = pObserver->type(); pController->channel = pObserver->channel(); pController->param = pObserver->param(); pController->logarithmic = pObserver->isLogarithmic(); pController->feedback = pObserver->isFeedback(); pController->invert = pObserver->isInvert(); pController->hook = pObserver->isHook(); controllers.append(pController); } } pMidiControl->saveControllers(pDocument, pElement, controllers); qDeleteAll(controllers); } // Map/realize plugin parameter controllers (MIDI). void qtractorPlugin::mapControllers ( const qtractorMidiControl::Controllers& controllers ) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl) { QListIterator iter(controllers); while (iter.hasNext()) { qtractorMidiControl::Controller *pController = iter.next(); qtractorPluginParam *pParam = findParam(pController->index); if (pParam == NULL) continue; qtractorMidiControlObserver *pObserver = pParam->observer(); pObserver->setType(pController->ctype); pObserver->setChannel(pController->channel); pObserver->setParam(pController->param); pObserver->setLogarithmic(pController->logarithmic); pObserver->setFeedback(pController->feedback); pObserver->setInvert(pController->invert); pObserver->setHook(pController->hook); pMidiControl->mapMidiObserver(pObserver); } } } // Load plugin automation curves (monitor, gain, pan, record, mute, solo). void qtractorPlugin::loadCurveFile ( QDomElement *pElement, qtractorCurveFile *pCurveFile ) { if (pCurveFile) pCurveFile->load(pElement); } // Save plugin automation curves (monitor, gain, pan, record, mute, solo). void qtractorPlugin::saveCurveFile ( qtractorDocument *pDocument, QDomElement *pElement, qtractorCurveFile *pCurveFile ) const { if (pCurveFile == NULL) return; qtractorCurveList *pCurveList = pCurveFile->list(); if (pCurveList == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; pCurveFile->clear(); pCurveFile->setBaseDir(pSession->sessionDir()); unsigned short iParam = 0; Params::ConstIterator param = m_params.constBegin(); const Params::ConstIterator param_end = m_params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); qtractorCurve *pCurve = pParam->subject()->curve(); if (pCurve) { unsigned short controller = (iParam % 0x7f); if (controller == 0x00 || controller == 0x20) ++iParam; // Avoid bank-select controllers, please. qtractorCurveFile::Item *pCurveItem = new qtractorCurveFile::Item; pCurveItem->name = pParam->name(); pCurveItem->index = pParam->index(); pCurveItem->ctype = qtractorMidiEvent::CONTROLLER; pCurveItem->channel = ((iParam / 0x7f) % 16); pCurveItem->param = (iParam % 0x7f); pCurveItem->mode = pCurve->mode(); pCurveItem->process = pCurve->isProcess(); pCurveItem->capture = pCurve->isCapture(); pCurveItem->locked = pCurve->isLocked(); pCurveItem->logarithmic = pCurve->isLogarithmic(); pCurveItem->color = pCurve->color(); pCurveItem->subject = pCurve->subject(); pCurveFile->addItem(pCurveItem); ++iParam; } } if (pCurveFile->isEmpty()) return; QString sBaseName(list()->name()); sBaseName += '_'; sBaseName += type()->label(); sBaseName += '_'; sBaseName += QString::number(type()->uniqueID(), 16); sBaseName += "_curve"; // int iClipNo = (pCurveFile->filename().isEmpty() ? 0 : 1); pCurveFile->setFilename(pSession->createFilePath(sBaseName, "mid", 1)); pCurveFile->save(pDocument, pElement, pSession->timeScale()); } // Apply plugin automation curves (monitor, gain, pan, record, mute, solo). void qtractorPlugin::applyCurveFile ( qtractorCurveFile *pCurveFile ) const { if (pCurveFile == NULL) return; if (pCurveFile->items().isEmpty()) return; qtractorCurveList *pCurveList = pCurveFile->list(); if (pCurveList == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; pCurveFile->setBaseDir(pSession->sessionDir()); QListIterator iter(pCurveFile->items()); while (iter.hasNext()) { qtractorCurveFile::Item *pCurveItem = iter.next(); qtractorPluginParam *pParam = findParam(pCurveItem->index); if (pParam) pCurveItem->subject = pParam->subject(); } pCurveFile->apply(pSession->timeScale()); } //---------------------------------------------------------------------------- // qtractorPluginParam -- Plugin parameter (control input port) instance. // // Current port value. void qtractorPluginParam::setValue ( float fValue, bool bUpdate ) { // Decimals caching.... if (m_iDecimals < 0) { m_iDecimals = 0; if (!isInteger()) { float fDecs = ::log10f(maxValue() - minValue()); if (fDecs < -3.0f) m_iDecimals = 6; else if (fDecs < 0.0f) m_iDecimals = 3; else if (fDecs < 1.0f) m_iDecimals = 2; else if (fDecs < 6.0f) m_iDecimals = 1; if (isLogarithmic()) ++m_iDecimals; } } // Sanitize value... if (isBoundedAbove() && fValue > maxValue()) fValue = maxValue(); else if (isBoundedBelow() && fValue < minValue()) fValue = minValue(); m_observer.setValue(fValue); // Update specifics. if (bUpdate) m_pPlugin->updateParam(this, fValue, true); if (m_pPlugin->directAccessParamIndex() == long(m_iIndex)) m_pPlugin->updateDirectAccessParam(); } void qtractorPluginParam::updateValue ( float fValue, bool bUpdate ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorPluginParam[%p]::updateValue(%g, %d)", this, fValue, int(bUpdate)); #endif // Make it a undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { pSession->execute( new qtractorPluginParamCommand(this, fValue, bUpdate)); } } // Constructor. qtractorPluginParam::Observer::Observer ( qtractorPluginParam *pParam ) : qtractorMidiControlObserver(pParam->subject()), m_pParam(pParam) { setCurveList((pParam->plugin())->list()->curveList()); } // Virtual observer updater. void qtractorPluginParam::Observer::update ( bool bUpdate ) { qtractorMidiControlObserver::update(bUpdate); qtractorPlugin *pPlugin = m_pParam->plugin(); if (bUpdate && pPlugin->directAccessParamIndex() == long(m_pParam->index())) pPlugin->updateDirectAccessParam(); pPlugin->updateParam(m_pParam, qtractorMidiControlObserver::value(), bUpdate); } // end of qtractorPlugin.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorObserver.h0000644000175000001440000000012312161335204020760 xustar000000000000000027 mtime=1371912836.382031 26 atime=1381134666.95008 30 ctime=1381134666.951080048 qtractor-0.5.11/src/qtractorObserver.h0000644000175000001440000001540512161335204020254 0ustar00rncbcusers00000000000000// qtractorObserver.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorObserver_h #define __qtractorObserver_h #include #include // Forward declarations. class qtractorSubject; class qtractorObserver; class qtractorCurve; //--------------------------------------------------------------------------- // qtractorSubject - Scalar parameter value model. class qtractorSubject { public: // Constructor. qtractorSubject(float fValue = 0.0f, float fDefaultValue = 0.0f); // Destructor. ~qtractorSubject(); // Direct value accessors. void setValue(float fValue, qtractorObserver *pSender = NULL); float value() const { return m_fValue; } float prevValue() const { return m_fPrevValue; } // Observers notification. void notify(qtractorObserver *pSender, bool bUpdate); // Observer list accessors. void attach(qtractorObserver *pObserver) { m_observers.append(pObserver); } void detach(qtractorObserver *pObserver) { m_observers.removeAll(pObserver); } const QList& observers() const { return m_observers; } // Queue status accessors. void setQueued(bool bQueued) { m_bQueued = bQueued; } bool isQueued() const { return m_bQueued; } // Direct address accessor. float *data() { return &m_fValue; } // Parameter name accessors. void setName(const QString& sName) { m_sName = sName.trimmed(); } const QString& name() const { return m_sName; } // Value limits accessors. void setMaxValue(float fMaxValue) { m_fMaxValue = fMaxValue; } float maxValue() const { return m_fMaxValue; } void setMinValue(float fMinValue) { m_fMinValue = fMinValue; } float minValue() const { return m_fMinValue; } // Default value accessor. void setDefaultValue(float fDefaultValue) { m_fDefaultValue = fDefaultValue; } float defaultValue() const { return m_fDefaultValue; } void resetValue(qtractorObserver *pSender = NULL) { setValue(m_fDefaultValue, pSender); } // Toggled mode accessors. void setToggled(bool bToggled) { m_bToggled = bToggled; } bool isToggled() const { return m_bToggled; } // Filter value within legal bounds. float safeValue (float fValue) const { if (m_bToggled) { const float fThreshold = 0.5f * (m_fMinValue + m_fMaxValue); fValue = (fValue > fThreshold ? m_fMaxValue : m_fMinValue); } else if (fValue > m_fMaxValue) fValue = m_fMaxValue; else if (fValue < m_fMinValue) fValue = m_fMinValue; return fValue; } // Normalized scale converters. float valueFromScale ( float fScale ) const { return m_fMinValue + fScale * (m_fMaxValue - m_fMinValue); } float scaleFromValue ( float fValue ) const { return (fValue - m_fMinValue) / (m_fMaxValue - m_fMinValue); } // Automation curve association. void setCurve(qtractorCurve *pCurve) { m_pCurve = pCurve; } qtractorCurve *curve() const { return m_pCurve; } // Queue flush (singleton) -- notify all pending observers. static void flushQueue(bool bUpdate); // Queue reset (clear). static void resetQueue(); private: // Instance variables. float m_fValue; bool m_bQueued; float m_fPrevValue; // Human readable name/label. QString m_sName; // Value limits. float m_fMinValue; float m_fMaxValue; // Default value. float m_fDefaultValue; // Toggled value mode (max or min). bool m_bToggled; // Automation curve association. qtractorCurve *m_pCurve; // List of observers (obviously) QList m_observers; }; //--------------------------------------------------------------------------- // qtractorObserver - Scalar parameter value control/view. class qtractorObserver { public: // Constructor. qtractorObserver(qtractorSubject *pSubject = NULL) : m_pSubject(pSubject) { if (m_pSubject) m_pSubject->attach(this); } // Virtual destructor. virtual ~qtractorObserver() { if (m_pSubject) m_pSubject->detach(this); } // Subject value accessor. void setSubject(qtractorSubject *pSubject) { if (m_pSubject /* && pSubject*/) m_pSubject->detach(this); m_pSubject = pSubject; if (m_pSubject) m_pSubject->attach(this); } qtractorSubject *subject() const { return m_pSubject; } // Indirect value accessors. void setValue(float fValue) { if (m_pSubject) m_pSubject->setValue(fValue, this); } float value() const { return (m_pSubject ? m_pSubject->value() : 0.0f); } float prevValue() const { return (m_pSubject ? m_pSubject->prevValue() : 0.0f); } // Value limits accessors. float maxValue() const { return (m_pSubject ? m_pSubject->maxValue() : 1.0f); } float minValue() const { return (m_pSubject ? m_pSubject->minValue() : 0.0f); } // Default value accessor. void setDefaultValue(float fDefaultValue) { if (m_pSubject) m_pSubject->setDefaultValue(fDefaultValue); } float defaultValue() const { return (m_pSubject ? m_pSubject->defaultValue() : 0.0f); } void resetValue() { if (m_pSubject) m_pSubject->resetValue(this); } // Queue status accessors. bool isQueued() const { return (m_pSubject ? m_pSubject->isQueued() : false); } // Toggled mode accessors. bool isToggled() const { return (m_pSubject ? m_pSubject->isToggled() : false); } // Filter value within legal bounds. float safeValue(float fValue) const { return (m_pSubject ? m_pSubject->safeValue(fValue) : 0.0f); } // Normalized scale converters. float valueFromScale ( float fScale ) const { return (m_pSubject ? m_pSubject->valueFromScale(fScale) : 0.0f); } float scaleFromValue ( float fValue ) const { return (m_pSubject ? m_pSubject->scaleFromValue(fValue) : 0.0f); } // Automation curve association. void setCurve(qtractorCurve *pCurve) { if (m_pSubject) m_pSubject->setCurve(pCurve); } qtractorCurve *curve() const { return (m_pSubject ? m_pSubject->curve() : NULL); } // Pure virtual view updater. virtual void update(bool bUpdate) = 0; private: // Instance variables. qtractorSubject *m_pSubject; }; #endif // __qtractorObserver_h // end of qtractorObserver.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorBusForm.h0000644000175000001440000000012312073012112020536 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134666.35508 30 ctime=1381134666.355080039 qtractor-0.5.11/src/qtractorBusForm.h0000644000175000001440000000462012073012112020027 0ustar00rncbcusers00000000000000// qtractorBusForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorBusForm_h #define __qtractorBusForm_h #include "ui_qtractorBusForm.h" // Forward declarations... class qtractorBus; //---------------------------------------------------------------------------- // qtractorBusForm -- UI wrapper form. class qtractorBusForm : public QDialog { Q_OBJECT public: // Constructor. qtractorBusForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); void setBus(qtractorBus *pBus); qtractorBus *bus(); bool isDirty(); protected slots: void reject(); void refreshBuses(); void selectBus(); void createBus(); void updateBus(); void deleteBus(); void changed(); void stabilizeForm(); void contextMenu(const QPoint&); void midiSysex(); void addInputPlugin(); void removeInputPlugin(); void moveUpInputPlugin(); void moveDownInputPlugin(); void addOutputPlugin(); void removeOutputPlugin(); void moveUpOutputPlugin(); void moveDownOutputPlugin(); protected: enum { Create = 1, Update = 2, Delete = 4 }; unsigned int flags() const; void showBus(qtractorBus *pBus); bool updateBus(qtractorBus *pBus); void updateMidiInstruments(); void updateMidiSysex(); void resetPluginLists(); private: // The Qt-designer UI struct... Ui::qtractorBusForm m_ui; // Instance variables... qtractorBus *m_pBus; QTreeWidgetItem *m_pAudioRoot; QTreeWidgetItem *m_pMidiRoot; int m_iDirtySetup; int m_iDirtyCount; int m_iDirtyTotal; }; #endif // __qtractorBusForm_h // end of qtractorBusForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorTimeScaleForm.ui0000644000175000001440000000012312166134117022056 xustar000000000000000027 mtime=1373157455.942698 26 atime=1381134666.62608 30 ctime=1381134666.626080043 qtractor-0.5.11/src/qtractorTimeScaleForm.ui0000644000175000001440000003127712166134117021357 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorTimeScaleForm 0 0 520 280 Qt::StrongFocus Tempo Map / Markers - Qtractor :/images/qtractorTracks.png Qt::Horizontal 4 320 120 Tempo map / Markers false true true Bar Time Tempo Marker Location 40 0 &Bar: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter BarSpinBox Bar location 1 99999 1 40 0 T&ime: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter TimeSpinBox 120 0 Time/frame location Qt::Horizontal 20 20 Node 40 0 &Tempo: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter TempoSpinBox 80 0 Tempo (BPM) / Signature T&ap Qt::Horizontal 20 20 Qt::Vertical 20 20 Marker Marker text 24 24 Marker color :/images/formColor.png ... 4 0 Refresh tempo map Re&fresh :/images/formRefresh.png Alt+F Qt::Horizontal QSizePolicy::MinimumExpanding 20 20 Add node &Add :/images/formAdd.png Alt+A Update node &Update :/images/formAccept.png Alt+U Remove node &Remove :/images/formRemove.png Alt+R Close this dialog Close qtractorTimeSpinBox QSpinBox
qtractorSpinBox.h
qtractorTempoSpinBox QSpinBox
qtractorSpinBox.h
TimeScaleListView BarSpinBox TimeSpinBox TempoSpinBox TempoPushButton MarkerTextLineEdit MarkerColorToolButton RefreshPushButton AddPushButton UpdatePushButton RemovePushButton ClosePushButton
qtractor-0.5.11/src/PaxHeaders.10084/qtractorDocument.cpp0000644000175000001440000000012312076024570021310 xustar000000000000000027 mtime=1358440824.829564 26 atime=1381134666.56608 30 ctime=1381134666.566080042 qtractor-0.5.11/src/qtractorDocument.cpp0000644000175000001440000002320712076024570020603 0ustar00rncbcusers00000000000000// qtractorDocument.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorDocument.h" #ifdef CONFIG_LIBZ #include "qtractorZipFile.h" #endif #include #include #include #include // Local prototypes. static void remove_dir_list(const QList& list); static void remove_dir(const QString& sDir); // Remove specific file path. static void remove_dir ( const QString& sDir ) { const QDir dir(sDir); remove_dir_list( dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot)); QDir cwd = QDir::current(); if (cwd.absolutePath() == dir.absolutePath()) { cwd.cdUp(); QDir::setCurrent(cwd.path()); } dir.rmdir(sDir); } static void remove_dir_list ( const QList& list ) { QListIterator iter(list); while (iter.hasNext()) { const QFileInfo& info = iter.next(); const QString& sPath = info.absoluteFilePath(); if (info.isDir()) { remove_dir(sPath); } else { QFile::remove(sPath); } } } //------------------------------------------------------------------------- // qtractorDocument -- Session file import/export helper class. // // Default document type suffixes (file name extensions). QString qtractorDocument::g_sDefaultExt = "qts"; QString qtractorDocument::g_sTemplateExt = "qtt"; QString qtractorDocument::g_sArchiveExt = "qtz"; // Extracted archive paths (static). QStringList qtractorDocument::g_extractedArchives; // Extra-ordinary archive files (static). qtractorDocument *qtractorDocument::g_pArchive = NULL; // Constructor. qtractorDocument::qtractorDocument ( QDomDocument *pDocument, const QString& sTagName, Flags flags ) : m_pDocument(pDocument), m_sTagName(sTagName), m_flags(flags), m_pZipFile(NULL) { } // Default destructor. qtractorDocument::~qtractorDocument (void) { #ifdef CONFIG_LIBZ if (m_pZipFile) delete m_pZipFile; #endif } //------------------------------------------------------------------------- // qtractorDocument -- accessors. // QDomDocument *qtractorDocument::document (void) const { return m_pDocument; } // Base document name (derived from filename). const QString& qtractorDocument::name (void) const { return m_sName; } // Regular text element factory method. void qtractorDocument::saveTextElement ( const QString& sTagName, const QString& sText, QDomElement *pElem ) { QDomElement eTag = m_pDocument->createElement(sTagName); eTag.appendChild(m_pDocument->createTextNode(sText)); pElem->appendChild(eTag); } // Document flags property. void qtractorDocument::setFlags ( Flags flags ) { m_flags = flags; } qtractorDocument::Flags qtractorDocument::flags (void) const { return m_flags; } bool qtractorDocument::isTemplate (void) const { return (m_flags & Template); } bool qtractorDocument::isArchive (void) const { return (m_flags & Archive); } bool qtractorDocument::isTemporary (void) const { return (m_flags & Temporary); } //------------------------------------------------------------------------- // qtractorDocument -- loaders. // // External storage simple load method. bool qtractorDocument::load ( const QString& sFilename, Flags flags ) { // Hold template mode. setFlags(flags); #ifdef CONFIG_LIBZ // Was it an archive previously? if (m_pZipFile) { delete m_pZipFile; m_pZipFile = NULL; g_pArchive = NULL; } #endif // Is it an archive about to stuff? const QFileInfo info(sFilename); m_sName = info.completeBaseName(); QString sDocname = info.filePath(); QIODevice::OpenMode mode = QIODevice::ReadOnly; #ifdef CONFIG_LIBZ if (isArchive()) { // ATTN: Always move to session file's directory first... if (!info.isWritable() || isTemporary()) { // Read-only/temporary media? const QString& sPath = QDir::temp().path() + QDir::separator() + QTRACTOR_TITLE; QDir dir(sPath); if (!dir.exists()) dir.mkpath(sPath); QDir::setCurrent(sPath); } else QDir::setCurrent(info.path()); m_pZipFile = new qtractorZipFile(sDocname, mode); if (!m_pZipFile->isReadable()) { delete m_pZipFile; m_pZipFile = NULL; return false; } m_pZipFile->extractAll(); m_pZipFile->close(); delete m_pZipFile; m_pZipFile = NULL; // ATTN: Archived sub-directory must exist! if (!QDir(m_sName).exists()) { const QStringList& dirs = QDir().entryList( QStringList() << info.baseName() + '*', QDir::Dirs | QDir::NoDotAndDotDot, QDir::Time | QDir::Reversed); if (!dirs.isEmpty()) m_sName = dirs.first(); } sDocname = m_sName + '.' + g_sDefaultExt; if (QDir::setCurrent(m_sName)) g_extractedArchives.append(QDir::currentPath()); } else #endif QDir::setCurrent(info.absolutePath()); // Open file... QFile file(sDocname); if (!file.open(mode)) return false; // Parse it a-la-DOM :-) if (!m_pDocument->setContent(&file)) { file.close(); return false; } file.close(); // Get root element and check for proper taqg name. QDomElement elem = m_pDocument->documentElement(); if (elem.tagName() != m_sTagName) return false; return loadElement(&elem); } //------------------------------------------------------------------------- // qtractorDocument -- savers. // bool qtractorDocument::save ( const QString& sFilename, Flags flags ) { // Hold template mode. setFlags(flags); // We must have a valid tag name... if (m_sTagName.isEmpty()) return false; #ifdef CONFIG_LIBZ // Was it an archive previously? if (m_pZipFile) { delete m_pZipFile; m_pZipFile = NULL; g_pArchive = NULL; } #endif // Is it an archive about to stuff? const QFileInfo info(sFilename); m_sName = info.completeBaseName(); QString sDocname = info.filePath(); QIODevice::OpenMode mode = QIODevice::WriteOnly | QIODevice::Truncate; #ifdef CONFIG_LIBZ if (isArchive()) { m_pZipFile = new qtractorZipFile(sDocname, mode); if (!m_pZipFile->isWritable()) { delete m_pZipFile; m_pZipFile = NULL; return false; } sDocname = m_sName + '.' + g_sDefaultExt; g_pArchive = this; } #endif // Save spec... QDomElement elem = m_pDocument->createElement(m_sTagName); if (!saveElement(&elem)) return false; m_pDocument->appendChild(elem); // Finally, we're ready to save to external file. QFile file(sDocname); #ifdef CONFIG_LIBZ bool bRemove = !file.exists(); #endif if (!file.open(mode)) return false; QTextStream ts(&file); ts << m_pDocument->toString() << endl; file.close(); #ifdef CONFIG_LIBZ // Commit to archive. if (m_pZipFile) { // The session document itself, at last... m_pZipFile->addFile(sDocname, m_sName + '/' + sDocname); m_pZipFile->processAll(); m_pZipFile->close(); delete m_pZipFile; m_pZipFile = NULL; g_pArchive = NULL; // Kill temporary, if didn't exist... if (bRemove) file.remove(); } #endif return true; } // Archive filename filter. QString qtractorDocument::addFile ( const QString& sFilename ) const { #ifdef CONFIG_LIBZ if (isArchive() && m_pZipFile) { const QString sAlias = m_pZipFile->alias(sFilename); m_pZipFile->addFile(sFilename, m_sName + '/' + sAlias); return sAlias; } #endif return sFilename; } //------------------------------------------------------------------------- // qtractorDocument -- helpers. // bool qtractorDocument::boolFromText ( const QString& sText ) { return (sText == "true" || sText == "on" || sText == "yes" || sText == "1"); } QString qtractorDocument::textFromBool ( bool bBool ) { return QString::number(bBool ? 1 : 0); } //------------------------------------------------------------------------- // qtractorDocument -- filename extensions (suffix) accessors. // void qtractorDocument::setDefaultExt ( const QString& sDefaultExt ) { g_sDefaultExt = sDefaultExt; } void qtractorDocument::setTemplateExt ( const QString& sTemplateExt ) { g_sTemplateExt = sTemplateExt; } void qtractorDocument::setArchiveExt ( const QString& sArchiveExt ) { g_sArchiveExt = sArchiveExt; } const QString& qtractorDocument::defaultExt (void) { return g_sDefaultExt; } const QString& qtractorDocument::templateExt (void) { return g_sTemplateExt; } const QString& qtractorDocument::archiveExt (void) { return g_sArchiveExt; } //------------------------------------------------------------------------- // qtractorDocument -- extracted archive paths simple management. // const QStringList& qtractorDocument::extractedArchives (void) { return g_extractedArchives; } void qtractorDocument::clearExtractedArchives ( bool bRemove ) { if (bRemove) { QStringListIterator iter(g_extractedArchives); while (iter.hasNext()) remove_dir(iter.next()); } g_extractedArchives.clear(); } //------------------------------------------------------------------------- // qtractorDocument -- extra-ordinary archive files management. // QString qtractorDocument::addArchiveFile ( const QString& sFilename ) { return (g_pArchive ? g_pArchive->addFile(sFilename) : sFilename); } // end of qtractorDocument.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorCurve.cpp0000644000175000001440000000012212216161104020604 xustar000000000000000027 mtime=1379459652.987839 26 atime=1381134670.83708 29 ctime=1381134670.83808011 qtractor-0.5.11/src/qtractorCurve.cpp0000644000175000001440000004353212216161104020103 0ustar00rncbcusers00000000000000// qtractorCurve.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorCurve.h" #include "qtractorTimeScale.h" #include // Possible cube root optimization. // (borrowed from metamerist.com) static inline float cbrtf2 ( float x ) { #ifdef CONFIG_FLOAT32 // Avoid strict-aliasing optimization (gcc -O2). union { float f; int i; } u; u.f = x; u.i = (u.i / 3) + 710235478; return u.f; #else return cbrtf(x); #endif } static inline float cubef2 ( float x ) { return x * x * x; } //---------------------------------------------------------------------- // qtractorCurve::updateNode -- Node coefficients computation helpers. // // (Sample &)Hold. inline void updateNodeHold ( qtractorCurve::Node *pNode, float y0, const qtractorCurve::Node *pPrev, const qtractorCurve::Node */*pNext*/ ) { if (pPrev) pNode->a = pPrev->value; else pNode->a = y0; pNode->b = pNode->c = pNode->d = 0.0f; } // Linear. inline void updateNodeLinear ( qtractorCurve::Node *pNode, float y0, const qtractorCurve::Node *pPrev, const qtractorCurve::Node */*pNext*/ ) { float y1, x1 = float(pNode->frame); if (pPrev) { x1 -= float(pPrev->frame); y1 = pPrev->value; } else { y1 = y0; } pNode->b = pNode->value; if (x1 > 0.0f) pNode->a = (y1 - pNode->b) / x1; else pNode->a = 0.0f; pNode->c = pNode->d = 0.0f; } // Spline. inline void updateNodeSpline ( qtractorCurve::Node *pNode, float y0, const qtractorCurve::Node *pPrev, const qtractorCurve::Node *pNext ) { // Shamelessly using the same reference source article as Ardour ;) // CJC Kuger, "Constrained Cubic Spline Interpolation", August 2002 // http://www.korf.co.uk/spline.pdf const float fZero = 1e-9f; float x0 = float(pNode->frame); float y1, x1 = x0; float s1 = 0.0f; float f1 = 0.0f; float y2 = pNode->value; float s2 = 0.0f; float f2 = 0.0f; if (pPrev) { x1 -= float(pPrev->frame); y1 = pPrev->value; } else { y1 = y0; } if (fabs(y1 - y2) > fZero) s1 = x1 / (y1 - y2); if (pPrev) { pPrev = pPrev->prev(); if (pPrev && (fabs(y1 - pPrev->value) > fZero)) { float s0 = (x1 - float(pPrev->frame) - x0) / (y1 - pPrev->value); if (s1 * s0 > 0.0f && fabs(s1 + s0) > fZero) f1 = 2.0f / (s1 + s0); } } if (pNext && (fabs(pNext->value - y2) > fZero)) s2 = (float(pNext->frame) - x0) / (pNext->value - y2); if (s2 * s1 > 0.0f && fabs(s2 + s1) > fZero) f2 = 2.0f / (s2 + s1); float x12 = x1 * x1; float dy = y2 - y1; // Compute second derivative for either side of control point... float ff1 = (((2.0f * (f2 + (2.0f * f1))) / x1)) + ((6.0f * dy) / x12); float ff2 = (-2.0f * ((2.0f * f2) + f1) / x1) - ((6.0f * dy) / x12); // Compute and store polynomial coefficients... pNode->a = (ff1 - ff2) / (6.0f * x1); pNode->b = ff2 / 2.0f; pNode->c = - (dy / x1 + (pNode->b * x1) + (pNode->a * x12)); pNode->d = y1 - (pNode->c * x1) - (pNode->b * x12) - (pNode->a * x12 * x1); } //---------------------------------------------------------------------- // qtractorCurve::value -- Interpolation computation helpers. // // (Sample &)Hold. inline float valueHold ( const qtractorCurve::Node *pNode, float /*x*/ ) { return pNode->a; } // Linear. inline float valueLinear ( const qtractorCurve::Node *pNode, float x ) { return pNode->a * x + pNode->b; } // Spline. inline float valueSpline ( const qtractorCurve::Node *pNode, float x ) { return ((pNode->a * x + pNode->b) * x + pNode->c) * x + pNode->d; } //---------------------------------------------------------------------- // class qtractorCurve -- The generic curve declaration. // // Constructor. qtractorCurve::qtractorCurve ( qtractorCurveList *pList, qtractorSubject *pSubject, Mode mode, unsigned int iMinFrameDist ) : m_pList(pList), m_mode(mode), m_iMinFrameDist(iMinFrameDist), m_observer(pSubject, this), m_state(Idle), m_cursor(this), m_bLogarithmic(false), m_color(Qt::darkRed), m_pEditList(NULL) { m_nodes.setAutoDelete(true); m_pEditList = new qtractorCurveEditList(this); m_tail.frame = 0; // m_tail.value = m_observer.defaultValue(); clear(); m_observer.setCurve(this); m_pList->addCurve(this); } // Destructor. qtractorCurve::~qtractorCurve (void) { m_pList->removeCurve(this); m_observer.setCurve(NULL); clear(); delete m_pEditList; } // Curve list reset method. void qtractorCurve::clear (void) { // m_state = Idle; // m_tail.frame = 0; m_tail.value = m_observer.defaultValue(); m_tail.a = 0.0f; m_tail.b = 0.0f; m_tail.c = 0.0f; m_tail.d = 0.0f; m_nodes.clear(); m_cursor.reset(NULL); updateNodeEx(NULL); } // Insert a new node, in frame order. qtractorCurve::Node *qtractorCurve::addNode ( unsigned long iFrame, float fValue, qtractorCurveEditList *pEditList ) { fValue = m_observer.safeValue(fValue); #ifdef CONFIG_DEBUG_0 qDebug("qtractorCurve[%p]::addNode(%lu, %g, %p)", this, iFrame, fValue, pEditList); #endif Node *pNode = NULL; Node *pNext = m_cursor.seek(frameDist(iFrame)); Node *pPrev = (pNext ? pNext->prev() : m_nodes.last()); if (pNext && pNext->frame == m_cursor.frame()) pNode = pNext; else if (pPrev && pPrev->frame == m_cursor.frame()) pNode = pPrev; else { // Smoothing... float y0 = (pPrev ? pPrev->value : m_tail.value); float y1 = fValue; float y2 = (pNext ? pNext->value : fValue); if (m_mode == Hold || m_observer.isToggled()) { const float fThreshold = (m_bLogarithmic ? 0.1f * fabs(y1) : 0.01f) * (m_observer.maxValue() - m_observer.minValue()); if (fabs(y2 - y1) < fThreshold) pNode = pNext; else if (fabs(y1 - y0) < fThreshold) return NULL; } else { const float fThreshold = 0.5f; // (m_bLogarithmic ? 0.1f : 0.5f); float x0 = (pPrev ? float(pPrev->frame) : 0.0f); float x1 = float(iFrame); float x2 = (pNext ? float(pNext->frame) : m_tail.frame); float s1 = (x1 > x0 ? (y1 - y0) / (x1 - x0) : 0.0f); float y3 = (x2 > x1 ? s1 * (x2 - x1) + y1 : y1); if (fabs(y3 - y2) < fThreshold * fabs(y3 - y1)) return NULL; if (pPrev) { pNode = pPrev; pPrev = pNode->prev(); x0 = (pPrev ? float(pPrev->frame) : 0.0f); y0 = (pPrev ? pPrev->value : m_tail.value); x1 = float(pNode->frame); y1 = pNode->value; x2 = float(iFrame); y2 = fValue; s1 = (y1 - y0) / (x1 - x0); y3 = s1 * (x2 - x1) + y1; if (fabs(y3 - y2) > fThreshold * fabs(y3 - y1)) pNode = NULL; } } } if (pNode) { // Move/update the existing one as average... if (pEditList) pEditList->moveNode(pNode, pNode->frame); pNode->frame = m_cursor.frame(); pNode->value = fValue; } else { // Create a brand new node, // insert it in the right frame... pNode = new Node(m_cursor.frame(), fValue); if (pNext) m_nodes.insertBefore(pNode, pNext); else m_nodes.append(pNode); if (pEditList) pEditList->addNode(pNode); } updateNode(pNode); // Dirty up... m_pList->notify(); return pNode; } // Insert curve node in correct frame order. void qtractorCurve::insertNode ( Node *pNode ) { if (pNode == NULL) return; #ifdef CONFIG_DEBUG_0 qDebug("qtractorCurve[%p]::insertNode(%p)", this, pNode); #endif Node *pNext = m_cursor.seek(pNode->frame); if (pNext) m_nodes.insertBefore(pNode, pNext); else m_nodes.append(pNode); updateNode(pNode); // Dirty up... m_pList->notify(); } // Unlink an existing node from curve. void qtractorCurve::unlinkNode ( Node *pNode ) { if (pNode == NULL) return; #ifdef CONFIG_DEBUG_0 qDebug("qtractorCurve[%p]::unlinkNode(%p)", this, pNode); #endif m_cursor.reset(pNode); Node *pNext = pNode->next(); m_nodes.unlink(pNode); updateNode(pNext); // Dirty up... m_pList->notify(); } // Remove an existing node from curve. void qtractorCurve::removeNode ( Node *pNode ) { if (pNode == NULL) return; #ifdef CONFIG_DEBUG_0 qDebug("qtractorCurve[%p]::removeNode(%p)", this, pNode); #endif m_cursor.reset(pNode); Node *pNext = pNode->next(); m_nodes.remove(pNode); updateNode(pNext); // Dirty up... m_pList->notify(); } // Snap to minimum distance frame. unsigned long qtractorCurve::frameDist ( unsigned long iFrame ) const { if (m_iMinFrameDist > 0) { const unsigned long q = m_iMinFrameDist; iFrame = q * ((iFrame + (q >> 1)) / q); } return iFrame; } // Node interpolation coefficients updater. void qtractorCurve::updateNode ( qtractorCurve::Node *pNode ) { updateNodeEx(pNode); if (pNode) updateNodeEx(pNode->next()); } void qtractorCurve::updateNodeEx ( qtractorCurve::Node *pNode ) { Node *pPrev, *pNext = NULL; if (pNode) { pPrev = pNode->prev(); pNext = pNode->next(); if (pNext == NULL) pNext = &m_tail; } else { pNode = &m_tail; pPrev = m_nodes.last(); } if (m_tail.frame < pNode->frame) m_tail.frame = pNode->frame; switch (m_mode) { case Hold: updateNodeHold(pNode, m_tail.value, pPrev, pNext); break; case Linear: updateNodeLinear(pNode, m_tail.value, pPrev, pNext); break; case Spline: updateNodeSpline(pNode, m_tail.value, pPrev, pNext); break; } } // Refresh all coefficients. void qtractorCurve::update (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorCurve[%p]::update()", this); #endif for (Node *pNode = m_nodes.first(); pNode; pNode = pNode->next()) updateNodeEx(pNode); updateNodeEx(NULL); m_pList->notify(); } // Default value accessors. void qtractorCurve::setDefaultValue ( float fDefaultValue ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorCurve[%p]::setDefaultValue(%g)", this, fDefaultValue); #endif m_tail.value = fDefaultValue; Node *pLast = m_nodes.last(); updateNode(pLast); Node *pFirst = m_nodes.first(); if (pFirst != pLast) updateNode(pFirst); m_pList->notify(); } // Default length accessors. void qtractorCurve::setLength ( unsigned long iLength ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorCurve[%p]::setLength(%ld)", this, iLength); #endif m_tail.frame = iLength; Node *pNode = m_nodes.last(); while (pNode && pNode->frame > m_tail.frame) { Node *pPrev = pNode->prev(); m_nodes.remove(pNode); pNode = pPrev; } updateNode(pNode); m_pList->notify(); } // Intra-curve frame positioning node seeker. qtractorCurve::Node *qtractorCurve::Cursor::seek ( unsigned long iFrame ) { Node *pNode = m_pNode; if (iFrame > m_iFrame) { // Seek forward... if (pNode == NULL) pNode = m_pCurve->nodes().first(); while (pNode && pNode->frame < iFrame) pNode = pNode->next(); } else { // Seek backward... if (pNode == NULL) pNode = m_pCurve->nodes().last(); while (pNode && pNode->prev() && (pNode->prev())->frame > iFrame) pNode = pNode->prev(); } m_iFrame = iFrame; m_pNode = pNode; return (pNode && pNode->frame >= iFrame ? pNode : NULL); } // Intra-curve frame positioning reset. void qtractorCurve::Cursor::reset ( qtractorCurve::Node *pNode ) { m_pNode = (pNode ? pNode->next() : NULL); m_iFrame = (m_pNode ? m_pNode->frame : 0); } // Common interpolate method. float qtractorCurve::value ( const Node *pNode, unsigned long iFrame ) const { if (pNode == NULL) { pNode = m_nodes.last(); if (pNode == NULL) pNode = &m_tail; } float x = float(pNode->frame) - float(iFrame); float y = pNode->value; if (x > 0.0f) { switch (m_mode) { case Hold: y = valueHold(pNode, x); break; case Linear: y = valueLinear(pNode, x); break; case Spline: y = valueSpline(pNode, x); break; } } return y; } float qtractorCurve::value ( unsigned long iFrame ) { return value(m_cursor.seek(iFrame), iFrame); } // Normalized scale converters. float qtractorCurve::valueFromScale ( float fScale ) const { if (m_bLogarithmic) { const float fMaxValue = m_observer.maxValue(); const float fMinValue = m_observer.minValue(); if (fMinValue < 0.0f && fMaxValue > 0.0f) { const float fMidScale = fMinValue / (fMinValue - fMaxValue); if (fScale > fMidScale) { const float fMaxScale = (1.0f - fMidScale); fScale = (fScale - fMidScale) / fMaxScale; fScale = fMidScale + fMaxScale * ::cubef2(fScale); } else { fScale = (fMidScale - fScale) / fMidScale; fScale = fMidScale - fMidScale * ::cubef2(fScale); } } else fScale = ::cubef2(fScale); } return m_observer.valueFromScale(fScale); } float qtractorCurve::scaleFromValue ( float fValue ) const { float fScale = m_observer.scaleFromValue(fValue); if (m_bLogarithmic) { const float fMaxValue = m_observer.maxValue(); const float fMinValue = m_observer.minValue(); if (fMinValue < 0.0f && fMaxValue > 0.0f) { const float fMidScale = fMinValue / (fMinValue - fMaxValue); if (fScale > fMidScale) { const float fMaxScale = (1.0f - fMidScale); fScale = (fScale - fMidScale) / fMaxScale; fScale = fMidScale + fMaxScale * ::cbrtf2(fScale); } else { fScale = (fMidScale - fScale) / fMidScale; fScale = fMidScale - fMidScale * ::cbrtf2(fScale); } } else fScale = ::cbrtf2(fScale); } return fScale; } // Convert MIDI sequence events to curve nodes. void qtractorCurve::readMidiSequence ( qtractorMidiSequence *pSeq, qtractorMidiEvent::EventType ctype, unsigned short iChannel, unsigned short iParam, qtractorTimeScale *pTimeScale ) { qtractorTimeScale ts; if (pTimeScale) ts.copy(*pTimeScale); ts.setTicksPerBeat(pSeq->ticksPerBeat()); // Cleanup all existing nodes... clear(); // Convert events to nodes... if (pSeq->channel() == iChannel) { qtractorMidiEvent *pEvent = pSeq->events().first(); while (pEvent) { if (pEvent->type() == ctype && pEvent->note() == iParam) { unsigned long iFrame = ts.frameFromTick(pEvent->time()); float fScale; if (ctype == qtractorMidiEvent::PITCHBEND) fScale = float(pEvent->pitchBend()) / float(0x3fff); else fScale = float(pEvent->value()) / float(0x7f); float fValue = m_observer.valueFromScale(fScale); m_nodes.append(new Node(iFrame, fValue)); } pEvent = pEvent->next(); } } update(); } // Convert curve node to MIDI sequence events. void qtractorCurve::writeMidiSequence ( qtractorMidiSequence *pSeq, qtractorMidiEvent::EventType ctype, unsigned short iChannel, unsigned short iParam, qtractorTimeScale *pTimeScale ) const { qtractorTimeScale ts; if (pTimeScale) ts.copy(*pTimeScale); ts.setTicksPerBeat(pSeq->ticksPerBeat()); // Set proper sequence channel... pSeq->setChannel(iChannel); // Cleanup existing nodes... qtractorMidiEvent *pEvent = pSeq->events().first(); while (pEvent) { qtractorMidiEvent *pEventNext = pEvent->next(); if (pEvent->type() == ctype && pEvent->note() == iParam) pSeq->removeEvent(pEvent); pEvent = pEventNext; } // Convert nodes to events... qtractorCurve::Node *pNode = m_nodes.first(); while (pNode) { unsigned long iTime = ts.tickFromFrame(pNode->frame); qtractorMidiEvent *pEvent = new qtractorMidiEvent(iTime, ctype, iParam); float fScale = m_observer.scaleFromValue(pNode->value); if (ctype == qtractorMidiEvent::PITCHBEND) pEvent->setPitchBend(float(0x3fff) * fScale); else pEvent->setValue(float(0x7f) * fScale); pSeq->insertEvent(pEvent); pNode = pNode->next(); } pSeq->close(); } void qtractorCurve::setCapture ( bool bCapture ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorCurve[%p]::setCapture(%d)", this, int(bCapture)); #endif bool bOldCapture = (m_state & Capture); m_state = State(bCapture ? (m_state | Capture) : (m_state & ~Capture)); if ((bCapture && !bOldCapture) || (!bCapture && bOldCapture)) m_pList->updateCapture(bCapture); } void qtractorCurve::setProcess ( bool bProcess ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorCurve[%p]::setProcess(%d)", this, int(bProcess)); #endif bool bOldProcess = (m_state & Process); m_state = State(bProcess ? (m_state | Process) : (m_state & ~Process)); if ((bProcess && !bOldProcess) || (!bProcess && bOldProcess)) m_pList->updateProcess(bProcess); } void qtractorCurve::setLocked ( bool bLocked ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorCurve[%p]::setLocked(%d)", this, int(bLocked)); #endif bool bOldLocked = (m_state & Locked); m_state = State(bLocked ? (m_state | Locked) : (m_state & ~Locked)); if ((bLocked && !bOldLocked) || (!bLocked && bOldLocked)) m_pList->updateLocked(bLocked); } //---------------------------------------------------------------------- // qtractorCurveEditList -- Curve node edit list. // Curve edit list command executive. bool qtractorCurveEditList::execute ( bool bRedo ) { if (m_pCurve == NULL) return false; QListIterator iter(m_items); if (!bRedo) iter.toBack(); while (bRedo ? iter.hasNext() : iter.hasPrevious()) { Item *pItem = (bRedo ? iter.next() : iter.previous()); // Execute the command item... switch (pItem->command) { case AddNode: { if (bRedo) m_pCurve->insertNode(pItem->node); else m_pCurve->unlinkNode(pItem->node); pItem->autoDelete = !bRedo; break; } case MoveNode: { qtractorCurve::Node *pNode = pItem->node; unsigned long iFrame = pNode->frame; float fValue = pNode->value; pNode->frame = pItem->frame; pNode->value = pItem->value; pItem->frame = iFrame; pItem->value = fValue; break; } case RemoveNode: { if (bRedo) m_pCurve->unlinkNode(pItem->node); else m_pCurve->insertNode(pItem->node); pItem->autoDelete = bRedo; break; } default: break; } } return true; } // end of qtractorCurve.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorPluginForm.cpp0000644000175000001440000000012312166526620021617 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134666.91508 30 ctime=1381134666.916080047 qtractor-0.5.11/src/qtractorPluginForm.cpp0000644000175000001440000010077512166526620021120 0ustar00rncbcusers00000000000000// qtractorPluginForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorPluginForm.h" #include "qtractorPluginCommand.h" #include "qtractorAudioEngine.h" #include "qtractorPlugin.h" #include "qtractorPluginListView.h" #include "qtractorInsertPlugin.h" #include "qtractorObserverWidget.h" #include "qtractorMidiControlObserverForm.h" #include "qtractorBusForm.h" #include "qtractorOptions.h" #include "qtractorSession.h" #include "qtractorEngine.h" #include #include #include #include #include #include #include #include #include #include #include #include "math.h" // This shall hold the default preset name. static QString g_sDefPreset; //---------------------------------------------------------------------------- // qtractorPluginForm -- UI wrapper form. // Constructor. qtractorPluginForm::qtractorPluginForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QWidget(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); const QFont& font = QWidget::font(); QWidget::setFont(QFont(font.family(), font.pointSize() - 1)); m_pPlugin = NULL; m_iDirtyCount = 0; m_iUpdate = 0; m_pDirectAccessParamMenu = new QMenu(); m_ui.DirectAccessParamPushButton->setMenu(m_pDirectAccessParamMenu); m_ui.PresetComboBox->setValidator( new QRegExpValidator(QRegExp("[\\w-]+"), m_ui.PresetComboBox)); m_ui.PresetComboBox->setInsertPolicy(QComboBox::NoInsert); m_ui.PresetComboBox->setCompleter(NULL); // Have some effective feedback when toggling on/off... QIcon iconParams; iconParams.addPixmap( QPixmap(":/images/formParamsOff.png"), QIcon::Active, QIcon::Off); iconParams.addPixmap( QPixmap(":/images/formParamsOn.png"), QIcon::Active, QIcon::On); m_ui.ParamsToolButton->setIcon(iconParams); QIcon iconActivate; iconActivate.addPixmap( QPixmap(":/images/itemLedOff.png"), QIcon::Active, QIcon::Off); iconActivate.addPixmap( QPixmap(":/images/itemLedOn.png"), QIcon::Active, QIcon::On); m_ui.ActivateToolButton->setIcon(iconActivate); if (g_sDefPreset.isEmpty()) g_sDefPreset = tr("(default)"); // UI signal/slot connections... QObject::connect(m_ui.PresetComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(changePresetSlot(const QString&))); QObject::connect(m_ui.PresetComboBox, SIGNAL(activated(const QString &)), SLOT(loadPresetSlot(const QString&))); QObject::connect(m_ui.OpenPresetToolButton, SIGNAL(clicked()), SLOT(openPresetSlot())); QObject::connect(m_ui.SavePresetToolButton, SIGNAL(clicked()), SLOT(savePresetSlot())); QObject::connect(m_ui.DeletePresetToolButton, SIGNAL(clicked()), SLOT(deletePresetSlot())); QObject::connect(m_ui.ParamsToolButton, SIGNAL(toggled(bool)), SLOT(paramsSlot(bool))); QObject::connect(m_ui.EditToolButton, SIGNAL(toggled(bool)), SLOT(editSlot(bool))); QObject::connect(m_ui.SendsToolButton, SIGNAL(clicked()), SLOT(sendsSlot())); QObject::connect(m_ui.ReturnsToolButton, SIGNAL(clicked()), SLOT(returnsSlot())); QObject::connect(m_ui.AudioBusNameComboBox, SIGNAL(activated(const QString&)), SLOT(changeAudioBusNameSlot(const QString&))); QObject::connect(m_ui.AudioBusNameToolButton, SIGNAL(clicked()), SLOT(clickAudioBusNameSlot())); QObject::connect(m_ui.ActivateToolButton, SIGNAL(toggled(bool)), SLOT(activateSlot(bool))); QObject::connect(m_pDirectAccessParamMenu, SIGNAL(aboutToShow()), SLOT(updateDirectAccessParamSlot())); } // Destructor. qtractorPluginForm::~qtractorPluginForm (void) { clear(); delete m_pDirectAccessParamMenu; } // Plugin accessors. void qtractorPluginForm::setPlugin ( qtractorPlugin *pPlugin ) { clear(); // Set the new reference... m_pPlugin = pPlugin; if (m_pPlugin == NULL) return; // Dispatch any pending updates. qtractorSubject::flushQueue(true); qtractorPluginType *pType = m_pPlugin->type(); const bool bVstPlugin = (pType->typeHint() == qtractorPluginType::Vst); const int MaxRowsPerPage = (bVstPlugin ? 12 : 8); const int MaxColumnsPerPage = (bVstPlugin ? 2 : 3); const int MaxParamsPerPage = MaxRowsPerPage * MaxColumnsPerPage; const qtractorPlugin::Params& params = m_pPlugin->params(); int iParams = params.count(); int iParamsPerPage = iParams; int iParamsOnLastPage = 0; if (iParamsPerPage > MaxParamsPerPage) { iParamsPerPage = MaxParamsPerPage; iParamsOnLastPage = (iParams % iParamsPerPage); while (iParamsOnLastPage > 0 && iParamsOnLastPage < ((3 * iParamsPerPage) >> 2)) iParamsOnLastPage = (iParams % --iParamsPerPage); } int iPages = 1; int iRowsPerPage = iParamsPerPage; int iColumnsPerPage = 1; if (iRowsPerPage > MaxRowsPerPage) { iPages = (iParams / iParamsPerPage); if (iParamsOnLastPage > 0) ++iPages; while (iRowsPerPage > MaxRowsPerPage && iColumnsPerPage < MaxColumnsPerPage) iRowsPerPage = (iParamsPerPage / ++iColumnsPerPage); if (iParamsPerPage % iColumnsPerPage) // Adjust to balance. ++iRowsPerPage; } // Maybe we need a tabbed widget... QTabWidget *pTabWidget = NULL; QVBoxLayout *pVBoxLayout = NULL; if (iPages > 1) { pTabWidget = new QTabWidget(); pVBoxLayout = new QVBoxLayout(); pVBoxLayout->setMargin(0); pVBoxLayout->setSpacing(4); } QGridLayout *pGridLayout = new QGridLayout(); pGridLayout->setMargin(8); pGridLayout->setSpacing(4); int iPage = 0; const QString sPage = tr("Page %1"); QWidget *pPageWidget = NULL; if (pTabWidget) { pPageWidget = new QWidget(); pPageWidget->setLayout(pGridLayout); pTabWidget->addTab(pPageWidget, sPage.arg(++iPage)); } // Plugin might not have its own editor... pGridLayout->setHorizontalSpacing(16); // FIXME: Couldn't stand more than a hundred widgets? // or do we have one dedicated editor GUI? int iRow = 0; int iColumn = 0; qtractorPlugin::Params::ConstIterator param = params.constBegin(); const qtractorPlugin::Params::ConstIterator param_end = params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); qtractorPluginParamWidget *pParamWidget = new qtractorPluginParamWidget(pParam, this); m_paramWidgets.insert(pParam->index(), pParamWidget); pGridLayout->addWidget(pParamWidget, iRow, iColumn); qtractorMidiControlObserver *pMidiObserver = pParam->observer(); if (pMidiObserver) { // pMidiObserver->setCurveList(pPlugin->list()->curveList()); addMidiControlAction(pParamWidget, pMidiObserver); } if (++iRow >= iRowsPerPage) { iRow = 0; if (++iColumn >= iColumnsPerPage) { iColumn = 0; if (pTabWidget && iPage < iPages) { pGridLayout = new QGridLayout(); pGridLayout->setMargin(8); pGridLayout->setSpacing(4); pPageWidget = new QWidget(); pPageWidget->setLayout(pGridLayout); pTabWidget->addTab(pPageWidget, sPage.arg(++iPage)); } } } } if (pVBoxLayout && pTabWidget) { pVBoxLayout->addWidget(pTabWidget); m_ui.ParamsGridWidget->setLayout(pVBoxLayout); } else { m_ui.ParamsGridWidget->setLayout(pGridLayout); } // Show editor button if available? bool bEditor = pType->isEditor(); m_ui.EditToolButton->setVisible(bEditor); if (bEditor) toggleEditor(m_pPlugin->isEditorVisible()); // Show insert tool options... bool bInsertPlugin = (pType->typeHint() == qtractorPluginType::Insert); m_ui.SendsToolButton->setVisible(bInsertPlugin); m_ui.ReturnsToolButton->setVisible(bInsertPlugin); // Show aux-send tool options... bool bAuxSendPlugin = (pType->typeHint() == qtractorPluginType::AuxSend ); m_ui.AudioBusNameComboBox->setVisible(bAuxSendPlugin); m_ui.AudioBusNameLabel->setVisible(bAuxSendPlugin); m_ui.AudioBusNameToolButton->setVisible(bAuxSendPlugin); // Set initial plugin preset name... setPreset(m_pPlugin->preset()); // Set plugin name as title, // maybe redundant but necessary... m_pPlugin->updateEditorTitle(); // This should trigger paramsSlot(!bEditor) // and adjust the size of the params dialog... m_ui.ParamsToolButton->setVisible(iParams > 0); m_ui.ParamsToolButton->setChecked(iParams > 0); m_ui.DirectAccessParamPushButton->setVisible(iParams > 0); paramsSlot(iParams > 0); // Clear any initial param update. qtractorSubject::resetQueue(); updateActivated(); refresh(); stabilize(); show(); } void qtractorPluginForm::activateForm (void) { if (!isVisible()) { if (m_pPlugin) toggleEditor(m_pPlugin->isEditorVisible()); show(); } raise(); activateWindow(); } // Editor widget methods. void qtractorPluginForm::toggleEditor ( bool bOn ) { if (m_pPlugin == NULL) return; if (m_iUpdate > 0) return; ++m_iUpdate; m_ui.EditToolButton->setChecked(bOn); --m_iUpdate; } // Plugin accessor. qtractorPlugin *qtractorPluginForm::plugin (void) const { return m_pPlugin; } // Plugin preset accessors. void qtractorPluginForm::setPreset ( const QString& sPreset ) { QString sEditText = sPreset; if (sEditText.isEmpty()) sEditText = g_sDefPreset; ++m_iUpdate; m_ui.PresetComboBox->setEditText(sEditText); --m_iUpdate; } QString qtractorPluginForm::preset (void) const { QString sPreset = m_ui.PresetComboBox->currentText(); if (sPreset == g_sDefPreset || m_iDirtyCount > 0) sPreset.clear(); return sPreset; } // Update activation state. void qtractorPluginForm::updateActivated (void) { if (m_pPlugin == NULL) return; if (m_iUpdate > 0) return; ++m_iUpdate; m_ui.ActivateToolButton->setChecked(m_pPlugin->isActivated()); --m_iUpdate; } // Update specific aux-send audio bus settings. void qtractorPluginForm::updateAudioBusName (void) { if (m_pPlugin == NULL) return; m_ui.AudioBusNameComboBox->clear(); const QIcon icon(":/images/trackAudio.png"); m_ui.AudioBusNameComboBox->addItem(icon, tr("(none)")); qtractorAuxSendPlugin *pAuxSendPlugin = NULL; if ((m_pPlugin->type())->typeHint() == qtractorPluginType::AuxSend) pAuxSendPlugin = static_cast (m_pPlugin); if (pAuxSendPlugin == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine == NULL) return; for (qtractorBus *pBus = pAudioEngine->buses().first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Output) { qtractorAudioBus *pAudioBus = static_cast (pBus); if (pAudioBus && pAudioBus->channels() == m_pPlugin->channels()) m_ui.AudioBusNameComboBox->addItem(icon, pAudioBus->busName()); } } const QString& sAudioBusName = pAuxSendPlugin->audioBusName(); int iIndex = m_ui.AudioBusNameComboBox->findText(sAudioBusName); if (iIndex < 0) iIndex = 0; m_ui.AudioBusNameComboBox->setCurrentIndex(iIndex); } // Update port widget state. void qtractorPluginForm::changeParamValue ( unsigned long /*iIndex*/ ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorPluginForm[%p]::changeParamValue(%lu)", this, iIndex); #endif #if 0 qtractorPluginParamWidget *pParamWidget = m_paramWidgets.value(iIndex, NULL); if (pParamWidget) pParamWidget->refresh(); #endif // Sure is dirty... ++m_iDirtyCount; stabilize(); } // Preset management slots... void qtractorPluginForm::changePresetSlot ( const QString& sPreset ) { if (m_iUpdate > 0) return; if (!sPreset.isEmpty() && m_ui.PresetComboBox->findText(sPreset) >= 0) ++m_iDirtyCount; stabilize(); } void qtractorPluginForm::loadPresetSlot ( const QString& sPreset ) { if (m_pPlugin == NULL) return; if (m_iUpdate > 0 || sPreset.isEmpty()) return; // We'll need this, sure. qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; if (sPreset == g_sDefPreset) { // Reset to default... pSession->execute( new qtractorResetPluginCommand(m_pPlugin)); } else if (!m_pPlugin->loadPreset(sPreset)) { // An existing preset is about to be loaded... QSettings& settings = pOptions->settings(); // Should it be load from known file?... if ((m_pPlugin->type())->isConfigure()) { settings.beginGroup(m_pPlugin->presetGroup()); m_pPlugin->loadPresetFile(settings.value(sPreset).toString()); settings.endGroup(); refresh(); } else { //...or make it as usual (parameter list only)... settings.beginGroup(m_pPlugin->presetGroup()); QStringList vlist = settings.value(sPreset).toStringList(); settings.endGroup(); if (!vlist.isEmpty()) { pSession->execute( new qtractorPresetPluginCommand(m_pPlugin, sPreset, vlist)); } } } stabilize(); } void qtractorPluginForm::openPresetSlot (void) { if (m_pPlugin == NULL) return; if (!(m_pPlugin->type())->isConfigure()) return; if (m_iUpdate > 0) return; // We'll need this, sure. qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; // We'll assume that there's an external file... QString sFilename; // Prompt if file does not currently exist... const QString sExt("qtx"); const QString& sTitle = tr("Open Preset") + " - " QTRACTOR_TITLE; const QString& sFilter = tr("Preset files (*.%1)").arg(sExt); #if 0//QT_VERSION < 0x040400 // Ask for the filename to save... sFilename = QFileDialog::getOpenFileName(this, sTitle, pOptions->sPresetDir, sFilter); #else // Construct save-file dialog... QFileDialog fileDialog(this, sTitle, pOptions->sPresetDir, sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::ExistingFile); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(pOptions->sPresetDir)); fileDialog.setSidebarUrls(urls); // Show dialog... if (fileDialog.exec()) sFilename = fileDialog.selectedFiles().first(); #endif // Have we a filename to load a preset from? if (!sFilename.isEmpty()) { if (m_pPlugin->loadPresetFile(sFilename)) { // Got it loaded alright... QFileInfo fi(sFilename); setPreset(fi.baseName() .replace((m_pPlugin->type())->label() + '-', QString())); pOptions->sPresetDir = fi.absolutePath(); } else { // Failure (maybe wrong plugin)... QMessageBox::critical(this, tr("Error") + " - " QTRACTOR_TITLE, tr("Preset could not be loaded\n" "from \"%1\".\n\n" "Sorry.").arg(sFilename), QMessageBox::Cancel); } } refresh(); stabilize(); } void qtractorPluginForm::savePresetSlot (void) { if (m_pPlugin == NULL) return; const QString& sPreset = m_ui.PresetComboBox->currentText(); if (sPreset.isEmpty() || sPreset == g_sDefPreset) return; // We'll need this, sure. qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; // The current state preset is about to be saved... // this is where we'll make it! if (!m_pPlugin->savePreset(sPreset)) { QSettings& settings = pOptions->settings(); settings.beginGroup(m_pPlugin->presetGroup()); // Which mode of preset? if ((m_pPlugin->type())->isConfigure()) { // Sure, we'll have something complex enough // to make it save into an external file... const QString sExt("qtx"); QFileInfo fi(QDir(pOptions->sPresetDir), (m_pPlugin->type())->label() + '-' + sPreset + '.' + sExt); QString sFilename = fi.absoluteFilePath(); // Prompt if file does not currently exist... if (!fi.exists()) { const QString& sTitle = tr("Save Preset") + " - " QTRACTOR_TITLE; const QString& sFilter = tr("Preset files (*.%1)").arg(sExt); #if 0//QT_VERSION < 0x040400 // Ask for the filename to save... sFilename = QFileDialog::getSaveFileName(this, sTitle, sFilename, sFilter); #else // Construct save-file dialog... QFileDialog fileDialog(this, sTitle, sFilename, sFilter); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptSave); fileDialog.setFileMode(QFileDialog::AnyFile); fileDialog.setDefaultSuffix(sExt); // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(pOptions->sSessionDir)); urls.append(QUrl::fromLocalFile(pOptions->sPresetDir)); fileDialog.setSidebarUrls(urls); // Show dialog... if (fileDialog.exec()) sFilename = fileDialog.selectedFiles().first(); else sFilename.clear(); #endif } // We've a filename to save the preset if (!sFilename.isEmpty()) { if (QFileInfo(sFilename).suffix().isEmpty()) sFilename += '.' + sExt; if (m_pPlugin->savePresetFile(sFilename)) { settings.setValue(sPreset, sFilename); pOptions->sPresetDir = QFileInfo(sFilename).absolutePath(); } } } // Just leave it to simple parameter value list... else settings.setValue(sPreset, m_pPlugin->valueList()); settings.endGroup(); } refresh(); stabilize(); } void qtractorPluginForm::deletePresetSlot (void) { if (m_pPlugin == NULL) return; const QString& sPreset = m_ui.PresetComboBox->currentText(); if (sPreset.isEmpty() || sPreset == g_sDefPreset) return; // We'll need this, sure. qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions == NULL) return; // A preset entry is about to be deleted; // prompt user if he/she's sure about this... if (pOptions->bConfirmRemove) { if (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("About to delete preset:\n\n" "\"%1\" (%2)\n\n" "Are you sure?") .arg(sPreset) .arg((m_pPlugin->type())->name()), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; } // Go ahead... if (!m_pPlugin->deletePreset(sPreset)) { QSettings& settings = pOptions->settings(); settings.beginGroup(m_pPlugin->presetGroup()); #ifdef QTRACTOR_REMOVE_PRESET_FILES if ((m_pPlugin->type())->isConfigure()) { const QString& sFilename = settings.value(sPreset).toString(); if (QFileInfo(sFilename).exists()) QFile(sFilename).remove(); } #endif settings.remove(sPreset); settings.endGroup(); } refresh(); stabilize(); } // Params slot. void qtractorPluginForm::paramsSlot ( bool bOn ) { if (m_pPlugin == NULL) return; if (m_iUpdate > 0) return; ++m_iUpdate; m_ui.ParamsGridWidget->setVisible(bOn); if (bOn) m_ui.ParamsGridWidget->show(); else m_ui.ParamsGridWidget->hide(); // Shake it a little bit first, but // make it as tight as possible... resize(width() + 1, height() + 1); adjustSize(); --m_iUpdate; } // Editor slot. void qtractorPluginForm::editSlot ( bool bOn ) { if (m_pPlugin == NULL) return; if (m_iUpdate > 0) return; ++m_iUpdate; if (bOn) m_pPlugin->openEditor(this); else m_pPlugin->closeEditor(); --m_iUpdate; } // Outputs (Sends) slot. void qtractorPluginForm::sendsSlot (void) { qtractorPluginListView::insertPluginBus(m_pPlugin, qtractorBus::Output); } // Inputs (Returns) slot. void qtractorPluginForm::returnsSlot (void) { qtractorPluginListView::insertPluginBus(m_pPlugin, qtractorBus::Input); } // Audio bus name (aux-send) select slot. void qtractorPluginForm::changeAudioBusNameSlot ( const QString& sAudioBusName ) { if (m_pPlugin == NULL) return; qtractorAuxSendPlugin *pAuxSendPlugin = NULL; if (m_pPlugin->type()->typeHint() == qtractorPluginType::AuxSend) pAuxSendPlugin = static_cast (m_pPlugin); if (pAuxSendPlugin == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; pSession->execute( new qtractorAuxSendPluginCommand(pAuxSendPlugin, sAudioBusName)); } // Audio bus name (aux-send) browse slot. void qtractorPluginForm::clickAudioBusNameSlot (void) { if (m_pPlugin == NULL) return; qtractorAuxSendPlugin *pAuxSendPlugin = NULL; if (m_pPlugin->type()->typeHint() == qtractorPluginType::AuxSend) pAuxSendPlugin = static_cast (m_pPlugin); if (pAuxSendPlugin == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine == NULL) return; // Call here the bus management form. qtractorBusForm busForm(this); // Pre-select bus... const QString& sAudioBusName = m_ui.AudioBusNameComboBox->currentText(); if (!sAudioBusName.isEmpty()) busForm.setBus(pAudioEngine->findBus(sAudioBusName)); // Go for it... busForm.exec(); // Check if any buses have changed... if (busForm.isDirty()) updateAudioBusName(); } // Direct access parameter slots void qtractorPluginForm::updateDirectAccessParamSlot (void) { m_pDirectAccessParamMenu->clear(); if (m_pPlugin == NULL) return; QAction *pAction; int iDirectAccessParamIndex = m_pPlugin->directAccessParamIndex(); const qtractorPlugin::Params& params = m_pPlugin->params(); qtractorPlugin::Params::ConstIterator param = params.constBegin(); const qtractorPlugin::Params::ConstIterator param_end = params.constEnd(); for ( ; param != param_end; ++param) { qtractorPluginParam *pParam = param.value(); int iParamIndex = int(param.key()); pAction = m_pDirectAccessParamMenu->addAction( pParam->name(), this, SLOT(changeDirectAccessParamSlot())); pAction->setCheckable(true); pAction->setChecked(iDirectAccessParamIndex == iParamIndex); pAction->setData(iParamIndex); } if (!params.isEmpty()) m_pDirectAccessParamMenu->addSeparator(); pAction = m_pDirectAccessParamMenu->addAction( tr("&None"), this, SLOT(changeDirectAccessParamSlot())); pAction->setCheckable(true); pAction->setChecked(iDirectAccessParamIndex < 0); pAction->setData(int(-1)); } void qtractorPluginForm::changeDirectAccessParamSlot (void) { if (m_pPlugin == NULL) return; if (m_iUpdate > 0) return; // Retrieve direct access parameter index from action data... QAction *pAction = qobject_cast (sender()); if (pAction == NULL) return; int iDirectAccessParamIndex = pAction->data().toInt(); ++m_iUpdate; // Make it a undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) pSession->execute( new qtractorDirectAccessParamCommand(m_pPlugin, iDirectAccessParamIndex)); --m_iUpdate; } // Activation slot. void qtractorPluginForm::activateSlot ( bool bOn ) { if (m_pPlugin == NULL) return; if (m_iUpdate > 0) return; ++m_iUpdate; // Make it a undoable command... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) pSession->execute( new qtractorActivatePluginCommand(m_pPlugin, bOn)); --m_iUpdate; } // Parameter-widget refreshner-loader. void qtractorPluginForm::refresh (void) { if (m_pPlugin == NULL) return; if (m_iUpdate > 0) return; #ifdef CONFIG_DEBUG qDebug("qtractorPluginForm[%p]::refresh()", this); #endif ++m_iUpdate; qtractorSubject::flushQueue(true); const QString sOldPreset = m_ui.PresetComboBox->currentText(); m_ui.PresetComboBox->clear(); m_ui.PresetComboBox->insertItems(0, m_pPlugin->presetList()); m_ui.PresetComboBox->model()->sort(0); m_ui.PresetComboBox->addItem(g_sDefPreset); m_ui.PresetComboBox->setEditText(sOldPreset); ParamWidgets::ConstIterator iter = m_paramWidgets.constBegin(); const ParamWidgets::ConstIterator& iter_end = m_paramWidgets.constEnd(); for ( ; iter != iter_end; ++iter) iter.value()->refresh(); updateAudioBusName(); m_pPlugin->idleEditor(); qtractorSubject::resetQueue(); m_iDirtyCount = 0; --m_iUpdate; } // Preset control. void qtractorPluginForm::stabilize (void) { bool bExists = false; bool bEnabled = (m_pPlugin != NULL); m_ui.ActivateToolButton->setEnabled(bEnabled); if (bEnabled) { bEnabled = ( (m_pPlugin->type())->controlIns() > 0 || (m_pPlugin->type())->isConfigure()); } m_ui.PresetComboBox->setEnabled(bEnabled); m_ui.OpenPresetToolButton->setVisible( bEnabled && (m_pPlugin->type())->isConfigure()); if (bEnabled) { const QString& sPreset = m_ui.PresetComboBox->currentText(); bEnabled = !sPreset.isEmpty() && sPreset != g_sDefPreset && !m_pPlugin->isReadOnlyPreset(sPreset); bExists = (m_ui.PresetComboBox->findText(sPreset) >= 0); } m_ui.SavePresetToolButton->setEnabled( bEnabled && (!bExists || m_iDirtyCount > 0)); m_ui.DeletePresetToolButton->setEnabled( bEnabled && bExists); } // Clear up plugin form... void qtractorPluginForm::clear (void) { if (m_pPlugin) m_pPlugin->closeEditor(); qDeleteAll(m_paramWidgets); m_paramWidgets.clear(); m_pDirectAccessParamMenu->clear(); } // Keyboard event handler. void qtractorPluginForm::keyPressEvent ( QKeyEvent *pKeyEvent ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorPluginForm::keyPressEvent(%d)", pKeyEvent->key()); #endif int iKey = pKeyEvent->key(); switch (iKey) { case Qt::Key_Escape: close(); break; default: QWidget::keyPressEvent(pKeyEvent); break; } } // MIDI controller/observer attachment (context menu) void qtractorPluginForm::addMidiControlAction ( QWidget *pWidget, qtractorMidiControlObserver *pMidiObserver ) { qtractorMidiControlObserverForm::addMidiControlAction( this, pWidget, pMidiObserver); } void qtractorPluginForm::midiControlActionSlot (void) { qtractorMidiControlObserverForm::midiControlAction( this, qobject_cast (sender())); } void qtractorPluginForm::midiControlMenuSlot ( const QPoint& pos ) { qtractorMidiControlObserverForm::midiControlMenu( qobject_cast (sender()), pos); } //---------------------------------------------------------------------- // class qtractorPluginParamDisplay -- Observer display label. // class qtractorPluginParamDisplay : public QLabel { public: // Local observer. class Observer : public qtractorObserver { public: // Constructor. Observer(qtractorSubject *pSubject, qtractorPluginParamDisplay *pDisplay) : qtractorObserver(pSubject), m_pDisplay(pDisplay) {} // Observer updater. void update(bool bUpdate) { if (bUpdate) m_pDisplay->updateDisplay(); } private: // Members. qtractorPluginParamDisplay *m_pDisplay; }; // Constructor. qtractorPluginParamDisplay(qtractorPluginParam *pParam) : QLabel(), m_pParam(pParam), m_observer(pParam->subject(), this) {} // Observer accessor. Observer *observer() { return &m_observer; } protected: void updateDisplay() { QLabel::setText(m_pParam->display()); } private: // Parameter reference. qtractorPluginParam *m_pParam; // Observer instance. Observer m_observer; }; //---------------------------------------------------------------------- // class qtractorPluginParamWidget::SliderInterface -- Observer interface. // // Local converter interface. class qtractorPluginParamWidget::SliderInterface : public qtractorObserverSlider::Interface { public: // Constructor. SliderInterface ( qtractorObserverSlider *pSlider, qtractorPluginParam *pParam ) : qtractorObserverSlider::Interface(pSlider), m_pParam(pParam) {} // Formerly Pure virtuals. float scaleFromValue ( float fValue ) const { return 10000.0f * m_pParam->observer()->scaleFromValue(fValue, m_pParam->isLogarithmic()); } float valueFromScale ( float fScale ) const { return m_pParam->observer()->valueFromScale((fScale / 10000.0f), m_pParam->isLogarithmic()); } private: // Instance references. qtractorPluginParam *m_pParam; }; //---------------------------------------------------------------------------- // qtractorPluginParamWidget -- Plugin port widget. // // Constructor. qtractorPluginParamWidget::qtractorPluginParamWidget ( qtractorPluginParam *pParam, QWidget *pParent ) : QFrame(pParent), m_pParam(pParam) { m_pSlider = NULL; m_pSpinBox = NULL; m_pCheckBox = NULL; m_pDisplay = NULL; QGridLayout *pGridLayout = new QGridLayout(); pGridLayout->setMargin(0); pGridLayout->setSpacing(4); if (m_pParam->isToggled()) { m_pCheckBox = new qtractorObserverCheckBox(/*this*/); m_pCheckBox->setText(m_pParam->name()); m_pCheckBox->setSubject(m_pParam->subject()); // m_pCheckBox->setChecked(m_pParam->value() > 0.1f); pGridLayout->addWidget(m_pCheckBox, 0, 0); } else if (m_pParam->isInteger()) { pGridLayout->setColumnMinimumWidth(0, 120); QLabel *pLabel = new QLabel(/*this*/); pLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); pLabel->setText(m_pParam->name() + ':'); if (m_pParam->isDisplay()) { pGridLayout->addWidget(pLabel, 0, 0); } else { pGridLayout->addWidget(pLabel, 0, 0, 1, 2); } m_pSpinBox = new qtractorObserverSpinBox(/*this*/); m_pSpinBox->setMaximumWidth(64); m_pSpinBox->setDecimals(0); m_pSpinBox->setMinimum(m_pParam->minValue()); m_pSpinBox->setMaximum(m_pParam->maxValue()); m_pSpinBox->setAlignment(Qt::AlignHCenter); m_pSpinBox->setSubject(m_pParam->subject()); // m_pSpinBox->setValue(int(m_pParam->value())); if (m_pParam->isDisplay()) { pGridLayout->addWidget(m_pSpinBox, 0, 1); m_pDisplay = new qtractorPluginParamDisplay(m_pParam); m_pDisplay->setAlignment(Qt::AlignCenter | Qt::AlignVCenter); // m_pDisplay->setText(m_pParam->display()); // m_pDisplay->setFixedWidth(72); m_pDisplay->setMinimumWidth(64); pGridLayout->addWidget(m_pDisplay, 0, 2); } else { pGridLayout->addWidget(m_pSpinBox, 0, 2); } } else { QLabel *pLabel = new QLabel(/*this*/); if (m_pParam->isDisplay()) { pLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); // pLabel->setFixedWidth(72); pLabel->setMinimumWidth(64); pLabel->setText(m_pParam->name()); pGridLayout->addWidget(pLabel, 0, 0); } else { pLabel->setAlignment(Qt::AlignLeft | Qt::AlignBottom); pLabel->setText(m_pParam->name() + ':'); pGridLayout->addWidget(pLabel, 0, 0, 1, 3); } m_pSlider = new qtractorObserverSlider(/*this*/); m_pSlider->setInterface(new SliderInterface(m_pSlider, m_pParam)); m_pSlider->setOrientation(Qt::Horizontal); m_pSlider->setTickPosition(QSlider::NoTicks); m_pSlider->setMinimumWidth(120); m_pSlider->setMinimum(0); m_pSlider->setMaximum(10000); m_pSlider->setPageStep(1000); m_pSlider->setSingleStep(100); m_pSlider->setSubject(m_pParam->subject()); // m_pSlider->setValue(m_pSlider->scaleFromValue(m_pParam->value())); if (m_pParam->isDisplay()) { pGridLayout->addWidget(m_pSlider, 0, 1); m_pDisplay = new qtractorPluginParamDisplay(m_pParam); m_pDisplay->setAlignment(Qt::AlignCenter | Qt::AlignVCenter); // m_pDisplay->setText(m_pParam->display()); // m_pDisplay->setFixedWidth(72); m_pDisplay->setMinimumWidth(64); pGridLayout->addWidget(m_pDisplay, 0, 2); } else { pGridLayout->addWidget(m_pSlider, 1, 0, 1, 2); int iDecimals = m_pParam->decimals(); m_pSpinBox = new qtractorObserverSpinBox(/*this*/); m_pSpinBox->setMaximumWidth(64); m_pSpinBox->setDecimals(iDecimals); m_pSpinBox->setMinimum(m_pParam->minValue()); m_pSpinBox->setMaximum(m_pParam->maxValue()); m_pSpinBox->setSingleStep(::powf(10.0f, - float(iDecimals))); m_pSpinBox->setAccelerated(true); m_pSpinBox->setSubject(m_pParam->subject()); // m_pSpinBox->setValue(m_pParam->value()); pGridLayout->addWidget(m_pSpinBox, 1, 2); } } if (m_pCheckBox) { QObject::connect(m_pCheckBox, SIGNAL(valueChanged(float)), SLOT(updateValue(float))); } if (m_pSpinBox) { QObject::connect(m_pSpinBox, SIGNAL(valueChanged(float)), SLOT(updateValue(float))); } if (m_pSlider) { QObject::connect(m_pSlider, SIGNAL(valueChanged(float)), SLOT(updateValue(float))); } QFrame::setLayout(pGridLayout); // QFrame::setFrameShape(QFrame::StyledPanel); // QFrame::setFrameShadow(QFrame::Raised); QFrame::setToolTip(m_pParam->name()); } // Refreshner-loader method. void qtractorPluginParamWidget::refresh (void) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorPluginParamWidget[%p]::refresh()", this); #endif if (m_pCheckBox) m_pCheckBox->observer()->update(true); if (m_pSpinBox) m_pSpinBox->observer()->update(true); if (m_pSlider) m_pSlider->observer()->update(true); if (m_pDisplay) m_pDisplay->observer()->update(true); } // Parameter value change slot. void qtractorPluginParamWidget::updateValue ( float fValue ) { m_pParam->updateValue(fValue, true); } // end of qtractorPluginForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioBuffer.h0000644000175000001440000000012312205103645021365 xustar000000000000000027 mtime=1377077157.186997 26 atime=1381134667.36708 30 ctime=1381134667.368080055 qtractor-0.5.11/src/qtractorAudioBuffer.h0000644000175000001440000001732512205103645020664 0ustar00rncbcusers00000000000000// qtractorAudioBuffer.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorAudioBuffer_h #define __qtractorAudioBuffer_h #include "qtractorList.h" #include "qtractorAudioFile.h" #include "qtractorRingBuffer.h" #ifdef CONFIG_LIBSAMPLERATE // libsamplerate API #include #endif #include #include #include // Forward declarations. class qtractorAudioPeak; class qtractorAudioBuffer; class qtractorTimeStretcher; //---------------------------------------------------------------------- // class qtractorAudioBufferThread -- Ring-cache manager thread. // class qtractorAudioBufferThread : public QThread { public: // Constructor. qtractorAudioBufferThread(unsigned int iSyncSize = 8); // Destructor. ~qtractorAudioBufferThread(); // Thread run state accessors. void setRunState(bool bRunState); bool runState() const; // Wake from executive wait condition (RT-safe). void sync(qtractorAudioBuffer *pAudioBuffer = NULL); // Bypass executive wait condition (non RT-safe). void syncExport(); // Conditional resize check. void checkSyncSize(unsigned int iSyncSize); protected: // The main thread executives. void run(); void process(); private: // Instance variables. unsigned int m_iSyncSize; unsigned int m_iSyncMask; qtractorAudioBuffer **m_ppSyncItems; volatile unsigned int m_iSyncRead; volatile unsigned int m_iSyncWrite; // Whether the thread is logically running. volatile bool m_bRunState; // Thread synchronization objects. QMutex m_mutex; QWaitCondition m_cond; }; //---------------------------------------------------------------------- // class qtractorAudioBuffer -- Ring buffer/cache template declaration. // class qtractorAudioBuffer { public: // Constructor. qtractorAudioBuffer( qtractorAudioBufferThread *pSyncThread, unsigned short iChannels, unsigned int iSampleRate); // Default destructor. ~qtractorAudioBuffer(); // Internal file descriptor accessors. qtractorAudioFile *file() const; // File implementation properties. unsigned short channels() const; unsigned long frames() const; unsigned int sampleRate() const; // Operational properties. unsigned int bufferSize() const; // Resample ratio accessor. float resampleRatio() const; // Operational initializer/terminator. bool open(const QString& sFilename, int iMode = qtractorAudioFile::Read); void close(); // Buffer data read/write. int read(float **ppFrames, unsigned int iFrames, unsigned int iOffset = 0); int write(float **ppFrames, unsigned int iFrames, unsigned short iChannels = 0, unsigned int iOffset = 0); // Special kind of super-read/channel-mix. int readMix(float **ppFrames, unsigned int iFrames, unsigned short iChannels, unsigned int iOffset, float fGain); // Buffer data seek. bool seek(unsigned long iFrame); // Reset this buffer's state. void reset(bool bLooping); // Logical clip-offset (in frames from beginning-of-file). void setOffset(unsigned long iOffset); unsigned long offset() const; // Logical clip-length (in frames from clip-start/offset). void setLength(unsigned long iLength); unsigned long length() const; // Current (last known) file length accessor. unsigned long fileLength() const; // Loop points accessors. void setLoop(unsigned long iLoopStart, unsigned long iLoopEnd); unsigned long loopStart() const; unsigned long loopEnd() const; // Time-stretch factor. void setTimeStretch(float fTimeStretch); float timeStretch() const; bool isTimeStretch() const; // Pitch-shift factor. void setPitchShift(float fPitchShift); float pitchShift() const; bool isPitchShift() const; // Sync thread state flags accessors. enum SyncFlag { InitSync = 1, ReadSync = 2, WaitSync = 4, CloseSync = 8 }; void setSyncFlag(SyncFlag flag, bool bOn = true); bool isSyncFlag(SyncFlag flag) const; // Initial thread-sync executive (if file is on read mode, // check whether it can be cache-loaded integrally). void initSync(); // Base sync method. void sync(); // Audio frame process synchronization predicate method. bool inSync(unsigned long iFrameStart, unsigned long iFrameEnd); // Export-mode sync executive. void syncExport(); // Internal peak descriptor accessors. void setPeak(qtractorAudioPeak *pPeak); qtractorAudioPeak *peak() const; // Sample-rate converter type accessor (global option). static void setResampleType(int iResampleType); static int resampleType(); // WSOLA time-stretch modes (global options). static void setWsolaTimeStretch(bool bWsolaTimeStretch); static bool isWsolaTimeStretch(); static void setWsolaQuickSeek(bool bWsolaQuickSeek); static bool isWsolaQuickSeek(); protected: // Read-sync mode methods (playback). void readSync(); // Write-sync mode method (recording). void writeSync(); // Internal-seek sync executive. bool seekSync(unsigned long iFrame); // Last-mile frame buffer-helper processor. int writeFrames(float **ppFrames, unsigned int iFrames); int flushFrames(unsigned int iFrames); // Buffer process methods. int readBuffer (unsigned int iFrames); int writeBuffer (unsigned int iFrames); // Special kind of super-read/channel-mix buffer helper. int readMixFrames(float **ppFrames, unsigned int iFrames, unsigned short iChannels, unsigned int iOffset, float fGain); // I/O buffer release. void deleteIOBuffers(); // Frame position converters. unsigned long framesIn(unsigned long iFrames) const; unsigned long framesOut(unsigned long iFrames) const; private: // Audio buffer instance variables. qtractorAudioBufferThread *m_pSyncThread; unsigned short m_iChannels; unsigned int m_iSampleRate; qtractorAudioFile *m_pFile; qtractorRingBuffer *m_pRingBuffer; unsigned int m_iThreshold; unsigned int m_iBufferSize; volatile unsigned char m_syncFlags; volatile unsigned long m_iReadOffset; volatile unsigned long m_iWriteOffset; unsigned long m_iFileLength; bool m_bIntegral; unsigned long m_iOffset; unsigned long m_iLength; volatile unsigned long m_iLoopStart; volatile unsigned long m_iLoopEnd; unsigned long m_iSeekOffset; qtractorAtomic m_seekPending; float **m_ppFrames; bool m_bTimeStretch; float m_fTimeStretch; bool m_bPitchShift; float m_fPitchShift; qtractorTimeStretcher *m_pTimeStretcher; float m_fNextGain; int m_iRampGain; #ifdef CONFIG_LIBSAMPLERATE bool m_bResample; float m_fResampleRatio; unsigned int m_iInputPending; float **m_ppInBuffer; float **m_ppOutBuffer; SRC_STATE **m_ppSrcState; #endif qtractorAudioPeak *m_pPeak; // Sample-rate converter type global option. static int g_iResampleType; // Time-stretch mode global options. static bool g_bWsolaTimeStretch; static bool g_bWsolaQuickSeek; }; #endif // __qtractorAudioBuffer_h // end of qtractorAudioBuffer.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorObserverWidget.h0000644000175000001440000000012312161335204022124 xustar000000000000000027 mtime=1371912836.382031 26 atime=1381134667.26408 30 ctime=1381134667.264080053 qtractor-0.5.11/src/qtractorObserverWidget.h0000644000175000001440000001147112161335204021417 0ustar00rncbcusers00000000000000// qtractorObserverWidget.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorObserverWidget_h #define __qtractorObserverWidget_h #include "qtractorObserver.h" //---------------------------------------------------------------------- // class qtractorObserverWidget -- Template widget observer/visitor. // #include #include #include template class qtractorObserverWidget : public Widget { public: // Local interface converter. class Interface { public: // Constructor. Interface(qtractorObserverWidget *pWidget) : m_pWidget(pWidget) {} qtractorObserverWidget *widget() const { return m_pWidget; } // Virtual destructor. virtual ~Interface() {} // Pure virtuals. virtual float scaleFromValue(float fValue) const = 0; virtual float valueFromScale(float fScale) const = 0; private: // Members. qtractorObserverWidget *m_pWidget; }; // Local observer. class Observer : public qtractorObserver { public: // Constructor. Observer(qtractorSubject *pSubject, qtractorObserverWidget *pWidget) : qtractorObserver(pSubject), m_pWidget(pWidget) {} // Observer updater. void update(bool bUpdate) { if (bUpdate) m_pWidget->updateValue(value()); } private: // Members. qtractorObserverWidget *m_pWidget; }; // Constructor. qtractorObserverWidget(QWidget *pParent = 0) : Widget(pParent), m_pInterface(NULL), m_observer(NULL, this) {} // Destructor. ~qtractorObserverWidget() { if (m_pInterface) delete m_pInterface; } // Setup. void setSubject(qtractorSubject *pSubject) { m_observer.setSubject(pSubject); } qtractorSubject *subject() const { return m_observer.subject(); } // Observer accessor. Observer *observer() { return &m_observer; } // Interface setup. void setInterface(Interface *pInterface) { if (m_pInterface) delete m_pInterface; m_pInterface = pInterface; } // Interface methods. float scaleFromValue(float fValue) const { return (m_pInterface ? m_pInterface->scaleFromValue(fValue) : fValue); } float valueFromScale(float fScale) const { return (m_pInterface ? m_pInterface->valueFromScale(fScale) : fScale); } protected: // Pure virtual visitor. virtual void updateValue(float fValue) = 0; private: // Members. Interface *m_pInterface; Observer m_observer; }; //---------------------------------------------------------------------- // class qtractorObserverCheckBox -- Concrete widget observer. // class qtractorObserverCheckBox : public qtractorObserverWidget { Q_OBJECT public: // Constructor. qtractorObserverCheckBox(QWidget *pParent = 0); protected: // Visitors overload. void updateValue(float fValue); protected slots: void checkBoxChanged(bool bValue); signals: void valueChanged(float); }; //---------------------------------------------------------------------- // class qtractorObserverSpinBox -- Concrete widget observer. // class qtractorObserverSpinBox : public qtractorObserverWidget { Q_OBJECT public: // Constructor. qtractorObserverSpinBox(QWidget *pParent = 0); protected: // Visitors overload. void updateValue(float fValue); protected slots: void spinBoxChanged(double value); signals: void valueChanged(float); }; //---------------------------------------------------------------------- // class qtractorObserverSlider -- Concrete widget observer. // class qtractorObserverSlider : public qtractorObserverWidget { Q_OBJECT public: // Constructor. qtractorObserverSlider(QWidget *pParent = 0); protected: // Alternate mouse behavior event handlers. void mousePressEvent(QMouseEvent *pMouseEvent); void wheelEvent(QWheelEvent *pWheelEvent); // Visitors overload. void updateValue(float fValue); protected slots: void sliderChanged(int iValue); signals: void valueChanged(float); }; #endif // __qtractorObserverWidget_h // end of qtractorObserverWidget.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditList.cpp0000644000175000001440000000012312156061017022052 xustar000000000000000027 mtime=1371038223.355862 26 atime=1381134666.77208 30 ctime=1381134666.772080045 qtractor-0.5.11/src/qtractorMidiEditList.cpp0000644000175000001440000003140312156061017021342 0ustar00rncbcusers00000000000000// qtractorMidiEditList.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiEditList.h" #include "qtractorMidiEditor.h" #include "qtractorMidiEditView.h" #include #include #include #include #include #include #ifdef CONFIG_GRADIENT #include #endif //---------------------------------------------------------------------------- // qtractorMidiEditList -- MIDI sequence key scale widget. // Constructor. qtractorMidiEditList::qtractorMidiEditList ( qtractorMidiEditor *pEditor, QWidget *pParent ) : qtractorScrollView(pParent) { m_pEditor = pEditor; m_iItemHeight = ItemHeightBase; m_dragState = DragNone; m_iNoteOn = -1; m_iNoteVel = -1; qtractorScrollView::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); qtractorScrollView::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); qtractorScrollView::setFocusPolicy(Qt::NoFocus); // qtractorScrollView::viewport()->setFocusPolicy(Qt::ClickFocus); // qtractorScrollView::viewport()->setFocusProxy(this); // qtractorScrollView::viewport()->setAcceptDrops(true); // qtractorScrollView::setDragAutoScroll(false); qtractorScrollView::setMouseTracking(true); const QFont& font = qtractorScrollView::font(); qtractorScrollView::setFont(QFont(font.family(), font.pointSize() - 2)); // QObject::connect(this, SIGNAL(contentsMoving(int,int)), // this, SLOT(updatePixmap(int,int))); // Trap for help/tool-tips and leave events. qtractorScrollView::viewport()->installEventFilter(this); } // Destructor. qtractorMidiEditList::~qtractorMidiEditList (void) { } // Item height methods. void qtractorMidiEditList::setItemHeight ( unsigned short iItemHeight ) { if (iItemHeight > ItemHeightMax) iItemHeight = ItemHeightMax; else if (iItemHeight < ItemHeightMin) iItemHeight = ItemHeightMin; if (iItemHeight == m_iItemHeight) return; m_iItemHeight = iItemHeight; updateContentsHeight(); } unsigned short qtractorMidiEditList::itemHeight (void) const { return m_iItemHeight; } // Update key-list content height. void qtractorMidiEditList::updateContentsHeight (void) { int iContentsHeight = 128 * m_iItemHeight; qtractorScrollView::resizeContents( qtractorScrollView::contentsWidth(), iContentsHeight); // Force an update on other views too... m_pEditor->editView()->resizeContents( m_pEditor->editView()->contentsWidth(), iContentsHeight); // m_pEditor->editView()->updateContents(); } // Rectangular contents update. void qtractorMidiEditList::updateContents ( const QRect& rect ) { updatePixmap( qtractorScrollView::contentsX(), qtractorScrollView::contentsY()); qtractorScrollView::updateContents(rect); } // Overall contents update. void qtractorMidiEditList::updateContents (void) { updatePixmap( qtractorScrollView::contentsX(), qtractorScrollView::contentsY()); qtractorScrollView::updateContents(); } // Resize event handler. void qtractorMidiEditList::resizeEvent ( QResizeEvent *pResizeEvent ) { qtractorScrollView::resizeEvent(pResizeEvent); updateContents(); } // (Re)create the complete view pixmap. void qtractorMidiEditList::updatePixmap ( int /*cx*/, int cy ) { QWidget *pViewport = qtractorScrollView::viewport(); int w = pViewport->width(); int h = pViewport->height(); if (w < 1 || h < 1) return; const QPalette& pal = qtractorScrollView::palette(); m_pixmap = QPixmap(w, h); m_pixmap.fill(pal.base().color()); QPainter p(&m_pixmap); p.initFrom(this); // Draw horizontal key-lines... p.setPen(pal.midlight().color()); p.setBrush(pal.shadow().color()); int ch = qtractorScrollView::contentsHeight() - cy; float hk = (12.0f * m_iItemHeight) / 7.0f; // Key height. int wk = (w << 1) / 3; // Key width. int q0 = (cy / m_iItemHeight); int n0 = 127 - q0; int y0 = q0 * m_iItemHeight - cy; int n, y, x = w - wk; p.setPen(pal.midlight().color()); #ifdef CONFIG_GRADIENT QLinearGradient litegrad(x, 0, w, 0); litegrad.setColorAt(0.0f, pal.midlight().color()); litegrad.setColorAt(0.1f, pal.base().color()); p.setBrush(litegrad); #else p.setBrush(pal.base().color()); #endif y = y0; n = n0; while (y < h && y < ch) { int k = (n % 12); if (k >= 5) ++k; if ((k % 2) == 0) { float yk = ch - ((n / 12) * 7 + (k / 2) + 1) * hk + 1; p.drawRect(QRectF(x, yk, wk, hk)); if (k == 0) { int y1 = y + m_iItemHeight; p.drawText(2, y1 - 2, tr("C%1").arg((n / 12) - 1)); // p.drawLine(0, y1, x, y1); } } y += m_iItemHeight; --n; } #ifdef CONFIG_GRADIENT QLinearGradient darkgrad(x, 0, x + wk, 0); darkgrad.setColorAt(0.0f, pal.midlight().color()); darkgrad.setColorAt(0.3f, pal.shadow().color()); p.setBrush(darkgrad); #else p.setBrush(pal.shadow().color()); #endif y = y0; n = n0; while (y < h && y < ch) { int k = (n % 12); if (k >= 5) ++k; if (k % 2) p.drawRect(x, y, (wk * 6) / 10, m_iItemHeight); y += m_iItemHeight; --n; } if (y > ch) p.fillRect(0, ch, w, h - ch, pal.dark().color()); } // Draw the time scale. void qtractorMidiEditList::drawContents ( QPainter *pPainter, const QRect& rect ) { pPainter->drawPixmap(rect, m_pixmap, rect); // Are we sticking in some note? if (m_iNoteOn >= 0) { pPainter->fillRect(QRect( contentsToViewport(m_rectNote.topLeft()), m_rectNote.size()), m_iNoteVel > 0 ? QColor(255, 0, 120, 120) : QColor(120, 120, 255, 120)); } } // To have keyline in v-sync with main view. void qtractorMidiEditList::contentsYMovingSlot ( int /*cx*/, int cy ) { if (qtractorScrollView::contentsY() != cy) qtractorScrollView::setContentsPos(qtractorScrollView::contentsX(), cy); } // Piano keyboard handlers. void qtractorMidiEditList::dragNoteOn ( int iNote, int iVelocity ) { // If it ain't changed we won't change it ;) if (iNote == m_iNoteOn && m_iNoteVel >= iVelocity) return; // Were we pending on some sounding note? if (m_iNoteOn >= 0) { // Turn off old note... if (m_iNoteVel > 0) m_pEditor->sendNote(m_iNoteOn, 0); m_iNoteOn = m_iNoteVel = -1; qtractorScrollView::viewport()->update( QRect(contentsToViewport(m_rectNote.topLeft()), m_rectNote.size())); } // Now for the sounding new one... if (iNote >= 0) { // This stands for the keyboard area... QWidget *pViewport = qtractorScrollView::viewport(); int w = pViewport->width(); int wk = (w << 1) / 3; int xk = w - wk; #if 0 float yk, hk; int k = (iNote % 12); if (k >= 5) ++k; if ((k % 2) == 0) { hk = (12.0f * m_iItemHeight) / 7.0f; yk = (128 * m_iItemHeight) - ((iNote / 12) * 7 + (k / 2) + 1) * hk + 2; } else { hk = m_iItemHeight; yk = ((127 - iNote) * hk) + 1; wk = (wk * 6) / 10; } #else int hk = m_iItemHeight; int k = (iNote % 12); if (k >= 5) ++k; if (k % 2) wk = (wk * 6) / 10; int yk = ((127 - iNote) * hk) + 1; #endif // This is the new note on... m_iNoteOn = iNote; m_iNoteVel = iVelocity; m_rectNote.setRect(xk, yk, wk, hk); if (m_iNoteVel > 0) m_pEditor->sendNote(m_iNoteOn, m_iNoteVel); // Otherwise, reset any pending note... qtractorScrollView::viewport()->update( QRect(contentsToViewport(m_rectNote.topLeft()), m_rectNote.size())); } } void qtractorMidiEditList::dragNoteOn ( const QPoint& pos, int iVelocity ) { // Compute new key cordinates... int ch = qtractorScrollView::contentsHeight(); dragNoteOn((ch - pos.y()) / m_iItemHeight, iVelocity); } // Handle item selection/dragging -- mouse button press. void qtractorMidiEditList::mousePressEvent ( QMouseEvent *pMouseEvent ) { // Force null state. m_dragState = DragNone; // Which mouse state? const bool bModifier = (pMouseEvent->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)); // Make sure we'll reset selection... if (!bModifier) m_pEditor->selectAll(m_pEditor->editView(), false); // Direct snap positioning... const QPoint& pos = viewportToContents(pMouseEvent->pos()); switch (pMouseEvent->button()) { case Qt::LeftButton: // Remember what and where we'll be dragging/selecting... m_dragState = DragStart; m_posDrag = pos; // Are we keying in some keyboard? dragNoteOn(pos); break; default: break; } // qtractorScrollView::mousePressEvent(pMouseEvent); } // Handle item selection/dragging -- mouse pointer move. void qtractorMidiEditList::mouseMoveEvent ( QMouseEvent *pMouseEvent ) { // Are we already moving/dragging something? const QPoint& pos = viewportToContents(pMouseEvent->pos()); int x = m_pEditor->editView()->contentsX(); switch (m_dragState) { case DragSelect: // Rubber-band selection... m_rectDrag.setBottom(pos.y()); m_pEditor->editView()->ensureVisible(x, pos.y(), 0, 16); m_pEditor->selectRect(m_pEditor->editView(), m_rectDrag, pMouseEvent->modifiers() & Qt::ControlModifier, false); // Are we keying in some keyboard? dragNoteOn(pos); break; case DragStart: // Rubber-band starting... if ((m_posDrag - pos).manhattanLength() > QApplication::startDragDistance()) { // We'll start dragging alright... int w = m_pEditor->editView()->contentsWidth(); m_rectDrag.setTop(m_posDrag.y()); m_rectDrag.setLeft(0); m_rectDrag.setRight(w); m_rectDrag.setBottom(pos.y()); m_dragState = DragSelect; qtractorScrollView::setCursor(QCursor(Qt::SizeVerCursor)); } // Fall thru... case DragNone: default: // Are we hovering in some keyboard? dragNoteOn(pos, -1); break; } // qtractorScrollView::mouseMoveEvent(pMouseEvent); } // Handle item selection/dragging -- mouse button release. void qtractorMidiEditList::mouseReleaseEvent ( QMouseEvent *pMouseEvent ) { // qtractorScrollView::mouseReleaseEvent(pMouseEvent); // Direct snap positioning... switch (m_dragState) { case DragSelect: // Do the final range selection... m_pEditor->selectRect(m_pEditor->editView(), m_rectDrag, pMouseEvent->modifiers() & Qt::ControlModifier, true); // Keyboard notes are reset later anyway... break; case DragStart: case DragNone: default: break; } // Clean up. resetDragState(); } // Handle zoom with mouse wheel. void qtractorMidiEditList::wheelEvent ( QWheelEvent *pWheelEvent ) { if (pWheelEvent->modifiers() & Qt::ControlModifier) { int delta = pWheelEvent->delta(); if (delta > 0) m_pEditor->zoomIn(); else m_pEditor->zoomOut(); } else qtractorScrollView::wheelEvent(pWheelEvent); } // Keyboard event handler. void qtractorMidiEditList::keyPressEvent ( QKeyEvent *pKeyEvent ) { if (pKeyEvent->key() == Qt::Key_Escape) resetDragState(); if (!m_pEditor->keyPress(this, pKeyEvent->key(), pKeyEvent->modifiers())) qtractorScrollView::keyPressEvent(pKeyEvent); } // Reset drag/select/move state. void qtractorMidiEditList::resetDragState (void) { // Were we stuck on some keyboard note? dragNoteOn(-1); // Cancel any dragging out there... switch (m_dragState) { case DragSelect: qtractorScrollView::updateContents(); // Fall thru... qtractorScrollView::unsetCursor(); // Fall thru again... case DragNone: default: break; } // Also get rid of any meta-breadcrumbs... m_pEditor->resetDragState(this); // Force null state. m_dragState = DragNone; // HACK: give focus to track-view... m_pEditor->editView()->setFocus(); } // Trap for help/tool-tip events. bool qtractorMidiEditList::eventFilter ( QObject *pObject, QEvent *pEvent ) { if (static_cast (pObject) == qtractorScrollView::viewport()) { if (pEvent->type() == QEvent::ToolTip) { QHelpEvent *pHelpEvent = static_cast (pEvent); if (pHelpEvent) { const QPoint& pos = qtractorScrollView::viewportToContents(pHelpEvent->pos()); const QString sToolTip("%1 (%2)"); int ch = qtractorScrollView::contentsHeight(); int note = (ch - pos.y()) / m_iItemHeight; QToolTip::showText(pHelpEvent->globalPos(), sToolTip.arg(m_pEditor->noteName(note)).arg(note)); return true; } } else if (pEvent->type() == QEvent::Leave) { dragNoteOn(-1); return true; } } // Not handled here. return qtractorScrollView::eventFilter(pObject, pEvent); } // end of qtractorMidiEditList.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTrackCommand.cpp0000644000175000001440000000012312221411230022056 xustar000000000000000027 mtime=1380323992.023236 26 atime=1381134671.19908 30 ctime=1381134671.199080115 qtractor-0.5.11/src/qtractorTrackCommand.cpp0000644000175000001440000006344512221411230021361 0ustar00rncbcusers00000000000000// qtractorTrackCommand.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorTrackCommand.h" #include "qtractorClipCommand.h" #include "qtractorMainForm.h" #include "qtractorTracks.h" #include "qtractorTrackList.h" #include "qtractorMidiEngine.h" #include "qtractorMidiControl.h" #include "qtractorMidiClip.h" #include "qtractorMixer.h" //---------------------------------------------------------------------- // class qtractorTrackCommand - implementation // // Constructor. qtractorTrackCommand::qtractorTrackCommand ( const QString& sName, qtractorTrack *pTrack ) : qtractorCommand(sName), m_pTrack(pTrack) { setClearSelect(true); } // Destructor. qtractorTrackCommand::~qtractorTrackCommand (void) { if (isAutoDelete()) delete m_pTrack; } // Track command methods. bool qtractorTrackCommand::addTrack ( qtractorTrack *pAfterTrack ) { #ifdef CONFIG_DEBUG qDebug("qtractorTrackCommand::addTrack(%p, %p)", m_pTrack, pAfterTrack); #endif if (m_pTrack == NULL) return false; qtractorSession *pSession = m_pTrack->session(); if (pSession == NULL) return false; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return false; qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks == NULL) return false; // Guess which item we're adding after... if (pAfterTrack == NULL) pAfterTrack = m_pTrack->prev(); if (pAfterTrack == NULL) pAfterTrack = pSession->tracks().last(); int iTrack = pSession->tracks().find(pAfterTrack) + 1; // Link the track into session... pSession->insertTrack(m_pTrack, pAfterTrack); // And the new track list view item too... qtractorTrackList *pTrackList = pTracks->trackList(); iTrack = pTrackList->insertTrack(iTrack, m_pTrack); // Special MIDI track cases... if (m_pTrack->trackType() == qtractorTrack::Midi) pTracks->updateMidiTrack(m_pTrack); // (Re)open all clips... qtractorClip *pClip = m_pTrack->clips().first(); for ( ; pClip; pClip = pClip->next()) pClip->open(); // Mixer turn... qtractorMixer *pMixer = pMainForm->mixer(); if (pMixer) pMixer->updateTracks(true); // Let the change get visible. pTrackList->setCurrentTrackRow(iTrack); // ATTN: MIDI controller map feedback. qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl) pMidiControl->sendAllControllers(iTrack); // Avoid disposal of the track reference. setAutoDelete(false); return true; } bool qtractorTrackCommand::removeTrack (void) { #ifdef CONFIG_DEBUG qDebug("qtractorTrackCommand::removeTrack(%p)", m_pTrack); #endif if (m_pTrack == NULL) return false; qtractorSession *pSession = m_pTrack->session(); if (pSession == NULL) return false; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return false; qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks == NULL) return false; // Get the list view item reference of the intended track... int iTrack = pSession->tracks().find(m_pTrack); if (iTrack < 0) return false; // Close all clips... qtractorClip *pClip = m_pTrack->clips().last(); for ( ; pClip; pClip = pClip->prev()) pClip->close(); // Second, remove from session... pSession->unlinkTrack(m_pTrack); // Third, remove track from list view... qtractorTrackList *pTrackList = pTracks->trackList(); iTrack = pTrackList->removeTrack(iTrack); if (iTrack >= 0) pTrackList->setCurrentTrackRow(iTrack); // Mixer turn... qtractorMixer *pMixer = pMainForm->mixer(); if (pMixer) pMixer->updateTracks(); // ATTN: MIDI controller map feedback. qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl) pMidiControl->sendAllControllers(iTrack); // Make ths track reference disposable. setAutoDelete(true); return true; } //---------------------------------------------------------------------- // class qtractorAddTrackCommand - implementation // // Constructor. qtractorAddTrackCommand::qtractorAddTrackCommand ( qtractorTrack *pTrack, qtractorTrack *pAfterTrack ) : qtractorTrackCommand(QObject::tr("add track"), pTrack), m_pAfterTrack(pAfterTrack) { } // Track insertion command methods. bool qtractorAddTrackCommand::redo (void) { return addTrack(m_pAfterTrack); } bool qtractorAddTrackCommand::undo (void) { return removeTrack(); } //---------------------------------------------------------------------- // class qtractorRemoveTrackCommand - implementation // // Constructor. qtractorRemoveTrackCommand::qtractorRemoveTrackCommand ( qtractorTrack *pTrack ) : qtractorTrackCommand(QObject::tr("remove track"), pTrack) { } // Track-removal command methods. bool qtractorRemoveTrackCommand::redo (void) { return removeTrack(); } bool qtractorRemoveTrackCommand::undo (void) { return addTrack(); } //---------------------------------------------------------------------- // class qtractorMoveTrackCommand - implementation // // Constructor. qtractorMoveTrackCommand::qtractorMoveTrackCommand ( qtractorTrack *pTrack, qtractorTrack *pNextTrack ) : qtractorTrackCommand(QObject::tr("move track"), pTrack) { m_pNextTrack = pNextTrack; } // Track-move command methods. bool qtractorMoveTrackCommand::redo (void) { qtractorTrack *pTrack = track(); if (pTrack == NULL) return false; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return false; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return false; qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks == NULL) return false; int iTrack = pSession->tracks().find(pTrack); if (iTrack < 0) return false; // Save the next track alright... qtractorTrack *pNextTrack = pTrack->next(); // Remove and insert back again... qtractorTrackList *pTrackList = pTracks->trackList(); pTrackList->removeTrack(iTrack); // Get actual index of new position... int iNextTrack = pTrackList->trackRow(m_pNextTrack); // Make it all set back. pSession->moveTrack(pTrack, m_pNextTrack); // Just insert under the track list position... // We'll renumber all items now... iNextTrack = pTrackList->insertTrack(iNextTrack, pTrack); if (iNextTrack >= 0) pTrackList->setCurrentTrackRow(iNextTrack); // Swap it nice, finally. m_pNextTrack = pNextTrack; // Mixer turn... qtractorMixer *pMixer = pMainForm->mixer(); if (pMixer) pMixer->updateTracks(true); // ATTN: MIDI controller map feedback. qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl) { if (iTrack > iNextTrack) iTrack = iNextTrack; pMidiControl->sendAllControllers(iTrack); } return true; } bool qtractorMoveTrackCommand::undo (void) { // As we swap the prev/track this is non-idempotent. return redo(); } //---------------------------------------------------------------------- // class qtractorResizeTrackCommand - implementation // // Constructor. qtractorResizeTrackCommand::qtractorResizeTrackCommand ( qtractorTrack *pTrack, int iZoomHeight ) : qtractorTrackCommand(QObject::tr("resize track"), pTrack) { m_iZoomHeight = iZoomHeight; } // Track-resize command methods. bool qtractorResizeTrackCommand::redo (void) { // Save the previous item height alright... int iZoomHeight = track()->zoomHeight(); // Just set new one... track()->setZoomHeight(m_iZoomHeight); // Swap it nice, finally. m_iZoomHeight = iZoomHeight; return true; } bool qtractorResizeTrackCommand::undo (void) { // As we swap the prev/track this is non-identpotent. return redo(); } //---------------------------------------------------------------------- // class qtractorImportTrackCommand - implementation // // Constructor. qtractorImportTrackCommand::qtractorImportTrackCommand ( qtractorTrack *pAfterTrack ) : qtractorCommand(QObject::tr("import track")), m_pAfterTrack(pAfterTrack) { // Session properties backup preparation. m_iSaveCount = 0; m_pSaveCommand = NULL; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { m_sessionProps = pSession->properties(); m_pSaveCommand = new qtractorPropertyCommand (name(), pSession->properties(), m_sessionProps); } setClearSelect(true); } // Destructor. qtractorImportTrackCommand::~qtractorImportTrackCommand (void) { if (m_pSaveCommand) delete m_pSaveCommand; qDeleteAll(m_trackCommands); m_trackCommands.clear(); } // Track-import list methods. void qtractorImportTrackCommand::addTrack ( qtractorTrack *pTrack ) { m_trackCommands.append( new qtractorAddTrackCommand(pTrack, m_pAfterTrack)); m_pAfterTrack = pTrack; } // Track-import command methods. bool qtractorImportTrackCommand::redo (void) { bool bResult = true; if (m_pSaveCommand && m_iSaveCount > 0) { if (!m_pSaveCommand->redo()) bResult = false; } ++m_iSaveCount; QListIterator iter(m_trackCommands); while (iter.hasNext()) { qtractorAddTrackCommand *pTrackCommand = iter.next(); if (!pTrackCommand->redo()) bResult = false; } return bResult; } bool qtractorImportTrackCommand::undo (void) { bool bResult = true; QListIterator iter(m_trackCommands); iter.toBack(); while (iter.hasPrevious()) { qtractorAddTrackCommand *pTrackCommand = iter.previous(); if (!pTrackCommand->undo()) bResult = false; } if (m_pSaveCommand && !m_pSaveCommand->undo()) bResult = false; return bResult; } //---------------------------------------------------------------------- // class qtractorEditTrackCommand - implementation // // Constructor. qtractorEditTrackCommand::qtractorEditTrackCommand ( qtractorTrack *pTrack, const qtractorTrack::Properties& props ) : qtractorPropertyCommand ( QObject::tr("track properties"), pTrack->properties(), props) { m_pTrack = pTrack; } // Overridden track-edit command methods. bool qtractorEditTrackCommand::redo (void) { if (m_pTrack == NULL) return false; qtractorSession *pSession = m_pTrack->session(); if (pSession == NULL) return false; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return false; // Howdy, maybe we're already have a name on recording... bool bRecord = m_pTrack->isRecord(); if (bRecord) pSession->trackRecord(m_pTrack, false, 0, 0); // Trap dirty clips (only MIDI at this time...) if (m_pTrack->trackType() == qtractorTrack::Midi) { for (qtractorClip *pClip = m_pTrack->clips().first(); pClip; pClip = pClip->next()) { // Are any dirty changes pending commit? if (pClip->isDirty()) { qtractorMidiClip *pMidiClip = static_cast (pClip); if (pMidiClip) pMidiClip->saveCopyFile(); } } } // Make the track property change... bool bResult = qtractorPropertyCommand::redo(); // Reopen to assign a probable new bus... if (bResult) bResult = m_pTrack->open(); if (!bResult) { pMainForm->appendMessagesError( QObject::tr("Track assignment failed:\n\n" "Track: \"%1\" Input: \"%2\" Output: \"%3\"") .arg(m_pTrack->trackName()) .arg(m_pTrack->inputBusName()) .arg(m_pTrack->outputBusName())); } else // Reassign recording... if (bRecord) { unsigned long iClipStart = pSession->playHead(); if (pSession->isPunching()) { unsigned long iPunchIn = pSession->punchIn(); if (iClipStart < iPunchIn) iClipStart = iPunchIn; } unsigned long iFrameTime = pSession->frameTimeEx(); pSession->trackRecord(m_pTrack, true, iClipStart, iFrameTime); } // Refresh track item, at least the names... m_pTrack->updateTracks(); // Special MIDI track cases... if (m_pTrack->trackType() == qtractorTrack::Midi) { // Re-open all MIDI clips (channel might have changed?)... qtractorClip *pClip = m_pTrack->clips().first(); for ( ; pClip; pClip = pClip->next()) pClip->open(); } // Finally update any outstanding clip editors... m_pTrack->updateClipEditors(); return bResult; } bool qtractorEditTrackCommand::undo (void) { return redo(); } //---------------------------------------------------------------------- // class qtractorTrackControlCommand - implementation. // // Constructor. qtractorTrackControlCommand::qtractorTrackControlCommand ( const QString& sName, qtractorTrack *pTrack, bool bMidiControl ) : qtractorTrackCommand(sName, pTrack), m_bMidiControl(bMidiControl), m_iMidiControlFeedback(0) { } // Primitive control predicate. bool qtractorTrackControlCommand::midiControlFeedback (void) { return (m_bMidiControl ? (++m_iMidiControlFeedback > 1) : true); } //---------------------------------------------------------------------- // class qtractorTrackStateCommand - implementation. // // Constructor. qtractorTrackStateCommand::qtractorTrackStateCommand ( qtractorTrack *pTrack, qtractorTrack::ToolType toolType, bool bOn, bool bMidiControl ) : qtractorTrackControlCommand(QString(), pTrack, bMidiControl) { m_toolType = toolType; m_bOn = bOn; m_pClipCommand = NULL; m_iRecordCount = 0; switch (m_toolType) { case qtractorTrack::Record: qtractorTrackCommand::setName(QObject::tr("track record")); break; case qtractorTrack::Mute: qtractorTrackCommand::setName(QObject::tr("track mute")); break; case qtractorTrack::Solo: qtractorTrackCommand::setName(QObject::tr("track solo")); break; } // Toggle/update all other? Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers(); if (m_toolType != qtractorTrack::Record && (modifiers & (Qt::ShiftModifier | Qt::ControlModifier))) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { if (modifiers & Qt::ControlModifier) bOn = !bOn; for (qtractorTrack *pTrackEx = pSession->tracks().first(); pTrackEx; pTrackEx = pTrackEx->next()) { if (pTrackEx != track()) m_tracks.append(new TrackItem(pTrackEx, bOn)); } } } setRefresh(m_toolType != qtractorTrack::Record); } // Destructor. qtractorTrackStateCommand::~qtractorTrackStateCommand (void) { if (m_pClipCommand) delete m_pClipCommand; qDeleteAll(m_tracks); } // Track-button command method. bool qtractorTrackStateCommand::redo (void) { qtractorTrack *pTrack = track(); if (pTrack == NULL) return false; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return false; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return false; bool bOn = false; qtractorMmcEvent::SubCommand scmd = qtractorMmcEvent::TRACK_NONE; qtractorMidiControl::Command ccmd = qtractorMidiControl::Command(0); switch (m_toolType) { case qtractorTrack::Record: scmd = qtractorMmcEvent::TRACK_RECORD; ccmd = qtractorMidiControl::TRACK_RECORD; // Special stuffing if currently recording at first place... bOn = pTrack->isRecord(); if (bOn && !m_bOn && m_pClipCommand == NULL && m_iRecordCount == 0) { m_pClipCommand = new qtractorClipCommand(QString()); // Do all the record stuffing here... unsigned long iFrameTime = pSession->frameTimeEx(); if (m_pClipCommand->addClipRecord(pTrack, iFrameTime)) { // Yes, we've recorded something... setRefresh(true); } else { // nothing was actually recorded... delete m_pClipCommand; m_pClipCommand = NULL; } } // Was it before (skip undos)? if (m_pClipCommand && (m_iRecordCount % 2) == 0) m_pClipCommand->redo(); ++m_iRecordCount; // Carry on... pTrack->setRecord(m_bOn); break; case qtractorTrack::Mute: scmd = qtractorMmcEvent::TRACK_MUTE; ccmd = qtractorMidiControl::TRACK_MUTE; bOn = pTrack->isMute(); pTrack->setMute(m_bOn); break; case qtractorTrack::Solo: scmd = qtractorMmcEvent::TRACK_SOLO; ccmd = qtractorMidiControl::TRACK_SOLO; bOn = pTrack->isSolo(); pTrack->setSolo(m_bOn); break; default: // Whaa? return false; } // Send MMC MASKED_WRITE command... qtractorMidiEngine *pMidiEngine = pSession->midiEngine(); int iTrack = pSession->tracks().find(pTrack); if (pMidiEngine) pMidiEngine->sendMmcMaskedWrite(scmd, iTrack, m_bOn); // Send MIDI controller command... if (midiControlFeedback()) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl) pMidiControl->processTrackCommand(ccmd, iTrack, m_bOn); } // Update track list item... qtractorTrackList *pTrackList = pMainForm->tracks()->trackList(); pTrackList->updateTrack(pTrack); // Reset for undo. m_bOn = bOn; // Toggle/update all other? if (!m_tracks.isEmpty()) { // Exclusive mode. qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); QListIterator iter(m_tracks); while (iter.hasNext()) { TrackItem *pTrackItem = iter.next(); pTrack = pTrackItem->track; bOn = false; if (m_toolType == qtractorTrack::Mute) { bOn = pTrack->isMute(); pTrack->setMute(pTrackItem->on); } else if (m_toolType == qtractorTrack::Solo) { bOn = pTrack->isSolo(); pTrack->setSolo(pTrackItem->on); } // Send MMC MASKED_WRITE command... int iTrack = pTrackList->trackRow(pTrack); if (pMidiEngine) pMidiEngine->sendMmcMaskedWrite(scmd, iTrack, pTrackItem->on); // Send MIDI controller command... if (pMidiControl) pMidiControl->processTrackCommand(ccmd, iTrack, pTrackItem->on); // Update track list item... pTrackList->updateTrack(pTrack); // Swap for undo... pTrackItem->on = bOn; } // Done with exclusive mode. } return true; } bool qtractorTrackStateCommand::undo (void) { if (m_pClipCommand) m_pClipCommand->undo(); return redo(); } //---------------------------------------------------------------------- // class qtractorTrackMonitorCommand - implementation. // // Constructor. qtractorTrackMonitorCommand::qtractorTrackMonitorCommand ( qtractorTrack *pTrack, bool bMonitor, bool bMidiControl ) : qtractorTrackControlCommand( QObject::tr("track monitor"), pTrack, bMidiControl) { m_bMonitor = bMonitor; // Toggle/update all other? Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers(); if (modifiers & (Qt::ShiftModifier | Qt::ControlModifier)) { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { if (modifiers & Qt::ControlModifier) bMonitor = !bMonitor; for (qtractorTrack *pTrackEx = pSession->tracks().first(); pTrackEx; pTrackEx = pTrackEx->next()) { if (pTrackEx != pTrack) m_tracks.append(new TrackItem(pTrackEx, bMonitor)); } } } setRefresh(false); } // Destructor. qtractorTrackMonitorCommand::~qtractorTrackMonitorCommand (void) { qDeleteAll(m_tracks); } // Track-monitor command method. bool qtractorTrackMonitorCommand::redo (void) { qtractorTrack *pTrack = track(); if (pTrack == NULL) return false; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return false; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return false; // Save undo value... bool bMonitor = pTrack->isMonitor(); // Set track monitoring... pTrack->setMonitor(m_bMonitor); // Send MIDI controller command(s)... if (midiControlFeedback()) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl) { int iTrack = pSession->tracks().find(pTrack); pMidiControl->processTrackCommand( qtractorMidiControl::TRACK_MONITOR, iTrack, m_bMonitor); } } // Set undo value... m_bMonitor = bMonitor; // Toggle/update all other? if (!m_tracks.isEmpty()) { // Exclusive mode. qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); QListIterator iter(m_tracks); while (iter.hasNext()) { TrackItem *pTrackItem = iter.next(); pTrack = pTrackItem->track; bMonitor = pTrack->isMonitor(); pTrack->setMonitor(pTrackItem->on); // Send MIDI controller command... if (pMidiControl) { int iTrack = pSession->tracks().find(pTrack); pMidiControl->processTrackCommand( qtractorMidiControl::TRACK_MONITOR, iTrack, pTrackItem->on); } // Swap for undo... pTrackItem->on = bMonitor; } // Done with exclusive mode. } return true; } //---------------------------------------------------------------------- // class qtractorTrackGainCommand - implementation. // // Constructor. qtractorTrackGainCommand::qtractorTrackGainCommand ( qtractorTrack *pTrack, float fGain, bool bMidiControl ) : qtractorTrackControlCommand( QObject::tr("track gain"), pTrack, bMidiControl) { m_fGain = fGain; m_fPrevGain = pTrack->prevGain(); setRefresh(false); // Try replacing an previously equivalent command... static qtractorTrackGainCommand *s_pPrevGainCommand = NULL; if (s_pPrevGainCommand) { qtractorSession *pSession = qtractorSession::getInstance(); qtractorCommand *pLastCommand = (pSession->commands())->lastCommand(); qtractorCommand *pPrevCommand = static_cast (s_pPrevGainCommand); if (pPrevCommand == pLastCommand && s_pPrevGainCommand->track() == pTrack) { qtractorTrackGainCommand *pLastGainCommand = static_cast (pLastCommand); if (pLastGainCommand) { // Equivalence means same (sign) direction too... float fPrevGain = pLastGainCommand->prevGain(); float fLastGain = pLastGainCommand->gain(); int iPrevSign = (fPrevGain > fLastGain ? +1 : -1); int iCurrSign = (fPrevGain < m_fGain ? +1 : -1); if (iPrevSign == iCurrSign || m_fGain == m_fPrevGain) { m_fPrevGain = fLastGain; (pSession->commands())->removeLastCommand(); } } } } s_pPrevGainCommand = this; } // Track-gain command method. bool qtractorTrackGainCommand::redo (void) { qtractorTrack *pTrack = track(); if (pTrack == NULL) return false; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return false; // Set undo value... float fGain = m_fPrevGain; // Set track gain (respective monitor gets set too...) pTrack->setGain(m_fGain); #if 0 // MIDI tracks are special... if (pTrack->trackType() == qtractorTrack::Midi) { // Gotta make sure we've a proper MIDI bus... qtractorMidiBus *pMidiBus = static_cast (pTrack->outputBus()); if (pMidiBus) pMidiBus->setVolume(pTrack, m_fGain); } #endif // Send MIDI controller command(s)... if (midiControlFeedback()) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl) { int iTrack = pSession->tracks().find(pTrack); pMidiControl->processTrackCommand( qtractorMidiControl::TRACK_GAIN, iTrack, m_fGain, pTrack->trackType() == qtractorTrack::Audio); } } // Set undo value... m_fPrevGain = m_fGain; m_fGain = fGain; return true; } //---------------------------------------------------------------------- // class qtractorTrackPanningCommand - implementation. // // Constructor. qtractorTrackPanningCommand::qtractorTrackPanningCommand ( qtractorTrack *pTrack, float fPanning, bool bMidiControl ) : qtractorTrackControlCommand( QObject::tr("track pan"), pTrack, bMidiControl) { m_fPanning = fPanning; m_fPrevPanning = pTrack->prevPanning(); setRefresh(false); // Try replacing an previously equivalent command... static qtractorTrackPanningCommand *s_pPrevPanningCommand = NULL; if (s_pPrevPanningCommand) { qtractorSession *pSession = qtractorSession::getInstance(); qtractorCommand *pLastCommand = (pSession->commands())->lastCommand(); qtractorCommand *pPrevCommand = static_cast (s_pPrevPanningCommand); if (pPrevCommand == pLastCommand && s_pPrevPanningCommand->track() == pTrack) { qtractorTrackPanningCommand *pLastPanningCommand = static_cast (pLastCommand); if (pLastPanningCommand) { // Equivalence means same (sign) direction too... float fPrevPanning = pLastPanningCommand->prevPanning(); float fLastPanning = pLastPanningCommand->panning(); int iPrevSign = (fPrevPanning > fLastPanning ? +1 : -1); int iCurrSign = (fPrevPanning < m_fPanning ? +1 : -1); if (iPrevSign == iCurrSign || m_fPanning == m_fPrevPanning) { m_fPrevPanning = fLastPanning; (pSession->commands())->removeLastCommand(); } } } } s_pPrevPanningCommand = this; } // Track-panning command method. bool qtractorTrackPanningCommand::redo (void) { qtractorTrack *pTrack = track(); if (pTrack == NULL) return false; qtractorSession *pSession = pTrack->session(); if (pSession == NULL) return false; // Set undo value... float fPanning = m_fPrevPanning; // Set track panning (respective monitor gets set too...) pTrack->setPanning(m_fPanning); // MIDI tracks are special... if (pTrack->trackType() == qtractorTrack::Midi) { // Gotta make sure we've a proper MIDI bus... qtractorMidiBus *pMidiBus = static_cast (pTrack->outputBus()); if (pMidiBus) pMidiBus->setPanning(pTrack, m_fPanning); } // Send MIDI controller command(s)... if (midiControlFeedback()) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl) { int iTrack = pSession->tracks().find(pTrack); pMidiControl->processTrackCommand( qtractorMidiControl::TRACK_PANNING, iTrack, m_fPanning); } } // Set undo value... m_fPrevPanning = m_fPanning; m_fPanning = fPanning; return true; } // end of qtractorTrackCommand.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorClipForm.ui0000644000175000001440000000012212165325675021110 xustar000000000000000027 mtime=1372957629.743777 26 atime=1381134668.98708 29 ctime=1381134668.98708008 qtractor-0.5.11/src/qtractorClipForm.ui0000644000175000001440000003674512165325675020417 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorClipForm 0 0 420 480 Qt::StrongFocus Clip - Qtractor :/images/editClip.png &Name: ClipNameLineEdit Clip name &File: FilenameComboBox Clip filename true 22 22 22 22 Qt::TabFocus Browse for clip file :/images/fileOpen.png Track/&Channel: TrackChannelSpinBox 40 0 Clip track/channel Qt::Horizontal 20 8 Parameters Qt::Horizontal 20 8 120 0 Clip start 120 0 Clip offset 120 0 Clip length 60 0 Offs&et: ClipOffsetSpinBox 60 0 &Length: ClipLengthSpinBox 60 0 &Start: ClipStartSpinBox Gain/Volume 72 0 Clip gain/volume 1 0.1 Format Time display format Frames Time BBT Fade In/Out 60 0 Fade &In: FadeInLengthSpinBox 120 0 Clip fade-in length Clip fade-in type Qt::Horizontal 20 8 60 0 Fade &Out: FadeOutLengthSpinBox 120 0 Clip fade-out length Clip fade-out type Audio Qt::Horizontal 20 8 60 0 Time St&retch: TimeStretchSpinBox 66 0 Clip time-stretch percentage % 1 1.0 400.0 100.0 Pitch S&hift: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter PitchShiftSpinBox 66 0 Clip pitch-shift in semitones semitones 1 -24.0 24.0 0.0 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qtractorTimeSpinBox QSpinBox
qtractorSpinBox.h
ClipNameLineEdit FilenameComboBox FilenameToolButton ClipGainSpinBox TrackChannelSpinBox ClipStartSpinBox ClipOffsetSpinBox ClipLengthSpinBox FormatComboBox FadeInLengthSpinBox FadeInTypeComboBox FadeOutLengthSpinBox FadeOutTypeComboBox PitchShiftSpinBox TimeStretchSpinBox DialogButtonBox
qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioPeak.h0000644000175000001440000000012312100727353021036 xustar000000000000000027 mtime=1359195883.616032 26 atime=1381134666.88208 30 ctime=1381134666.882080047 qtractor-0.5.11/src/qtractorAudioPeak.h0000644000175000001440000001360312100727353020330 0ustar00rncbcusers00000000000000// qtractorAudioPeak.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorAudioPeak_h #define __qtractorAudioPeak_h #include #include #include #include // Forward declarations. class qtractorAudioPeakThread; //---------------------------------------------------------------------- // class qtractorAudioPeakFile -- Audio peak file (ref'counted) // class qtractorAudioPeakFile { public: // Constructor. qtractorAudioPeakFile(const QString& sFilename, float fTimeStretch); // Default destructor. ~qtractorAudioPeakFile(); // Audio properties accessors. const QString& filename() const; float timeStretch() const; // Peak cache properties accessors. QString name() const; unsigned short period(); unsigned short channels(); // Audio peak file header. struct Header { unsigned short period; unsigned short channels; }; // Audio peak file frame record. struct Frame { unsigned char max; unsigned char min; unsigned char rms; }; // Peak cache file methods. bool openRead(); Frame *read(unsigned long iPeakOffset, unsigned int iPeakFrames); void closeRead(); // Write peak from audio frame methods. bool openWrite(unsigned short iChannels, unsigned int iSampleRate); void write(float **ppAudioFrames, unsigned int iAudioFrames); void closeWrite(); // Auto-delete property. //bool isAutoRemove() const; // Reference count methods. void addRef(); void removeRef(); // Sync thread state flags accessors. void setWaitSync(bool bWaitSync); bool isWaitSync() const; protected: // Internal creational methods. void writeFrame(); // Read frames from peak file into local buffer cache. unsigned int readBuffer(unsigned int iBuffOffset, unsigned long iPeakOffset, unsigned int iPeakFrames); private: // Instance variables. QString m_sFilename; float m_fTimeStretch; QFile m_peakFile; enum { None = 0, Read = 1, Write = 2 } m_openMode; Header m_peakHeader; Frame *m_pBuffer; unsigned int m_iBuffSize; unsigned int m_iBuffLength; unsigned long m_iBuffOffset; unsigned long m_iWriteOffset; float *m_peakMax; float *m_peakMin; float *m_peakRms; unsigned short m_iPeakPeriod; unsigned short m_iPeak; QMutex m_mutex; volatile bool m_bWaitSync; // Current reference count. unsigned int m_iRefCount; }; //---------------------------------------------------------------------- // class qtractorAudioPeak -- Audio Peak file pseudo-cache. // class qtractorAudioPeak { public: // Constructor. qtractorAudioPeak(qtractorAudioPeakFile *pPeakFile) { m_pPeakFile = pPeakFile; m_pPeakFile->addRef(); } // Copy consructor. qtractorAudioPeak(const qtractorAudioPeak& peak) { m_pPeakFile = peak.m_pPeakFile; m_pPeakFile->addRef(); } // Default destructor. ~qtractorAudioPeak() { m_pPeakFile->removeRef(); } // Reference accessor. qtractorAudioPeakFile *peakFile() const { return m_pPeakFile; } // Peak file accessors. const QString& filename() const { return m_pPeakFile->filename(); } // Peak cache properties. unsigned short period() const { return m_pPeakFile->period(); } unsigned short channels() const { return m_pPeakFile->channels(); } // Peak cache file methods. bool openRead() { return m_pPeakFile->openRead(); } qtractorAudioPeakFile::Frame *read( unsigned long iPeakOffset, unsigned int iPeakFrames) { return m_pPeakFile->read(iPeakOffset, iPeakFrames); } void closeRead() { m_pPeakFile->closeRead(); } // Write peak from audio frame methods. bool openWrite(unsigned short iChannels, unsigned int iSampleRate) { return m_pPeakFile->openWrite(iChannels, iSampleRate); } void write(float **ppAudioFrames, unsigned int iAudioFrames) { m_pPeakFile->write(ppAudioFrames, iAudioFrames); } void closeWrite() { m_pPeakFile->closeWrite(); } private: // Instance variable (ref'counted). qtractorAudioPeakFile *m_pPeakFile; }; //---------------------------------------------------------------------- // class qtractorAudioPeakFactory -- Audio peak file factory (singleton). // class qtractorAudioPeakFactory : public QObject { Q_OBJECT public: // Constructor. qtractorAudioPeakFactory(QObject *pParent = NULL); // Default destructor. ~qtractorAudioPeakFactory(); // The peak file factory-method. qtractorAudioPeak *createPeak(const QString& sFilename, float fTimeStretch); void removePeak(qtractorAudioPeakFile *pPeakFile); // Auto-delete property. void setAutoRemove(bool bAutoRemove); bool isAutoRemove() const; // Peak ready event notification. void notifyPeakEvent(); // Base sync method. void sync(qtractorAudioPeakFile *pPeakFile = NULL); signals: // Peak ready signal. void peakEvent(); private: // Factory mutex. QMutex m_mutex; // The list of managed peak files. QHash m_peaks; // Auto-delete property. bool m_bAutoRemove; // The peak file creation detached thread. qtractorAudioPeakThread *m_pPeakThread; }; #endif // __qtractorAudioPeak_h // end of qtractorAudioPeak.h qtractor-0.5.11/src/PaxHeaders.10084/images0000644000175000001440000000013212224470514016434 xustar000000000000000030 mtime=1381134668.916080079 30 atime=1381134668.175080067 30 ctime=1381134668.916080079 qtractor-0.5.11/src/images/0000755000175000001440000000000012224470514016000 5ustar00rncbcusers00000000000000qtractor-0.5.11/src/images/PaxHeaders.10084/editModeDraw.png0000644000175000001440000000012311374221375021573 xustar000000000000000027 mtime=1274094333.783476 26 atime=1381134668.91408 30 ctime=1381134668.914080079 qtractor-0.5.11/src/images/editModeDraw.png0000644000175000001440000000175511374221375021072 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®Îé§IDAT8ËÅ”MlÛdÇÿ¶c;NÒ&ëÇÚ5k¥¬”1ÄG:M* !NÀeŽÀÞhÝ b‡uœvAšú²‰ Ø$˜ªŠ!11è>`¢M´nkËÆÚ*]Ú®©Û4i>êØ¯ýrH3²5Ùʉçb[¶~ïï}ü^5ê@ÿØ´Ã/}óéñé:ØÅïc(ÇJª|u¸ðÚ;xóÙg[òkëM3÷›‚YÇL[Ð|ªÖss öD°«*Æo/vœùü×Þù™åfÑJqΦÁîy|øÏå*Cï¥ö ž¸òþå¡=Š[>àºÇ§NÛÌÎ5¶úÙØÕ©M­ „<¸§” ÕŒ›F.þõÆ•oí³Š,SÈ/™†5À(OLU•âápb1€^ /ƒº€gÉíQ’Œ9ºiX³5³SÎ9‰üÛkJéCˆWGuËEͫت&·möªÚ¡6€ˆµ G8L P BÈæTþ£–ϯ¥˜e»V×v­Ì—U·¼;jRƒoú:Ÿ{˧/t*ÌÉ–¡” ‡KÖ„PJ#¨ˆ‹PµdbuÛ…3£Ý“Ñxo*¹öüÜŒÞ!ŠbÊ[ï¾?=~ôÝG¡Ýݨ„ÒªqÛ+ @êÜä%Ëb7Œ¼lïjÙYÉ=3<Øw¤ô«S?È·%É­ ÎÝIª=åœs>0‚à„®y_‰wþrûÎÞSÔ¾På?žÀæµLºvüÕ·?Nü}s®GŸO7gVò³FÁüŒYö@©‘£ÑXÍž§“Ç:ºZ&[ýKŽítÌMëû³Ûl挱lMnÉvóö7ÞUž/òÙñùÞ×÷œRÔ¾a€¼ˆÇÙòè/Y׆–ëj¾Øþáñ_>QµC—òÒC©¨Va B AÕHm+£ñÖ©[ó@H0jIi öTÒúVè›iÎ]ÑÖ¶´Q•~Ö|½x5ûÃ0Œ³QQ,šø-¸ž÷ˆÅàÚ}¾ý‡ª¢-"Rüö¤µV23bÈL‰y œ5¼êr“¾Ç"U@›!*æñò 3•úH”ÈÌ~â‚Ò}n"‚œó†tš¦ÃO&lôÚ8oCÛÌÂF·¯¤ãHèP }÷Š/–]Å·’®Ä·“z+n%u3âì*gÆf91í>ÏÏÓÅ ‘ ”f†:@IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/transportForward.png0000644000175000001440000000012311354101152022570 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64508 30 ctime=1381134668.768080077 qtractor-0.5.11/src/images/transportForward.png0000644000175000001440000000044311354101152022060 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;êIDAT8Ëí“1n1EßGT\"‡€;Påæ\cs Љnkª)6«àH*FŠ]V ˜x¥á3’õýþÈÃ]ÿ#gv{¯3[,·†3K^rfÏ«AñÍ7Œùß6bêAbF ’âÞ}43þÄ|\ƒ`~% ò!ìOS¨ ¸‡W$Q¸Ë€:\ù€€ËÙ„d<Ž^@°h*Ÿó›uȶ¨kLXP©?¸öû3ª:psdœGJÖüþyH¯eY‚sMhýyʲ…Íô“m˜„$°?8˜ÿ˜Paã½ë–:  aVíoIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/transportBackward.png0000644000175000001440000000012311354101152022702 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64408 30 ctime=1381134668.644080075 qtractor-0.5.11/src/images/transportBackward.png0000644000175000001440000000043411354101152022172 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;ãIDAT8Ëí“?AÅ+Û¹„;Ðê5n Þ½†kì9 ÑM­ÒHÌ&FA£@ò»ɬ5B4^5Þ÷›7_fà¯ß(‘>ïM¤é|/ÈÔL¤Élçõƾ»96&Ì[°›Èkó‚×îT ÷rä@ˆp~.ig…$¬D ¬ïVMâc¶— °NH0©íO¼=Óõá° ?Å‚jp…Uk!‰Ó ˆ*®qCÁÖÀ˜bÒí¾õZÏ·Ócn‡(n¶¤Å{2å'xññëˆû÷Þ JeúŽ÷¯OêVÓ{J}$CIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/editCopy.png0000644000175000001440000000012311354101152020767 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.28808 30 ctime=1381134668.288080069 qtractor-0.5.11/src/images/editCopy.png0000644000175000001440000000042211354101152020254 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®ÎéÌIDAT8Ëí”=ƒ0 FŸ+ÎÇØ­ÊÖK´ƒz˜˜aã8½Œ; ‡Ÿ¢vâ“¢(‘õÅyv‡~-.TÕ¼ U•]§¨ªU–¥\·xÖ™@¾Å<ñ6Ó4 iš7/©ª3Ïûȳ|ÂÌ ª¢,Šh6ã^—¢"äp(;ŸÖ‘ºeÈ‘G‘MÌ7eÜ„Ñ;3v:f¹³üQÙœ¼"&ÎKôªœoÍØCQÄŒ×^;Êxª§[ ÕŸÐ‚Ö<çâø×ÿ§ë›Ø„¿±­IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/formEdit.png0000644000175000001440000000012311354101152020760 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.91408 30 ctime=1381134668.914080079 qtractor-0.5.11/src/images/formEdit.png0000644000175000001440000000042711354101152020252 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ :/J1J—IDAT8Ëå’Á à —È¥P›ÛÀ‘ì&¨ÀEï”1yK‚•gVâ´sp·'ý(7à¡çÿV@)%I’÷¾a8ڶÿïþv{fFn%ŒÂÀÌ03ÖUT³ø÷×ç|.÷@’SJvæ¾Hz–P¡Øìs\äþú_þ º/¹@žš:ó¨áxešàx+ÂÙ< ¼Ã\yÂ*¦áIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/transportStop.png0000644000175000001440000000012311475730273022131 xustar000000000000000027 mtime=1291301051.792833 26 atime=1381134668.64408 30 ctime=1381134668.644080075 qtractor-0.5.11/src/images/transportStop.png0000644000175000001440000000030411475730273021415 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®Îé~IDAT8Ëc`C0â”IûÿŸ(f12opÚÿÿs½Þ4óÏ_†ôàu éæ°àÒôôõo‚ÿý‡[§Áω0øÏ¿ÿ¤üôõ/" &ÇÅoþ4ø÷¹ø/9?#"Œñ&Zeº|ŽvYša&qYK®C_?+“sšIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/qtractorMidiEditor.png0000644000175000001440000000012311354101152023020 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.37908 30 ctime=1381134668.379080071 qtractor-0.5.11/src/images/qtractorMidiEditor.png0000644000175000001440000000046211354101152022311 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®ÎéìIDAT8Ëí•;Ž„0DŸWsrbâÞ3µÏÔ}&:æ8½x†å“ÀL6%!a#?Ê%ÀWoRªjšYº~ðsjf˜™Ù~œ™¯‰Pkå®ãšˆ5‚R+ªz/ÓL23Ól¾o9o3þB?-ëÁ²Aµ‰{AJUeš&†aØÁܽì&U5ךÝîšYž x{l_¸;9¥2_N»®C–¦­k?,ˆ»Ïö„Š}ßÿ.9ÌøqþïÜ&3»ÔªCð8ŽgÛ¼n¼CÛã‘7yíwpîn´©A?úkùH™äÕÙ3IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemAudioPortOut.png0000644000175000001440000000012311354101152022464 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.91508 30 ctime=1381134668.915080079 qtractor-0.5.11/src/images/itemAudioPortOut.png0000644000175000001440000000040411354101152021751 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ 1ˆí °„IDAT8ËÓÁ Ä DÑO¶0ÒCg.%8BÄ%Zl$_žÆØò§žÅþT;2Øý ¶0–4Óë¨KùÂob »óØÜ¡wD)Ig0—F͵máÆÛw1+Ž&/;ŽãßÒþeÆYʸ3C@ß\[ÒBm43› fVß;ÞtÄ¿ÏÜIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/transportFastForward.png0000644000175000001440000000012311354101152023406 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.23008 30 ctime=1381134668.230080068 qtractor-0.5.11/src/images/transportFastForward.png0000644000175000001440000000055711354101152022704 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;6IDAT8ËíÒ½JQ†áwÆ”Þ]DÁR°ÑÆÎK› XZÙêØf/@¬,L!–6"â’B¬lÉp7þ€Ù„±È‹=n6X¤ñ+?8Ï ‡ÿL'ÙD}Uôô²k$0;¿z³ª¸úÊ8ís¼þRØ0Nú„[i¥Í½°K{¸nƒåΆ¸nFœf­¸±¸Nú¸$Ã¥»sO9ÒÃFkØ'{õçR\|¼¡¨*‚¨_óŠ@Ó¶÷7Qá죞÷àÅׇ¨¢‚ŠÑž]á«;kHŽ_× xÍÿªù¶ ‚  œ„ùð€¸sŸZaÁðÂbE@CÌfÚNQèÝÜ û*pJ1ÜF^ô׫(C ý$ç6öñ´þZ’¦MÖÿgùzÒ™ÔnQNIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemFile.png0000644000175000001440000000012311354101152020745 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.37708 30 ctime=1381134668.377080071 qtractor-0.5.11/src/images/itemFile.png0000644000175000001440000000060411354101152020234 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿaKIDAT8Ë“ËJÃ@†¿ Å^,4ˆP¡]ˆH *‚ˆÏ£ècø>€¯àÂMׂ¸±}‹xA…j›f.ÇEˆMÓ6úÁ0Ì|󟙉bÄ>°ÎtÞ6ð@2m¬»;[ô¥Bžùr‘© B  NÀSјÊåYªVÇ EˆwŸ ÂqA'P̧ZLŸAœ`C“%pQ‚,´ûG‚LýCèQÿÓZɘÔ;ˆ/K©è[©hÎLAuLjWè]$ç$QÿüÓ´K€VRË1 1XIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/fileNew.png0000644000175000001440000000012311354101152020600 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.76808 30 ctime=1381134668.768080077 qtractor-0.5.11/src/images/fileNew.png0000644000175000001440000000031011354101152020061 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®Îé‚IDAT8Ëí’± Ä ËPDÔ±u|=”±ÔrNüÁË6<؉%F"Áìé8`²ãÎIZë!I×FÒ®d’ @5|é Í9Ã{I¨É—ѶäëÐǸC{€Ï-qágcÄcå¥<ÞãSübñå¸ÕFéÖ¹Ò¿»³Ë“!6l@GBpIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/editModeOn.png0000644000175000001440000000012311354101152021236 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.28908 30 ctime=1381134668.289080069 qtractor-0.5.11/src/images/editModeOn.png0000644000175000001440000000032311354101152020523 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®ÎéIDAT8Ëí”± Ã0 ÏA6âN¯™Ä™¤™>…íÂA"´þŠ€ ÓQw¶,•Ë’¼×™y`= \G=‚þöHlæœ0çnLlÀD$ X2‘Tš‰mlÛ½ã10àítCÿ*éS­¶çBWÛÑ-égèóÛah)$ÈÌdi·ì†åÖ?l,¼sY^ ×§âIª` IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/formCreate.png0000644000175000001440000000012311354101152021276 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64308 30 ctime=1381134668.643080075 qtractor-0.5.11/src/images/formCreate.png0000644000175000001440000000026711354101152020572 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®ÎéqIDAT8ËÍR[À «»8; œ‰} >¶iÌ–5!*´UTà×P… )³‰˜¡½õ­¡‘TìóO'"'›øGÄ(wŽ(Û¹ì¿j×(šl>I »¤–1ÞÛw°ð Ëÿ @•€ªú¦ßãB…惈${ÑIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/fadeOut.png0000644000175000001440000000012311442712070020603 xustar000000000000000027 mtime=1284215864.052967 26 atime=1381134668.28908 30 ctime=1381134668.289080069 qtractor-0.5.11/src/images/fadeOut.png0000644000175000001440000000422011442712070020070 0ustar00rncbcusers00000000000000‰PNG  IHDRpÎûsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ ) ËaIDATXõ™{lTuÇ?¿Þ{™>¦Paî8ÐÚNV¢@Y¡ d‹& ®0º ºìÊ’‚mX]I¶(–n…µ‚YŒ¼/`ºaÂ#E ‹Ô†’ÐòX t ,ÚÒyœýçNÒ˜–΃ýþyïùïùsçñ»JDtÀ4)¥:ˆ"’,üÀyà?À ¥”?ÂõÜSJcàŸÌ®{€ï"åîbÿRÀüüœ€ŽÞl‘>€fÉJ öOµìõÀ>àB¤¾HXµjÕXà`ŽˆhQò'õëׯÈëõ:3‚Á`>° xGDžŽ`½ÑÐÐ0øxœè1-;;{nEEEgss³ø3P$"£°ÿ¯×›QWW—ÞØØøDggg.ð7 xEDÜXß§µµõw–ü€ìŸêv»_.//׫««ioo ¬Þ‘ÔH(»ÝnnÛ¶íÇüüü!@•RêÓ( ° “““]©©©].WÒÌ™3‹ŠŠúÙl¶D`ŸRjÓÖO:tèkõõõ6`?°1ÊSø(0áp82.\ØXRRâÎÿPJµD`ÿívû]×SRRú 0 5;;Û¿`Á‚¦ÜÜÜÁ@;°øw7¶Í-,,_ZZêV(¥ÎFÀ°ý™ ¿ÊÎθlÙ²†7Þx#ø(WJ…zSòªaæþýûËEÄ‘Â(èô²€\`ÓéÜR[[»:}N]×Í]»v}hÉ:ˆ ©À €éñxÊ,]ó#Ì(6+…§C€ÑÀ뺮›ƒþâܹsá}xD$ákŸw¹\¦õ~±CéÀl]×Ͳ²²,“"Y¬oæ‘#GÖZ ߊ!†ñP ˜G ë›ÿîù#GŽ4Àç"²Œøð¬¦iæW_}õÅ›£ 輘^¯·´‡ õ·Ûí¦Ïç«‘åV=Œ0Óáp˜>ŸïcYßk ‚À§ÀÉœœœ4¯×ÛL²ò,Aüɪ©ßO˜0!­ººú'"㻑 GjjjîUVVÞF‰ÈÈ8ð}0üféÒ¥™?¯Ç¨'Üþ*((p]¼xñðšˆdu‘kkkk»¼cÇŽN`¸•‰âA8ÜÜÜüßŠŠŠþ@Šˆ<Ó[ÃXTåçç§ïÙ³§ÁJ‡ â0æ# :77÷Ñ›7oÞþ "t#÷plñâÅ;;;Ûˆ¤ÄÈö_¸páö† B€[DžŠÓ©ïÞ½{zÖ¬YƒÁðf—w÷C¡Ðw;wîL·œÿâG+P½wï^#øq‘à3¿ß¿oöìÙá“CMìŠu·nݺ4gΜÔP(¤êA®ÒçóÝ]²d‰ß*ì/ÆÁÙ/++K³ðbœí6ž9sÆ¿víÚ6`°ˆLO@]uuuðüùó·Q!ˆµ555÷;::~MƒÀ&¿ß_5}úôôo¿ý¶x6ŽšØ l>xð`ÂæÍ›ïOuÙ|W´[***úÖÕÕݦˆÈ“q8àÐÙ³gïŸ>}Úd‰ˆ3N‡^¾yûí·SC¡Àk~¸ØÑÑqvåÊ•«™óøà¿~ýºê--'ô‡fM¬-^¼¸ÿ;w~^‘´näg¦M›–â÷ûCÀï#…ºA#p©¨¨È°ºÌ)Á©ÛB¡|òÉ'ÍÀP Ûz_¿ž«W¯¶ZõÞõø~>~ü¸†ˆ<Mÿ5ñË–––Çì@Arÿ¼víZ`Ñ¢E­ÖX²0|yàÀãÒ¥K-ÀxIÓ¡T–––ö·ºÅ'»¤ËÃÀ•‚‚‚dÀ°>öÄ8ùÎoß¾=<挈§­õÄ9'†10Ož<¹FDÖ?૘[·n Ï_ñŒ%£Gþ¬Ë\˜§SIIIf}}}¹ˆ|ð‹ eæûï¿¿Êâ['×3€ÙÖÖ¶IDJzÊF½mèaÖÄàû—^z)HrzÐqøfîܹVUUµX£Eqloø×©S§úîÞ½û2ŒŠ7­µ··ŸÞ¸qc HîòîðyIIÉc»víºjÕñ÷D¤Œ¥çp¯¸¸ø6à&Ç1›Pt=‰¯Æ&º®›_ýuøæÅÙ߆ V‹ÈY'"¹"’%"}#š5`~zzºÙÔÔ¾¡y!ŽÚ 0}âĉáÛ—ç»9Ã0Ì5kÖ¬_Xr¯‹Èh""i"’$"¶¸&išfÖÖÖ†off‹Hz×N7Ú–÷-Ã0&UVV†ïN‹•R—£LÉóÆŽ;ýرc÷5Mû\)UõùW€Ü¼¼¼ŽÕ«Wßq»ÝÎP(Ô."75M» ¬SJÝï…3 X’™™ùÄÁƒ³²²œÖŸ†Zà€RêF”>š‘‘±âĉ̓ :®”ÚÚÍ Ì3fLÒòå˯̘1#]×u# ¶w€MÓn½ØŸüÅápŒÙ½{wÃsÏ=—Ü|Àeà@´Ô€yv»}úŠ+ÖžPJ¢Ôá6 ã¯Ã† 3kjjEðëçi`¦Íf{Úív·{<žû“'OfĈMº®¨”j€s °011qؼyóšß}÷]ÃétÚ4MÛª”òF›E”R…ƒ ª÷ù|¦Rª³§} Øl·Ûm£Fº———>|x‚ËåÂív_Ñu}eö§ót]Ÿ˜““ÓR\\¬Æ—˜œœÒ4mëÿ•ݬ3ŽMôIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/trackMidiOff.png0000644000175000001440000000012311354101152021551 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.37708 30 ctime=1381134668.377080071 qtractor-0.5.11/src/images/trackMidiOff.png0000644000175000001440000000123111354101152021035 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÔ,‹îQ &IDATxÚÍ’?oÓPÅÏ{ví¸®Ò¦ÂBRŠT))´‚¡ õÀ êP± &>#_„ï€ ˆ¡Ll”©Ciì&nÓÒ:Nâçç÷‡…J-3œéÞ«{~:Ò½À¿ùs°¶¶6ãûþŒçx0¬ !¤m™»úãööö×Ñù}ã|Óh4ªφcþ†ó è.Dýø†Y'P÷n.×\­u³×ë%ß÷ç‡ÏS.Ÿ:î\e/ìz‡'î~t4ý½¹gµÃVq¶8½°´´4Í9ÿÒï÷3 ç¢û݃þc óò핺}­|•:¶ Ã4@©AÃqáÓÖÖõ0 Ÿ,..Þ=ó™gEÆóG‚ÞA3´XÆÑþÑãR(%­0ìããã+óóó›>\ð\UwÛ”ó|f¿q…ÓÁg6€WÀËýÄlýaÔÖçµ/õ‘ÑÑIÀÜW Ý–¢è7‚õªâ8Ö³«Õl6{ ÛS J j'?]]S3”jͶ–WüJ&“™F ÔZÒÆV›5iÉÿ¨­m©R—~4BÍ/,~3 ãl’”Ja_öH¥`eÒcè@šÙÛ˜)Ýaîî#r'Ìc`Œš‚½^Õ­Zâ®r½Ñ"ø¾I½Ñ$“>ÈÉÜ0ã¹C g‡4”T«¶àɔǙY ÿŠÇü»{»{ÆÎ›€ ÝÀíñ HËo¥¥rWg  øWa Ÿ®yœ¾iñ|Ê£ò¾ 7À¶í·Çlâáë‚NNŸ3w Åb±ïèzÛðuÚãè0Ó?ï—ð}×uûŠô\áøˆJ‘À,Y¼™{ÝqªKÎçóÿü™ ’.ôý…†an²ƒÅ.’!Ã0¼½Þÿ/T1<ê44IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/qtractorTracks.png0000644000175000001440000000012311354101152022216 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.77008 30 ctime=1381134668.770080077 qtractor-0.5.11/src/images/qtractorTracks.png0000644000175000001440000000041111354101152021501 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®ÎéÃIDAT8Ëí•Á à EªncùL×0c4gÆ‚Yè"«€ÛBr«%dé#};yúøW©í]`æ'`®65ÁIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/trackAdd.png0000644000175000001440000000012311354101152020724 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.28708 30 ctime=1381134668.287080069 qtractor-0.5.11/src/images/trackAdd.png0000644000175000001440000000042611354101152020215 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®ÎéÐIDAT8ËÕT±ƒ0 |r,CMÍ$ôÏLÒLÑL¢4$ñ„"Ò¹±¥·üz ø7k"Á$=ßSÕær$©€¥ØöÔ @÷CwqÜF9-Ä q¾âÔáx&+÷„ó¶šÓ£}6oÊŸ± Γ%QÅYà¥L¥k´é¸F¹ à ]×m+‚¤Iñ]€‹Èç|QE™ 3 q>Ï3Ì,Í#-r¼Þ÷=Æq\W7äÞ§©*$TñéY¡ª· z¿ˆ÷Ötqñ"øïž]²[Œ”söÞaIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/editSelectRect.png0000644000175000001440000000012311354101152022112 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.76908 30 ctime=1381134668.770080077 qtractor-0.5.11/src/images/editSelectRect.png0000644000175000001440000000023511354101152021401 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;dIDAT8ËíTA€ kïÏç‰ÆÍÈ’hÖ¤í  … ö ̬Ø(Oë/oœ„Ó¬Ža’44@»æŒå­ŒñuòPQfÞ‰{Û©æMeüáŒç=éãvéO¨ðl-Ó.ÿïJIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/formAdd.png0000644000175000001440000000012311354101152020563 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.37908 30 ctime=1381134668.379080071 qtractor-0.5.11/src/images/formAdd.png0000644000175000001440000000036711354101152020060 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ (é!æwIDAT8Ëc`hÀˆSæ Ã8û,C:vµLx?‹„êI7€ÀD½0@ö3ÜÙ`Œ& ¼špÉ!¤‘b/°`„86'ãqˆŸê‘¤®é,Ã,†ü@@#›†FªG# ÁTH¶èaB+ 0öU“‚ÔIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/formSave.png0000644000175000001440000000012311354101152020771 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.28808 30 ctime=1381134668.288080069 qtractor-0.5.11/src/images/formSave.png0000644000175000001440000000027711354101152020266 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®ÎéyIDAT8ËÅ“Í €0 F_¥; ÝÁ5ê ß-· äJOJQQ¬ˆ9¥!yù-¼”`fsK°™…¸>b4JtäîH"¥»–Ìî¾éM€¾ŸÞjù÷½Uó¹íÿ8sxT@)Ã7[tzdÿo!TzˇÃΟs×Ó°÷0DIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/viewEvents.png0000644000175000001440000000012311354101152021346 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.23008 30 ctime=1381134668.230080068 qtractor-0.5.11/src/images/viewEvents.png0000644000175000001440000000101711354101152020634 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ0, Þà·IDAT8Ëí•=K#Q†Ÿ¢†Q!+‚ˆ ba![ [lëñ ,ÕB´"˜êVV‹Xn¹[l£,k!øÚXX$(%N&ã|‹(‚™t`;_88‡ûœ.÷\øÔÿ–Š©F"êpœ¦hÊy~ W¥ëZ_ÿ 0œ"¾ÿåÛª„a(G'çÕ|>? ¦»žÈÅĤ¼äÃó’Ô=»ÈßÃ0¦€¾ƒmWÄzhÄ-²wp)"•šÈ½ãÉï?»7J©Å8@&®áPž5ÉdàzÆ$Ûš£¸õ‹µÂÛ?÷éî5ª”:Ÿû뚊ÝÈ8.߯¾Rsê¹6Ú;:‘P)5ò~pÕkÞ¤«¨¹3è|UÔ€ AM{¸kš’¬êÈ~C‘Üp,™|ÙÔÜÏ›ÍýMxû‰Ž­eU–›!F@:°ó¹“ö ½ÐìØÙH鸧 J/ÐVh†ø’Îqv(¯~¼ã!µ|t»%m¸·ÆŽÝÏ"VO?<Ìû |’ñIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/formRefresh.png0000644000175000001440000000012311354101152021471 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64308 30 ctime=1381134668.643080075 qtractor-0.5.11/src/images/formRefresh.png0000644000175000001440000000112711354101152020761 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿaIDATxÚ­’]HS†ŸmžÍÖü(ZBö£7Ñ¢‚~è"¼N¨!A¢À¢èJº »©›¢ £›®Š¨IhÙ¢Ò¢ÔdË¥’†ÎÎqÆçqcÇ3·sº8¹μé½ûøxÞïµ°‘ºæ*¬û°ü™Æ"MÕƒ«ë‚ j‰Ähž1g%‡Ú¼ ÞjÎxiæGò o4Ñ×>Ê´ê 4€XÂ;ó'x¹KØÙÊØ(Ò  ÀŒz¶mÉO$иj±fÍÞH Qg+½a¬&_úH§`a Äi jösàBËZ@ÜÞAà HŸ ‚÷ÎŒ^Àï›G‚áÛíhJ›•žë@aî„Gr"¥È~½ó÷Í£žs[ÄfPXÖƒ°YÀUÝHB~b&ˆÑ@T=ñð¬ÙT Rx¿¢È¥#8¡|Ç©Ü ±ŒM›@úç[‹ô2¤UW $û±XÁU•{®k~*ïÁj+`iŽç7ꃨ1’8rùæºS »g!.Crþõß_ø5~•Ì ¸ë\œŽÐ6´;»ë–wѹ0ͤº‰û§€> ÛpS ×ÞS^wŒ²íPUŬ°Éb  v&Dëéc’™ÞÃÀ·µ°à9Ý»þ"Žb+Î ³…ŠdƉ|=Œä ùUŠ»þ,®ª“d4;ŠôøÜsà-°ÌÿÔo’JÑú•fIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/formDisconnectAll.png0000644000175000001440000000012311354101152022615 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.37808 30 ctime=1381134668.378080071 qtractor-0.5.11/src/images/formDisconnectAll.png0000644000175000001440000000114611354101152022106 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿa-IDATxÚÅ“[HÓqÇ?ÿÿ¶ÿÔVNVN›X ©5Ó¨XoÞz)#Ã.¾!…ùÒCïQ!¥ÑÅ‚̔DÍL#š /+/û»Í­­Íÿ~=”±™½8‡ó=_¾çÿÛ¤Ä@\ KsQñÙÍý¢I¹«¤D\œù± 4ý…²>îéAê ׿¼îð¨ý]|ùÛ;Z½“ÔÎG@Þ28uIr"Ø7¨ÉV((7aêPyДÏ%¯›“w."Ýð½z §kr˜ôLãr¾dj5 K£ñ: ‘8Ëcaö,ĸYeÆaKý‰‰½>ÂG?Q$­5Ù<#޳›tnÀ0Ãßãg‡N¢/¬a]! ï_bŸ^4 CÜõ©ìðv÷Å1²nÙSIßµžg-S” ‡(HØ\•bu(½“,ù£(ñ_™Lžª uùè<—ÃùLF‚<:5AÝjµºfZ·­óXzqçeÂn#aìv//fcËMä¤P¸Ó„üD¥ëž#ÇhœÙOÛÌÚ}ÕÄZ‹ÛÒˆ€ñ¸•ñW¥ˆ×¥Ä›ó9˜T¼|£Ë‰ÖSŠèv ÚŠUéÄ3+˜u2Ö¦\üŠUf&9‰¤ÒÌ•íi|-IcΞ‚G-@Ò‘Yô”åQeôkmONð¿ÙF ãŸ~㤯Íwó;Y±IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/viewConnections.png0000644000175000001440000000012311354101152022364 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64508 30 ctime=1381134668.645080075 qtractor-0.5.11/src/images/viewConnections.png0000644000175000001440000000067311354101152021661 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;bKGDÿÿÿ ½§“ pHYs  šœtIMEÖ /4ôþXHIDAT8Ëí”?KÃ@ÆŸ?B*"¸dtéêÐ/pÖo`të7Ú­]²i¾B—R²ˆ T¨àr(‚ŽRH\rY:$¯Cš^®‹¦¾ppÞ÷É{Ïïî€uüu0ù}#‰iLJc Q¥6+‰—W#€r9ÂðävIoSnfÚëWT·Ï¢¬ˆ¦½>X,0ríÆ*VxRÇç€Nóùu§[©µë ^Øn?sA¯÷T‚Ç>¾ï?k ©º4õžóèÁæ9èt:ÏÀ pz(TMÛ¶çû’Øjµîµø²˜£ê8ÖÎô´ ZoÀ øÒ}€"¨QÙR¢!éŸþ|_Ÿ±˜#¿&ÕIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemAudioFile.png0000644000175000001440000000012311354101152021727 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.91508 30 ctime=1381134668.915080079 qtractor-0.5.11/src/images/itemAudioFile.png0000644000175000001440000000107711354101152021223 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿaIDAT8Ë“MkQ†Ÿ™L:MìÇhí‚H+©¶‚"HéN܈Á¥àFýué®?@Ü»hA*Q,*V*bC¥­Ö6ˆ6´j’™ÌÌ=.jLÆÄâ ïæÀyî{Îáj45 äé¬`øÈº)ä¡l¿U‡lû0| E‚ êï¥=QJÉû…=˲n¹<_¤êF½T(Šë‹TÜP^½~·›L&oC&½•(pƒ¦ë!ü¬úu¥3:>fÍ<šŸÒ4m´Ñc´üêA4–ÑÕÍôýy~l;Œ·™83œíH; ÁóAµDëï·8î4ÕšK²ÛäPO""ÔC¨ù tm¿¦&™?µî4^oxÔêQ€ˆPvJ,¾™cei…ÁŒE.—Ëg³Ù®……¿m •wK<˜½ËÖÙu(ÁçUØØØ˜TJ]µm{&r_í'ðü¦_ÎñuduÔ Èu1â™øÓ4s´ªpx…ð$ð¸j ‡µ‰µ.¦l¸~s~%ÐûÉB=<àÈeà)¤î¥ð{‰Ÿ–Yô°4À¯ÕQ.H¦j}ŒjÍH¦ºf´šw¯…#µT:pûÔ½™-k]0É·ÎDªzúW~OƒEÞ{˜œs×@UA!„î¾&8ߺÏŽ=eE¾¤‘±·=žy)[àže[àÞKÙ/yœ½[Ñš!tENœòø™P—dû¿^õ{n¯xzˆŽUIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/formAccept.png0000644000175000001440000000012311354101152021272 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64308 30 ctime=1381134668.643080075 qtractor-0.5.11/src/images/formAccept.png0000644000175000001440000000027311354101152020563 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®ÎéuIDAT8Ëå‘Ñ À DŸ¥#u¦¬¡]Ùt&ûU04ÑJ?{ Ç;/~ªB»¯ÛÃèL®D€Ý0@hd‚ ÞÇl Íð dp꣺ϤÑ€zâ‘4EzH¢ÕyY¦À\¶'XHVǬ0` Ù™Cz{]Ãÿ¬> maqøðG@IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemAudioPortPhysOut.png0000644000175000001440000000012311354101152023330 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64308 30 ctime=1381134668.643080075 qtractor-0.5.11/src/images/itemAudioPortPhysOut.png0000644000175000001440000000053611354101152022623 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®ÎéIDAT8Ë•S1N1"†ÞHí}Â=Á¢ºDéñôWE‘â J„¨¨(ö~`!JÄݶ§X ¸SrºKK–¬µgv4³>Cú²;gPàpY–c©uí4„ î`’Ê@DyEUš¦éêç©ø#Œ!03D$`óþ¦ÛË+”ó9 IWЂQUˆÓ)bþÿŠTG;S]+9§ Ò^ H{<•]`c"Ì– >­sìÙrÑfnwöðºzTò^á\_¶1*3w4”‚ýùúÆÅçðüB}—EyžËϲìY–ˆ”ÆÒ¸½¹Öcþ0sK°ŸÂf½ÒÕÚR~¢1} Cªªþo&öÞÿ u‘Ùq)TÙIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/viewPreview.png0000644000175000001440000000012311354101152021523 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.37908 30 ctime=1381134668.379080071 qtractor-0.5.11/src/images/viewPreview.png0000644000175000001440000000041711354101152021014 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®ÎéÉIDAT8Ëí”Kƒ0Cß´Ü n–áfÃÉÜE“B)ŸPe×zE/–cþʺ_8«¼NÍnwGî® OÍ Š5ƒº»Ü]!IúÕÑtšA/hþNgÐn Ry/;º?c¥K-ÜÍŽ=Ç›º}nÙbGfVew\Û{Q,µ‹JgK ¥jW£X«/ ­¨Êx`p‡q¤¦›²÷áàOʳƒ˜Ù°˜u•ÛŠ&wûè—þj~¼Á› ¡Õ£6…þˆ^5µÑé>ÎÿIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemMidiFile.png0000644000175000001440000000012311354101152021550 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64408 30 ctime=1381134668.644080075 qtractor-0.5.11/src/images/itemMidiFile.png0000644000175000001440000000112411354101152021035 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿaIDAT8Ë“ßKSaÇ?çxlÇ9ç±Ò ¶ ‰PP¨AýÐØàe$xmÔ_ÐuAt×MZt3Fu#’‚´XaX3È’¦ù«‰u<;¿ž.ÖrG—ô…^x>ï÷y¿¼ z¨¯ |äH9®'+«kf"™¼ t ð<× Ö÷­=ñ}_ÞÏ/ì†q èü' ìˆ˜V°æVÅrD~YžÌ¾~û#ßÕ!µ–àú`¹e{ðÓtpl_¥÷ü9#ûb⮢(½Õ­àx`»A[Ú û'ØØ,Ñ}6ÉÕ ]§A9ràzPvÀ¯±ÖÚjpùb sß"¬‡hŽD©ëÀö`ß_@U*=E Åþöô&¨Þ~PvaßD„Íõ^½å]>G2'•꽞z433cyƒªƒª6×WÈ<ax(Jsc™p(r#“Y*¶··ß üŠƒZ½™ex(Êììét'…Â}}‰FMk»3>þyº®ƒZåó9ÚÂeÒéN C'•Š“Í~b{{O/‹]êa€åT¢´Ýʹ£#NÃÐñÿì68ØaD"M=cuÐr*‘ö\ºÎÓìlÛellaqqGr¹­yMÓ6+ÄN‚+Ám×È~ýÀ³çÓLN.¡ë¦¦–¿-/—ž”J¥¼ò?ßYUÕ¦–––Äîîn, © Ó4ë¿)5s\ÁIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/trackCurveEnabled.png0000644000175000001440000000012311577116263022613 xustar000000000000000027 mtime=1308400819.477997 26 atime=1381134668.91508 30 ctime=1381134668.916080079 qtractor-0.5.11/src/images/trackCurveEnabled.png0000644000175000001440000000116011577116263022100 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®Îé*IDAT8ËÍRMOQ=¯†ÒZ¬6Ö6©4˜¦€t¢Dã¸ce¨¢‰Å­&þŒ&·D7†€,‰¦Fí´£v˜iç1oæÍ{®J@t­guïÍ=ç~ÿä÷@£Ñk6›eÃøz·oÛ·¥<™œx§iÚûƒÝÝ]~:_9íT«ÕÉååå'AÝÿîøÊ§gÌuŽÄT6uGOL]×× ÃxnÛ¶7âÄGF­VSWWWŸq{W/—æ4œtž „,¶»Î¸íE8lã }Ç•óÁŸÈ(˜¦9>==}ã\œ‡r8pÅú‰‡ Ì?ÆñÐ< b'µ8çò|+=«vzˆ"…ˆÀCŸp6„`®„@²Ù,°9â,1“ɼlÔ+Š?°<êöˆïöx? ü#@ðÑϸ•JEM¥R¯ÏѲ,gfæJ)T/~i©2òUˆ€û³,ûÞÕØ£Z¦iº ½Ä$IŽ*~r³O†.€H¬…ž±À7𠜀3p \Т×%¸(äú§Ÿï“n{ú¸ˆoIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/transportAutoBackward.png0000644000175000001440000000012311354101152023533 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.91608 30 ctime=1381134668.916080079 qtractor-0.5.11/src/images/transportAutoBackward.png0000644000175000001440000000045311354101152023024 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;òIDAT8Ë퓱mÃ0Eƒ‰Ë ‘â2‚=ÅyorSD#¸·´ˆÉNàÂíB—@ )RŒTúÀÄIxø÷I¬ÿÕžë_¥þ¡‡ ³Dä3 ú–§œ.Ç‚OÐ7àg<ø1è´è+Ð؂ֺB¼¬K`ƒvÜzЋAàËÖ'«gàXtà~ö¡ãC·¨èŠÚ\:³à"õÛÏFÑØªÀGäﳇgQR°¾£MÒöâðãÉ:>÷öŠC¸ò(Ñû_¦À¾|xeÓø*sŽÇÀU]ßçå)ŽjêË+»Q“ðIà N"šáø,nÓ§Oïfa 0IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/transportPause.png0000644000175000001440000000012311354101152022241 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64308 30 ctime=1381134668.644080075 qtractor-0.5.11/src/images/transportPause.png0000644000175000001440000000036011354101152021527 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;·IDAT8Ëí“1 1Eÿ<˜7°ñ+VÅNÐCˆ§ÚÀ& `gVb‘ÕMFY°ì¯Ÿy™ùÌ£Š³NÂó½'öTpÂfÚ€H`½8XòámgG¬æ‡Þ{Ñ$×pm=È&þŽÀü¼y°q×Xœ»ŒàÚzÓiëA6®‹2’…À®ë÷iZˆu©²àóå–-jNþëË¿¤<°²1»þl?.KóF¯;çÔ9þ„©ùÎIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/clipNew.png0000644000175000001440000000012311577140237020626 xustar000000000000000027 mtime=1308410015.909726 26 atime=1381134668.37708 30 ctime=1381134668.377080071 qtractor-0.5.11/src/images/clipNew.png0000644000175000001440000000034711577140237020121 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®Îé¡IDAT8Ëí”ë à „ÔÁØ ØŒ`¦Ë× (ôEJTU9É,øl 2ðW"Aþ+ œ–3Ø[’äBÔjÿè ¼BºG h3­Õ–åãúîìxnub B)`îVK|¥È¾_«ñ„_1í;çÖg’9Xû>i'˜i3&cŒë:¥¤Ÿ&Bرn/n0Üì¬fÏê”íÒÉZ”(énîS IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/transportPunch.png0000644000175000001440000000012311354101152022241 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.91608 30 ctime=1381134668.916080079 qtractor-0.5.11/src/images/transportPunch.png0000644000175000001440000000062211354101152021530 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®ÎéLIDAT8Ëí“=KA†Ÿ½¤ó_¤±Na#X¨•…"¤´÷Ú€ÿ }@°ºóOHú U41‚A(ù¸\Anw,ŒG4·gŒ)30° 3ïλ «ø5ŽEþÓãØÎv^OÒ i=Žm®êT¥¥z¡¦t¾Ÿ·‚»ƒÈ -®?ÑDqË{3ð¬ üøüž¼Sßç8<ÙËåêää ¸* Vá+ÃB‘muÏ¥wÅ,Yñ”ÃùÑ} ´ÅÍÚ¤îû3€þÐîCö»Or›S ¹ð–V¥–¨*H1ø‡y®jUj£(N EüỪS­ jÝ ýôÁ,òõ>¦f] &ƒc¬øªx~#Sõ@Vl€Åpž@;ãp<Áî"V@@&sb”6Ÿ.³XR;9œÏÀ+o °˜€aŒÞ÷pjà-üSðvFLÞZ`+Zg<'¤p<]Ï#H/„ÔÏg3>^n-wXî®Q^ݹ4µ¯ƒMùú‘vñ8lCëÝme/TÌÑ$HEGü¼m+`E¯c-èäp6‡üd.c¼´€]¡N• ¤ nµ”½Xï×QïjØuåñtYÆÓù A·)¸ß×Pü‰˜&h°1(ñºœ@ß§®PŸ½‘ì'iW¤æ_“’s ¢ÃvC¿ÜBt-ÿìßV`ÑY¨IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/formMoveUp.png0000644000175000001440000000012311354101152021306 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.23008 30 ctime=1381134668.230080068 qtractor-0.5.11/src/images/formMoveUp.png0000644000175000001440000000030711354101152020575 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®ÎéIDAT8ËÝ’Á € E ±kcØ™ìLx¢"TŒñâ¿–þ—6-ð¥–Ù%g‘´ÒÌ"°´kéÎ\ԃЈYƒÐ¨¹¡'æÄ”$3ŸŠ¬µS% î€ès7¡Õ B3Uó” â1˜ÞÛ¦·çÑ› åÏlakðG×ÿoƒIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemControllers.png0000644000175000001440000000012311354101152022374 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.76808 30 ctime=1381134668.768080077 qtractor-0.5.11/src/images/itemControllers.png0000644000175000001440000000104211354101152021660 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ 89r°@¯IDAT8Ë¥“1kSQÇ7„6-± ZE:tpÍœUð8ˆÝ ï«Ý\ú:ØÅ—ÅEAœìà`K±ÃE4P‹:XJ0¦-i^’¾¼÷wxI}ѤEçÔ£cà³ÜƒåPÖò´óÙ¤r>Å0¼ÈõO+XmîÙ­v?3nöð!P ª„Ì;GÝ„D€+à:Ú Ú¬ãÕ£)¼ n ø+€¬Ã6ÆýÞíqÁQÜ[ 8çžóŽc©ÖqÎiŒ7p¸yè¿ÅØÙ¸KÖ=Ð.ø‘âXެKÊ’òݾ"•¬ñÃГc¼'‡Úž^f@F8ý=XÆ•?Ÿ.aòOèÿÅ7Òf™iœI°ÑIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemAudioClientOut.png0000644000175000001440000000012311446201132022757 xustar000000000000000027 mtime=1285096026.477404 26 atime=1381134668.77008 30 ctime=1381134668.770080077 qtractor-0.5.11/src/images/itemAudioClientOut.png0000644000175000001440000000041011446201132022241 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ *53Ü/ ˆIDAT8ËÅ’Á Ä Ç(]î,.R“ï„“rî‘ý w¼àO‰™ùS³™±¨jÚ\kØ;¤&»3îä¾""¸û°‚õ¨êéÑ Ú&k(§ÈŸ\ŠͲ!¿ e:İ [_ca;k5ÓW†hž^áʵ´o™}Æ£ ༩/Î 5!¨(ãIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/transportRewind.png0000644000175000001440000000012311354101152022414 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.37808 30 ctime=1381134668.378080071 qtractor-0.5.11/src/images/transportRewind.png0000644000175000001440000000051011354101152021677 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;IDAT8Ëí’1NÃ0†¿eë `¨8‹;ôe€c¤œ0;ŒÜ †Ne`hç.0€D2$ƒi ÄI!$†þƒ%Ïï³üdØåÿ$QíÅC¥7ó7« ~ïá@"½<*ÉÊ^øÛâmÒóQNV( ¾‰ÃĉêéÁ3y)(`Ïn©8þBV€ˆ¢-æ¸Mz‘zull,ç8Îétºº’£­4ÝÝÝ‘‰‰‰§|¿¶å‹cGûLièG}ìÝýLhûæ}ròoNžddtœäc;H%%²îá·ƒ 8p}ƒ×€•Rï½³ï­_ë{¶Õ¬ç5ŸŠëQX˜ã—ÁaΜ!~ïzz“X+§°Z;izà…7wo9 ¥Té—{×°8D€Ni©Â¹¡ '~AXQv=ÝÅýkfîE ¿Š qÓà¯kš•+”ç/syú*?ž%»àóx²‹G6.£UF \BH”&†¥n‰ïÓƒédcbÏw*”? Ky¤³Ia𦏠°W]&ûoŽ¦èЇ°«ËèÔ0¤@J‰M†Áˆ€Œ4®z.WK|wDa!0M!­ÿÍ £`4£išÁê R©ºø~°-±•B)…eY3²DÌ»XÖâ|øùÏ~"‘Xç8NdÕŽk¾OÈÒ 7I ]¯£[-`¶‚ÑLÝìàÛSSÁþ÷ûƒ\n®ëÖm§ÓéÅÕÃó}BئÀÒ,t»¬µ`¶qöÏ%>8äg.MÌç §‹ÅâÙ™™ìBC3Ò´$º´1… MŸµÙð;ÿ·ßÏž›_¸X(NS@­¡ðÊåràÙ›kÑ{: Õr³ó®ý͉#¹ÜÜ¥b±øS½^Ê«]Fí:¿©½=öz¼#†”Ïóp=ft,óƒëºù;Ïä¶õ˜5§Ÿß¯IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/formOpen.png0000644000175000001440000000012311354101152020774 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64308 30 ctime=1381134668.643080075 qtractor-0.5.11/src/images/formOpen.png0000644000175000001440000000035411354101152020265 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®Îé¦IDAT8˽“Aà ‡¨?gåLžòKû-î¡¡J(UH+e/+k ÀŸríFÎÙšµ¦åœm/±Øê±/N)¡ªxP¼̳X§™ûÒ‘ƒ÷T¡SK®÷U=ø¦èÎ2¶J)£*„–Áéuž!Nõ6×Õ yÙ V C¾Å6 ¾£Å¥t¿@º€+1* }çvñ/-½¹SOÑ)ÓðAIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemMidiPortIn.png0000644000175000001440000000012311446201132022105 xustar000000000000000027 mtime=1285096026.477404 26 atime=1381134668.23008 30 ctime=1381134668.230080068 qtractor-0.5.11/src/images/itemMidiPortIn.png0000644000175000001440000000051211446201132021372 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ +{[ÊIDAT8Ë­’±ƒ0 E¿“,!S¨¤i|,@É× §`W˜ðJ‘#üR:?Iþ¸BI’HY–r†!WCƒ$Š"1Æ!"aæU˜š˜Î9c@D "Ôu çœÚxC´ÖÐZoBî €j2A½Þ¤iŠaª‚ýì?–Ö !|Õ¬µ "0³ü:grÆìeívh´SÚ¶•®ë!·=õ}ï=¼÷PJ!Ïsü½É°¦i$ŽãÍ|,‚Š¢,ËÎ%õÈäU=Ú@z'HTáIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemLedOff.png0000644000175000001440000000012311354101152021225 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.28808 30 ctime=1381134668.288080069 qtractor-0.5.11/src/images/itemLedOff.png0000644000175000001440000000057511354101152020523 0ustar00rncbcusers00000000000000‰PNG  IHDRľ‹bKGDÿÿÿ ½§“ pHYs  šœtIMEÖ åJÏ´ IDATÓÁ?NƒPà_òÀBŠ‘8àb„8ˆMI¼£qqsö žÁ±7ðN^Âî%‘ÔšÚJ¡òï <>ðûžçñŽãœÊü cÜ þ ¹gß÷W‚ã\žÔñ#-ÈÍ>ÛIÁrÓó]u=½° Ó4Ÿ„ŠÐÒU·'†¡,‚O(ëò}ˆªìûζí\HòÒÒX >Ö°‹Shi=£P5J’Ä0Æ]°ü‚šP  *€5º!mÛv`ÞSL²x¿éþêzÖ‚,ËDÅ9ïN'ëÃñè8Ú®N-çLUÕʲ¬„ÐŒ—$)Õõ£…,Ëœ¢(LÓ´µ®ë¯¡Y†ïÿÚôˆ³ŸO IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/clipEdit.png0000644000175000001440000000012311577140237020762 xustar000000000000000027 mtime=1308410015.909726 26 atime=1381134668.76908 30 ctime=1381134668.769080077 qtractor-0.5.11/src/images/clipEdit.png0000644000175000001440000000032711577140237020253 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®Îé‘IDAT8Ëí”a €0…ŸÑQvOtLïb?V±j«Í zð~8ñsð«S À攚,y“ƨ™Yé\ˆHjEC ”ˆjIxÀTU«ð^ðB(¯š 7Ï—šÃ ñL籪æÓÀûüy*<͸’ç'³ì+6§J O côÜIÄžqë{à–_¬Õ¿^Ö |ŠTSŽÖIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/viewZoomIn.png0000644000175000001440000000012311354101152021315 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.37808 30 ctime=1381134668.378080071 qtractor-0.5.11/src/images/viewZoomIn.png0000644000175000001440000000036611354101152020611 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®Îé°IDAT8˵SÁ à ¼TÙÏdÆHÖ3Ù3]?…$n!J«ž„Æ>ÎÀ€‡±Œ’§°&˜Y ˆH/÷ 43F˜ͬªËnE$U•öš–ËÓ«†”ÒNp&9á%çÖwAÉyØ÷ºm­x;\fUÁ*"p÷¶‘Rڳܫªud#›}¡ØÝ‘÷V†v²^h°ªJ’—vö^âm’®ºH2ß ˜°”òógûº…x]ªdÄÍ?IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemNrpns.png0000644000175000001440000000012311354101152021166 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.28808 30 ctime=1381134668.288080069 qtractor-0.5.11/src/images/itemNrpns.png0000644000175000001440000000103611354101152020455 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ 8>Ù «IDAT8Ë¥“OkQÅ/ ±J¨‚J«–‚]Hm â"[¿„]Ï]ûúܸšÙ¸Ä¥+±‹ m‰m`hUl Y¨`ÑTiÔ4ÿ:39.¦­MZćû.ïÃå¼÷à?aëpµÏ™m`xw”™ÕÂHŸ6?7GÇÆî¹# ¢H Ã߬~««ÛíêõÛr=›ÍÞÆ5èÒüKGûu­¼©v 5Ú‘ŠË~-“ÉÜF4:ÒöNÌï iÉÿ ]©Ö”~´ÍÍ/~5ÆÜJŠRÉ&ˆ ôÊ’JÁrÑ2t,ÍÃG/˜}ð”'ÏV8!wÌDR3”l®LºÔqm¶:Üœž¤Ùj“IçÄð0’4РÞÕ’åú Å2÷¼|°'`|bPa¯ðz2بJÅŠ´´óþ¬«Aœ¿&ºðqÝrmÚåMÉRûR¬µ=i»®;8Ä“—\ÞWãš™98ŽÓ÷êz Z»°U±œ>ÕŠåçÖc|ßÇó¼¾&=gGàò”K(ÈM¹œ»O°/Îçóÿü™ ’n÷ý…ÆXÀK†¸¸Ç$dŒY8ìýÿߨôE¤ÚVIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/fadeIn.png0000644000175000001440000000012311442712070020402 xustar000000000000000027 mtime=1284215864.052967 26 atime=1381134668.76808 30 ctime=1381134668.768080077 qtractor-0.5.11/src/images/fadeIn.png0000644000175000001440000000416111442712070017673 0ustar00rncbcusers00000000000000‰PNG  IHDRpÎûsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ £c›ñIDATXõ™{L•÷Ç?ÜDŠPµÈÃB™»Õµ#V—Åx™µfF3,ÉtëJ7§ël1FÍæ¢Fb¼A:Qê%6BÕ½bã1(Ñ‘©C$BÁ+‡Š£G{är8‡ó¾çÙ?¿“ž›{þ=ÏûÜoßß Á‘0à÷@FAAAQ^^ÞÝO€¿µ··k)))_./üoó7 Ãè·X,Îææf²³³»º»»·ý>è,~jµZ­eee‘mmm‡j?íVõôô܈Հçø9 ˜D ôY­VÃf³…šÍf²³³ïwwwoõf¿ˆÄ¨˜Oïïï·µ´´„ÔÖ֎ܹs§Ûd2 Ç?Z ̬¬¬¼·~ýúÀ]? `:•™™¹pçŸÃÿét:[¶l騨¨H4›Íôôô<²ÛíO·:G?Z»vmÇž={­Vk;Ð\Ê^Û°aCŒ*ÞÃCøøkàW@Ô©S§îïÝ»7Ád2E?~ü¸§¯¯Ï¦ëº£···Û›ý" ü øù¾}ûÚ·mÛ–l2™¹Ýîv÷&*o•ˆh§OŸþ4""B>Fú[½"¢•——o ×€Doúw$&&ö™@* Œð¥`Dä}Ñrrr  ˜Ä ‰HºˆhIII0ûÙ€‹HŽˆh·nÝÚ1~üøÊÏ%ÀdàU`4Dú k¦ˆh………Û”œ…@âר‘ED«©©Ù­‚ð!€óŸèºþù¤I“4àýádx‚^[[ëÑ·€¾ÑŽ?¾9,,L¦‰Èùkgggñ¨Q£4`ìPÉ­®®Þ®ìþ»â PßþÎÎÎÄÅÅijüœpFÞ{ÀÌêêꮌŒŒà ðYÆLÞ:vìØ£††jc¾©ÀÜúúú‡Ó¦M‹®ÛŒù’î¼¼¼Ã0ª”¬`(x³¬¬¬Ën·ßìƒìNþ`2™dee%_{ƒ(–4 º¸¸x„ÕjmÎ ¯Pv^æ‰'ÚçÍ›— öUAÆD9ý+V¬üøf¾1À=zô0333¨4y"2˜PRRâ¾sçÎà´/;Ó ý0Ž=šàv»ëç ßþl†¾`Á‚ïõöö6¥Aêú…®ë®“'OF¨8ô Åú¼äé¼… &»\®SATÔ»@üÊ•+]½À±aø>r»Ýá‹-Šyüøq›Ú{Ò»º®» G® Çguûöí'õõõpõÛ,`üîÝ»í---.•}ú´{ÅŠcUÀ¯áüÛ@äêÕ«#€6 #ÈîKæšÍæžýû÷Ô¯ß~¼k×.«ÛíàŸÁfND^".^¼(@÷óxCÿ;o-R—/_ÞóàÁØ9 _0*'''Âf³=¾ Âù`j[[›íÌ™3ÁÈRòFª¢ŽÈÊÊz ¸ï)B5V_¶oß>V­yÝ÷3 òÈ‘#·Åy9ž¿È "ÚáÇw¨“zêpÕ&"û¯\¹R¤ø&¡3ÔA&Ož¼ÈݰTD´uëÖ(ûR'WD6߸qãÓ¨¨(Mü`õňH¾ÝnÿBéK{¸›Kï<Õyî¼1ªóÒΟ?o[¼xq¼Ú ‡)3€èìììuæ7áÿ[ÀÜŠŠŠ»×®]K6Ä0àe`90±¼¼ÜœŸŸŸ|®F²‡^RJKKŸô÷÷7yw>êLX³fåõµHD>ðtžÊøªÀm¬ˆ¤ŠH¦ˆì‘C%%%;¼É‘DÑ*++=/3qATíѺºº žûPðÌ·‘"%"£EäU™,"KDDÓuý@QQÑŽAéÙ›a¶ˆhÓ§O×€Œ`.\I‘…êõi›zx˜éíÛp £²²ò^VVÖ«ªó>óCq$°Ì0Œ¤q¡¡¡Q­­­¹¹¹áUUU¯'U'G?0 ùqãÆd]×Oßúéx<ðŽÚÉmmm³gÏNìêêº÷6A”ý1 ãõ,ørXXXŒÂ_÷7mÚ4¾®®NÔý×8ò;‹ÅzïÞ½8 =€ÄyìO¾ Œ»téRûüùó“ è.xM`AAAÑúõë?v¹\§Ÿ¡º®mllŒ=wîœóÀ´¶¶&:ί àk/ß_œ2eÊÈæææß(cýÙi†a¤wtt8óóó­¥¥¥‰‡£YáG›öǶ¶¶&˜ÍfšššÜUUU}W¯^îííWØ·hæû/ÓÒÒÂ-ËOkÍ÷¦asìv{èåË—›7o¶ÕÔÔ$ëº~AåÂëÃCˆêÂ$tŸQÀ'ꬾ \âåo¢A¡dô²st…Ñ,À  ÎÝûóÔãò·À=wÚU<¼Ù4BjG€è;Ê~¸œîø‹ÿ\uš ż“IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/editRedo.png0000644000175000001440000000012311354101152020746 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.37708 30 ctime=1381134668.377080071 qtractor-0.5.11/src/images/editRedo.png0000644000175000001440000000033211354101152020233 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®Îé”IDAT8Ëí”Á à EU7rf23ÁL0“{HÔ„P·¤Ê‘'qÀ o›o“É™àž¨YË!Œ ?]ÑZ¡Ö>žCò)6PÍb Ðv%Û:ѽ«´ï û—×RìC ‹žd #Ò?ÓEaußÿ¯©x›·ÄC¥ Å­¡îTÀÚª”t‡º„1£¾ÒLÅíèüC&÷ñOHíC­ï°IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/viewZoomOut.png0000644000175000001440000000012311354101152021516 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.91408 30 ctime=1381134668.914080079 qtractor-0.5.11/src/images/viewZoomOut.png0000644000175000001440000000034711354101152021011 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®Îé¡IDAT8˵SÁ à ¼TÙÏDÆ#ÌtÌä~ˆÒª'!ËÖùlcþ€€VgŸ‘ã+,q;(Iµ ©$s7ó¶KReyŠÜSªwɽHƒÕâ¶!¥T|çüq [ïfä+¼ND¤©Ü ¥¼0x×d›\ ‡ÛUæ 5ëSェêí:G/ñ±È°;+²>XhŒñçÏöõ—øÞºªTFãHìIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/editModeOff.png0000644000175000001440000000012311354101152021374 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.91608 30 ctime=1381134668.916080079 qtractor-0.5.11/src/images/editModeOff.png0000644000175000001440000000030611354101152020662 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®Îé€IDAT8ËÝÔË € EÑ7ÑZÇžìÉ:,ã¹P Í0,ô&¬H$|€¯5Tæ`°D/Êch8L² ÎT4μHœ¶(œwEà,ÕŠ³V Χ¼x ³ã‚oVìæÙòòT•‘&Gµû/Cµ‚»²»êö¨¹ EXœxjÆoÚ*•fÅÙÂBIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/trackProperties.png0000644000175000001440000000012311354101152022370 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.91508 30 ctime=1381134668.915080079 qtractor-0.5.11/src/images/trackProperties.png0000644000175000001440000000046211354101152021661 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®ÎéìIDAT8Ëí•;Ž„0DŸWsrbâÞ3µÏÔ}&:æ8½x†å“ÀL6%!a#?Ê%ÀWoRªjšYº~ðsjf˜™Ù~œ™¯‰Pkå®ãšˆ5‚R+ªz/ÓL23Ól¾o9o3þB?-ëÁ²Aµ‰{AJUeš&†aØÁܽì&U5ךÝîšYž x{l_¸;9¥2_N»®C–¦­k?,ˆ»Ïö„Š}ßÿ.9ÌøqþïÜ&3»ÔªCð8ŽgÛ¼n¼CÛã‘7yíwpîn´©A?úkùH™äÕÙ3IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/editDelete.png0000644000175000001440000000012311354101152021257 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.37808 30 ctime=1381134668.378080071 qtractor-0.5.11/src/images/editDelete.png0000644000175000001440000000031511354101152020545 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®Îé‡IDAT8Ëí”Ñ € DO&sÖ€9À9p²úaHP m*‰~päÊë¥%S_+=Juœ'C@ çé ©Tž¿<}b߀S ´ÏùÙ`´9í\T@@< iDp†îÅ™€(¥vBZÊÐ ˆ+°”ÍÌê-Êò†oi¹í§7`ÅÅ0úšúN»{h ~¹¯IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemAudioPortPhysIn.png0000644000175000001440000000012311354101152023127 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64208 30 ctime=1381134668.643080075 qtractor-0.5.11/src/images/itemAudioPortPhysIn.png0000644000175000001440000000037711354101152022425 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®Îé¹IDAT8Ë•“Aà ‡¶ÿj~Æægî˶ Q‚‚/‰±×^üf®çÙ°$×$y¶1àˆpDx–dIŽÛ6ð==Í·p6¸Þóüi @Îmni$2멪ÕvÀ‚-^åhS§ "Hi¨¦´ÐÛ¾'‰ˆ»zªyÞä7 Ÿ´@µÇ-ÑCºü€X$XWž¸°EºP€Êëâ-)¥å°½•W-Õ¿1úÊÃýè’L/Ói¸CøÁ˵PoÑ|IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemGroup.png0000644000175000001440000000012311354101152021162 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.37908 30 ctime=1381134668.379080071 qtractor-0.5.11/src/images/itemGroup.png0000644000175000001440000000146411354101152020456 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿaûIDAT8Ë}’Ohe‡Ÿ™o¾™ovw²Ikt·­”niSi‹ ‰‡-ÁÙ€(æ$жT*‚5¥”"´JEkQ¬7E²bkÑjZ1mÐdÛÆÄ¤uógw›ÝdwfgÇKµM-þn//Ï—‡n‰ëºòæ9‹E“ÉäS™Œ{ääÉÏ–{{{ûnÞë·ÀëÝ®ë*€x<žN$>üèƒ÷ú•)ìR©Ôí8Î}ÿ0ÆuÐð}g.—Û–Ïçgt]ßÜÞÞ¾{ïÞ=‡ö?¿/Òqg«váÂWgþäÑG2/Ž\×ý-›ÍÖµžžgrrò± hlûäÄñ~SúñŸ†ûö<ݹµSŸšúƒÓg†› ýÐ.2éqÖÝÿz†‡4¥Ô[oxí¹—úŸl3›E0 æù”çùah„ŸÎ’¼{=}é ¬•ÓXm]D¶<û*ð&€¡”ª¼òBß–† Ñ©,×8?œãÔ£+ÎÓw³iÍ»ˆÔ¤VI74M ÃÚUª W¸2soÏŽ‘_ x8ÝÍWÐj£P­ ¤@JÃR« B¯Â×Ù!pºØ˜ÚÁ3] LÁr)ÀŒ( Ã@Ó4·)ðë+äÿ*°ëÞ ú0v}†H)B ÉHç¿ußãZ¥Fà-("l!¦i"¤ul£MÓô0 oœ¸4•ž^Î7ÅäÙÄa›ˆXÉûúÙ¦#Šj¿ÊÙ‚¤Ý᯼ ÍtúśÙIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemMidiPortOut.png0000644000175000001440000000012311446201132022306 xustar000000000000000027 mtime=1285096026.477404 26 atime=1381134668.37708 30 ctime=1381134668.377080071 qtractor-0.5.11/src/images/itemMidiPortOut.png0000644000175000001440000000050311446201132021573 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ +|tÚBÃIDAT8˽ÑÍ ƒ0 à—žX!Sx¶±X€#ŠØ‚8° '`„xŒ×KS¥jùR}Œü9–ðÏòÞSD˜¿=®à¦iPðô¯"Bï=I‡a`]×_›b’œç™Ø¶-·ö}Oo<Ž#Cø±…UfU…s˲`]Wt].õº=lfˆ1"ƈišò6·¹A‚96³Ÿxw@޳îèðTU`Jàu°s¹‡X–eÊø:®ªêÚÀ×ë¾[O‰­˜‡·#%IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/formMoveDown.png0000644000175000001440000000012311354101152021631 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.28808 30 ctime=1381134668.288080069 qtractor-0.5.11/src/images/formMoveDown.png0000644000175000001440000000030611354101152021117 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®Îé€IDAT8Ëí“Á … DŸÆŽöׄeˆeHMNMxñ€¸ø^Ýæ‘Í ðr:O\—kMcÒéþÐ"KòÎ0—zÿv…P¤àEçÄðSwèA0²™ÝzUID`>ã¤4»M¼‚Ôæf•=ˆgnjHËüw‚‘ƒ‘÷?ðx.ͼ:à…·cIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/editSelectClip.png0000644000175000001440000000012311354101152022104 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64408 30 ctime=1381134668.644080075 qtractor-0.5.11/src/images/editSelectClip.png0000644000175000001440000000021211354101152021366 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;QIDAT8Ëc`¸ÀACCÃlæ°`lll$Ú! XÅ™hås&º…14ÌHÅ”E®ˆ¢8òpEÔÈ<úäB’r)¹pç<2sá(‘£µ¨¬ªIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemMidiClientIn.png0000644000175000001440000000012311446201132022377 xustar000000000000000027 mtime=1285096026.477404 26 atime=1381134668.91608 30 ctime=1381134668.916080079 qtractor-0.5.11/src/images/itemMidiClientIn.png0000644000175000001440000000064411446201132021672 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ + œ¡3\$IDAT8Ë¥’1jÃ0†¿e<æ<é:@;ôõê)“Wõ"oÈIƒUÒH˛ҨÓÐ$ V€èî& Ó^‚›wQR& ß+“+ž5J/p@n½ºAÊIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/formParamsOff.png0000644000175000001440000000012311354101152021751 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.23108 30 ctime=1381134668.231080068 qtractor-0.5.11/src/images/formParamsOff.png0000644000175000001440000000030511354101152021236 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿabKGDùC» pHYs  šœtIMEØ 24½t‘RIDAT8ËÝÒ1À CÑ/ëÞ)— Ý€¤d©ðá'@_FRúl[Ì]’W€÷&^2HKþ‰—€’ÌìtŒ2€}våˆÊÑ&jöæ Óôx?60ôkIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/formDisconnect.png0000644000175000001440000000012311354101152022164 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.28808 30 ctime=1381134668.288080069 qtractor-0.5.11/src/images/formDisconnect.png0000644000175000001440000000105411354101152021453 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿaóIDATxÚÅ“_HSqÇ?÷îŸÝ®,u!ÙV²,‡õ ½H“zjBT/¦oå›HP”EOõP/½øVà¤p“ÄŠþFK¤\èls›Ê6·{çýõTl7…‚œ‡ßï|Ηó;çüà›T|qa|±97¿@+‰õ±q%̹l† £€øôáƒï·C©7ÜŒ-pòå2AÀÿ;ùRö#÷ã3øyÐ Å9ÔYJêɱ£ÊÆa—]ûUÔ`’g½Û¸šøJ×½(Üž£0’D]$š5¸+™žd?]ÍûYB|ÈÐîkdB‰1Š!]™!ÉÓ„ÐÍØ$*»k™j«¤"gP˜ÌÒœÒé&Ùó:ÍqàQ1/›tAb NË«e4EƺÕA(³Ê±·iNͼ¼Öh"=|ˆÓ>µ‚¨±ãl*çÉ7Àø+ü4·NÕÐÙÿƒ ¶—Qï¬ÅZÌ…NÎ,}ãZ$ƒ;°@(ª‘ݧ²³ÖA½WÁú4Åè*¹.Ì!0ëghñú¢AA|€£ËÅ—ç^Ęãrm%ÉÚQᬎ{cˆÁ݈V'pö£ÊT÷naé¡Ѭ2iÞ`Z7q}¯Â|ƒBÌ]Ƽ }æþ”[hª²—`d½ÞÉE¾ž9 ÿô7þx¼°Ú]‡‡IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemInstrument.png0000644000175000001440000000012311354101152022236 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.91608 30 ctime=1381134668.916080079 qtractor-0.5.11/src/images/itemInstrument.png0000644000175000001440000000033711354101152021530 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®Îé™IDAT8Ë’Ñ ƒ0 DÏ-Ù…%üí%º‹g»~´F&Ĥpy/gÁUe¼›™`áÖ ÷>ÝSFUéî$Iü5‰çìîkIGVM^yAf†¯ ‘8dßRÙ[DrU]6ÙFI†c¤Õ?)%³VKfp4É—îRRR JÉÞ®î×Ir>IžÀIË Iä?|Do®LÇ.IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/trackRemove.png0000644000175000001440000000012311354101152021471 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64308 30 ctime=1381134668.643080075 qtractor-0.5.11/src/images/trackRemove.png0000644000175000001440000000053711354101152020765 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®ÎéIDAT8Ëí”-rÃ0…?w Ë;Æ õô¦1–îL¢Å¢(æ1.ö!‚U`»•lù§IÊú˜w¥÷vß® ÿø%ô¹yRn‚`.·Lz!˜Ë‘,ÚÊ ¼¶ À0÷È<_H®»ªÎ^uÎûÖ7Z1)ðÒ‘§S¾úxZË:ôt k‰uå  êĦªNB#µ‹²"TégžS–%/ÆpÊs²,@D’Èt´‹ÁZû=(kmë½îãm-Ò¡@]ס 1àùp@)ä7— ÕnGÓ4ˆˆÿÄ%µî_VÀu¿Gm·#ÑvUÇã(žÆ—ög¼éùU-Šb$º\ñ ýµˆ=ŸîF2~wÁô5&üq{cù;|t³'±‡œdIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/transportRecord.png0000644000175000001440000000012311354101152022402 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.28908 30 ctime=1381134668.289080069 qtractor-0.5.11/src/images/transportRecord.png0000644000175000001440000000075211354101152021675 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;±IDAT8ËíÓÁjÔPÆñÿMÒ”® S«gS,(*¤ ¸q'‚Oà‹øŠâB|WnÚb¡ JµÐŠ £3¥Í$¹÷~.’‘b§“éBW=p7çÂ/çæÀyýë2“.Ó¥¥nØj=7ssw±E”¢(²ìCÞë=]ÙÛ{}føçòòfxãæ%·rõ‚_X@A€Y‹KSòOýáööÖõÏ_ºSýNgݬ­u‹NǸ(ÂH „‘GÖ’ïìè`cãÝêîî <ú»‘ÌϯjqñJ6;kÊ4ER…x_¥„‰c´Û·Þöûï /'ÂÌÌ<;Š¢v‘$8©Jˆj¬Jüçc&†/€É°lyoØÿEq0¨¨fP%f4ÀÎZ¬µGá³aœÿå8*„0^u«î œD>ÌâF¸ÌsÊ<ÁMñ¯ p@9æ.8Cq–E¨‡SLïM›S§õuZÁ~#ìࡤ á¼àI#| Þ{ø6zûqǶBUÂÖ#x3õJ¯Ã¦ƒË@ '-ë¤E…Ž]éà4ø6t<ÈáÕ!} Wb_K¸z^ÿ§~¶*íô€_¯»IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/viewMessages.png0000644000175000001440000000012311354101152021651 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64408 30 ctime=1381134668.644080075 qtractor-0.5.11/src/images/viewMessages.png0000644000175000001440000000056011354101152021141 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;bKGDÿÿÿ ½§“ pHYs  šœtIMEÖ ¸RÍãýIDAT8Ë픡nAEÏ#ü‹@ðý|’¤b7)_S‹àšR…EW´†TôªšÌTîÞ f)a˜Ý„ÖpÅ$3;9ïî{™ WYí$“Z‘æfÇÁ™´!„a¨¶‹@fjW$˜L|Çëö¾@‚éô)Éèbqû[aOu°+¹Ÿ=˜”î£Í¹{ééaôYûÖ©;.ÃïegÝVw¼+΃/Ï­2sÚ±+ƒÝÿ:nþN7IÃó—kÅö’å yxôå ‡7|€Ràƒõ;.Ò½n¼FµA3C»P¹6¸HŽEÒíxk—n{tÕßèq}ƒÁ¦àIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/editUndo.png0000644000175000001440000000012311354101152020762 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.28708 30 ctime=1381134668.287080069 qtractor-0.5.11/src/images/editUndo.png0000644000175000001440000000032311354101152020247 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®ÎéIDAT8Ëí“KÃ0Dǹ=ÓäLæLáLtQ5þÆUTwSy$6a`i©V¸M÷Ƨ!|àËK“ûņà”AÁÒîÂé)AŽØD¦ Ê÷mXÀ 9·Ù‰PÝÔíc÷f=NºŠØîL°GhV¦ `ßë©F§Â ¿–P¼Á:ë°º”©ú té_õJn•º!”IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemMidiClientOut.png0000644000175000001440000000012311446201132022600 xustar000000000000000027 mtime=1285096026.477404 26 atime=1381134668.76808 30 ctime=1381134668.768080077 qtractor-0.5.11/src/images/itemMidiClientOut.png0000644000175000001440000000066511446201132022076 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ *.¹¹æÌ5IDAT8Ë¥’1jÃ0†¿gÈä1 d6:€¶,ÍÐÜ@ó;@WuÌ<çÞ¼i „Ì9 £!à@ꪵk§ö!$ýï{¿àŸš8çâ_‹sdƘ‡‹½÷7À âìNpOLjЛÁõ‰ж-§Ó‰¦iX½?ó2bóœ×ùœ·ÙŒŽµ p½Î"Âz½F)Eº®Ùl6üô?Å.Ëk-J)´Ö(¥°ÖR–åÀ;ˆEQ µ`¿ß µ¦( D€Ëå2X.—½Â¤´Nççóyb)] išq@aн›"„ÀõzÔuýë¿HçY–}?£÷çmÛ²Ûí8,‹¯Ø)Ñáp`»ÝbŒ!ÏóÎg"«ªŠ@¬ª*ŠH¼ãJD¢1f`þÜëé;GŒY\ú§¸IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/qtractor.png0000644000175000001440000000012312162667325021067 xustar000000000000000027 mtime=1372286677.433926 26 atime=1381134668.23008 30 ctime=1381134668.231080068 qtractor-0.5.11/src/images/qtractor.png0000644000175000001440000000375512162667325020370 0ustar00rncbcusers00000000000000‰PNG  IHDR szzô´IDATXõ–kŒ]UÇÿkï}Î=ç>æÎéLçÕéLÛ¡thiA m¥ÐD|¿h‚ئZR!~ÑD¤¢ÑDcÔÄIü M¤ °¦¡¥)0´ÐN§/;í<î<îëÜ{î9{ï凛vÒNa%ûÃÙgïõÿísÖ^k×`ÌLþnœ®ÄáÚmÉÎǾySG{K³±6:úþÉ¡¿zö0óIxÏìüö–Mn~¸9—½Þu_kr¥zvr²°ÏËûûÄ/w½öI4<ûÇþ|`ç¶Õ*Þ{ù|B‹[¡««$Ü™·‡hÛOžú¸Ô3;wüôKŸ¿ë{'†Ocßþƒ\,–ëRž+‘JùtC?:»ºqìÄÈcn}üqúÿ9“W«þé «ïÜòð—Ÿ*ÌÜ×÷´ZkrR*()bª×C>?r̆–õ.½óÖ›o˜ÞóÒþ À#ÛøÎšþ›[KJIc ãZk€-„ “ùq(IÔÓ³ôŽ\cöàCGOÏ÷'®R¿cEoçÆB¡­5|ß3ÃZ ¶ÖÄÚ@k 6 ih踞Ê6 l¸ñûš®  )—YœkÌô–Êxž¶–uA̰ÚÀh c-˜f–§N A ºëg?þÖ×kÌ´&“^S¬5¤ˆã:l\‡ÕzÂÌ0ÆÂh k™™•JE?íó¿ÂU$\™‘R€ˆÀÖr†k5„Õ*¢0„Ñ1h6CÂZÀZ†µ !&óã°¶¾ö»;¾¶~Áa=ÖF()`t„r©ˆb¡€j ÖÕ#X£!.B0˜Á€@ÖQ.ÐÓµè¾T‚Z¡†5¥jA•¦ò“(˨×Bè8‚1Ö °`&a-@Â7H,`"_œÈç ¼DÅB£&©P¬P­V‡Ö°–À "‚ €ˆb&fë!¬ÑKüd¶mA-èžI§3)”JFÇgÔbÄÆ[ž!ˆ”D$`-$HJF[Ô£ÈûÜ=·¶Àïž~”Ô•Šß¶®ãÞ·,~¦°XJlc– ¶ ! ) ¤ )%”T,¤,“a†P{ɬǑò\‘€jµŠ+Øt{ï½oëýs&¥Z‹¥*ò°vÝj>~Œg¦‹Hú x Žë°ëºP D°–É2\ׇŸl@µ¢¡µA„‚Jí©XÎFè ÷­LJ'@Çg7¯ûµãº«ÆòÁP~ª\‘BЪþ~ÏQ01y^~Ò‡çûð’7©@©46¶ÂK¦Qb‹éÝ/¾ùûr¹2Ñоül迱½µa›rœÓ‡ß}@uIWKw2•Y=|&ÿ÷çö¼ñ‰W^;qóÓK–=ºjõšF!%ÏLMSÇLB€¤3AÃOe‘kn¡8ÖR¡Z­ç/\€Ý{öñeA˜I§›—v·?43Sð WàÜH¾žÉdÌòÞ®<€W¼xf¤ð—Ýÿxåm4–_·’z–¯äŽî^äš[É÷“$ å:hlj¡öÎeÔmb¢Ù+91UzÀÌÅÚ~)À;GÏU¿xÿ݃}}ýÍÛ¾ñõEQ„±ütwsSºéÔéÑâ%KÏþé¯{Ÿîénë»gó¦[[Û[)¬[Ž"z"Öš×KA)$LNŒ Š":<üü¥íÚe1P(V¼r%Ôc3 ‡Þ>¾âÈ{gú*A°òìFËØõÒ¿+Au@ @@}ï¾#§V.oéïlomM¸y~†3‹É.B¦!ÏOÁõ’Ê34>zCÃçÿù¿= öa‘`m{kzm¤ù+Æð²LÚs” grºg³éXpQ±X w†Õ@=²åþmw¬_;Ífáz PnÆ€$˜AŤ8q|ƒG†ÞÝõ·}ÛÃ0|ý£Z²†¾ÞÜz»›·:J¬”TBŸv³iN%}Ã`I ksjt¼0tâä…‰ÛoéOl¸i}{[óÒTÒ‡” ”*Μ9;qîçž?ðd¬íËìGHÏ[;Ûü_¸Žôgoäì2¥$˜³i–@R@I ×U¨ÕôÁ·ŽŽo'`ég6®º³)×ÐEDnµOžóØÐèKŽÏÿ@0Ž#Ïy^¢˜ô€•R‰Ù,…€˜D€”‚B5 ¼Ë”|ußû{¤çÒ|@@ø¡îü‰d*!3™”—ô !Õœ(Íõzââ³³·8Ѝƒ˜šWÖbÏŸ¨U#¤SI•òÀB¹R͉ϊ’ !.ÔêVa6£¿rEÛ@S.“v`­†T”ëB\rr!fË­ ÄâãH<ôÕûžèhkÞQ®L# Êl∔ë²ëyPJAý‚¤`œ™`Á—nlµ6Z¿¼¯mmí°”p$'½ü„‹TÒG2é#é'à{.¼„×QH¥|´·å6¬YÕq÷Bäå0vñõ×uÔ«¥RI¾KŽ#Éq$)E$‰‰$È‘EÂuѲhQ˲žÅ.iOO½óÞùƒWð_ÈþmÀkf% IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/viewZoomTool.png0000644000175000001440000000012311354101152021664 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.28708 30 ctime=1381134668.287080069 qtractor-0.5.11/src/images/viewZoomTool.png0000644000175000001440000000033511354101152021154 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®Îé—IDAT8˵“Ñ Ã D/U7ªgÊ¡k0Óy¦ëO@Ô” Zõ$„@öÃæøƒjÆq¼…µ€dÝ0³Ql'‘TI‘,Õ\—]“š™'dÖN=½Kî!oºÅ_¸ñà‹–@23¸ÒÝ‹ix¶Á1¹§©•åBƒ}Ú÷]’¦vŽ^â2dX]„Üåœþl_·ðQ/ì}¤…(h£ËIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/helpShortcuts.png0000644000175000001440000000012311354101152022056 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.37808 30 ctime=1381134668.378080071 qtractor-0.5.11/src/images/helpShortcuts.png0000644000175000001440000000150311354101152021344 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l; IDAT8ËÕ•ÁK+WÆ÷Þ™I¢¢ ˆÁìÏ)BÀ]©;ÿ]ºp£DqÕ¸,t§A\èªÐ¯  ‚•ЄÔÄ"d43sçvQçòRK—oàÂeî9ß9÷û¾3ßÚ#FlnnîïïRJå…c†ÎµÖoJ©~ÿ_ççç>??7½^Ïôz=ÓívM§Ó±ëúúÚ¬¬¬|YZZÿ·|çìOÙl­5B´Ö â8 N“J¥>ù¾?ôÿ™,?äI‚ ¢!)†á‡t~ì8q³³³Ãóó³}oŒ!Žc„)Ñh`!®ëâ8Åb¥ZkŒ1cR"„ îüðää$„aH†h­-ÏR޾°°½½-]×<>>rrr¢Z­¾ï£”Âu]2™Œ½…RŠwеµ5•6›Íøìì̈ÕÕÕÏÇÇǬ¯¯_‹ÅbÒí`0ÈŽ»ï{*• Æ.//Qêoœ——ãºî“1!ÕjõÏýýýJ>Ÿ/ €¹¹¹Ó£££fffˆãØò àû>{{{4›Mvww­x777  …QQ©T~©ÕjkÎ;Wa"¥DkMEh­­½Òé4RJ¢( ÞÞÞ¸½½ell cL"ðä+’!H"é*Š"‚ °B !ˆã˜»»;J¥½^F£Áëë«Íµâ !PJqzzJ§Ó!–——™µÔH)QJá8OOO\]]1==M¿ß§Z­’ËåH¸¶'Iõz Èår8Žc;ô<)%žç¡”¢ÛíR.—9<<$ C¦¦¦Râºî°Ý¤”d2¶¶¶l‡_¯d <ÏCÁÂÂAP.— ÃÐRçyÞ0°‚v»M¿ß·>uÇî3™ B¤”Ôëu&&&†b¾Îö<ϯÕjÖø —J)KS»Ý Q­V½T*5“}×*°_¦ÅÅÅï...>ßQÏóül6ûk«ÕÊK#¾”J¥ëF£ñÛ7÷Ëã/›è„4Dì7ñIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemChannel.png0000644000175000001440000000012311354101152021436 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.28908 30 ctime=1381134668.289080069 qtractor-0.5.11/src/images/itemChannel.png0000644000175000001440000000055011354101152020725 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ 7"´JšõIDAT8ËÕ“¡nÂP†¿»4„,d@¨A2A²†Lî0ó`xtƒÅ x0‰!´ )íÖ.½—%jº)Ž9çÞ›ÿœïOÎ…»46ÐʨÝ{ ¨K)š.ÄH:ÁD1òŒu‰¸¼P©¥„1|†0·V”‹Ìa¹µÂvÜ›©ÍF sØ#ŸSg ÀÁóÁv\ÆovGUÏÞ_SÑwGxJÐM>rjŸ²ù¯áÙSEëÃziQ­”hw¬—Vºðü^xLXBðxé+äd^ 4¿ 6†ß2›C`ûïEºÿ¿Ä°IìߎòëIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/fileSave.png0000644000175000001440000000012311354101152020745 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64408 30 ctime=1381134668.644080075 qtractor-0.5.11/src/images/fileSave.png0000644000175000001440000000031511354101152020233 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®Îé‡IDAT8Ëí“Á †0 FŸÒ„îàîðÝrËÿÿJOÛJEAðA/iúh“>î¦ÛÌln™ÙÆŽ’B0R‘T”¹;’ˆ1LÀoÝë¯>ÙÝã—ÅÃð¿Gœã}âPª]¦/ÕúŵƒÍ7Hi|v*$U?Ïû¦"Çܰ¦3Íëö‰Í,Ý'c¨&»IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemGroupOpen.png0000644000175000001440000000012311354101152022004 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.23008 30 ctime=1381134668.230080068 qtractor-0.5.11/src/images/itemGroupOpen.png0000644000175000001440000000156211354101152021277 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿa9IDAT8Ë…’h”uÇ_ß{ž»çîv·›ûátSk‰#ZÍÚˆÚè R !pØsX¬‘•’âÊ’ Êf«Õ°I²Ž˜³D–m퇮»Úìnλæµ_m·»gwÏ=÷íL†½þ{óáoÞ|àt]·/ÌJIII]MMÍñ¦¦¦ /¼ÛîWêºîÈËË«ž=ÔøJÃͧNÔ/YœïÖ4m}mm­÷GÜÕl6[FWF"‘a!DÜív?¶qÃ÷¾þêË;ï*-È4YáÁå[º«ººzÀ²¬ )¡ëº7 m0’ÉÞ?vt»ÝaWN}ü‰|©þYÏ#–)6R -*Y5Õ³l÷’%×£eIDAT8ËÍ’ËOQÆÏ—ƒ2m­‚BERؘh0Aƒ/bLºÀ.»5®HŒ 6îuÓÄ„.lîÜú¸2Ä "Ê7Uä¡0rÛéŒÓ¹w¦÷θ±Ä¤²Öour’ï—“ó}ÿZè/;ibbâ¤eÙCãË<à<΂ðajjjØž€D"Ñ6>>þ¤ÎQ²­³gGŠÿâº5ï{q>Q5VŽ ôB¡ðØqœJ •JÉÙlöÅ¡£'âCWo®[DZš[åÆì²gl˜ÂNÓëÚÆË硵|>ÿ q‰ÐŒŒŒ €¨ö^¹vk­3.Ÿ:ÚÊáþU”Uxë\ªªªzÏqœ3étº¿áÛ˜fõNWÏ©o‹Û6š1 ZÅv2Œqà<€ —ËY­­­ºmÛ×wÖ8çƒþ¾Ž%}#ØlŠëÛV ,ÿì*EĦˆÒ:xš¦½'„Üh0ÎÁ£®?·É°¬€ì3 ¦‹\Ã¬Š 5Ÿ ”ç2~cðÞnL:× °KàÆ˜J'3ð=ŒÝŒQÉR­0ž¬s÷!¶eT//Ïgmù^éíö›â;€Ke.¹œß ø<ãþ«¤“ï2æeàO1‘¤mÛ"rX¿Øã%ã-öMÓtµÙ°Ð»Ô¼Ì[q(ÌSîúé¦^þßt›?Û=rýü42ù­ï•8ŒËŒ$IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemRpns.png0000644000175000001440000000012311354101152021010 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64408 30 ctime=1381134668.644080075 qtractor-0.5.11/src/images/itemRpns.png0000644000175000001440000000104511354101152020277 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ 7¤öµ²IDAT8Ë¥“=hSQÇ7-AJ¨‚„Ö*:8Ð)¸¹º¹ØÉáÝú ¢»—‚]\|Y\qì$*(Ømá"6бh´¶•4_}yïïð}O“ñÀáÜ{¹ÿçžsü§™ØºïqgXÞï³úÃüv OkŸë#££—ñ=A µÛ¿½²^U†zû®\Íd2—€c»Z¾tá…£n|S^SÓ—jÍ@¥×Þf:žFúj-ic;ò­š4ï}ÐöŽ´Y—~4|=}>÷Ís&.JÅ7~W_YR)¸R² ìäîý'LÍ<âáìÙ#ã‡ÀäúuÁ®Wu¯Ö„°C®7ZT¾oQo4Iîg,;D.{`ävEqZµ×-wN¹\[°¬>.'Þx.7¨¨sTLÔ`¹"•V¤ùåÈoL¹êg€óW~·—,Ó']n.Z>~)3ƒµ6‘‰ëºý‹xñ¨Ëj%Ч‡'~ ÇéÙº ±3+–ƒCQ|öõžçQ,{B€ÃÃpë„K[Q<;eÐçóù¦‚¤ó=§Ð ãEœëxÜdŒy¹Ûÿÿ Ä.J PBIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemAudioClientIn.png0000644000175000001440000000012311446201132022556 xustar000000000000000027 mtime=1285096026.477404 26 atime=1381134668.37808 30 ctime=1381134668.378080071 qtractor-0.5.11/src/images/itemAudioClientIn.png0000644000175000001440000000037511446201132022052 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ *)'Ýso}IDAT8˽’K€0D߯Íäh½.ŒŸjý ‰lHó†ÂÇ’»Ç[±»Ó˜YZ\J˜¤$§SÎ*b@Quð53[,½Ê`~dÅÝÑsÎEw«‰§€fŠ;h\´éû©ÚÀ9h ”]A÷!öó·Ìž‘‹mÿ­ á+!ƒÎ¯yIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/transportLoop.png0000644000175000001440000000012311354101152022075 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.76808 30 ctime=1381134668.768080077 qtractor-0.5.11/src/images/transportLoop.png0000644000175000001440000000056111354101152021366 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;8IDAT8ËÝ”1NÃ@Eÿ¹t”ˆXˆîDe×(=Bô@AeWHœ 7À€DG…„DÎÆ‰h¼ EV6I6ëµLe{Foÿþ™1ð¿#ñ-mý¼1ølçÍ Þnª(Ë5Ž6{8€²¬OÈïuœ†îo]p_ÐZÀßv±:u¹a{05]JëȆb)"/󊉡Œ½é ¹% ×^èÞZ]¾¦®g‹ÞÆðÃÅ4MuÐÑð=ÊQ(G"ÊŜʋñ±|ߥ?ÄŽ_ú‰ÍX˜ë)„*ø—E·oB÷u“ÇiK¤PH[",ÏgV•¬Ø½ÁûW}53!f-W=Ïqþ“ÃÜ XV¢ã*ŽDÚ ¤¢7fæ~¾f÷înöD–G¼•‡Ù5øŒßu€lÒ·³Bô,Ͳ­>Í€[@X%‰DÎÞú›}öÏ$ßÎ1T»°Y‹rÀ«´œçNj,;é±á¨ßäδÍÝ'Ö ŽD —u‹IÜÚÉ—µ!ã;« T,Å?€ðüŸf4P°kù7®zâskêÚ7ÚBò§ólrÁšAÏÆ¥¬õù<ÍÒQ´?P×G8ôÏtÑ·¢Ì^ÝX¨ú´Äài*@üÁ›y‚Õ÷ÑqpE<©r?Üà4pÈi³š\vhvò³ÆÀ^CÓ-[âX.†(¡¸wSºiNƒ3=˜_¤˜Í+#|]Uª}®ñwš§)FG2t]ÀÄ+Ez |@ PH äg“þÆ£>Ÿ‘`?JIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/editSelectCurve.png0000644000175000001440000000012312211607471022311 xustar000000000000000027 mtime=1378291513.535077 26 atime=1381134668.76908 30 ctime=1381134668.769080077 qtractor-0.5.11/src/images/editSelectCurve.png0000644000175000001440000000102712211607471021600 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;ÞIDAT8Ë¥•¡rÛ@†¿õ˜e¦™É8%&E– ]Ð,‰ð©¯Ð )ïôÎÔ¢¡AE 1¸3t Ãå é¤t $9—³$ÇíÎh4«»û´»³ûŸ0lX m°0‹¿å°– ̨bEÈ[?X ¡]?6ãÐQÅziÊÜ92ç°­Ÿ$ ò´[…«ÞC’(eA6Ø®a*PdI¢xÀ0M´i˜~ÈÚ+EY`'¶ÞÊÓ{{’ó9ãö=<¼ƒù+ØDlB°q;¨œ§~·P¹„Ÿ øó÷¿x¸€/€‹kÞUc£ŠØ®ýîÌd6CDøzuÅ'óó4g2ãL„y ´Ï£í,‹q­<º±hå½VÞ+ o^£ß¯QçP`Ù¤n8ÂLY kucë7 ªª€«‚:WCʽIêÈ[p?ÊŒjî%¬–o버à¾<,¿Áý%¬T÷Á|°£È_|<=ý­ ü¡è:T³±GÕÚÖSå‚ ´Ï^ùNT,¸¨7û€á³GÒ×ξ‹7ŠH[‚`úM†¤¯™ –VY —Zæò>½EÑ×üpä °O2»»"žñ å»Xp‚Îè´ñ¡k¦CÁr±‡ê<î9ÌÀ÷Cþ“Ð÷]ˆü‡ýÜr$ÑÉX‹YIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/transportMetro.png0000644000175000001440000000012311354101152022252 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.77008 30 ctime=1381134668.770080077 qtractor-0.5.11/src/images/transportMetro.png0000644000175000001440000000070011354101152021536 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;bKGDÿÿÿ ½§“ pHYs  šœtIME× #?ÊMIDAT8Ëc`ƒ¤ýÿ/ì|þ?±Ê™ˆ5´×ö%CU‚$ÃL¢ g!Ö_üÃî‹»Þî5d$ÍÅiÿÿ×>cøýç?Ãï?ÿj§ûÀ]-|÷C~„8ÃÛ½§ÈsñÇ/QøyÝž KwœÿŸ"ÆP—º™¼‹¯¿ÿ?¾þþˆ+gþ¯¿ÿ_Øùüÿ¼îGÿ‰ o¬ßA1@Øù<’E䤊´ÿÿo¡ƒ°óùÿ¶¼ w18¦;àM!xÃøÃ—¿ ç—f``Hgv>ÿ_O…‹aCï^cc†háNœ‹ÓþÿWzq…áãg„æ·{O1ìŸyb‰3ÃÇÏ”ü¬pº§‹?~ýMFéÐô™Îˆ°Äñ­ñ™ÿÂÌ8]̈͵ gÏBØ006FR—ÎH|:†i$0b&5}¦3Ž–Òô¤’Áo^É—IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/editCut.png0000644000175000001440000000012311354101152020610 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.76908 30 ctime=1381134668.769080077 qtractor-0.5.11/src/images/editCut.png0000644000175000001440000000031111354101152020072 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;IDATxÚí”=€ ƒ‹á,žÒ¡§á@žÅ¤ ÿxÆA»–ï•R~]Iíík¤ LGðæ©S¾&¹Ä`mbÎUg.¯¹ØŽÇš'˪eE¥|ƒÌ[‘¢hó¸;ÀŸt `(ôy :wÃqÙ ºÂ½«ŽâbòòÒ <€ r¬ùÕ‚d­ÉúÚ™@¾­ öM5Ô‚ IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/transportPanic.png0000644000175000001440000000012311723216126022226 xustar000000000000000027 mtime=1330453590.950629 26 atime=1381134668.37808 30 ctime=1381134668.378080071 qtractor-0.5.11/src/images/transportPanic.png0000644000175000001440000000177511723216126021527 0ustar00rncbcusers00000000000000‰PNG  IHDRÄ´l;sRGB®Îé·IDAT8˵•ÏO$EÇ?U=™Åd1ô4r#Ä ‚†2{`dh†Dþ{ñài³'ÿŠÍz7ѽ20€œÈø#aYŒ¡»g˜´»‹,3vOWy©1ãn<ØI¥Óý^êu½ï{þ§K¼Âþpìò}fV¨ÿnÇ*•ÊCÛ¶ÓZë¿|ƒ Hfggï{@Ô»77@Ç*•Êã¡¡¡LÇé“““´ã8À÷}FFF”eYI†\.wøð€¤ ‘×€ïT*•Ç·¯®®n÷º®{¨”’J)éºîϧ§§©(ŠzûûûooooL}¼nð 0Öl63Qõ(¥¬¥¥¥§@SJ™!4‹Å)¥RJYÍf3ÜÆ«} ÿW*•‡ÃÃÃi­µôú^@t‚EE=[[[ÏÏÏoù¾OGÂÞ1>zssóÃöžç‰ÅÅÅýr¹\L’Äl—àç333Ç¥R©èºî÷F^˜„ö½Zk©”’Zk±¼¼|´ººú®ã8är¹/:k£õzý‘‘È ”Ѫz€”ã8Âh<mÕjµðp ü¨N°‚\.w?•JµJ¥Ò{®ë~×Qíf´²²ò´T*½-¥Tóóó_Uà¸tª \~­Õj±ã8=@T­VÛ¶õÞÞÞ´)ëÄ÷}Ýjµž;Ž£}ß×ÀKàÐüu ÐÝ:Ö@5NÇBU.—g …Âçõz=Bh­µðPFÍzi’ð¦¹ÿübªOýÛ±Œ¼úã…y×oì/Lt¯›@^tDüÊ™';ŽJuõïëžÿ6šþ•5Á''Jä)IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/trackMidiOn.png0000644000175000001440000000012311354101152021413 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.37708 30 ctime=1381134668.377080071 qtractor-0.5.11/src/images/trackMidiOn.png0000644000175000001440000000125011354101152020700 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÔ&k;¸>5IDATxÚÍ’MkQ†ß{g2“ÉÔ6• jlÚJS‹±B#¢ƒt£D»(nŠ+Kwþ þA]¹P]Ù¸ê¢Ø&“’&£I?&“Ì÷½×…´Tƒk=«sç}xçÿ:ÈŸJ¥2fšæÕP‰« K˜êË[d(ÞÕ6j_777‡§ç¥ÓEµZ-¬®®>”¢'XÑîXËGÓögVÉM¾²8VÒ…;Nǘ¦™­Þ»ûØ_bµ[Ù©z®•îœ9Ô÷ô^fÛ¨+»óñ‰ýÌô™ËDQ´ÑívC 'Ö¯WÌöLw-Ëç–² êEõÕ$‘@‰ös^úÃúû™f±ù 8[¼q¬;„j|ß[䯶ÒT>%5ìò–€!'  óCuÿÚþù ¬ëäã$JóÂZ~Äâ±=ØÇóÑŒ†4TÐv¾í§Õôô( …Ëûè%.¤XFLb„Ô‡/;HR.„8çH’DŒ¬@ú¼a¸ºê 'ŽR]¸©¼ÔbÅW†€Ä|²>™¦}Zq@]¼Öjâ6f)O4.E²ÿK õ@ µšMôÍÈ)¡½Ë™K9å…öüŽk® 5" ˆÁ•®”ž–ZFÍxÙl6_8Žþ°m; „|[¥ ÕRóã|\žpôŽîMmLñüóüwã‹ñªÑh<³,ëÇ__¹\.OŠÓWüµ@ ò,aœ8¤Eä­Ý¶?[–uˆÿ*~^¿í¼ƒ‘IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/formRemove.png0000644000175000001440000000012311354101152021330 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.91508 30 ctime=1381134668.915080079 qtractor-0.5.11/src/images/formRemove.png0000644000175000001440000000030511354101152020615 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®ÎéIDAT8˵SÉ€ \©Ìjhê°ëÀÊâÃAÑ,¯ü`$ËüPá!¶ ÑÂB„-ìLHš¨0¿azOLD Û9\îˆéJVxŽ] —ÎNÔ ‹çâ,@dS8Ò]²xâ ¥i³jµ²Ø»[i§ƒŽ§ xóY>¯R£h û¬#IEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/itemProperty.png0000644000175000001440000000012311354101152021712 xustar000000000000000027 mtime=1269858922.193315 26 atime=1381134668.64408 30 ctime=1381134668.645080075 qtractor-0.5.11/src/images/itemProperty.png0000644000175000001440000000027111354101152021201 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ +@fH?FIDAT8Ëc`ŒXÄÒè™…ÌaÁ¦âÌ™33±‰›˜˜¤£‹±à²&=UmZv‡1QoÖ08{ö,N?S=GÜÄ 4×ÝIEND®B`‚qtractor-0.5.11/src/images/PaxHeaders.10084/qtractor.svgz0000644000175000001440000000012312162631071021261 xustar000000000000000027 mtime=1372271161.859609 26 atime=1381134668.23108 30 ctime=1381134668.287080069 qtractor-0.5.11/src/images/qtractor.svgz0000644000175000001440000001655312162631071020562 0ustar00rncbcusers00000000000000‹Åœ[s[Ç•…ßý+ÎÐ/q öýÂHJyœñTª’JU.5Ï IHH@B¶ä_?ßÚ  "i‹qä“çœîÞ—µÖÞÝà³ß½¿¾~˜¯o«åó?s'Ã|y±º\,_??ùûß¾Ÿ¶“áfs¾¼<¿Z-çÏO–«“ß½øêÙL§Ãwëùùf~9ü¸Ø¼þ°üçÍÅùÛùð›7›ÍÛ³ÓÓüq¶Ø^œ­Ö¯O¿¦Ó_}õìæ‡×_ ÃÀ¸Ë›³Ë‹ç'ÛÞ¾[_Ù—§ó«ùõ|¹¹9õ3zrwûÅÝí}ñÃübu}½ZÞØ“Ë›¯÷n^_¾º½[³ù1ÚM¾÷~êÂiSî˜Þ|XnÎßOeŽÇ ιS>»»óqw½¿ÂŸŒ}jwï9ÂÛ…—›7ÏObpöë›ùâõ›ÍÝï‹Ëç'ŒB-'/¸ðìrþêFŒé7>köŸ2Îü|ý?ëóËÖïï<ü$Dï¶ÏðÔÍfõvwïvH®pÏ8ÅñßÍæÃÕ|üdz±ºZ­Ï¾.¯Jˆé·viõöüb±ùp¶ÿÈêÕ«›9‹!äN,Ü?X}UKÎl–5\¼¸pª÷ço{vzhãŸí÷—¸\òÊþNÛýR—¸\rt°™ ®EþõMê%8Ÿå"÷€‹ŽŸ‰¤ü/uThíAG…ÖïŸüürî_ö§ÉЈŠz^}O•;¡»û‡ë¡¾ŠXÛSº$>Â%éþiûKïû8žÊø¯ÿbß{³ž#¾>?»û^o/þ}¹Ø@ÿïnæë¿b™ùŸ—¿™r×ßÖçË›W«õõó“ëóÍzñþ7~Ök"ÝêÄñ_˜A£©õ2™²:¼puê#³èµœÜ›Bõ‘¦jOh*—bë®›©ü,–êZÊ“©Ç¹±öÔ±Zœeþ=ÒR¥Îb÷ÕØ*%r¦»=9#[%½™„¯¶byPHîí^[íEݯi«ÔkŒ·¶Ê¥´ã¶Š2V3¸¸öz`¬¬ǜ«¹YKt;0–}Öb)á~c=6ŸÒX±÷LŠmš*²~y`•2‹Ñ·=81[ñºØËÈZ`åY±î)L ¬g5×ü@`=. ¥Ÿ0°jð=îl£ë½ù/HÂÄš¡ت¦YH@{9¬Pf¹ñÄa\õ0sÄw¿ÏVÑ僭¼ï¹å¼µU¨‰i¶_n«Ðx%àÐVdfG$‡t`+e›s!—C[yw¼7®¢ûwäàSV„HäÔŒk›¹æ?bB%l 9¦Ã$ÌÙó½L÷_u_`ù§ ¬”‘: ¡P[¦TúÄâæêBꇑÕb›Õ¾Wk[¦YwÍ…ÃÀj=Í ç’ﵕ\`=¥­òÌ')¶¶µU¨5CdáK«"Z8DwÁX+È×Ã,ì:Ù–f¬Oî=j¬ö« EMÀ×ZÛVŽ–Pb(¿ÜV!ÿ1Öˆ>£Ø¤Ñá#ÌqæCz ÷쯧۪ǵºÅ+~ôÏàÕã2Æó1§C}å}™¹ÞÜG)h/.îÐV*Hâï³U*îW*<[pz,[[åžÈ‰/©q¢2¥•‰&ŸâGØž¥ºêG¢ !2]»7°ö…ý¯%p­ë iÚ!$Þ)2Ö=%uotûªA%58s¹Ü…uÑà(÷½ÚYϧ8+>*jòw)äû*êèâãT×Óf&‰à(kwª«‡‚²¸73Ÿª7n?½GØ{o'{êNÍí~›&òŽäÏ‘1Jò>äo¶•M^‡ˆæßºéíùæÍn |v=$Ôk ‰Å“(.Æáb˜FÒd³˜],ÃTXò …6=ëŽ)½—I×Xs¦e¿Õ>ñæF ž m%|O%Aã¥6K ë ÓŽÛkhÅIiÃ4‹+”é+–y˜zj·ÚcÕè%º6À NkîÄ¢w‘‡¸5é™"kTaÂ- R<©a˜R-çäQÀjÇ ¬¸©Î ´#ÿ)dFâA&êîqȳŒŒ‹æÁZf†Ì«¥†'™r ÞVUÔ÷‘Ã[mqH¼kMüØBJå=¯\Â{ÊR1k˜&Çâ¹£²‚„„ šlÇ–q`=«Ø)3_(5@E Íü,'Tç”®¸Æ·hÆL9¥¬æNŠ53Ù˜²Í¥OQþuo$âýÀýE®¿½ŸÑbèÜÏŠ=Þ£5énÈIþcm­³ÈIœ¹ˆ5‰ŒY-5¡YtÁ[fçlÓ»šòèÒàa•Z•{¢úiU™2#ª‚,â1jb½…¼áWìÅK½Ö&—óö”ëD‰EÂ]Ð<˜·7˜¿‚Y„èÝkjEÄÉzX–¦=`„4‘›+sW¸¨-¯¸IY>€wžÈ* `ó,‚@N f?Ê?Pæq©šçø)CÓ3‰iÊDm|§’·›XËáÿ1)¡± ¹­É³P‘5%޶ŽÊD&-b!3ÃÛYB"Td†•g U,C4t§°“€›‰ñàênQ] fS ¥ê‹î!™¸9±òï‰ð@^*fôR䥴÷ذóXÐ<q©ÙMSÂhÊ9KÇîDÂÜEàN%YÝ0 Æ,¥£!|ÐòH‹TªÌL·éU€~ÎW’Öp˜ I@Ñ*ê-À™V©V˜Ä>˜² ‚]GB×& ÊJLZCiV–N]"}Joöc (p×ʈTŠÌK Eæ+JÔÿÎÄXÐ.rƒ% EÄ0Œb`LVµ^9!C´ƒ Oìå ‚… …¬²<©­’žH Tpg5¥bå£EH^ÓÄa à„W8áFªjž0T¦8ÍKÚD^[ëCTö—R`4ÎC"®¼kšpAÌAaÜJÍ9¯œ I(ç}V@â§®wb® ~8ÒrÚƒBÔå’XÔï"T9í´ÉEÀkì–gÅ ¤Ø›2Oa׃¹@ªý4\óä6 aN:^Ȳ Î6˜ Á•®( qPSÉ ‰@’ÃOÚ@ÔâžâØî0¼Z\]}íìßoõËþö eVJ%××ï®ægóæËÕååoo6ëÕ?çgËÕr~§‚>¥WíD±¦¶r±éOƒ»p‘•W¥¶&™ZšÀ>Ñ%iÌ@$à_‰Á²Äg?@Á½Ó zZ,# B¡¥M‚Àµ…À„k.½]9‘œƒË”«ü°MìXz5š„|ñL#u½•¨½Ô]²,i-ƒ¾Awy'àÄý¥Ã®zÁf¿AJð“Ò¾ÀøÔŒ×«+¶Ê‚¯‚ÚB­[&"˜¬#–0&¦A½3¢Ìs%¥€\Ý’ˆï•$¡);¥HÝ1g/Á`ùj U™:QòI[d ¸#¨AÌ+$ à}†-BwBV¯4ŽNâ€ÉY`OP{”y‘9¦D¾òDª”fÚl™ˆW[Ð ©À$à0Êâç†À ¦¡S†ÀH]NíÊxchè¶g3€^®ÅEešYDj)ÏÌh¹+îÈX‹:5™(HáQ—‘ÁÈ0uŸ2&¨…»èÁmËÞÞ¨@€“èN~€ýk7”1’(\‰U±±#-%P@糡aÃ~wU ñ”cjþ9`p`W»KªT"Éx …Ý’Bÿ¬y!üÐ'beók%–ˆ€0‹ûN, ŠE9ˆ\SÜ3(ÿbejõ¢ÆÆhSOȇâRhapÕÐxOÖÊD­)¯H3ðÔô‹à^çLùhtÐКÅH¸JŒÙL‰Ei:26ˆ´åKÜ»!èjf«¯’«2BÐè½Y)e ¦2–ûèmiAlŸ)ËŒ¼sÓ=<œˆÅ‚´[…^€Æ …»IZÍ2™$.£.“šÔ]¥yEo”âÉÊ.P5’æuŠ?5êR÷¦Ý€6…Uv3ƒå)8§%ŒÀ \²#K T‹·Î?Í0dâ'ÂÄFFùêRP£Ö%Y2îV=ÑGŒp.Å’ÁimUIÁ…\ÊFÒ¦#›f„ÎøV)§ü¶Z° Ú9XdŸ1–c™ƒÍÝtWâõV)Ix'•ƒ*¡Å·lÙŠ´‰BAýÊ"eÁ¥f~£¬Š$#S-ø¨›’*Ê®¦¼ Ž<3Ac³2‰áªÔlˆ†÷eˆQ¬Jì&B¶XÒ±d "±? Œ·ð0#8iz•~aT¬Í›‚£|!©(íš¼+äx„†²:Iw1ëï^⤎sÍ„B&þÔ–J£jè¥Z™Ò»S:IE†,ëɉù)U'N V$?åUÊ–P06‹ª… b»Å!‘,<;€ŠwQ3X[ÂUù­x4áP$âëJQ†d–k.X¦¡jâ(ÁåûÏŠ†½-Ú_M4(¸'1·-~K5h- sì"Âdò'¹?k_ŒKMÍ1–ärîÆ±Žz±‰¢t`¡*Ô™¡ï’Œ>Æn㉽0IÐXçc›\ Ý–á-U'Ï 1)Þ y¤ªöì o’ C§txT`.5ÙÐ-< Í)¸Dƒ ²®‘MŸd•Å:ÿ t ž‡-Éá&öO#êwÞ.\•ÞdõÊSßUщz£àH’%1_çæjË#ê\á©ZCAŒ \®†’ÆwNMÔ1YC±¸eÝT&•Z cOªQ2³0 ¦ôJJ|6hŸ^õQUw#U@’$ãýŒ”}Ú±K2ƒl²Ãµb©FƒPŽxį2~Í1Œœ'²'o1Úñ‚²ÙÐê&¯cË)äÈø"À¬JºK- à:rýÄïÚ×ì’a„HŒÙ˜µÐ4¢ &°³Çr"sxÆ[ùM®ÞmV‡Vì_’$DÊÒF¦Â ·¤"ÉùìÆi¡ ¼ÅM (j&{(bo'P“”»†74ªkáÀ_‚¼"ÊV%BÐaЖHØÒ xÝø¨NŒU_;üV¿"æq—Š5Fó9¨<‘!ÆËXü7ÓëF£FE >BPAŽt(¸7wd³Vð¬Øc‰Ñ æÉ‚q»ÿŽê¦w+n•èŠ&ÕÕ¼=&ƒ–ÖI‚óœ)4J2Q_ºD(£”î°â–ûFrÝ–šØÌˈž‘ÚÀë0”õFTÒ—ÄÖ‘ˆ ‡vÅ;æ A*Z| *$=Óœ%‰>BÉ‘œ !wÉ€³9˃ÕmD|U…L8«_¢,M¥Íc|aUÉœô’õÇR—Ôál@Âr¥˜®òjõ’„Ò3^Eƒ íæM¡Áê¶h"QHMí]NµÐ¨c\ØR€@$Q­îP´Ý)?”Þ Â«’IóŠ*ŽÇ‚“ǶÚ×CņÔqTÃ)Y¡. ò&2ê.vÒ¶u¦%dkyt,TGØIÝ@¹ÔMv°µ֪-˜àô},•«å‘ª¹¦"Ľï*¿ G вYŽ!‹u˜!e…aØ®%ÑV)Fc‹’§ÄWük¦4æ8¯£ôäÚ(Ò0R°h“Ýï&ÑT2¹±ç¡•¥'»j÷(æ_NåM³ŽDª–«‡„Ô‚M’zIîeqQ˜Ë­ECM‰lBíŠ3´ÖÞÆÖþ°\å‡dlߌ}ˆV!4Ñ/ªŽ`,jª?e…—ð ,ö7 !T¶g˜CÜQà‰Fh^èÕË­X³)}Õ1¨ª'M,©)míRhEŵzI lU¦~ìˆC¥Q}ZõŽÆù€Ôd1:’^]«‰àÏŠü¤ž%¥HP]‹Ëðšý4ü 5Ç#ļi?#j#L!b†•Êðʲ¯Õ‘úejë×4ÕæT‘Þ"17*5k*gmöIÎèdΠm±äGáZT$[ý oC-mœÙ±«†?¤[5‚Q'Y%èLî«Ì‹õ°³â@ª±I%Ép9Ú8×s©VK|Ü3¢¨Ïv“šÜmÅ¥lFp«ÌéDW3áFÝ—Æý¡$ j4%Õ´ogÁ~4mèyî­‘Öù$÷¶w Ã!ƒZã/0þ1nÛ;·ÿÔÜöìôµýo=¿Øn°o¿%¤A_ÜZß}/KG¥bî·ç|Öïu"ŸZ0å°«h×¶—nÛ¼;¢ÀmݘÄÝ]º©KäÛ—Ùv;3 hŠí¥ý¿[_ýæÓCí›C øÏ.|jk;óo7»ÕßñúÈê¶=¡Lƒe(kâØË†Ž)*Dœ]Ý׋‘cTºLtº@XÔî‚€¥©ýa¨ŠD, þ½¢òjÜ)]¼’Œ’/¥.˜Ð­ÛéÊ€&#!½A 0tÅ¿Ua]ûgäÑÕ`ûäÔdì˜K™ÙœÿcaYµY-Y˜Gö .Z]€nt¶é¥§#oB˪i§­j-2 cƒ0 ¥n Vš(ç¬_jýh“;¢PêYÕØ™Á¬RïI›€F=9Ø›º˜GÌŒ·›¸ö5…w¼J´Iîk¬x¬¢©ÈÌdBÅRµŒ³WÐeðU h›X M»1T bn%“3ºQÏcdnŠ1•äIÙéºU>:T¡iIÖÄ}¼µ³¿ëÞÜ&dèù‘ÑÉË~ntRÝäݽíâüíÙzõny¹ñ«År¼z4’ÿÁbV³…(PýµÀ³D¿Ü%ù‚ E,)ÜÃãEò\SøÀ7B…a¥\Ý5}T "Öæ=©1,yÑÅ l üÕ4E¤¹9éôzHªG@¥:ê‘$óUr)öx1ª¾BŽª¢Ä÷^¬[l^µ mÙw)㮉WH]! œ« tlÅŸz®¹G{.>ÚsÇÉáúCÜÙ¯IŸ ÜVÕ)îÚ4ðÚq¤¤Ü¦íç–›„!|¦ƒ2Ú'¿ªlÝp$%^Ó¡ ˆjÒµ¹–µ âTÓŒª{ÓöQËÚqèj˜¨`Ó‹ .—Eu. )æ3±Ý$DkÖ†˜WgZ,Px@NCzç0úÌ«‚ºí×MzGMi£‚_PS½XÆytµG\æë²Vn²¹Q;äϺäš%kg ˆSùEÎPVÔ¨¯­fíÄðƒÔ¹–¤¾3ÐWšÕÐm¤AädÓ¶_ÐQ´¨“Ô”ÄÔYŽ ˜T, »P†Aú‘R!Æ‹(‰y}Y§Ž'0(¾eîdÇÀ²y ¶PûÏzç^š‘: ++~´©¦½Õ$}”íU*Ú.²õi)Ž.õˆ?ÂçüñéI¹§£fáFEy©\U9à† 2¤Hk„.”í —86˜¼Õ<]]xL9T<ÐQ ~¤N%% Ý«á™× 0Ϥۖ¥/VŒ@=‚)•º³õ~;‰†8Wm\©yCîumš{H ufôe´d}·¨-Ñ´Ý Ö›ÑxÖ¦Hµ6 à+?MH©]?5ú±Œˆ·zéAqäžÐIG‚(ƒA ¯¾ºH^ÑŒø=jªí+aYnQO¥dÝ)0¬™ƒ¼¶¥µsìTijÆy´üÙûù5 T½:Ë JΪɶ"8ßÎÖ!”®ª@…z £Z.ê9}l(êDS´ÙÙ½>îŒ}*c í«ÞÑY£t|ÒßÝ2>‰~ôÚÌS¬†lª­ßšM§ ¨µ¬E§zFÇ«ã9B=Y¬ðªU§Ú¸ŸâLÈË2Õ±5•×ìlÈö£j…Œ½áÖ¿jjUk‰ÅG uןÎOE]{N‚NeÛø×áêËngAJ¨[,ðMM®¯ìÈ£Ýfûê2_v·©­ qjKèÈJÛ£¥ÃÏæ¡½•~R‰5w_…ÚbÙ¶WÚí—ìTˆ–:{…ØÇ׸MÛ£ðÞíeÝå´wo¿œ·W‰›_ä3/ÛvíåHO4ÛU·iÓΛ¶Î)"7¯ÙQ_ÑIÚÛ:ÖÒ]7žïÓ‘UëuºÔ*Úç®ñf¦Ç ¿˜üâ‰Ч¼P¬(7Jퟥܬ{Ií¢]rucu¶c»è£zÂ·× øâ%ÇݶÑXì(IÕ6†mÜ]»}ÈÙλ CMç„Âv¼±g§Û¶—¶cØÉÄÛ)èHQ}·7«íýŸØ8Ý~eö!£‚ŸÎÆÒ¤^Ý™‰ºX*A¬Vß)Æ¢>'Õ@²½yÉè¤óH:«Ã}Vb®« ë¶Y¨Shú Ý ÓrQ{OÈ mkõ'륱išÇ§R“"PϨëäp0ƒªk§Ý)£¾¨6¡z‚%é(„mº…¬¾9¢oz ÍtL*鸖Ngi[¡«˜Òùg-ÖUŠ=v„5ï¾í÷€6Ó¾øz {ÛM¬1©Öµ4)Ü¡V½qio·ÛI%_›ÎѪGŒ&“Ú¶IeSnáèûc&ø‚5^Ï7ç—ç›ó»áwWòí_Z_¾:ûËï¿¿ý#gÿ»Zÿs÷»þZÑÅ™¾qq¾y±¸>=×MúÏ÷×WÏNï>8¸yóáíüö‚œÖó›Õ»õÅüèß‘º¼¸^è¡Ó¿nXÚ4ÈÞŸÅçtµ¸˜/o~ï±?8µ}ö†A_òóåêú|±<=‚yÛ§7oæë{£hìo_ï}uçnìó—«w›ÛWoçË‹«ÅÛóõÆ=yqð„f±¹š¿ø37ßqçðíz3üqñr}¾þ`Æ?ßüt7úÞLOOõn€cïÒ§ø}þ"8×§.Oÿ›sg)Ÿåd÷Û‡‡·Ïo.Ö‹·›ÅjùâÛˆ¼^½}³Z·ÅÅj9¼ü0|»¼\Ͼ_l~ºY`ìÙðß›Åÿ½›o6óáºçf¾™ ߯W×HEÒàÏß}ûÇAÁ÷òüf>GÝã`ðÑ«/>cÛK¢xqutÄôôõí̦/?LÏ—«å‡ëÕ»›©}j£l_v0€ÅÉ긫?ç¹owïþ™Þúd,[á»—ÿ@œ¼@Qõ_ç¯?_W¯/d€ <;Ý^øì]Þ4ßùéIn»sÀÓܧøúâ;"÷ßr=‡M¸åÝÍââ‹oy»|ýÀ KÈK÷ßz£~é—ßòÃÑ×pÌŸÃPµ8ßç%Î?ÆçOòg@ó!ö¿¯!ˆ›_„ýË›¯ÿ2»^]¾»Ê|Â+_øîß/àÞÅËwÿ’wÏ׋ìûfÿ/EÞY|÷öxüÙéŽæ_|õLtýâ«ÿH×BRqtractor-0.5.11/src/images/PaxHeaders.10084/trackCurveProcess.png0000644000175000001440000000012311577116263022677 xustar000000000000000027 mtime=1308400819.477997 26 atime=1381134668.64508 30 ctime=1381134668.645080075 qtractor-0.5.11/src/images/trackCurveProcess.png0000644000175000001440000000116611577116263022172 0ustar00rncbcusers00000000000000‰PNG  IHDRóÿasRGB®Îé0IDAT8ËÍ’ÍKqÇ¿Ï¼í¬‹ø¾‹«îÚ e ¥…P(D „…‡.óÒ½SñÐ!At¬X]BËÅR2kgf·qgvgg/Vó\ßÓÃßÏËø×¢¿ô´ÅÅÅŒSs§œŠ3Ź`½]Ý«ºÔsËËË;Ø©€±±±………'£tãûÙjü[Ê#_Ô¸ù‰‰Ìæ@s´6¼¶´´ôØ÷ýJÛ£¶ ˲ôùùùçï/|žJÝÏd«ƒ‡ý®Vï-›Õ¾ƒÑŸ}Û·¶;£/µþÙôì¹õõõ”6`ffæòvgÉ™Ìßí°ô!õ Å @ƒ…4BŒ:6n ãÅÛsssömvÍyðãj]­5P’»²É$qbàR’ èè(Ý)‰‘Í‘{¶ŽZ¼uý »NN´mS¨"<4•L IjM@õJÉ(9qbθ dM-µeÈ–Ò ¦Ò@¨z`zh!@J Î9NÀå[ã+;¿?^†…qÉÔ˜îCÄ< A‰HÒZÛvtÄ„žx™~×ÍBÕëfY†ñ2Eq"^TN$š¨'W’0É|uâ¾ï»“ƒ7'ÊîžQ?è’F¨Aý#3-4ROS»™™\¡Px8p]Wxž÷fZŸçLKnSŒìد˜Ý³ÚSÎ>Ëf¶2ù|>ÿȶíÃS£œN§ ˲.¹¾;4‚k8r&™¯‹ÅâGÇq"üWú Š ­ a4(IEND®B`‚qtractor-0.5.11/src/PaxHeaders.10084/qtractorEngineCommand.cpp0000644000175000001440000000012311713300213022222 xustar000000000000000027 mtime=1328382091.720959 26 atime=1381134667.83108 30 ctime=1381134667.831080062 qtractor-0.5.11/src/qtractorEngineCommand.cpp0000644000175000001440000004476011713300213021524 0ustar00rncbcusers00000000000000// qtractorEngineCommand.cpp // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorEngineCommand.h" #include "qtractorAudioEngine.h" #include "qtractorMidiEngine.h" #include "qtractorSession.h" #include "qtractorMainForm.h" #include "qtractorTracks.h" #include "qtractorTrackList.h" #include "qtractorMonitor.h" #include "qtractorMixer.h" #include "qtractorMeter.h" //---------------------------------------------------------------------- // class qtractorBusCommand - implementation // // Constructor. qtractorBusCommand::qtractorBusCommand ( const QString& sName, qtractorBus *pBus, qtractorBus::BusMode busMode ) : qtractorCommand(sName), m_pBus(pBus), m_busMode(busMode), m_busType(qtractorTrack::None), m_bMonitor(false), m_iChannels(0), m_bAutoConnect(false) { setRefresh(false); // Set initial bus properties if any... if (m_pBus && m_busMode == qtractorBus::None) { m_busMode = m_pBus->busMode(); m_busType = m_pBus->busType(); m_sBusName = m_pBus->busName(); m_bMonitor = m_pBus->isMonitor(); // Special case typed buses... switch (m_pBus->busType()) { case qtractorTrack::Audio: { qtractorAudioBus *pAudioBus = static_cast (m_pBus); if (pAudioBus) { m_iChannels = pAudioBus->channels(); m_bAutoConnect = pAudioBus->isAutoConnect(); } break; } case qtractorTrack::Midi: { qtractorMidiBus *pMidiBus = static_cast (m_pBus); if (pMidiBus) { m_sInstrumentName = pMidiBus->instrumentName(); } break; } case qtractorTrack::None: default: break; } } } // Create a new bus. bool qtractorBusCommand::createBus (void) { if (m_pBus || m_sBusName.isEmpty()) return false; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; // Create the bus of proper type... m_pBus = NULL; qtractorAudioBus *pAudioBus = NULL; qtractorMidiBus *pMidiBus = NULL; switch (m_busType) { case qtractorTrack::Audio: { qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine) { pAudioBus = new qtractorAudioBus(pAudioEngine, m_sBusName, m_busMode, m_bMonitor, m_iChannels); pAudioBus->setAutoConnect(m_bAutoConnect); pAudioEngine->addBus(pAudioBus); pAudioEngine->resetPlayerBus(); pAudioEngine->resetMetroBus(); m_pBus = pAudioBus; } break; } case qtractorTrack::Midi: { qtractorMidiEngine *pMidiEngine = pSession->midiEngine(); if (pMidiEngine) { pMidiBus = new qtractorMidiBus(pMidiEngine, m_sBusName, m_busMode, m_bMonitor); pMidiBus->setInstrumentName(m_sInstrumentName); pMidiEngine->addBus(pMidiBus); pMidiEngine->resetControlBus(); pMidiEngine->resetMetroBus(); m_pBus = pMidiBus; } break; } default: break; } // Check if we really have a new bus... if (m_pBus == NULL) return false; // Open up the new bus... m_pBus->open(); // Yet special for audio buses... if (pAudioBus) pAudioBus->autoConnect(); // Update mixer (look for new strips...) qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) { qtractorMixer *pMixer = pMainForm->mixer(); if (pMixer) pMixer->updateBuses(true); } // Done. return true; } // Update bus properties. bool qtractorBusCommand::updateBus (void) { if (m_pBus == NULL || m_sBusName.isEmpty()) return false; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return false; // We need to hold things for a while... bool bPlaying = pSession->isPlaying(); pSession->lock(); pSession->setPlaying(false); // Save current bus properties... qtractorBus::BusMode busMode = m_pBus->busMode(); QString sBusName = m_pBus->busName(); bool bMonitor = m_pBus->isMonitor(); // Save current connections... qtractorBus::ConnectList inputs; qtractorBus::ConnectList outputs; if (busMode & qtractorBus::Input) m_pBus->updateConnects(qtractorBus::Input, inputs); if (busMode & qtractorBus::Output) m_pBus->updateConnects(qtractorBus::Output, outputs); // Special case typed buses... qtractorAudioBus *pAudioBus = NULL; qtractorMidiBus *pMidiBus = NULL; unsigned short iChannels = 0; bool bAutoConnect = false; QString sInstrumentName; switch (m_pBus->busType()) { case qtractorTrack::Audio: pAudioBus = static_cast (m_pBus); if (pAudioBus) { iChannels = pAudioBus->channels(); bAutoConnect = pAudioBus->isAutoConnect(); } break; case qtractorTrack::Midi: pMidiBus = static_cast (m_pBus); if (pMidiBus) { sInstrumentName = pMidiBus->instrumentName(); } break; case qtractorTrack::None: default: break; } // Update (reset) all applicable mixer strips... QList strips; qtractorMixerStrip *pStrip; qtractorMixer *pMixer = pMainForm->mixer(); if (pMixer) { if (m_pBus->busMode() & qtractorBus::Input) { pStrip = (pMixer->inputRack())->findStrip(m_pBus->monitor_in()); if (pStrip) { pStrip->clear(); if (m_busMode & qtractorBus::Input) { strips.append(pStrip); } else { (pMixer->inputRack())->removeStrip(pStrip); } } } if (m_pBus->busMode() & qtractorBus::Output) { pStrip = (pMixer->outputRack())->findStrip(m_pBus->monitor_out()); if (pStrip) { pStrip->clear(); if (m_busMode & qtractorBus::Output) { strips.append(pStrip); } else { (pMixer->outputRack())->removeStrip(pStrip); } } } } // Close all applicable tracks... for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { if (pTrack->inputBus() == m_pBus) pTrack->setInputBusName(m_sBusName); if (pTrack->outputBus() == m_pBus) pTrack->setOutputBusName(m_sBusName); if (pTrack->inputBus() == m_pBus || pTrack->outputBus() == m_pBus) { if (pMixer) { pStrip = (pMixer->trackRack())->findStrip(pTrack->monitor()); if (pStrip) { pStrip->clear(); strips.append(pStrip); } } pTrack->close(); } } // May close now the bus... m_pBus->close(); // Set new properties... m_pBus->setBusName(m_sBusName); m_pBus->setBusMode(m_busMode); m_pBus->setMonitor(m_bMonitor); // Special case for typed buses... if (pAudioBus) { pAudioBus->setChannels(m_iChannels); pAudioBus->setAutoConnect(m_bAutoConnect); } if (pMidiBus) { pMidiBus->setInstrumentName(m_sInstrumentName); } // May reopen up the bus... m_pBus->open(); // Yet special for audio buses... if (pAudioBus) pAudioBus->autoConnect(); // Restore previous connections... if (m_busMode & qtractorBus::Input) m_pBus->updateConnects(qtractorBus::Input, inputs, true); if (m_busMode & qtractorBus::Output) m_pBus->updateConnects(qtractorBus::Output, outputs, true); // (Re)open all applicable tracks // and (reset) respective mixer strips too ... qtractorTracks *pTracks = pMainForm->tracks(); for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { if (pTrack->inputBusName() == m_sBusName || pTrack->outputBusName() == m_sBusName) { // Reopen track back... pTrack->open(); // Update track list item... if (pTracks) (pTracks->trackList())->updateTrack(pTrack); } } // Update (reset) all applicable mixer strips... if (pMixer) { QListIterator iter(strips); while (iter.hasNext()) { pStrip = iter.next(); if (pStrip->track()) pStrip->setTrack(pStrip->track()); else if (pStrip->bus()) pStrip->setBus(pStrip->bus()); } pMixer->updateBuses(); } // Swap saved bus properties... m_busMode = busMode; m_sBusName = sBusName; m_bMonitor = bMonitor; m_iChannels = iChannels; m_bAutoConnect = bAutoConnect; m_sInstrumentName = sInstrumentName; // Carry on... pSession->setPlaying(bPlaying); pSession->unlock(); // Done. return true; } // Delete bus. bool qtractorBusCommand::deleteBus (void) { if (m_pBus == NULL) return false; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return false; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return false; // Get the device view root item... qtractorEngine *pEngine = NULL; switch (m_pBus->busType()) { case qtractorTrack::Audio: pEngine = pSession->audioEngine(); break; case qtractorTrack::Midi: pEngine = pSession->midiEngine(); break; default: break; } // Still valid? if (pEngine == NULL) return false; // We need to hold things for a while... bool bPlaying = pSession->isPlaying(); pSession->lock(); pSession->setPlaying(false); // Close all applicable tracks (and mixer strips)... qtractorMixerStrip *pStrip; qtractorMixer *pMixer = pMainForm->mixer(); QList strips; for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { if (pTrack->inputBus() == m_pBus || pTrack->outputBus() == m_pBus) { pTrack->close(); if (pMixer) { pStrip = (pMixer->trackRack())->findStrip(pTrack->monitor()); if (pStrip) { pStrip->clear(); strips.append(pStrip); } } } } // May close now the bus... m_pBus->close(); // And remove it... pEngine->removeBus(m_pBus); m_pBus = NULL; // Better update special buses anyway... switch (pEngine->syncType()) { case qtractorTrack::Audio: { qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine) { pAudioEngine->resetPlayerBus(); pAudioEngine->resetMetroBus(); } } case qtractorTrack::Midi: { qtractorMidiEngine *pMidiEngine = pSession->midiEngine(); if (pMidiEngine) { pMidiEngine->resetControlBus(); pMidiEngine->resetMetroBus(); } break; } default: break; } // Update mixer (clean old strips...) qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks && pMixer) { QListIterator iter(strips); while (iter.hasNext()) { qtractorTrack *pTrack = iter.next()->track(); if (pTrack) { pTrack->open(); // Update track list item... (pTracks->trackList())->updateTrack(pTrack); } } pMixer->updateBuses(); } // Carry on... pSession->setPlaying(bPlaying); pSession->unlock(); // Done. return true; } // Monitor meter accessor. qtractorMeter *qtractorBusCommand::meter (void) const { qtractorBus *pBus = bus(); if (pBus == NULL) return NULL; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return NULL; qtractorMixer *pMixer = pMainForm->mixer(); if (pMixer == NULL) return NULL; // Mixer strip determination... qtractorMixerStrip *pStrip = NULL; if ((busMode() & qtractorBus::Input) && pBus->monitor_in()) pStrip = pMixer->inputRack()->findStrip(pBus->monitor_in()); else if ((busMode() & qtractorBus::Output) && pBus->monitor_out()) pStrip = pMixer->outputRack()->findStrip(pBus->monitor_out()); return (pStrip ? pStrip->meter() : NULL); } //---------------------------------------------------------------------- // class qtractorCreateBusCommand - implementation. // // Constructor. qtractorCreateBusCommand::qtractorCreateBusCommand (void) : qtractorBusCommand(QObject::tr("create bus")) { } // Bus creation command methods. bool qtractorCreateBusCommand::redo (void) { return createBus(); } bool qtractorCreateBusCommand::undo (void) { return deleteBus(); } //---------------------------------------------------------------------- // class qtractorUpdateBusCommand - implementation. // // Constructor. qtractorUpdateBusCommand::qtractorUpdateBusCommand ( qtractorBus *pBus ) : qtractorBusCommand(QObject::tr("update bus"), pBus) { } // Bus update command methods. bool qtractorUpdateBusCommand::redo (void) { return updateBus(); } //---------------------------------------------------------------------- // class qtractorDeleteBusCommand - implementation. // // Constructor. qtractorDeleteBusCommand::qtractorDeleteBusCommand ( qtractorBus *pBus ) : qtractorBusCommand(QObject::tr("delete bus"), pBus) { } // Bus deletion command methods. bool qtractorDeleteBusCommand::redo (void) { return deleteBus(); } bool qtractorDeleteBusCommand::undo (void) { return createBus(); } //---------------------------------------------------------------------- // class qtractorBusMonitorCommand - implementation. // // Constructor. qtractorBusMonitorCommand::qtractorBusMonitorCommand ( qtractorBus *pBus, bool bMonitor ) : qtractorBusCommand(QObject::tr("bus pass-through"), pBus, pBus->busMode()) { setMonitor(bMonitor); } // Bus-gain command method. bool qtractorBusMonitorCommand::redo (void) { qtractorBus *pBus = bus(); if (pBus == NULL) return false; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return false; // Set Bus gain (repective monitor gets set too...) float bMonitor = pBus->isMonitor(); pBus->setMonitor(qtractorBusCommand::isMonitor()); qtractorBusCommand::setMonitor(bMonitor); // Update (reset) all applicable mixer strips... qtractorMixer *pMixer = pMainForm->mixer(); if (pMixer) { if (pBus->busMode() & qtractorBus::Input) { pMixer->updateBusStrip(pMixer->inputRack(), pBus, qtractorBus::Input, true); } if (pBus->busMode() & qtractorBus::Output) { pMixer->updateBusStrip(pMixer->outputRack(), pBus, qtractorBus::Output, true); } } return true; } //---------------------------------------------------------------------- // class qtractorBusGainCommand - implementation. // // Constructor. qtractorBusGainCommand::qtractorBusGainCommand ( qtractorBus *pBus, qtractorBus::BusMode busMode, float fGain ) : qtractorBusCommand(QObject::tr("bus gain"), pBus, busMode) { m_fGain = fGain; m_fPrevGain = 1.0f; qtractorMeter *pMeter = meter(); if (pMeter) m_fPrevGain = pMeter->prevGain(); // Try replacing an previously equivalent command... static qtractorBusGainCommand *s_pPrevGainCommand = NULL; if (s_pPrevGainCommand) { qtractorSession *pSession = qtractorSession::getInstance(); qtractorCommand *pLastCommand = (pSession->commands())->lastCommand(); qtractorCommand *pPrevCommand = static_cast (s_pPrevGainCommand); if (pPrevCommand == pLastCommand && s_pPrevGainCommand->bus() == pBus && s_pPrevGainCommand->busMode() == busMode) { qtractorBusGainCommand *pLastGainCommand = static_cast (pLastCommand); if (pLastGainCommand) { // Equivalence means same (sign) direction too... float fPrevGain = pLastGainCommand->prevGain(); float fLastGain = pLastGainCommand->gain(); int iPrevSign = (fPrevGain > fLastGain ? +1 : -1); int iCurrSign = (fPrevGain < m_fGain ? +1 : -1); if (iPrevSign == iCurrSign || m_fGain == m_fPrevGain) { m_fPrevGain = fLastGain; (pSession->commands())->removeLastCommand(); } } } } s_pPrevGainCommand = this; } // Bus-gain command method. bool qtractorBusGainCommand::redo (void) { qtractorBus *pBus = bus(); if (pBus == NULL) return false; // Set Bus gain (repective monitor gets set too...) float fGain = m_fPrevGain; qtractorMeter *pMeter = meter(); if (pMeter) pMeter->setGain(m_fGain); // MIDI buses are special... if (pBus->busType() == qtractorTrack::Midi) { // Now we gotta make sure of proper MIDI bus... qtractorMidiBus *pMidiBus = static_cast (pBus); if (pMidiBus) pMidiBus->setMasterVolume(m_fGain); } // Set undo value... m_fPrevGain = m_fGain; m_fGain = fGain; return true; } //---------------------------------------------------------------------- // class qtractorBusPanningCommand - implementation. // // Constructor. qtractorBusPanningCommand::qtractorBusPanningCommand ( qtractorBus *pBus, qtractorBus::BusMode busMode, float fPanning ) : qtractorBusCommand(QObject::tr("bus pan"), pBus, busMode) { m_fPanning = fPanning; m_fPrevPanning = 0.0f; qtractorMeter *pMeter = meter(); if (pMeter) m_fPrevPanning = pMeter->prevPanning(); // Try replacing an previously equivalent command... static qtractorBusPanningCommand *s_pPrevPanningCommand = NULL; if (s_pPrevPanningCommand) { qtractorSession *pSession = qtractorSession::getInstance(); qtractorCommand *pLastCommand = (pSession->commands())->lastCommand(); qtractorCommand *pPrevCommand = static_cast (s_pPrevPanningCommand); if (pPrevCommand == pLastCommand && s_pPrevPanningCommand->bus() == pBus && s_pPrevPanningCommand->busMode() == busMode) { qtractorBusPanningCommand *pLastPanningCommand = static_cast (pLastCommand); if (pLastPanningCommand) { // Equivalence means same (sign) direction too... float fPrevPanning = pLastPanningCommand->prevPanning(); float fLastPanning = pLastPanningCommand->panning(); int iPrevSign = (fPrevPanning > fLastPanning ? +1 : -1); int iCurrSign = (fPrevPanning < m_fPanning ? +1 : -1); if (iPrevSign == iCurrSign || m_fPanning == m_fPrevPanning) { m_fPrevPanning = fLastPanning; (pSession->commands())->removeLastCommand(); } } } } s_pPrevPanningCommand = this; } // Bus-panning command method. bool qtractorBusPanningCommand::redo (void) { qtractorBus *pBus = bus(); if (pBus == NULL) return false; // Set Bus panning (repective monitor gets set too...) float fPanning = m_fPrevPanning; qtractorMeter *pMeter = meter(); if (pMeter) pMeter->setPanning(m_fPanning); // MIDI buses are special... if (pBus->busType() == qtractorTrack::Midi) { // Now we gotta make sure of proper MIDI bus... qtractorMidiBus *pMidiBus = static_cast (pBus); if (pMidiBus) pMidiBus->setMasterPanning(m_fPanning); } // Set undo value... m_fPrevPanning = m_fPanning; m_fPanning = fPanning; return true; } // end of qtractorEngineCommand.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiControlObserver.cpp0000644000175000001440000000012312161335204023457 xustar000000000000000027 mtime=1371912836.382031 26 atime=1381134667.36708 30 ctime=1381134667.367080055 qtractor-0.5.11/src/qtractorMidiControlObserver.cpp0000644000175000001440000001221712161335204022751 0ustar00rncbcusers00000000000000// qtractorMidiControlObserver.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiControlObserver.h" #include // Possible cube root optimization. // (borrowed from metamerist.com) static inline float cbrtf2 ( float x ) { #ifdef CONFIG_FLOAT32 // Avoid strict-aliasing optimization (gcc -O2). union { float f; int i; } u; u.f = x; u.i = (u.i / 3) + 710235478; return u.f; #else return cbrtf(x); #endif } static inline float cubef2 ( float x ) { return x * x * x; } //---------------------------------------------------------------------- // class qtractorMidiControlObserver -- MIDI controller observers. // // Constructor. qtractorMidiControlObserver::qtractorMidiControlObserver ( qtractorSubject *pSubject ) : qtractorObserver(pSubject), m_ctype(qtractorMidiEvent::CONTROLLER), m_iChannel(0), m_iParam(0), m_bLogarithmic(false), m_bFeedback(false), m_bInvert(false), m_bHook(false), m_bMidiValueInit(false), m_bMidiValueSync(false), m_fMidiValue(0.0f), m_pCurveList(NULL) { } // Destructor (virtual). qtractorMidiControlObserver::~qtractorMidiControlObserver (void) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl && pMidiControl->isMidiObserverMapped(this)) pMidiControl->unmapMidiObserver(this); } // MIDI mapped value converters. void qtractorMidiControlObserver::setMidiValue ( unsigned short iValue ) { const unsigned short iRatio = (m_ctype == qtractorMidiEvent::PITCHBEND ? 0x3fff : 0x7f); // setScaleValue(float(iValue) / float(iRatio)); float fScale = float(m_bInvert ? iRatio - iValue : iValue) / float(iRatio); float fValue = valueFromScale(fScale, m_bLogarithmic); if (m_bHook) m_bMidiValueSync = true; if (m_bMidiValueInit && !m_bMidiValueSync) { const float v0 = m_fMidiValue; const float v1 = qtractorObserver::value(); if ((fValue > v0 && v1 >= v0 && fValue >= v1) || (fValue < v0 && v0 >= v1 && v1 >= fValue)) m_bMidiValueSync = true; } if (m_bMidiValueSync) subject()->setValue(fValue); else m_bMidiValueInit = true; m_fMidiValue = fValue; } unsigned short qtractorMidiControlObserver::midiValue (void) const { const unsigned short iRatio = float(m_ctype == qtractorMidiEvent::PITCHBEND ? 0x3fff : 0x7f); unsigned short iValue = float(iRatio) * scaleValue(); return (m_bInvert ? iRatio - iValue : iValue); } // Normalized scale converters. float qtractorMidiControlObserver::valueFromScale ( float fScale, bool bLogarithmic ) const { if (bLogarithmic) { const float fMaxValue = qtractorObserver::maxValue(); const float fMinValue = qtractorObserver::minValue(); if (fMinValue < 0.0f && fMaxValue > 0.0f) { const float fMidScale = fMinValue / (fMinValue - fMaxValue); if (fScale > fMidScale) { const float fMaxScale = (1.0f - fMidScale); fScale = (fScale - fMidScale) / fMaxScale; fScale = fMidScale + fMaxScale * ::cubef2(fScale); } else { fScale = (fMidScale - fScale) / fMidScale; fScale = fMidScale - fMidScale * ::cubef2(fScale); } } else fScale = ::cubef2(fScale); } return qtractorObserver::valueFromScale(fScale); } float qtractorMidiControlObserver::scaleFromValue ( float fValue, bool bLogarithmic ) const { float fScale = qtractorObserver::scaleFromValue(fValue); if (bLogarithmic) { const float fMaxValue = qtractorObserver::maxValue(); const float fMinValue = qtractorObserver::minValue(); if (fMinValue < 0.0f && fMaxValue > 0.0f) { const float fMidScale = fMinValue / (fMinValue - fMaxValue); if (fScale > fMidScale) { const float fMaxScale = (1.0f - fMidScale); fScale = (fScale - fMidScale) / fMaxScale; fScale = fMidScale + fMaxScale * ::cbrtf2(fScale); } else { fScale = (fMidScale - fScale) / fMidScale; fScale = fMidScale - fMidScale * ::cbrtf2(fScale); } } else fScale = ::cbrtf2(fScale); } return fScale; } // Updater (feedback). void qtractorMidiControlObserver::update ( bool bUpdate ) { if (bUpdate && m_bFeedback) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl && pMidiControl->isMidiObserverMapped(this)) { pMidiControl->sendController( m_ctype, m_iChannel, m_iParam, midiValue()); } } m_bMidiValueSync = false; } // end of qtractorMidiControlObserver.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTimeStretch.h0000644000175000001440000000012312104041334021417 xustar000000000000000027 mtime=1360020188.980392 26 atime=1381134666.64508 30 ctime=1381134666.645080043 qtractor-0.5.11/src/qtractorTimeStretch.h0000644000175000001440000001552712104041334020720 0ustar00rncbcusers00000000000000// qtractorTimeStretch.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. Adapted and refactored from the SoundTouch library (L)GPL, Copyright (C) 2001-2012, Olli Parviainen. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorTimeStretch_h #define __qtractorTimeStretch_h #include "qtractorFifoBuffer.h" //--------------------------------------------------------------------------- // qtractorTimeStretch - Time-stretch (tempo change) processed sound. // class qtractorTimeStretch { public: // Constructor. qtractorTimeStretch( unsigned short iChannels = 2, unsigned int iSampleRate = 44100); // Destructor. ~qtractorTimeStretch(); // Sets the number of channels, 1=mono, 2=stereo. void setChannels(unsigned short iChannels); // Get the assigned number of channels, 1=mono, 2=stereo. unsigned short channels() const; // Sets new target tempo; smaller values represent // slower tempo, larger faster tempo. void setTempo(float fTempo); // Get assigned target tempo. float tempo() const; // Set quick-seek mode (hierachical search). void setQuickSeek(bool bQuickSeek); // Get quick-seek mode. bool isQuickSeek() const; // Default values for sound processing parameters. enum { // Default length of a single processing sequence, in milliseconds. // This determines to how long sequences the original sound is // chopped in the time-stretch algorithm. // // The larger this value is, the lesser number of sequences are used // in processing. In principle a bigger value sounds better when // slowing down tempo, but worse when increasing tempo and vice versa. // // Increasing this value reduces computational burden and vice versa. // DEFAULT_SEQUENCE_MS = 40 DEFAULT_SEQUENCE_MS = 0, // Seeking window default length in milliseconds for algorithm // that finds the best possible overlapping location. This determines // from how wide window the algorithm may look for an optimal joining // location when mixing the sound sequences back together. // // The bigger this window setting is, the higher the possibility // to find a better mixing position will become, but at the same time // large values may cause a "drifting" artifact because consequent // sequences will be taken at more uneven intervals. // // If there's a disturbing artifact that sounds as if a constant // frequency was drifting around, try reducing this setting. // // Increasing this value increases computational burden and vice versa. // DEFAULT_SEEKWINDOW_MS = 15 DEFAULT_SEEKWINDOW_MS = 0, // Overlap length in milliseconds. When the chopped sound sequences // are mixed back together, to form a continuous sound stream, // this parameter defines over how long period the two consecutive // sequences are let to overlap each other. // // This shouldn't be that critical parameter. If you reduce the // DEFAULT_SEQUENCE_MS setting by a large amount, you might wish // to try a smaller value on this. // // Increasing this value increases computational burden and vice versa. DEFAULT_OVERLAP_MS = 8 }; // Sets routine control parameters. // These control are certain time constants defining // how the sound is stretched to the desired duration. // // iSampleRate = sample rate of the sound. // iSequenceMS = one processing sequence length in milliseconds. // iSeekWindowMs = seking window length for scanning the best // verlapping position. // iOverlapMs = oerlapping length. void setParameters( unsigned int iSampleRate, unsigned int iSequenceMs = DEFAULT_SEQUENCE_MS, unsigned int iSeekWindowMs = DEFAULT_SEEKWINDOW_MS, unsigned int iOverlapMs = DEFAULT_OVERLAP_MS); // Get routine control parameters, see setParameters() function. // Any of the parameters to this function can be NULL in such // case corresponding parameter value isn't returned. void getParameters( unsigned int *piSampleRate, unsigned int *piSequenceMs, unsigned int *piSeekWindowMs, unsigned int *piOverlapMs); // Adds frames of samples into the input buffer. void putFrames(float **ppFrames, unsigned int iFrames); // Output frames from beginning of the sample buffer. // Copies requested frames output buffer and removes them // from the sample buffer. If there are less than frames() // samples in the buffer, returns all that available. unsigned int receiveFrames(float **ppFrames, unsigned int iFrames); // Returns number of frames currently available. unsigned int frames() const; // Flush any last samples that are hiding in the internal processing pipeline. void flushInput(); // Clears the input buffer void clearInput(); // Clears all buffers. void clear(); protected: // Calculates processing sequence length according to tempo setting. void calcSeekWindowLength(); // Calculates overlap period length in frames. void calcOverlapLength(); // Seeks for the optimal overlap-mixing position. unsigned int seekBestOverlapPosition(); // Slopes the amplitude of the mid-buffer samples. void calcCrossCorrReference(); // Clears mid sample frame buffer. void clearMidBuffer(); // Changes the tempo of the given sound sample frames. // Returns amount of framees returned in the output buffer. void processFrames(); private: unsigned short m_iChannels; float m_fTempo; bool m_bQuickSeek; unsigned int m_iSampleRate; unsigned int m_iSequenceMs; unsigned int m_iSeekWindowMs; unsigned int m_iOverlapMs; bool m_bAutoSequenceMs; bool m_bAutoSeekWindowMs; unsigned int m_iFramesReq; float **m_ppMidBuffer; float **m_ppRefMidBuffer; float **m_ppRefMidBufferUnaligned; float **m_ppFrames; unsigned int m_iOverlapLength; unsigned int m_iSeekLength; unsigned int m_iSeekWindowLength; float m_fNominalSkip; float m_fSkipFract; qtractorFifoBuffer m_outputBuffer; qtractorFifoBuffer m_inputBuffer; bool m_bMidBufferDirty; // Calculates the cross-correlation value over the overlap period. float (*m_pfnCrossCorr)(const float *, const float *, unsigned int); }; #endif // __qtractorTimeStretch_h // end of qtractorTimeStretch.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorThumbView.cpp0000644000175000001440000000012312217545361021447 xustar000000000000000027 mtime=1379846897.486885 26 atime=1381134667.03508 30 ctime=1381134667.035080049 qtractor-0.5.11/src/qtractorThumbView.cpp0000644000175000001440000003006112217545361020736 0ustar00rncbcusers00000000000000// qtractorThumbView.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorThumbView.h" #include "qtractorTrackView.h" #include "qtractorSession.h" #include "qtractorTracks.h" #include "qtractorClip.h" #include "qtractorRubberBand.h" #include "qtractorMainForm.h" #include #include #include #include #include #include //------------------------------------------------------------------------- // qtractorThumbView -- Session track line thumb view. // Constructor. qtractorThumbView::qtractorThumbView( QWidget *pParent ) : QFrame(pParent) { // Avoid intensively annoying repaints... QFrame::setAttribute(Qt::WA_StaticContents); QFrame::setAttribute(Qt::WA_OpaquePaintEvent); QFrame::setFrameShape(QFrame::Panel); QFrame::setFrameShadow(QFrame::Sunken); QFrame::setMinimumSize(QSize(120, 32)); QFrame::setSizePolicy( QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); QFrame::setFocusPolicy(Qt::ClickFocus); // Local contents length (in frames). m_iContentsLength = 0; // Local play-head positioning. m_iPlayHeadX = 0; m_dragState = DragNone; m_pRubberBand = new qtractorRubberBand(QRubberBand::Rectangle, this, 2); // QPalette pal(m_pRubberBand->palette()); // pal.setColor(m_pRubberBand->foregroundRole(), pal.highlight().color()); // m_pRubberBand->setPalette(pal); // m_pRubberBand->setBackgroundRole(QPalette::NoRole); m_pRubberBand->show(); QFrame::setToolTip(tr("Thumb view")); } // (Re)create the complete view pixmap. void qtractorThumbView::updateContents (void) { const int w = QFrame::width(); const int h = QFrame::height(); if (w < 1 || h < 1) return; const QPalette& pal = QFrame::palette(); m_pixmap = QPixmap(w, h); m_pixmap.fill(pal.dark().color()); QPainter painter(&m_pixmap); painter.initFrom(this); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; qtractorTimeScale *pTimeScale = pSession->timeScale(); if (pTimeScale == NULL) return; qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks == NULL) return; // Local contents length (in frames). m_iContentsLength = pSession->sessionEnd(); if (m_iContentsLength > 0) { qtractorTimeScale::Cursor cursor(pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(m_iContentsLength); m_iContentsLength += pNode->frameFromBeat( pNode->beat + 2 * pSession->beatsPerBar()) - pNode->frame; } else { m_iContentsLength += pTimeScale->frameFromPixel( pTracks->trackView()->width()); } const int ch = pTracks->trackView()->contentsHeight(); const int f2 = 1 + (m_iContentsLength / w); int x2, w2; if (ch > 0) { int y2 = 1; qtractorTrack *pTrack = pSession->tracks().first(); while (pTrack && y2 < h) { int h2 = ((h * pTrack->zoomHeight()) / ch); if (h2 < 2) h2 = 2; qtractorClip *pClip = pTrack->clips().first(); while (pClip) { x2 = int(pClip->clipStart() / f2); w2 = int(pClip->clipLength() / f2); painter.fillRect(x2, y2, w2, h2 - 1, pTrack->background()); pClip = pClip->next(); } y2 += h2; pTrack = pTrack->next(); } } // Draw the location marker lines, if any... qtractorTimeScale::Marker *pMarker = pTimeScale->markers().first(); while (pMarker) { x2 = int(pMarker->frame / f2); painter.setPen(pMarker->color); painter.drawLine(x2, 0, x2, h); pMarker = pMarker->next(); } // Draw the loop-bound lines, if any... if (pSession->isLooping()) { const QBrush shade(QColor(0, 0, 0, 60)); painter.setPen(Qt::darkCyan); x2 = int(pSession->loopStart() / f2); if (x2 < w) { painter.fillRect(QRect(0, 0, x2, h), shade); painter.drawLine(x2, 0, x2, h); } x2 = int(pSession->loopEnd() / f2); if (x2 < w) { painter.fillRect(QRect(x2, 0, w - x2, h), shade); painter.drawLine(x2, 0, x2, h); } } else // Don't forget the punch-in/out ones too... if (pSession->isPunching()) { const QBrush shade(QColor(0, 0, 0, 60)); painter.setPen(Qt::darkMagenta); x2 = int(pSession->punchIn() / f2); if (x2 < w) { painter.fillRect(QRect(0, 0, x2, h), shade); painter.drawLine(x2, 0, x2, h); } x2 = int(pSession->punchOut() / f2); if (x2 < w) { painter.fillRect(QRect(x2, 0, w - x2, h), shade); painter.drawLine(x2, 0, x2, h); } } // May trigger an update now. update(); } // Update thumb-position. void qtractorThumbView::updateThumb ( int dx ) { const int w = QFrame::width(); const int h = QFrame::height(); if (w < 1 || h < 1) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks == NULL) return; const int cw = pSession->pixelFromFrame(m_iContentsLength) + 1; int x2 = dx + (w * pTracks->trackView()->contentsX()) / cw; int w2 = (w * pTracks->trackView()->viewport()->width()) / cw; if (w2 < 8) w2 = 8; else if (w2 > w) w2 = w; if (x2 < 0) x2 = 0; else if (x2 > w - w2) x2 = w - w2; m_pRubberBand->setGeometry(x2, 0, w2, h); } // Update playhead-position. void qtractorThumbView::updatePlayHead ( unsigned long iPlayHead ) { const int w = QFrame::width(); const int h = QFrame::height(); if (w < 1 || h < 1) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks == NULL) return; const int f2 = 1 + (m_iContentsLength / w); // Extra: update current playhead position... const int x2 = int(iPlayHead / f2); if (m_iPlayHeadX != x2) { // Override old playhead line... update(QRect(m_iPlayHeadX, 0, 1, h)); // New position is in... m_iPlayHeadX = x2; // And draw it... update(QRect(m_iPlayHeadX, 0, 1, h)); } } // Update view-position. void qtractorThumbView::updateView ( int dx ) { const int w = QFrame::width(); if (w < 1) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks == NULL) return; const int cw = pSession->pixelFromFrame(m_iContentsLength) + 1; const int cy = pTracks->trackView()->contentsY(); int cx = pTracks->trackView()->contentsX() + (dx * cw) / w; if (cx < 0) cx = 0; pTracks->trackView()->setContentsPos(cx, cy); } // Set playhead-position (indirect). void qtractorThumbView::setPlayHeadX ( int iPlayHeadX ) { const int w = QFrame::width(); if (w < 1) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks == NULL) return; const int f2 = 1 + (m_iContentsLength / w); pSession->setPlayHead(f2 * iPlayHeadX); } // Session track-line paint method. void qtractorThumbView::paintEvent ( QPaintEvent *pPaintEvent ) { QPainter painter(this); // Render the famous pixmap region... const QRect& rect = pPaintEvent->rect(); painter.drawPixmap(rect, m_pixmap, rect); const int w = QFrame::width(); const int h = QFrame::height(); if (w < 1 || h < 1) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks == NULL) return; const int f2 = 1 + (m_iContentsLength / w); int x2; // Draw current edit-bound lines... painter.setPen(Qt::blue); x2 = int(pSession->editHead() / f2); if (x2 >= rect.left() && x2 <= rect.right()) painter.drawLine(x2, 0, x2, h); x2 = int(pSession->editTail() / f2); if (x2 >= rect.left() && x2 <= rect.right()) painter.drawLine(x2, 0, x2, h); // Draw current play-head as well... painter.setPen(Qt::red); x2 = m_iPlayHeadX; if (x2 >= rect.left() && x2 <= rect.right()) painter.drawLine(x2, 0, x2, h); } // Session track-line paint method. void qtractorThumbView::resizeEvent ( QResizeEvent *pResizeEvent ) { QFrame::resizeEvent(pResizeEvent); updateContents(); updateThumb(); } // Handle selection with mouse. void qtractorThumbView::mousePressEvent ( QMouseEvent *pMouseEvent ) { // Force null state. m_dragState = DragNone; // Only expected behavior with left-button pressed... if (pMouseEvent->button() == Qt::LeftButton) { m_posDrag = pMouseEvent->pos(); if (m_pRubberBand->geometry().contains(m_posDrag)) { m_dragState = DragStart; QFrame::setCursor(QCursor(Qt::SizeHorCursor)); } else { m_dragState = DragClick; QFrame::setCursor(QCursor(Qt::PointingHandCursor)); } } else if (pMouseEvent->button() == Qt::MidButton) { // Make it change playhead?... if (pMouseEvent->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) setPlayHeadX(pMouseEvent->pos().x()); } QFrame::mousePressEvent(pMouseEvent); } void qtractorThumbView::mouseMoveEvent ( QMouseEvent *pMouseEvent ) { // Only expected behavior with left-button pressed... if (pMouseEvent->buttons() & Qt::LeftButton) { const QPoint& pos = pMouseEvent->pos(); if (m_dragState == DragStart && (pos - m_posDrag).manhattanLength() > QApplication::startDragDistance()) m_dragState = DragMove; if (m_dragState == DragMove) updateThumb(pos.x() - m_posDrag.x()); } QFrame::mouseMoveEvent(pMouseEvent); } void qtractorThumbView::mouseReleaseEvent ( QMouseEvent *pMouseEvent ) { QFrame::mouseReleaseEvent(pMouseEvent); // Only expected behavior with left-button pressed... if (pMouseEvent->button() == Qt::LeftButton) { const QPoint& pos = pMouseEvent->pos(); if (m_dragState == DragMove) updateView(pos.x() - m_posDrag.x()); else { if (m_dragState == DragClick) { const QRect& rect = m_pRubberBand->geometry(); updateView(pos.x() - ((rect.left() + rect.right()) >> 1)); } // Make it change playhead?... if (pMouseEvent->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) setPlayHeadX(pos.x()); } } // Clean up. resetDragState(); } // Reset drag/select state. void qtractorThumbView::resetDragState (void) { // Restore uncommitted thumb position?... if (m_dragState == DragMove) updateThumb(); // Cancel any dragging out there... if (m_dragState != DragNone) QFrame::unsetCursor(); // Force null state. m_dragState = DragNone; // HACK: give focus to track-view... qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm && pMainForm->tracks()) pMainForm->tracks()->trackView()->setFocus(); } // Keyboard event handler. void qtractorThumbView::keyPressEvent ( QKeyEvent *pKeyEvent ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorThumbView::keyPressEvent(%d)", pKeyEvent->key()); #endif switch (pKeyEvent->key()) { case Qt::Key_Escape: resetDragState(); break; default: QFrame::keyPressEvent(pKeyEvent); break; } } // end of qtractorThumbView.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorEngineCommand.h0000644000175000001440000000012311514076275021710 xustar000000000000000027 mtime=1295023293.370359 26 atime=1381134667.31508 30 ctime=1381134667.315080054 qtractor-0.5.11/src/qtractorEngineCommand.h0000644000175000001440000001327711514076275021211 0ustar00rncbcusers00000000000000// qtractorEngineCommand.h // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorEngineCommand_h #define __qtractorEngineCommand_h #include "qtractorCommand.h" #include "qtractorEngine.h" // Forward declarations. class qtractorMeter; //---------------------------------------------------------------------- // class qtractorBusCommand - declaration. // class qtractorBusCommand : public qtractorCommand { public: // Constructor. qtractorBusCommand(const QString& sName, qtractorBus *pBus = NULL, qtractorBus::BusMode busMode = qtractorBus::None); // Bus accessors. void setBus(qtractorBus *pBus) { m_pBus = pBus; } qtractorBus *bus() const { return m_pBus; } // Bus properties accessors. void setBusMode(qtractorBus::BusMode busMode) { m_busMode = busMode; } qtractorBus::BusMode busMode() const { return m_busMode; } void setBusType(qtractorTrack::TrackType busType) { m_busType = busType; } qtractorTrack::TrackType busType() const { return m_busType; } void setBusName(const QString& sBusName) { m_sBusName = sBusName; } const QString& busName() const { return m_sBusName; } void setMonitor(bool bMonitor) { m_bMonitor = bMonitor; } bool isMonitor() const { return m_bMonitor; } // Special Audio bus properties accessors. void setChannels(unsigned short iChannels) { m_iChannels = iChannels; } unsigned short channels() const { return m_iChannels; } void setAutoConnect(bool bAutoConnect) { m_bAutoConnect = bAutoConnect; } bool isAutoConnect() const { return m_bAutoConnect; } // Special MIDI bus properties accessors. void setInstrumentName(const QString& sInstrumentName) { m_sInstrumentName = sInstrumentName; } const QString& instrumentName() const { return m_sInstrumentName; } protected: // Bus command methods. bool createBus(); bool updateBus(); bool deleteBus(); // Monitor meter accessor. qtractorMeter *meter() const; private: // Instance variables. qtractorBus *m_pBus; qtractorBus::BusMode m_busMode; qtractorTrack::TrackType m_busType; QString m_sBusName; bool m_bMonitor; unsigned short m_iChannels; bool m_bAutoConnect; QString m_sInstrumentName; }; //---------------------------------------------------------------------- // class qtractorCreateBusCommand - declaration. // class qtractorCreateBusCommand : public qtractorBusCommand { public: // Constructor. qtractorCreateBusCommand(); // Bus creation command methods. bool redo(); bool undo(); }; //---------------------------------------------------------------------- // class qtractorUpdateBusCommand - declaration. // class qtractorUpdateBusCommand : public qtractorBusCommand { public: // Constructor. qtractorUpdateBusCommand(qtractorBus *pBus); // Bus update command methods. bool redo(); bool undo() { return redo(); } }; //---------------------------------------------------------------------- // class qtractorDeleteBusCommand - declaration. // class qtractorDeleteBusCommand : public qtractorBusCommand { public: // Constructor. qtractorDeleteBusCommand(qtractorBus *pBus); // Bus deletion command methods. bool redo(); bool undo(); }; //---------------------------------------------------------------------- // class qtractorBusMonitorCommand - declaration. // class qtractorBusMonitorCommand : public qtractorBusCommand { public: // Constructor. qtractorBusMonitorCommand(qtractorBus *pBus, bool bMonitor); // Bus-gain command methods. bool redo(); bool undo() { return redo(); } }; //---------------------------------------------------------------------- // class qtractorBusGainCommand - declaration. // class qtractorBusGainCommand : public qtractorBusCommand { public: // Constructor. qtractorBusGainCommand(qtractorBus *pBus, qtractorBus::BusMode busMode, float fGain); // Bus-gain command methods. bool redo(); bool undo() { return redo(); } // Gain value retrieval. float gain() const { return m_fGain; } // Last known gain predicate. float prevGain() const { return m_fPrevGain; } private: // Instance variables. float m_fGain; float m_fPrevGain; }; //---------------------------------------------------------------------- // class qtractorBusPanningCommand - declaration. // class qtractorBusPanningCommand : public qtractorBusCommand { public: // Constructor. qtractorBusPanningCommand(qtractorBus *pBus, qtractorBus::BusMode busMode, float fPanning); // Bus-panning command methods. bool redo(); bool undo() { return redo(); } // Panning value retrieval. float panning() const { return m_fPanning; } // Last known panning predicate. float prevPanning() const { return m_fPrevPanning; } private: // Instance variables. float m_fPanning; float m_fPrevPanning; }; #endif // __qtractorEngineCommand_h // end of qtractorEngineCommand.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorPasteRepeatForm.ui0000644000175000001440000000012312164325352022426 xustar000000000000000027 mtime=1372695274.495194 26 atime=1381134667.26308 30 ctime=1381134667.263080053 qtractor-0.5.11/src/qtractorPasteRepeatForm.ui0000644000175000001440000001127112164325352021717 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorPasteRepeatForm 0 0 260 160 Qt::StrongFocus Paste Repeat - Qtractor :/images/editPaste.png Repeat &Count: RepeatCountSpinBox Repeat count 2 200 Qt::Horizontal 110 20 &Period: 120 0 Repeat period Repeat period format Frames Time BBT Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qtractorTimeSpinBox QSpinBox
qtractorSpinBox.h
RepeatCountSpinBox RepeatPeriodCheckBox RepeatPeriodSpinBox RepeatFormatComboBox DialogButtonBox
qtractor-0.5.11/src/PaxHeaders.10084/qtractorMeter.cpp0000644000175000001440000000012312166526620020611 xustar000000000000000027 mtime=1373285776.071674 26 atime=1381134667.66108 30 ctime=1381134667.662080059 qtractor-0.5.11/src/qtractorMeter.cpp0000644000175000001440000002515512166526620020110 0ustar00rncbcusers00000000000000// qtractorMeter.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMeter.h" #include "qtractorMonitor.h" #include "qtractorMidiControlObserver.h" #include "qtractorMidiControlObserverForm.h" #include "qtractorObserverWidget.h" #include #include #include #include #include #include #include //---------------------------------------------------------------------------- // qtractorMeterScale -- Meter bridge scale widget. // Constructor. qtractorMeterScale::qtractorMeterScale ( qtractorMeter *pMeter, QWidget *pParent ) : QFrame(pParent) { m_pMeter = pMeter; m_iLastY = 0; QFrame::setFrameShape(QFrame::Panel); QFrame::setFrameShadow(QFrame::Sunken); QFrame::setMinimumWidth(16); // QFrame::setBackgroundRole(QPalette::Mid); const QFont& font = QFrame::font(); QFrame::setFont(QFont(font.family(), font.pointSize() - 2)); } // Meter accessor. qtractorMeter *qtractorMeterScale::meter (void) const { return m_pMeter; } // Draw scale line and label; assumes labels drawed from top to bottom. void qtractorMeterScale::drawLineLabel ( QPainter *p, int y, const QString& sLabel ) { int iCurrY = QWidget::height() - y; int iWidth = QWidget::width(); const QFontMetrics& fm = p->fontMetrics(); int iMidHeight = (fm.height() >> 1); if (iCurrY < iMidHeight || iCurrY > (m_iLastY + iMidHeight)) { if (fm.width(sLabel) < iWidth - 5) p->drawLine(iWidth - 3, iCurrY, iWidth - 1, iCurrY); p->drawText(0, iCurrY - iMidHeight, iWidth - 3, fm.height(), Qt::AlignHCenter | Qt::AlignVCenter, sLabel); m_iLastY = iCurrY + 1; } } // Paint event handler. void qtractorMeterScale::paintEvent ( QPaintEvent * ) { QPainter painter(this); m_iLastY = 0; #ifndef CONFIG_GRADIENT painter.setPen(Qt::darkGray); #endif paintScale(&painter); } //---------------------------------------------------------------------- // class qtractorMeter::PanSliderInterface -- Observer interface. // // Local converter interface. class qtractorMeter::PanSliderInterface : public qtractorObserverSlider::Interface { public: // Constructor. PanSliderInterface ( qtractorObserverSlider *pSlider ) : qtractorObserverSlider::Interface(pSlider) {} // Formerly Pure virtuals. float scaleFromValue ( float fValue ) const { return 100.0f * fValue; } float valueFromScale ( float fScale ) const { return 0.01f * fScale; } }; //---------------------------------------------------------------------------- // qtractorMeter::PanObserver -- Local dedicated observer. class qtractorMeter::PanObserver : public qtractorMidiControlObserver { public: // Constructor. PanObserver(qtractorMeter *pMeter) : qtractorMidiControlObserver(NULL), m_pMeter(pMeter) {} protected: // Update feedback. void update(bool bUpdate) { m_pMeter->monitor()->update(); if (bUpdate) m_pMeter->updatePanning(); qtractorMidiControlObserver::update(bUpdate); } private: // Members. qtractorMeter *m_pMeter; }; //---------------------------------------------------------------------------- // qtractorMeter::GainObserver -- Local dedicated observer. class qtractorMeter::GainObserver : public qtractorMidiControlObserver { public: // Constructor. GainObserver(qtractorMeter *pMeter) : qtractorMidiControlObserver(NULL), m_pMeter(pMeter) {} protected: // Update feedback. void update(bool bUpdate) { m_pMeter->monitor()->update(); if (bUpdate) m_pMeter->updateGain(); qtractorMidiControlObserver::update(bUpdate); } private: // Members. qtractorMeter *m_pMeter; }; //---------------------------------------------------------------------------- // qtractorMeter -- Meter bridge slot widget. // Constructor. qtractorMeter::qtractorMeter ( QWidget *pParent ) : QWidget(pParent) { const QFont& font = QWidget::font(); QFont font7(font.family(), font.pointSize() - 1); QFontMetrics fm(font7); m_pVBoxLayout = new QVBoxLayout(); m_pVBoxLayout->setMargin(0); m_pVBoxLayout->setSpacing(2); QWidget::setLayout(m_pVBoxLayout); m_pPanSlider = new qtractorObserverSlider(/*this*/); m_pPanSlider->setOrientation(Qt::Horizontal); m_pPanSlider->setFixedHeight(20); m_pVBoxLayout->addWidget(m_pPanSlider); m_pPanSpinBox = new qtractorObserverSpinBox(/*this*/); m_pPanSpinBox->setFont(font7); m_pPanSpinBox->setFixedHeight(fm.lineSpacing() + 2); m_pPanSpinBox->setKeyboardTracking(false); m_pVBoxLayout->addWidget(m_pPanSpinBox); m_pTopWidget = new QWidget(/*this*/); m_pTopLayout = new QHBoxLayout(); m_pTopLayout->setMargin(0); m_pTopLayout->setSpacing(2); m_pTopWidget->setLayout(m_pTopLayout); m_pVBoxLayout->addWidget(m_pTopWidget); m_pBoxWidget = new QWidget(/*this*/); m_pBoxLayout = new QHBoxLayout(); m_pBoxLayout->setMargin(2); m_pBoxLayout->setSpacing(2); m_pBoxWidget->setLayout(m_pBoxLayout); m_pVBoxLayout->addWidget(m_pBoxWidget); m_pGainSlider = new qtractorObserverSlider(/*, m_pBoxWidget*/); m_pGainSlider->setOrientation(Qt::Vertical); m_pGainSlider->setFixedWidth(20); m_pBoxLayout->addWidget(m_pGainSlider); m_pGainSpinBox = new qtractorObserverSpinBox(/*this*/); m_pGainSpinBox->setFont(font7); m_pGainSpinBox->setFixedHeight(fm.lineSpacing() + 2); m_pGainSpinBox->setKeyboardTracking(false); m_pVBoxLayout->addWidget(m_pGainSpinBox); m_pPanObserver = new PanObserver(this); m_pGainObserver = new GainObserver(this); m_iPeakFalloff = 0; m_pPanSlider->setInterface(new PanSliderInterface(m_pPanSlider)); m_pPanSlider->setTickPosition(QSlider::NoTicks); m_pPanSlider->setMinimum(-100); m_pPanSlider->setMaximum(+100); m_pPanSlider->setPageStep(10); m_pPanSlider->setSingleStep(1); m_pPanSpinBox->setDecimals(1); m_pPanSpinBox->setMinimum(-1.0f); m_pPanSpinBox->setMaximum(+1.0f); m_pPanSpinBox->setSingleStep(0.1f); m_pPanSpinBox->setAlignment(Qt::AlignHCenter); m_pPanSpinBox->setAccelerated(true); m_pPanSpinBox->setToolTip(tr("Pan")); m_pGainSlider->setTickPosition(QSlider::NoTicks); m_pGainSlider->setMinimum(0); m_pGainSlider->setMaximum(10000); m_pGainSlider->setPageStep(1000); m_pGainSlider->setSingleStep(100); m_pGainSpinBox->setDecimals(1); // m_pGainSpinBox->setSingleStep(0.1f); m_pGainSpinBox->setAlignment(Qt::AlignHCenter); m_pGainSpinBox->setAccelerated(true); m_pGainSpinBox->setToolTip(tr("Gain")); QWidget::setMinimumHeight(140); QWidget::setSizePolicy( QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding)); } // Default destructor. qtractorMeter::~qtractorMeter (void) { delete m_pGainObserver; delete m_pPanObserver; // No need to delete child widgets, Qt does it all for us } // Dynamic layout accessors. QWidget *qtractorMeter::topWidget (void) const { return m_pTopWidget; } QHBoxLayout *qtractorMeter::topLayout (void) const { return m_pTopLayout; } QWidget *qtractorMeter::boxWidget (void) const { return m_pBoxWidget; } QHBoxLayout *qtractorMeter::boxLayout (void) const { return m_pBoxLayout; } // Panning subject accessors. void qtractorMeter::setPanningSubject ( qtractorSubject *pSubject ) { m_pPanSlider->setSubject(pSubject); m_pPanSpinBox->setSubject(pSubject); m_pPanObserver->setSubject(pSubject); m_pPanSpinBox->observer()->update(true); m_pPanSlider->observer()->update(true); } qtractorSubject *qtractorMeter::panningSubject (void) const { return m_pPanObserver->subject(); } qtractorMidiControlObserver *qtractorMeter::panningObserver (void) const { return static_cast (m_pPanObserver); } // Stereo panning accessors. void qtractorMeter::setPanning ( float fPanning ) { m_pPanObserver->setValue(fPanning); monitor()->update(); updatePanning(); } float qtractorMeter::panning (void) const { return m_pPanObserver->value(); } float qtractorMeter::prevPanning (void) const { return m_pPanObserver->prevValue(); } // Gain subject accessors. void qtractorMeter::setGainSubject ( qtractorSubject *pSubject ) { m_pGainSlider->setSubject(pSubject); m_pGainSpinBox->setSubject(pSubject); m_pGainObserver->setSubject(pSubject); m_pGainSpinBox->observer()->update(true); m_pGainSlider->observer()->update(true); } qtractorSubject *qtractorMeter::gainSubject (void) const { return m_pGainObserver->subject(); } qtractorMidiControlObserver *qtractorMeter::gainObserver (void) const { return static_cast (m_pGainObserver); } // Gain accessors. void qtractorMeter::setGain ( float fGain ) { m_pGainObserver->setValue(fGain); monitor()->update(); updateGain(); } float qtractorMeter::gain (void) const { return m_pGainObserver->value(); } float qtractorMeter::prevGain (void) const { return m_pGainObserver->prevValue(); } // Common slider/spin-box accessors. qtractorObserverSlider *qtractorMeter::panSlider (void) const { return m_pPanSlider; } qtractorObserverSpinBox *qtractorMeter::panSpinBox (void) const { return m_pPanSpinBox; } qtractorObserverSlider *qtractorMeter::gainSlider (void) const { return m_pGainSlider; } qtractorObserverSpinBox *qtractorMeter::gainSpinBox (void) const { return m_pGainSpinBox; } // Peak falloff mode setting. void qtractorMeter::setPeakFalloff ( int iPeakFalloff ) { m_iPeakFalloff = iPeakFalloff; } int qtractorMeter::peakFalloff (void) const { return m_iPeakFalloff; } // MIDI controller/observer attachment (context menu) activator. // void qtractorMeter::addMidiControlAction ( QWidget *pWidget, qtractorMidiControlObserver *pMidiObserver ) { qtractorMidiControlObserverForm::addMidiControlAction( this, pWidget, pMidiObserver); } void qtractorMeter::midiControlActionSlot (void) { qtractorMidiControlObserverForm::midiControlAction( this, qobject_cast (sender())); } void qtractorMeter::midiControlMenuSlot ( const QPoint& pos ) { qtractorMidiControlObserverForm::midiControlMenu( qobject_cast (sender()), pos); } // end of qtractorMeter.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMessages.h0000644000175000001440000000012311563576072020757 xustar000000000000000027 mtime=1305410618.253123 26 atime=1381134671.09408 30 ctime=1381134671.094080114 qtractor-0.5.11/src/qtractorMessages.h0000644000175000001440000000562211563576072020253 0ustar00rncbcusers00000000000000// qtractorMessages.h // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMessages_h #define __qtractorMessages_h #include // Forward declarations. class qtractorMessagesTextEdit; class QSocketNotifier; class QFile; //------------------------------------------------------------------------- // qtractorMessages - Messages log dockable window. // class qtractorMessages : public QDockWidget { Q_OBJECT public: // Constructor. qtractorMessages(QWidget *pParent); // Destructor. ~qtractorMessages(); // Stdout/stderr capture accessors. bool isCaptureEnabled() const; void setCaptureEnabled(bool bCapture); // Message font accessors. QFont messagesFont() const; void setMessagesFont(const QFont & font); // Maximum number of message lines accessors. int messagesLimit() const; void setMessagesLimit(int iMessagesLimit); // Logging settings. bool isLogging() const; void setLogging(bool bEnabled, const QString& sFilename = QString()); // The main utility methods. void appendMessages(const QString& s); void appendMessagesColor(const QString& s, const QString &c); void appendMessagesText(const QString& s); // Stdout capture functions. void appendStdoutBuffer(const QString& s); void flushStdoutBuffer(); // History reset. void clear(); protected: // Message executives. void appendMessagesLine(const QString& s); void appendMessagesLog(const QString& s); // Just about to notify main-window that we're closing. void closeEvent(QCloseEvent *); protected slots: // Stdout capture slot. void stdoutNotify(int fd); private: // The maximum number of message lines and current count. int m_iMessagesLines; int m_iMessagesLimit; int m_iMessagesHigh; // The textview main widget. qtractorMessagesTextEdit *m_pMessagesTextView; // Stdout capture variables. QSocketNotifier *m_pStdoutNotifier; QString m_sStdoutBuffer; int m_fdStdout[2]; // Logging stuff. QFile *m_pMessagesLog; }; #endif // __qtractorMessages_h // end of qtractorMessages.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiControl.cpp0000644000175000001440000000012212073104061021743 xustar000000000000000027 mtime=1357678641.548312 26 atime=1381134670.83608 29 ctime=1381134670.83608011 qtractor-0.5.11/src/qtractorMidiControl.cpp0000644000175000001440000006405412073104061021244 0ustar00rncbcusers00000000000000// qtractorMidiControl.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. Copyright (C) 2009, gizzmo aka Mathias Krause. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiControl.h" #include "qtractorMidiEngine.h" #include "qtractorMidiControlObserver.h" #include "qtractorMidiControlObserverForm.h" #include "qtractorTrackCommand.h" #include "qtractorDocument.h" #include #include // Translatable macro contextualizer. #undef _TR #define _TR(x) QT_TR_NOOP(x) #include // Possible cube root optimization. // (borrowed from metamerist.com) static inline float cbrtf2 ( float x ) { #ifdef CONFIG_FLOAT32 // Avoid strict-aliasing optimization (gcc -O2). union { float f; int i; } u; u.f = x; u.i = (u.i / 3) + 710235478; return u.f; #else return cbrtf(x); #endif } static inline float cubef2 ( float x ) { return x * x * x; } //---------------------------------------------------------------------- // qtractorMidiControl -- MIDI control map (singleton). // // Kind of singleton reference. qtractorMidiControl* qtractorMidiControl::g_pMidiControl = NULL; // Constructor. qtractorMidiControl::qtractorMidiControl (void) { // Pseudo-singleton reference setup. g_pMidiControl = this; // Default controller mapping... clear(); } // Destructor. qtractorMidiControl::~qtractorMidiControl (void) { // Pseudo-singleton reference shut-down. g_pMidiControl = NULL; } // Kind of singleton reference. qtractorMidiControl *qtractorMidiControl::getInstance (void) { return g_pMidiControl; } // Clear control map (reset to default). void qtractorMidiControl::clear (void) { m_controlMap.clear(); #ifdef TEST_USx2y // JLCooper faders (as in US-224)... mapChannelControllerParam(15, TrackGain, 0x40); // No feedback. #endif #ifdef TEST_BCx2000 // Generic track feedback controllers (eg. Behringer BCx2000)... mapChannelParamController(7, TrackGain, 0, true); mapChannelParamController(10, TrackPanning, 0, true); mapChannelParamController(20, TrackMute, 0, true); #endif m_observerMap.clear(); } // Insert new controller mappings. void qtractorMidiControl::mapChannelParam ( ControlType ctype, unsigned short iChannel, unsigned short iParam, Command command, int iTrack, bool bFeedback ) { m_controlMap.insert( MapKey(ctype, iChannel, iParam), MapVal(command, iTrack, bFeedback)); } void qtractorMidiControl::mapChannelTrack ( ControlType ctype, unsigned short iParam, Command command, int iTrack, bool bFeedback ) { mapChannelParam( ctype, TrackParam, iParam, command, iTrack, bFeedback); } void qtractorMidiControl::mapChannelParamTrack ( ControlType ctype, unsigned short iChannel, unsigned short iParam, Command command, int iTrack, bool bFeedback ) { mapChannelParam( ctype, iChannel, iParam | TrackParam, command, iTrack, bFeedback); } // Remove existing controller mapping. void qtractorMidiControl::unmapChannelParam ( ControlType ctype, unsigned short iChannel, unsigned short iParam ) { m_controlMap.remove(MapKey(ctype, iChannel, iParam)); } // Check if given channel, param triplet is currently mapped. bool qtractorMidiControl::isChannelParamMapped ( ControlType ctype, unsigned short iChannel, unsigned short iParam ) const { return m_controlMap.contains(MapKey(ctype, iChannel, iParam)); } // Resend all (tracks) controllers // (eg. session initialized, track added/removed) void qtractorMidiControl::sendAllControllers ( int iFirstTrack ) const { if (iFirstTrack < 0) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; #ifdef CONFIG_DEBUG qDebug("qtractorMidiControl::sendAllControllers(%d)", iFirstTrack); #endif // 1. Walk through midi controller map... ControlMap::ConstIterator it = m_controlMap.constBegin(); const ControlMap::ConstIterator& it_end = m_controlMap.constEnd(); for ( ; it != it_end; ++it) { const MapVal& val = it.value(); if (val.isFeedback()) { const MapKey& key = it.key(); unsigned short iChannel = key.channel(); unsigned short iParam = key.param(); if (key.isParamTrack()) iParam &= TrackParamMask; int iTrack = 0; for (qtractorTrack *pTrack = pSession->tracks().first(); pTrack; pTrack = pTrack->next()) { if (iTrack >= iFirstTrack) { if (key.isChannelTrack()) sendTrackController(key.type(), pTrack, val.command(), iTrack, iParam); else if (key.isParamTrack()) sendTrackController(key.type(), pTrack, val.command(), iChannel, iParam + iTrack); else if (val.track() == iTrack) { sendTrackController(key.type(), pTrack, val.command(), iChannel, iParam); break; // Bail out from inner track loop. } } ++iTrack; } } } // 2. Walk through midi observer map... if (iFirstTrack == 0) { ObserverMap::ConstIterator iter = m_observerMap.constBegin(); const ObserverMap::ConstIterator& iter_end = m_observerMap.constEnd(); for ( ; iter != iter_end; ++iter) { qtractorMidiControlObserver *pMidiObserver = iter.value(); if (pMidiObserver->isFeedback()) { sendController( pMidiObserver->type(), pMidiObserver->channel(), pMidiObserver->param(), pMidiObserver->midiValue()); } } } } // Find incoming controller event map. qtractorMidiControl::ControlMap::Iterator qtractorMidiControl::findEvent ( const qtractorCtlEvent& ctle ) { // Check if controller map includes this event... ControlMap::Iterator it = m_controlMap.begin(); const ControlMap::Iterator& it_end = m_controlMap.end(); for ( ; it != it_end; ++it) { const MapKey& key = it.key(); if (key.match(ctle.type(), ctle.channel(), ctle.param())) break; } return it; } // Process incoming controller event. bool qtractorMidiControl::processEvent ( const qtractorCtlEvent& ctle ) { bool bResult = false; // Find whether there's any observer assigned... qtractorMidiControlObserver *pMidiObserver = findMidiObserver(ctle.type(), ctle.channel(), ctle.param()); if (pMidiObserver) { pMidiObserver->setMidiValue(ctle.value()); bResult = true; } else { qtractorMidiControlObserverForm *pMidiObserverForm = qtractorMidiControlObserverForm::getInstance(); if (pMidiObserverForm) pMidiObserverForm->processEvent(ctle); } // Find incoming controller event map tuple. ControlMap::Iterator it = findEvent(ctle); // Is there one mapped, indeed? if (it == m_controlMap.end()) return bResult; // Find the track by number... const MapKey& key = it.key(); MapVal& val = it.value(); int iTrack = val.track(); if (key.isChannelTrack()) { iTrack += int(ctle.channel()); } else if (key.isParamTrack()) { unsigned short iParam = key.param() & TrackParamMask; if (int(ctle.param()) >= iParam) iTrack += int(ctle.param()) - iParam; } qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return bResult; qtractorTrack *pTrack = pSession->tracks().at(iTrack); if (pTrack == NULL) return bResult; float fValue; switch (val.command()) { case TRACK_GAIN: fValue = float(ctle.value()) / 127.0f; if (pTrack->trackType() == qtractorTrack::Audio) fValue = ::cubef2(fValue); if (val.sync(fValue, pTrack->gain())) { bResult = pSession->execute( new qtractorTrackGainCommand(pTrack, val.value(), true)); } break; case TRACK_PANNING: fValue = (float(ctle.value()) - 64.0f) / 63.0f; if (val.sync(fValue, pTrack->panning())) { bResult = pSession->execute( new qtractorTrackPanningCommand(pTrack, val.value(), true)); } break; case TRACK_MONITOR: fValue = (ctle.value() > 0 ? 1.0f : 0.0f); if (val.sync(fValue, (pTrack->isMonitor() ? 1.0f : 0.0f))) { bResult = pSession->execute( new qtractorTrackMonitorCommand(pTrack, val.value(), true)); } break; case TRACK_RECORD: fValue = (ctle.value() > 0 ? 1.0f : 0.0f); if (val.sync(fValue, (pTrack->isRecord() ? 1.0f : 0.0f))) { bResult = pSession->execute( new qtractorTrackStateCommand(pTrack, qtractorTrack::Record, val.value(), true)); } break; case TRACK_MUTE: fValue = (ctle.value() > 0 ? 1.0f : 0.0f); if (val.sync(fValue, (pTrack->isMute() ? 1.0f : 0.0f))) { bResult = pSession->execute( new qtractorTrackStateCommand(pTrack, qtractorTrack::Mute, val.value(), true)); } break; case TRACK_SOLO: fValue = (ctle.value() > 0 ? 1.0f : 0.0f); if (val.sync(fValue, (pTrack->isSolo() ? 1.0f : 0.0f))) { bResult = pSession->execute( new qtractorTrackStateCommand(pTrack, qtractorTrack::Solo, val.value(), true)); } break; default: break; } return bResult; } // Process incoming command. void qtractorMidiControl::processTrackCommand ( Command command, int iTrack, float fValue, bool bCubic ) { switch (command) { case TRACK_GAIN: if (bCubic) fValue = ::cbrtf2(fValue); sendTrackController(iTrack, command, int(127.0f * fValue)); break; case TRACK_PANNING: sendTrackController(iTrack, command, 0x40 + int(63.0f * fValue)); break; default: break; } } void qtractorMidiControl::processTrackCommand ( Command command, int iTrack, bool bValue ) { switch (command) { case TRACK_MONITOR: case TRACK_RECORD: case TRACK_MUTE: case TRACK_SOLO: sendTrackController(iTrack, command, (bValue ? 127 : 0)); break; default: break; } } // Further processing of outgoing midi controller messages void qtractorMidiControl::sendTrackController ( int iTrack, Command command, int iValue ) { // Search for the command and parameter in controller map... ControlMap::Iterator it = m_controlMap.begin(); const ControlMap::Iterator& it_end = m_controlMap.end(); for ( ; it != it_end; ++it) { const MapKey& key = it.key(); MapVal& val = it.value(); if (val.command() == command) { val.syncReset(); if (!val.isFeedback()) continue; // Now send the message out... unsigned short iParam = (key.param() & TrackParamMask); if (key.isChannelTrack()) sendController(key.type(), iTrack, iParam, iValue); else if (key.isParamTrack()) sendController(key.type(), key.channel(), iParam + iTrack, iValue); else if (val.track() == iTrack) sendController(key.type(), key.channel(), iParam, iValue); } } } void qtractorMidiControl::sendTrackController ( ControlType ctype, qtractorTrack *pTrack, Command command, unsigned short iChannel, unsigned short iParam ) const { int iValue = 0; switch (command) { case TRACK_GAIN: if (pTrack->trackType() == qtractorTrack::Audio) iValue = int(127.0f * ::cbrtf2(pTrack->gain())); else iValue = int(127.0f * pTrack->gain()); break; case TRACK_PANNING: iValue = 0x40 + int(63.0f * pTrack->panning()); break; case TRACK_MONITOR: iValue = (pTrack->isMonitor() ? 127 : 0); break; case TRACK_RECORD: iValue = (pTrack->isRecord() ? 127 : 0); break; case TRACK_MUTE: iValue = (pTrack->isMute() ? 127 : 0); break; case TRACK_SOLO: iValue = (pTrack->isSolo() ? 127 : 0); break; default: break; } sendController(ctype, iChannel, iParam, iValue); } // Send this value out to midi bus. void qtractorMidiControl::sendController ( ControlType ctype, unsigned short iChannel, unsigned short iParam, int iValue ) const { qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorMidiEngine *pMidiEngine = pSession->midiEngine(); if (pMidiEngine == NULL) return; qtractorMidiBus *pMidiBus = pMidiEngine->controlBus_out(); if (pMidiBus == NULL) return; if (iValue < 0) iValue = 0; else if (ctype == qtractorMidiEvent::PITCHBEND) { if (iValue > 0x3fff) iValue = 0x3fff; } else if (iValue > 0x7f) iValue = 0x7f; #ifdef CONFIG_DEBUG qDebug("qtractorMidiControl::sendController(0x%02x, %u, %u, %d)", int(ctype), iChannel, iParam, iValue); #endif pMidiBus->sendEvent(ctype, iChannel, iParam, iValue); } // Insert/remove observer mappings. void qtractorMidiControl::mapMidiObserver ( qtractorMidiControlObserver *pMidiObserver ) { MapKey key( pMidiObserver->type(), pMidiObserver->channel(), pMidiObserver->param()); m_observerMap.insert(key, pMidiObserver); } void qtractorMidiControl::unmapMidiObserver ( qtractorMidiControlObserver *pMidiObserver ) { MapKey key( pMidiObserver->type(), pMidiObserver->channel(), pMidiObserver->param()); m_observerMap.remove(key); } // Observer map predicate. bool qtractorMidiControl::isMidiObserverMapped ( qtractorMidiControlObserver *pMidiObserver ) const { return (findMidiObserver( pMidiObserver->type(), pMidiObserver->channel(), pMidiObserver->param()) == pMidiObserver); } // Observer finder. qtractorMidiControlObserver *qtractorMidiControl::findMidiObserver ( ControlType ctype, unsigned short iChannel, unsigned short iParam) const { return m_observerMap.value(MapKey(ctype, iChannel, iParam), NULL); } //---------------------------------------------------------------------- // qtractorMidiControl::Document -- MIDI control document. // class qtractorMidiControl::Document : public qtractorDocument { public: // Constructor. Document(QDomDocument *pDocument, qtractorMidiControl *pMidiControl) : qtractorDocument(pDocument, "midi-control"), m_pMidiControl(pMidiControl) {} // Elemental loader/savers... bool loadElement(QDomElement *pElement) { return m_pMidiControl->loadElement(this, pElement); } bool saveElement(QDomElement *pElement) { return m_pMidiControl->saveElement(this, pElement); } private: // Instance variables. qtractorMidiControl *m_pMidiControl; }; // Load controller rules. bool qtractorMidiControl::loadElement ( qtractorDocument * /*pDocument*/, QDomElement *pElement ) { for (QDomNode nItem = pElement->firstChild(); !nItem.isNull(); nItem = nItem.nextSibling()) { // Convert item node to element... QDomElement eItem = nItem.toElement(); if (eItem.isNull()) continue; if (eItem.tagName() == "map") { ControlType ctype = typeFromText(eItem.attribute("type")); unsigned short iChannel = keyFromText(eItem.attribute("channel")); unsigned short iParam = 0; bool bOldMap = (ctype == ControlType(0)); bool bOldTrackParam = false; if (bOldMap) { ctype = qtractorMidiEvent::CONTROLLER; iParam = keyFromText(eItem.attribute("controller")); bOldTrackParam = bool(iParam & TrackParam); } else { iParam = eItem.attribute("param").toUShort(); if (qtractorDocument::boolFromText(eItem.attribute("track"))) iParam |= TrackParam; } Command command = Command(0); int iTrack = 0; bool bFeedback = false; for (QDomNode nVal = eItem.firstChild(); !nVal.isNull(); nVal = nVal.nextSibling()) { // Convert value node to element... QDomElement eVal = nVal.toElement(); if (eVal.isNull()) continue; if (eVal.tagName() == "command") command = commandFromText(eVal.text()); else if (eVal.tagName() == "track") iTrack = eVal.text().toInt(); else if (eVal.tagName() == "feedback") bFeedback = qtractorDocument::boolFromText(eVal.text()); else if (eVal.tagName() == "param" && bOldMap) { iTrack = eVal.text().toInt(); if (bOldTrackParam) { iParam += iTrack; iTrack = 0; } } } m_controlMap.insert( MapKey(ctype, iChannel, iParam), MapVal(command, iTrack, bFeedback)); } } return true; } // Save controller rules. bool qtractorMidiControl::saveElement ( qtractorDocument *pDocument, QDomElement *pElement ) { ControlMap::ConstIterator it = m_controlMap.constBegin(); const ControlMap::ConstIterator& it_end = m_controlMap.constEnd(); for ( ; it != it_end; ++it) { const MapKey& key = it.key(); const MapVal& val = it.value(); QDomElement eItem = pDocument->document()->createElement("map"); eItem.setAttribute("type", textFromType(key.type())); eItem.setAttribute("channel", textFromKey(key.channel())); eItem.setAttribute("param", QString::number(key.param() & TrackParamMask)); eItem.setAttribute("track", qtractorDocument::textFromBool(key.isParamTrack())); pDocument->saveTextElement("command", textFromCommand(val.command()), &eItem); pDocument->saveTextElement("track", QString::number(val.track()), &eItem); pDocument->saveTextElement("feedback", qtractorDocument::textFromBool(val.isFeedback()), &eItem); pElement->appendChild(eItem); } return true; } // Document file methods. bool qtractorMidiControl::loadDocument ( const QString& sFilename ) { QDomDocument doc("qtractorMidiControl"); return qtractorMidiControl::Document(&doc, this).load(sFilename); } bool qtractorMidiControl::saveDocument ( const QString& sFilename ) { QDomDocument doc("qtractorMidiControl"); return qtractorMidiControl::Document(&doc, this).save(sFilename); } unsigned short qtractorMidiControl::keyFromText ( const QString& sText ) { if (sText == "*" || sText == "TrackParam" || sText.isEmpty()) return TrackParam; else return sText.toUShort(); } QString qtractorMidiControl::textFromKey ( unsigned short iKey ) { if (iKey & TrackParam) return "*"; // "TrackParam"; else return QString::number(iKey); } // Load meter controllers (MIDI). void qtractorMidiControl::loadControllers ( QDomElement *pElement, Controllers& controllers ) { qDeleteAll(controllers); controllers.clear(); for (QDomNode nController = pElement->firstChild(); !nController.isNull(); nController = nController.nextSibling()) { // Convert node to element, if any. QDomElement eController = nController.toElement(); if (eController.isNull()) continue; // Check for controller item... if (eController.tagName() == "controller") { Controller *pController = new Controller; pController->name = eController.attribute("name"); pController->index = eController.attribute("index").toULong(); pController->ctype = typeFromText(eController.attribute("type")); for (QDomNode nProp = eController.firstChild(); !nProp.isNull(); nProp = nProp.nextSibling()) { // Convert node to element, if any. QDomElement eProp = nProp.toElement(); if (eProp.isNull()) continue; // Check for property item... if (eProp.tagName() == "channel") pController->channel = eProp.text().toUShort(); else if (eProp.tagName() == "param") pController->param = eProp.text().toUShort(); else if (eProp.tagName() == "logarithmic") pController->logarithmic = qtractorDocument::boolFromText(eProp.text()); else if (eProp.tagName() == "feedback") pController->feedback = qtractorDocument::boolFromText(eProp.text()); else if (eProp.tagName() == "invert") pController->invert = qtractorDocument::boolFromText(eProp.text()); if (eProp.tagName() == "hook") pController->hook = qtractorDocument::boolFromText(eProp.text()); } controllers.append(pController); } } } // Save meter controllers (MIDI). void qtractorMidiControl::saveControllers ( qtractorDocument *pDocument, QDomElement *pElement, const Controllers& controllers ) { QListIterator iter(controllers); while (iter.hasNext()) { Controller *pController = iter.next(); QDomElement eController = pDocument->document()->createElement("controller"); eController.setAttribute("name", pController->name); eController.setAttribute("index", QString::number(pController->index)); eController.setAttribute("type", textFromType(pController->ctype)); pDocument->saveTextElement("channel", QString::number(pController->channel), &eController); pDocument->saveTextElement("param", QString::number(pController->param), &eController); pDocument->saveTextElement("logarithmic", qtractorDocument::textFromBool(pController->logarithmic), &eController); pDocument->saveTextElement("feedback", qtractorDocument::textFromBool(pController->feedback), &eController); pDocument->saveTextElement("invert", qtractorDocument::textFromBool(pController->invert), &eController); pDocument->saveTextElement("hook", qtractorDocument::textFromBool(pController->hook), &eController); pElement->appendChild(eController); } } //---------------------------------------------------------------------------- // MIDI Controller Type Text/Names - Default control types hash maps. static struct { qtractorMidiControl::ControlType ctype; const char *text; const char *name; } g_aControlTypes[] = { { qtractorMidiEvent::NOTEON, "NOTEON", _TR("Note On") }, { qtractorMidiEvent::NOTEOFF, "NOTEOFF", _TR("Note Off") }, { qtractorMidiEvent::KEYPRESS, "KEYPRESS", _TR("Key Press") }, { qtractorMidiEvent::CONTROLLER, "CONTROLLER", _TR("Controller") }, { qtractorMidiEvent::PGMCHANGE, "PGMCHANGE", _TR("Pgm Change") }, { qtractorMidiEvent::CHANPRESS, "CHANPRESS", _TR("Chan Press") }, { qtractorMidiEvent::PITCHBEND, "PITCHBEND", _TR("Pitch Bend") }, { qtractorMidiControl::ControlType(0), NULL, NULL } }; static QHash g_controlTypeTexts; static QHash g_textControlTypes; static void initControlTypeTexts (void) { if (g_controlTypeTexts.isEmpty()) { // Pre-load ontrol-types hash table... for (int i = 0; g_aControlTypes[i].text; ++i) { qtractorMidiControl::ControlType ctype = g_aControlTypes[i].ctype; const QString& sText = QString(g_aControlTypes[i].text); g_controlTypeTexts.insert(ctype, sText); g_textControlTypes.insert(sText, ctype); } } } static QHash g_controlTypeNames; static QHash g_nameControlTypes; static void initControlTypeNames (void) { if (g_controlTypeNames.isEmpty()) { // Pre-load ontrol-types hash table... for (int i = 0; g_aControlTypes[i].name; ++i) { qtractorMidiControl::ControlType ctype = g_aControlTypes[i].ctype; const QString& sName = QObject::tr(g_aControlTypes[i].name, "controlType"); g_controlTypeNames.insert(ctype, sName); g_nameControlTypes.insert(sName, ctype); } } } // Control type text (translatable) conversion helpers. qtractorMidiControl::ControlType qtractorMidiControl::typeFromText ( const QString& sText ) { initControlTypeTexts(); return g_textControlTypes[sText]; } const QString& qtractorMidiControl::textFromType ( qtractorMidiControl::ControlType ctype ) { initControlTypeTexts(); return g_controlTypeTexts[ctype]; } // Control type name (label) conversion helpers. qtractorMidiControl::ControlType qtractorMidiControl::typeFromName ( const QString& sName ) { initControlTypeNames(); return g_nameControlTypes[sName]; } const QString& qtractorMidiControl::nameFromType ( qtractorMidiControl::ControlType ctype ) { initControlTypeNames(); return g_controlTypeNames[ctype]; } //---------------------------------------------------------------------------- // MIDI Controller Command Text/Names - Default command names hash map. static struct { qtractorMidiControl::Command command; const char *text; const char *name; } g_aCommandNames[] = { { qtractorMidiControl::TRACK_GAIN, "TRACK_GAIN", _TR("Track Gain") }, { qtractorMidiControl::TRACK_PANNING, "TRACK_PANNING", _TR("Track Panning") }, { qtractorMidiControl::TRACK_MONITOR, "TRACK_MONITOR", _TR("Track Monitor") }, { qtractorMidiControl::TRACK_RECORD, "TRACK_RECORD", _TR("Track Record") }, { qtractorMidiControl::TRACK_MUTE, "TRACK_MUTE", _TR("Track Mute") }, { qtractorMidiControl::TRACK_SOLO, "TRACK_SOLO", _TR("Track Solo") }, { qtractorMidiControl::Command(0), NULL, NULL } }; static QHash g_commandTexts; static QHash g_textCommands; static void initCommandTexts (void) { if (g_commandTexts.isEmpty()) { // Pre-load command-names hash table... for (int i = 0; g_aCommandNames[i].text; ++i) { qtractorMidiControl::Command command = g_aCommandNames[i].command; const QString& sText = QString(g_aCommandNames[i].text); g_commandTexts.insert(command, sText); g_textCommands.insert(sText, command); } } } static QHash g_commandNames; static QHash g_nameCommands; static void initCommandNames (void) { if (g_commandNames.isEmpty()) { // Pre-load command-names hash table... for (int i = 0; g_aCommandNames[i].name; ++i) { qtractorMidiControl::Command command = g_aCommandNames[i].command; const QString& sName = QObject::tr(g_aCommandNames[i].name, "commandName"); g_commandNames.insert(command, sName); g_nameCommands.insert(sName, command); } } } qtractorMidiControl::Command qtractorMidiControl::commandFromText ( const QString& sText ) { #if 0 initCommandTexts(); return g_textCommands[sText]; #else if (sText == "TRACK_GAIN" || sText == "TrackGain") return TRACK_GAIN; else if (sText == "TRACK_PANNING" || sText == "TrackPanning") return TRACK_PANNING; else if (sText == "TRACK_MONITOR" || sText == "TrackMonitor") return TRACK_MONITOR; else if (sText == "TRACK_RECORD" || sText == "TrackRecord") return TRACK_RECORD; else if (sText == "TRACK_MUTE" || sText == "TrackMute") return TRACK_MUTE; else if (sText == "TRACK_SOLO" || sText == "TrackSolo") return TRACK_SOLO; else return Command(0); #endif } const QString& qtractorMidiControl::textFromCommand ( Command command ) { initCommandTexts(); return g_commandTexts[command]; } qtractorMidiControl::Command qtractorMidiControl::commandFromName ( const QString& sName ) { initCommandNames(); return g_nameCommands[sName]; } const QString& qtractorMidiControl::nameFromCommand ( Command command ) { initCommandNames(); return g_commandNames[command]; } // end of qtractorMidiControl.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiMonitor.cpp0000644000175000001440000000012211632156165021766 xustar000000000000000027 mtime=1315495029.097474 26 atime=1381134667.73408 29 ctime=1381134667.73408006 qtractor-0.5.11/src/qtractorMidiMonitor.cpp0000644000175000001440000001254611632156165021266 0ustar00rncbcusers00000000000000// qtractorMidiMonitor.cpp // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorMidiMonitor.h" #include "qtractorSession.h" #include "qtractorSessionCursor.h" #include "qtractorAudioEngine.h" #include "qtractorMidiEngine.h" // Module constants. const unsigned int c_iQueueSize = 16; // Must be power of 2; const unsigned int c_iQueueMask = c_iQueueSize - 1; // Singleton variables. unsigned int qtractorMidiMonitor::g_iFrameSlot = 0; unsigned int qtractorMidiMonitor::g_iTimeSlot[2] = { 0, 0 }; unsigned long qtractorMidiMonitor::g_iTimeSplit = 0; //---------------------------------------------------------------------------- // qtractorMidiMonitor -- MIDI monitor bridge value processor. // Constructor. qtractorMidiMonitor::qtractorMidiMonitor ( float fGain, float fPanning ) : qtractorMonitor(fGain, fPanning) { // Allocate actual buffer stuff... m_pQueue = new QueueItem [c_iQueueSize]; // May reset now... reset(); } // Destructor. qtractorMidiMonitor::~qtractorMidiMonitor (void) { delete [] m_pQueue; } // Monitor enqueue method. void qtractorMidiMonitor::enqueue ( qtractorMidiEvent::EventType type, unsigned char val, unsigned long tick ) { // Check whether this is a scheduled value... if (m_iTimeStart < tick && g_iTimeSlot[1] > 0) { // Find queue offset index... unsigned int iOffset = (tick - m_iTimeStart) / timeSlot(tick); // FIXME: Ignore outsiders (which would manifest as // out-of-time phantom monitor peak values...) if (iOffset > c_iQueueMask) iOffset = c_iQueueMask; unsigned int iIndex = (m_iQueueIndex + iOffset) & c_iQueueMask; // Set the value in buffer... QueueItem& item = m_pQueue[iIndex]; if (item.value < val && type == qtractorMidiEvent::NOTEON) item.value = val; // Increment enqueued count. ++(item.count); // Done enqueueing. } else { // Alternative is sending it directly // as a non-enqueued direct value... if (m_item.value < val && type == qtractorMidiEvent::NOTEON) m_item.value = val; // Increment direct count. ++(m_item.count); // Done direct. } } // Monitor value dequeue method. float qtractorMidiMonitor::value (void) { // Grab-and-reset current direct value... unsigned char val = m_item.value; m_item.value = 0; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession && g_iFrameSlot > 0) { // Sweep the queue until current time... unsigned long iFrameTime = pSession->frameTimeEx(); while (m_iFrameStart < iFrameTime) { QueueItem& item = m_pQueue[m_iQueueIndex]; if (val < item.value) val = item.value; m_item.count += item.count; item.value = 0; item.count = 0; ++m_iQueueIndex &= c_iQueueMask; m_iFrameStart += g_iFrameSlot; m_iTimeStart += timeSlot(m_iTimeStart); } } // Dequeue done. return (gain() * val) / 127.0f; } // Monitor count dequeue method. int qtractorMidiMonitor::count (void) { // Grab latest direct/dequeued count... int iCount = int(m_item.count); m_item.count = 0; return iCount; } // Clear monitor. void qtractorMidiMonitor::clear (void) { // (Re)initialize all... m_item.value = 0; m_item.count = 0; m_iQueueIndex = 0; // Time to reset buffer... for (unsigned int i = 0; i < c_iQueueSize; ++i) { m_pQueue[i].value = 0; m_pQueue[i].count = 0; } } // Reset monitor. void qtractorMidiMonitor::reset (void) { // (Re)initialize all... clear(); // Reset actual frame/time start... m_iFrameStart = 0; m_iTimeStart = 0; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) m_iFrameStart = pSession->frameTimeEx(); } // Update monitor (nothing really done here). void qtractorMidiMonitor::update (void) { // Do nothing yet... } // Singleton time base reset. void qtractorMidiMonitor::resetTime ( qtractorTimeScale *pTimeScale, unsigned long iFrame ) { g_iFrameSlot = pTimeScale->sampleRate() / c_iQueueSize; splitTime(pTimeScale, iFrame, 0); } // Singleton time base split (scheduled tempo change) void qtractorMidiMonitor::splitTime ( qtractorTimeScale *pTimeScale, unsigned long iFrame, unsigned long iTime ) { // Reset time references... qtractorTimeScale::Cursor cursor(pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(iFrame); unsigned long t0 = pNode->tickFromFrame(iFrame); // Time slot: the amount of time (in ticks) // each queue slot will hold scheduled events; g_iTimeSlot[0] = g_iTimeSlot[1]; g_iTimeSlot[1] = pNode->tickFromFrame(iFrame + g_iFrameSlot) - t0; // Relative time where time splits. g_iTimeSplit = iTime; } // end of qtractorMidiMonitor.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorTempoAdjustForm.ui0000644000175000001440000000012312166134117022447 xustar000000000000000027 mtime=1373157455.942698 26 atime=1381134667.43608 30 ctime=1381134667.436080056 qtractor-0.5.11/src/qtractorTempoAdjustForm.ui0000644000175000001440000002010312166134117021732 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - An Audio/MIDI multi-track sequencer. Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorTempoAdjustForm 0 0 340 260 Qt::StrongFocus Tempo - Qtractor :/images/transportMetro.png Metronome 60 0 Temp&o: TempoSpinBox 120 0 Tempo/Time signature Qt::Horizontal 20 20 T&ap Range 60 0 &Length: RangeLengthSpinBox Range beats 1 65536 A&djust 60 0 &Start: RangeStartSpinBox 60 0 B&eats: RangeLengthSpinBox 120 0 Range length 120 0 Range start Format Time display format Frames Time BBT Qt::Vertical 20 20 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qtractorTimeSpinBox QSpinBox
qtractorSpinBox.h
qtractorTempoSpinBox QSpinBox
qtractorSpinBox.h
TempoSpinBox TempoPushButton RangeStartSpinBox RangeLengthSpinBox RangeBeatsSpinBox AdjustPushButton FormatComboBox DialogButtonBox
qtractor-0.5.11/src/PaxHeaders.10084/qtractorTrack.cpp0000644000175000001440000000012212217361266020600 xustar000000000000000026 mtime=1379787446.61859 26 atime=1381134666.76008 30 ctime=1381134666.761080045 qtractor-0.5.11/src/qtractorTrack.cpp0000644000175000001440000016252012217361266020076 0ustar00rncbcusers00000000000000// qtractorTrack.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorTrack.h" #include "qtractorSession.h" #include "qtractorAudioClip.h" #include "qtractorMidiClip.h" #include "qtractorDocument.h" #include "qtractorAudioEngine.h" #include "qtractorAudioMonitor.h" #include "qtractorAudioBuffer.h" #include "qtractorMidiEngine.h" #include "qtractorMidiMonitor.h" #include "qtractorMidiBuffer.h" #include "qtractorInstrument.h" #include "qtractorPlugin.h" #include "qtractorMixer.h" #include "qtractorMeter.h" #include "qtractorCurveFile.h" #include "qtractorTrackCommand.h" #include "qtractorMainForm.h" #include "qtractorTracks.h" #include #include #include //------------------------------------------------------------------------ // qtractorTrack::StateObserver -- Local track state observer. class qtractorTrack::StateObserver : public qtractorMidiControlObserver { public: // Constructor. StateObserver(qtractorTrack *pTrack, ToolType toolType, qtractorSubject *pSubject) : qtractorMidiControlObserver(pSubject), m_pTrack(pTrack), m_toolType(toolType) {} protected: // Update feedback. void update(bool bUpdate) { bool bOn = (value() > 0.0f); switch (m_toolType) { case qtractorTrack::Record: m_pTrack->setRecord(bOn); break; case qtractorTrack::Mute: m_pTrack->setMute(bOn); break; case qtractorTrack::Solo: m_pTrack->setSolo(bOn); break; } qtractorMidiControlObserver::update(bUpdate); if (bUpdate) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->tracks()->updateContents(true); } } private: // Members. qtractorTrack *m_pTrack; ToolType m_toolType; }; //---------------------------------------------------------------------------- // qtractorTrack::MidiVolumeObserver -- Local dedicated observer. class qtractorTrack::MidiVolumeObserver : public qtractorObserver { public: // Constructor. MidiVolumeObserver(qtractorTrack *pTrack, qtractorSubject *pSubject) : qtractorObserver(pSubject), m_pTrack(pTrack), m_volume(0) {} protected: // Update feedback. void update(bool bUpdate) { const float fVolume = value(); const unsigned char vol = int(127.0f * fVolume) & 0x7f; if (m_volume != vol) { if (bUpdate) { qtractorMidiBus *pMidiBus = static_cast (m_pTrack->outputBus()); if (pMidiBus) pMidiBus->setVolume(m_pTrack, fVolume); } m_volume = vol; } } private: // Members. qtractorTrack *m_pTrack; unsigned char m_volume; }; //---------------------------------------------------------------------------- // qtractorTrack::MidiPanningObserver -- Local dedicated observer. class qtractorTrack::MidiPanningObserver : public qtractorObserver { public: // Constructor. MidiPanningObserver(qtractorTrack *pTrack, qtractorSubject *pSubject) : qtractorObserver(pSubject), m_pTrack(pTrack), m_panning(0) {} protected: // Update feedback. void update(bool bUpdate) { const float fPanning = value(); const unsigned char pan = (0x40 + int(63.0f * fPanning)) & 0x7f; if (m_panning != pan) { if (bUpdate) { qtractorMidiBus *pMidiBus = static_cast (m_pTrack->outputBus()); if (pMidiBus) pMidiBus->setPanning(m_pTrack, fPanning); } m_panning = pan; } } private: // Members. qtractorTrack *m_pTrack; unsigned char m_panning; }; //---------------------------------------------------------------------------- // qtractorTrack::MidiProgramObserver -- Local dedicated observer. class qtractorTrack::MidiProgramObserver : public qtractorObserver { public: // Constructor. MidiProgramObserver(qtractorTrack *pTrack, qtractorSubject *pSubject) : qtractorObserver(pSubject), m_pTrack(pTrack) {} protected: // Update feedback. void update(bool bUpdate) { const int iValue = int(value()); const int iBank = (iValue >> 7) & 0x3fff; const int iProg = (iValue & 0x7f); m_pTrack->setMidiBank(iBank); m_pTrack->setMidiProg(iProg); // Refresh track item, at least the names... if (bUpdate) m_pTrack->updateTracks(); } private: // Members. qtractorTrack *m_pTrack; }; //------------------------------------------------------------------------- // qtractorTrack::Properties -- Track properties structure. // Helper clear/reset method. void qtractorTrack::Properties::clear (void) { trackName.clear(); trackType = None; monitor = false; record = false; mute = false; solo = false; gain = 1.0f; panning = 0.0f; inputBusName.clear(); outputBusName.clear(); midiOmni = false; midiChannel = 0; midiBankSelMethod = -1; midiBank = -1; midiProg = -1; foreground = Qt::yellow; background = Qt::darkBlue; } // Helper copy method. qtractorTrack::Properties& qtractorTrack::Properties::copy ( const Properties& props ) { if (&props != this) { trackName = props.trackName; trackType = props.trackType; monitor = props.monitor; record = props.record; mute = props.mute; solo = props.solo; gain = props.gain; panning = props.panning; inputBusName = props.inputBusName; outputBusName = props.outputBusName; midiOmni = props.midiOmni; midiChannel = props.midiChannel; midiBankSelMethod = props.midiBankSelMethod; midiBank = props.midiBank; midiProg = props.midiProg; foreground = props.foreground; background = props.background; } return *this; } // Take(record) descriptor/id registry methods. void qtractorTrack::clearTakeInfo (void) const { m_idtakes.clear(); m_takeids.clear(); } // Retrieve take(record) descriptor/id from registry. qtractorTrack::TakeInfo *qtractorTrack::takeInfo ( int iTakeID ) const { return m_idtakes.value(iTakeID, NULL); } int qtractorTrack::takeInfoId ( qtractorTrack::TakeInfo *pTakeInfo ) const { return m_takeids.value(pTakeInfo, -1); } // Add/new take(record) descriptor/id to registry. int qtractorTrack::takeInfoNew ( qtractorTrack::TakeInfo *pTakeInfo ) const { QHash::ConstIterator iter = m_takeids.constFind(pTakeInfo); if (iter != m_takeids.constEnd()) { return iter.value(); } else { int iTakeID = m_takeids.count(); takeInfoAdd(iTakeID, pTakeInfo); return iTakeID; } } void qtractorTrack::takeInfoAdd ( int iTakeID, qtractorTrack::TakeInfo *pTakeInfo ) const { m_idtakes.insert(iTakeID, pTakeInfo); m_takeids.insert(pTakeInfo, iTakeID); } //------------------------------------------------------------------------- // qtractorTrack -- Track container. // Constructor. qtractorTrack::qtractorTrack ( qtractorSession *pSession, TrackType trackType ) { m_pSession = pSession; m_props.trackType = trackType; m_pInputBus = NULL; m_pOutputBus = NULL; m_pMonitor = NULL; m_iMidiTag = 0; m_pClipRecord = NULL; m_iClipRecordStart = 0; m_clips.setAutoDelete(true); m_pSyncThread = NULL; m_pMidiVolumeObserver = NULL; m_pMidiPanningObserver = NULL; m_pMonitorSubject = new qtractorSubject(); m_pMonitorSubject->setToggled(true); m_pRecordSubject = new qtractorSubject(); m_pMuteSubject = new qtractorSubject(); m_pSoloSubject = new qtractorSubject(); m_pRecordSubject->setToggled(true); m_pMuteSubject->setToggled(true); m_pSoloSubject->setToggled(true); m_pMonitorObserver = new qtractorMidiControlObserver(m_pMonitorSubject); m_pRecordObserver = new StateObserver(this, Record, m_pRecordSubject); m_pMuteObserver = new StateObserver(this, Mute, m_pMuteSubject); m_pSoloObserver = new StateObserver(this, Solo, m_pSoloSubject); unsigned int iSampleRate = 0; qtractorAudioEngine *pAudioEngine = pSession->audioEngine(); if (pAudioEngine) iSampleRate = pAudioEngine->sampleRate(); unsigned int iFlags = qtractorPluginList::Track; if (trackType == qtractorTrack::Midi) iFlags |= qtractorPluginList::Midi; m_pPluginList = new qtractorPluginList(0, 0, iSampleRate, iFlags); m_pCurveFile = new qtractorCurveFile(m_pPluginList->curveList()); m_pMidiProgramObserver = NULL; setHeight(HeightBase); // Default track height. clear(); } // Default desstructor. qtractorTrack::~qtractorTrack (void) { close(); clear(); if (m_pSoloObserver) delete m_pSoloObserver; if (m_pMuteObserver) delete m_pMuteObserver; if (m_pRecordObserver) delete m_pRecordObserver; if (m_pMonitorObserver) delete m_pMonitorObserver; if (m_pSoloSubject) delete m_pSoloSubject; if (m_pMuteSubject) delete m_pMuteSubject; if (m_pRecordSubject) delete m_pRecordSubject; if (m_pMonitorSubject) delete m_pMonitorSubject; qDeleteAll(m_controllers); m_controllers.clear(); if (m_pCurveFile) delete m_pCurveFile; if (m_pPluginList) delete m_pPluginList; if (m_pMonitor) delete m_pMonitor; } // Reset track. void qtractorTrack::clear (void) { setClipRecord(NULL); clearTakeInfo(); m_clips.clear(); m_pPluginList->clear(); m_pCurveFile->clear(); m_props.midiBankSelMethod = -1; m_props.midiBank = -1; m_props.midiProg = -1; m_props.monitor = false; m_props.record = false; m_props.mute = false; m_props.solo = false; m_props.gain = 1.0f; m_props.panning = 0.0f; if (m_pSyncThread) { if (m_pSyncThread->isRunning()) do { m_pSyncThread->setRunState(false); // m_pSyncThread->terminate(); m_pSyncThread->sync(); } while (!m_pSyncThread->wait(100)); delete m_pSyncThread; m_pSyncThread = NULL; } } // Track open method. bool qtractorTrack::open (void) { close(); if (m_pSession == NULL) return false; // Depending on track type... qtractorEngine *pEngine = NULL; qtractorAudioEngine *pAudioEngine = m_pSession->audioEngine(); qtractorMidiEngine *pMidiEngine = m_pSession->midiEngine(); switch (m_props.trackType) { case qtractorTrack::Audio: pEngine = pAudioEngine; break; case qtractorTrack::Midi: pEngine = pMidiEngine; break; default: break; } // Got it? if (pEngine == NULL) return false; // (Re)assign the input bus to the track. m_pInputBus = pEngine->findInputBus(inputBusName()); // Fallback to first usable one... if (m_pInputBus == NULL) { for (qtractorBus *pBus = pEngine->buses().first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Input) { m_pInputBus = pBus; break; } } // Set the bus name back... if (m_pInputBus) setInputBusName(m_pInputBus->busName()); } // (Re)assign the output bus to the track. m_pOutputBus = pEngine->findOutputBus(outputBusName()); // Fallback to first usable one... if (m_pOutputBus == NULL) { for (qtractorBus *pBus = pEngine->buses().first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Output) { m_pOutputBus = pBus; break; } } // Set the bus name back... if (m_pOutputBus) setOutputBusName(m_pOutputBus->busName()); } #if 0 // Check proper bus assignment... if (m_pInputBus == NULL || m_pOutputBus == NULL) return false; #endif // Remember current (output) monitor, for later deletion... qtractorMonitor *pMonitor = m_pMonitor; m_pMonitor = NULL; // (Re)allocate (output) monitor... switch (m_props.trackType) { case qtractorTrack::Audio: { qtractorAudioBus *pAudioBus = static_cast (m_pOutputBus); if (pAudioBus) { m_pMonitor = new qtractorAudioMonitor(pAudioBus->channels(), m_props.gain, m_props.panning); m_pPluginList->setBuffer(pAudioBus->channels(), pAudioEngine->bufferSize(), pAudioEngine->sampleRate(), qtractorPluginList::AudioTrack); } break; } case qtractorTrack::Midi: { qtractorMidiBus *pMidiBus = static_cast (m_pOutputBus); if (pMidiBus) { m_pMonitor = new qtractorMidiMonitor( m_props.gain, m_props.panning); m_pMidiVolumeObserver = new MidiVolumeObserver( this, m_pMonitor->gainSubject()); m_pMidiPanningObserver = new MidiPanningObserver( this, m_pMonitor->panningSubject()); } // Get audio bus as for the plugin list... qtractorAudioBus *pAudioBus = NULL; qtractorMidiManager *pMidiManager = m_pPluginList->midiManager(); if (pMidiManager) pAudioBus = pMidiManager->audioOutputBus(); if (pAudioBus == NULL) { // Output bus gets to be the first available output bus... for (qtractorBus *pBus = (pAudioEngine->buses()).first(); pBus; pBus = pBus->next()) { if (pBus->busMode() & qtractorBus::Output) { pAudioBus = static_cast (pBus); break; } } } // Set plugin-list buffer alright... if (pAudioBus) { m_pPluginList->setBuffer(pAudioBus->channels(), pAudioEngine->bufferSize(), pAudioEngine->sampleRate(), qtractorPluginList::MidiTrack); } // Set MIDI bank/program observer... if (m_pPluginList->midiProgramSubject()) { m_pMidiProgramObserver = new MidiProgramObserver(this, m_pPluginList->midiProgramSubject()); } break; } default: break; } // Mixer turn, before we get rid of old monitor... if (pMonitor) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) { qtractorMixer *pMixer = pMainForm->mixer(); if (pMixer) { qtractorMixerStrip *pStrip = pMixer->trackRack()->findStrip(pMonitor); if (pStrip) pStrip->setTrack(this); } } // Update gain and panning curve new subjects... qtractorCurveList *pCurveList = m_pPluginList->curveList(); if (pCurveList) { qtractorCurve *pCurve = pCurveList->first(); while (pCurve) { qtractorSubject *pSubject = pCurve->subject(); if (pSubject) { if (pSubject == pMonitor->gainSubject()) { pCurve->setSubject(m_pMonitor->gainSubject()); m_pMonitor->gainSubject()->setCurve(pCurve); } else if (pSubject == pMonitor->panningSubject()) { pCurve->setSubject(m_pMonitor->panningSubject()); m_pMonitor->panningSubject()->setCurve(pCurve); } } pCurve = pCurve->next(); } } // That's it... delete pMonitor; } // Ah, at least make new name feedback... updateTrackName(); // Done. return (m_pMonitor != NULL); } // Track close method. void qtractorTrack::close (void) { if (m_pMidiVolumeObserver) { delete m_pMidiVolumeObserver; m_pMidiVolumeObserver = NULL; } if (m_pMidiPanningObserver) { delete m_pMidiPanningObserver; m_pMidiPanningObserver = NULL; } if (m_pMidiProgramObserver) { delete m_pMidiProgramObserver; m_pMidiProgramObserver = NULL; } #if 0 if (m_pMonitor) { delete m_pMonitor; m_pMonitor = NULL; } #endif m_pInputBus = NULL; m_pOutputBus = NULL; setClipRecord(NULL); } // Session accessor. qtractorSession *qtractorTrack::session (void) const { return m_pSession; } // Track name accessors. const QString& qtractorTrack::trackName (void) const { return m_props.trackName; } void qtractorTrack::setTrackName ( const QString& sTrackName ) { m_props.trackName = sTrackName; } void qtractorTrack::updateTrackName (void) { const QString& sTrackName = m_props.trackName; m_pMonitorSubject->setName(QObject::tr("%1 Monitor").arg(sTrackName)); m_pRecordSubject->setName(QObject::tr("%1 Record").arg(sTrackName)); m_pMuteSubject->setName(QObject::tr("%1 Mute").arg(sTrackName)); m_pSoloSubject->setName(QObject::tr("%1 Solo").arg(sTrackName)); if (m_pMonitor) { if (m_props.trackType == qtractorTrack::Midi) { m_pMonitor->gainSubject()->setName( QObject::tr("%1 Volume").arg(sTrackName)); } else { m_pMonitor->gainSubject()->setName( QObject::tr("%1 Gain").arg(sTrackName)); } m_pMonitor->panningSubject()->setName( QObject::tr("%1 Pan").arg(sTrackName)); } m_pPluginList->setName(sTrackName); } // Track type accessors. qtractorTrack::TrackType qtractorTrack::trackType (void) const { return m_props.trackType; } void qtractorTrack::setTrackType ( qtractorTrack::TrackType trackType ) { // Don't change anything if we're already the same type... if (m_props.trackType == trackType) return; // Acquire a new midi-tag... if (m_props.trackType == qtractorTrack::Midi) m_pSession->releaseMidiTag(this); // Set new track type, now... m_props.trackType = trackType; // Acquire a new midi-tag and setup new plugin-list flags... unsigned int iFlags = qtractorPluginList::Track; if (m_props.trackType == qtractorTrack::Midi) { m_pSession->acquireMidiTag(this); iFlags |= qtractorPluginList::Midi; } // (Re)set plugin-list... unsigned int iSampleRate = 0; qtractorAudioEngine *pAudioEngine = m_pSession->audioEngine(); if (pAudioEngine) iSampleRate = pAudioEngine->sampleRate(); m_pPluginList->setBuffer(0, 0, iSampleRate, iFlags); } // Record monitoring status accessors. bool qtractorTrack::isMonitor (void) const { return (m_pMonitorSubject->value() > 0.0f); } void qtractorTrack::setMonitor ( bool bMonitor ) { m_props.monitor = bMonitor; m_pMonitorObserver->setValue(bMonitor ? 1.0f : 0.0f); } // Record status accessors. void qtractorTrack::setRecord ( bool bRecord ) { const bool bOldRecord = m_props.record; // isRecord(); if ((bOldRecord && !bRecord) || (!bOldRecord && bRecord)) m_pSession->setRecordTracks(bRecord); m_props.record = bRecord; m_pRecordObserver->setValue(bRecord ? 1.0f : 0.0f); if (m_pSession->isRecording()) { unsigned long iClipStart = m_pSession->playHead(); if (m_pSession->isPunching()) { unsigned long iPunchIn = m_pSession->punchIn(); if (iClipStart < iPunchIn) iClipStart = iPunchIn; } unsigned long iFrameTime = m_pSession->frameTimeEx(); m_pSession->trackRecord(this, bRecord, iClipStart, iFrameTime); } } bool qtractorTrack::isRecord (void) const { return m_props.record; // (m_pRecordSubject->value() > 0.0f); } // Mute status accessors. void qtractorTrack::setMute ( bool bMute ) { if (m_pSession->isPlaying() && bMute) m_pSession->trackMute(this, bMute); const bool bOldMute = m_props.mute; // isMute(); if ((bOldMute && !bMute) || (!bOldMute && bMute)) m_pSession->setMuteTracks(bMute); m_props.mute = bMute; m_pMuteObserver->setValue(bMute ? 1.0f : 0.0f); if (m_pSession->isPlaying() && !bMute) m_pSession->trackMute(this, bMute); } bool qtractorTrack::isMute (void) const { return m_props.mute; // (m_pMuteSubject->value() > 0.0f); } // Solo status accessors. void qtractorTrack::setSolo ( bool bSolo ) { if (m_pSession->isPlaying() && bSolo) m_pSession->trackSolo(this, bSolo); const bool bOldSolo = m_props.solo; // isSolo(); if ((bOldSolo && !bSolo) || (!bOldSolo && bSolo)) m_pSession->setSoloTracks(bSolo); m_props.solo = bSolo; m_pSoloObserver->setValue(bSolo ? 1.0f : 0.0f); if (m_pSession->isPlaying() && !bSolo) m_pSession->trackSolo(this, bSolo); } bool qtractorTrack::isSolo (void) const { return m_props.solo; // (m_pSoloSubject->value() > 0.0f); } // Track gain (volume) accessor. void qtractorTrack::setGain ( float fGain ) { m_props.gain = fGain; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) { qtractorMixer *pMixer = pMainForm->mixer(); if (pMixer) { qtractorMixerStrip *pStrip = pMixer->trackRack()->findStrip(m_pMonitor); if (pStrip && pStrip->meter()) pStrip->meter()->setGain(fGain); } } } float qtractorTrack::gain (void) const { return (m_pMonitor ? m_pMonitor->gain() : m_props.gain); } float qtractorTrack::prevGain (void) const { return (m_pMonitor ? m_pMonitor->prevGain() : 1.0f); } // Track stereo-panning accessor. void qtractorTrack::setPanning ( float fPanning ) { m_props.panning = fPanning; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) { qtractorMixer *pMixer = pMainForm->mixer(); if (pMixer) { qtractorMixerStrip *pStrip = pMixer->trackRack()->findStrip(m_pMonitor); if (pStrip && pStrip->meter()) pStrip->meter()->setPanning(fPanning); } } } float qtractorTrack::panning (void) const { return (m_pMonitor ? m_pMonitor->panning() : m_props.panning); } float qtractorTrack::prevPanning (void) const { return (m_pMonitor ? m_pMonitor->prevPanning() : 0.0f); } // MIDI specific: track-tag accessors. void qtractorTrack::setMidiTag ( unsigned short iMidiTag ) { m_iMidiTag = (iMidiTag % 0xff); } unsigned short qtractorTrack::midiTag (void) const { return m_iMidiTag; } // MIDI specific: omni (capture) mode acessors. void qtractorTrack::setMidiOmni ( bool bMidiOmni ) { m_props.midiOmni = bMidiOmni; } bool qtractorTrack::isMidiOmni (void) const { return m_props.midiOmni; } // MIDI specific: channel acessors. void qtractorTrack::setMidiChannel ( unsigned short iMidiChannel ) { m_props.midiChannel = iMidiChannel; } unsigned short qtractorTrack::midiChannel (void) const { return m_props.midiChannel; } // MIDI specific: bank accessors. void qtractorTrack::setMidiBankSelMethod ( int iMidiBankSelMethod ) { m_props.midiBankSelMethod = iMidiBankSelMethod; } int qtractorTrack::midiBankSelMethod (void) const { return m_props.midiBankSelMethod; } // MIDI specific: bank accessors. void qtractorTrack::setMidiBank ( int iMidiBank ) { m_props.midiBank = iMidiBank; } int qtractorTrack::midiBank (void) const { return m_props.midiBank; } // MIDI specific: program accessors. void qtractorTrack::setMidiProg ( int iMidiProg ) { m_props.midiProg = iMidiProg; } int qtractorTrack::midiProg (void) const { return m_props.midiProg; } // Assigned input bus name accessors. void qtractorTrack::setInputBusName ( const QString& sBusName ) { m_props.inputBusName = sBusName; } const QString& qtractorTrack::inputBusName (void) const { return m_props.inputBusName; } // Assigned output bus name accessors. void qtractorTrack::setOutputBusName ( const QString& sBusName ) { m_props.outputBusName = sBusName; } const QString& qtractorTrack::outputBusName (void) const { return m_props.outputBusName; } // Assigned audio bus accessors. qtractorBus *qtractorTrack::inputBus (void) const { return m_pInputBus; } qtractorBus *qtractorTrack::outputBus (void) const { return m_pOutputBus; } // Track monitor accessors. qtractorMonitor *qtractorTrack::monitor (void) const { return m_pMonitor; } // Track plugin-chain accessors. qtractorPluginList *qtractorTrack::pluginList (void) const { return m_pPluginList; } // Normalized view height accessors. int qtractorTrack::height (void) const { return m_iHeight; } void qtractorTrack::setHeight ( int iHeight ) { m_iHeight = iHeight; if (m_iHeight < HeightMin) m_iHeight = HeightMin; updateZoomHeight(); } void qtractorTrack::updateHeight (void) { if (m_pSession) { m_iHeight = (100 * m_iZoomHeight) / m_pSession->verticalZoom(); if (m_iHeight < HeightMin) m_iHeight = HeightMin; } } // Zoomed view height accessors. int qtractorTrack::zoomHeight (void) const { return m_iZoomHeight; } void qtractorTrack::setZoomHeight ( int iZoomHeight ) { m_iZoomHeight = iZoomHeight; if (m_iZoomHeight < HeightMin) m_iZoomHeight = HeightMin; updateHeight(); } void qtractorTrack::updateZoomHeight (void) { if (m_pSession) { m_iZoomHeight = (m_iHeight * m_pSession->verticalZoom()) / 100; if (m_iZoomHeight < HeightMin) m_iZoomHeight = HeightMin; } } // Clip list management methods. const qtractorList& qtractorTrack::clips (void) const { return m_clips; } // Insert a new clip in garanteed sorted fashion. void qtractorTrack::addClip ( qtractorClip *pClip ) { // Preliminary settings... pClip->setTrack(this); pClip->open(); // Special case for initial MIDI tracks... if (m_props.trackType == qtractorTrack::Midi) { qtractorMidiClip *pMidiClip = static_cast (pClip); if (pMidiClip) { if (midiBank() < 0) setMidiBank(pMidiClip->bank()); if (midiProg() < 0) setMidiProg(pMidiClip->prog()); } } // Now do insert the clip in proper place in track... insertClip(pClip); } void qtractorTrack::insertClip ( qtractorClip *pClip ) { qtractorClip *pNextClip = m_clips.first(); while (pNextClip && pNextClip->clipStart() < pClip->clipStart()) pNextClip = pNextClip->next(); if (pNextClip) m_clips.insertBefore(pClip, pNextClip); else m_clips.append(pClip); } void qtractorTrack::unlinkClip ( qtractorClip *pClip ) { m_clips.unlink(pClip); } void qtractorTrack::removeClip ( qtractorClip *pClip ) { // pClip->setTrack(NULL); pClip->close(); unlinkClip(pClip); } // Current clip on record (capture). void qtractorTrack::setClipRecord ( qtractorClip *pClipRecord, unsigned long iClipRecordStart ) { if (m_pClipRecord) delete m_pClipRecord; m_pClipRecord = pClipRecord; if (m_pSession && m_pSession->isPlaying()) m_iClipRecordStart = iClipRecordStart; else m_iClipRecordStart = (m_pClipRecord ? m_pClipRecord->clipStart() : 0); } qtractorClip *qtractorTrack::clipRecord (void) const { return m_pClipRecord; } // Current clip on record absolute start frame (capture). unsigned long qtractorTrack::clipRecordStart (void) const { return m_iClipRecordStart; } unsigned long qtractorTrack::clipRecordEnd ( unsigned long iFrameTime ) const { unsigned long iClipRecordEnd = 0; if (m_pSession && m_pSession->isPunching()) { unsigned long iPunchOut = m_pSession->punchOut(); unsigned long iLoopStart = m_pSession->loopStart(); unsigned long iLoopEnd = m_pSession->loopEnd(); if (iLoopStart < iLoopEnd && iPunchOut >= iLoopEnd) iClipRecordEnd += iLoopEnd; else iClipRecordEnd += iPunchOut; } else { iClipRecordEnd += iFrameTime; if (iClipRecordEnd > m_iClipRecordStart) iClipRecordEnd -= m_iClipRecordStart; if (m_pClipRecord) iClipRecordEnd += m_pClipRecord->clipStart(); } return iClipRecordEnd; } // Background color accessors. void qtractorTrack::setBackground ( const QColor& bg ) { m_props.background = bg; m_props.background.setAlpha(192); } const QColor& qtractorTrack::background (void) const { return m_props.background; } // Foreground color accessors. void qtractorTrack::setForeground ( const QColor& fg ) { m_props.foreground = fg; } const QColor& qtractorTrack::foreground (void) const { return m_props.foreground; } // Generate a default track color. QColor qtractorTrack::trackColor ( int iTrack ) { int c[3] = { 0xff, 0xcc, 0x99 }; return QColor(c[iTrack % 3], c[(iTrack / 3) % 3], c[(iTrack / 9) % 3]); } // Alternate properties accessor. qtractorTrack::Properties& qtractorTrack::properties (void) { return m_props; } // Track special process cycle executive. void qtractorTrack::process ( qtractorClip *pClip, unsigned long iFrameStart, unsigned long iFrameEnd ) { // Audio-buffers needs some preparation... unsigned int nframes = iFrameEnd - iFrameStart; qtractorAudioMonitor *pAudioMonitor = NULL; qtractorAudioBus *pOutputBus = NULL; if (m_props.trackType == qtractorTrack::Audio) { pAudioMonitor = static_cast (m_pMonitor); pOutputBus = static_cast (m_pOutputBus); // Prepare this track buffer... if (pOutputBus) { qtractorAudioBus *pInputBus = (m_pSession->isTrackMonitor(this) ? static_cast (m_pInputBus) : NULL); pOutputBus->buffer_prepare(nframes, pInputBus); } } // Playback... if (!isMute() && (!m_pSession->soloTracks() || isSolo())) { // Now, for every clip... while (pClip && pClip->clipStart() < iFrameEnd) { if (iFrameStart < pClip->clipStart() + pClip->clipLength()) pClip->process(iFrameStart, iFrameEnd); pClip = pClip->next(); } // Audio buffers needs monitoring and commitment... if (pAudioMonitor && pOutputBus) { // Plugin chain post-processing... if (m_pPluginList->activated() > 0) m_pPluginList->process(pOutputBus->buffer(), nframes); // Monitor passthru... pAudioMonitor->process(pOutputBus->buffer(), nframes); // Actually render it... pOutputBus->buffer_commit(nframes); } } } // Track special process record executive (audio recording only). void qtractorTrack::process_record ( unsigned long iFrameStart, unsigned long iFrameEnd ) { // Audio track-recording? qtractorAudioBus *pInputBus = static_cast (m_pInputBus); qtractorAudioClip *pAudioClip = static_cast (m_pClipRecord); if (pAudioClip && pInputBus) { // Clip recording... unsigned int nframes = iFrameEnd - iFrameStart; if (m_pSession->isPunching()) { // Punch-in/out recording... unsigned long iPunchIn = m_pSession->punchIn(); unsigned long iPunchOut = m_pSession->punchOut(); if (iPunchIn < iFrameEnd && iPunchOut > iFrameStart) { unsigned int offs = 0; // Punch-out (unlikely...) if (iPunchIn >= iFrameStart) { offs += (iPunchIn - iFrameStart); if (iPunchOut < iFrameEnd) nframes = (iPunchOut - iPunchIn); else nframes = (iFrameEnd - iPunchIn); } else // Punch-out (likely...) if (iPunchOut < iFrameEnd) nframes = (iPunchOut - iFrameStart); // Punch-in/out recording... pAudioClip->write( pInputBus->in(), nframes, pInputBus->channels(), offs); } } else { // Regular full-length recording... pAudioClip->write( pInputBus->in(), nframes, pInputBus->channels()); } // Record non-passthru metering... qtractorAudioMonitor *pAudioMonitor = static_cast (m_pMonitor); if (pAudioMonitor) { pAudioMonitor->process_meter( pInputBus->in(), nframes, pInputBus->channels()); } } } // Track special process automation executive. void qtractorTrack::process_curve ( unsigned long iFrame ) { qtractorCurveList *pCurveList = curveList(); if (pCurveList && pCurveList->isProcess()) pCurveList->process(iFrame); } // Track paint method. void qtractorTrack::drawTrack ( QPainter *pPainter, const QRect& trackRect, unsigned long iTrackStart, unsigned long iTrackEnd, qtractorClip *pClip ) { int y = trackRect.y(); int h = trackRect.height(); if (pClip == NULL) pClip = m_clips.first(); while (pClip) { unsigned long iClipStart = pClip->clipStart(); if (iClipStart > iTrackEnd) break; unsigned long iClipEnd = iClipStart + pClip->clipLength(); if (iClipStart < iTrackEnd && iClipEnd > iTrackStart) { unsigned long iClipOffset = 0; int x = trackRect.x(); int w = trackRect.width(); if (iClipStart >= iTrackStart) { x += m_pSession->pixelFromFrame(iClipStart - iTrackStart); } else { iClipOffset = iTrackStart - iClipStart; --x; // Give some clip left-border room. } if (iClipEnd < iTrackEnd) { w -= m_pSession->pixelFromFrame(iTrackEnd - iClipEnd);// + 1; } else { ++w; // Give some clip right-border room. } QRect rect(x, y, w - x, h); pClip->drawClip(pPainter, rect, iClipOffset); #if 0 // Draw the clip selection... if (pClip->isClipSelected()) { unsigned long iSelectStart = pClip->clipSelectStart(); unsigned long iSelectEnd = pClip->clipSelectEnd(); x = trackRect.x(); w = trackRect.width(); if (iSelectStart >= iTrackStart) { x += m_pSession->pixelFromFrame(iSelectStart - iTrackStart); } else { --x; // Give selection some left-border room. } if (iSelectEnd < iTrackEnd) { w -= m_pSession->pixelFromFrame(iTrackEnd - iSelectEnd); } else { ++w; // Give selection some right-border room. } rect.setRect(x, y, w - x, h); pPainter->fillRect(rect, QColor(0, 0, 255, 120)); } #endif } pClip = pClip->next(); } if (m_props.mute || (!m_props.solo && m_pSession->soloTracks())) pPainter->fillRect(trackRect, QColor(0, 0, 0, 60)); } // Track loop point setler. void qtractorTrack::setLoop ( unsigned long iLoopStart, unsigned long iLoopEnd ) { qtractorClip *pClip = m_clips.first(); while (pClip) { // Convert loop-points from session to clip... unsigned long iClipStart = pClip->clipStart(); unsigned long iClipEnd = iClipStart + pClip->clipLength(); if (iLoopStart < iClipEnd && iLoopEnd > iClipStart) { // Set clip inner-loop... pClip->setLoop( (iLoopStart > iClipStart ? iLoopStart - iClipStart : 0), (iLoopEnd < iClipEnd ? iLoopEnd : iClipEnd) - iClipStart); } else { // Clear/reaet clip-loop... pClip->setLoop(0, 0); } pClip = pClip->next(); } } // MIDI track instrument patching. void qtractorTrack::setMidiPatch ( qtractorInstrumentList *pInstruments ) { int iProg = midiProg(); if (iProg < 0) return; qtractorMidiBus *pMidiBus = static_cast (m_pOutputBus); if (pMidiBus == NULL) return; unsigned short iChannel = midiChannel(); const qtractorMidiBus::Patch& patch = pMidiBus->patch(iChannel); int iBank = midiBank(); int iBankSelMethod = midiBankSelMethod(); if (iBankSelMethod < 0) { if (!patch.instrumentName.isEmpty()) iBankSelMethod = (*pInstruments)[patch.instrumentName].bankSelMethod(); else if (iBank >= 0) iBankSelMethod = 0; } pMidiBus->setPatch(iChannel, patch.instrumentName, iBankSelMethod, iBank, iProg, this); } // Update all clips editors. void qtractorTrack::updateClipEditors (void) { qtractorClip *pClip = m_clips.first(); while (pClip) { pClip->updateEditor(true); pClip = pClip->next(); } } // Audio buffer ring-cache (playlist) methods. qtractorAudioBufferThread *qtractorTrack::syncThread (void) { if (m_pSyncThread == NULL) { m_pSyncThread = new qtractorAudioBufferThread(); m_pSyncThread->start(QThread::HighPriority); } else { m_pSyncThread->checkSyncSize(m_clips.count()); } return m_pSyncThread; } // Track state (monitor record, mute, solo) button setup. qtractorSubject *qtractorTrack::monitorSubject (void) const { return m_pMonitorSubject; } qtractorSubject *qtractorTrack::recordSubject (void) const { return m_pRecordSubject; } qtractorSubject *qtractorTrack::muteSubject (void) const { return m_pMuteSubject; } qtractorSubject *qtractorTrack::soloSubject (void) const { return m_pSoloSubject; } qtractorMidiControlObserver *qtractorTrack::monitorObserver (void) const { return m_pMonitorObserver; } qtractorMidiControlObserver *qtractorTrack::recordObserver (void) const { return static_cast (m_pRecordObserver); } qtractorMidiControlObserver *qtractorTrack::muteObserver (void) const { return static_cast (m_pMuteObserver); } qtractorMidiControlObserver *qtractorTrack::soloObserver (void) const { return static_cast (m_pSoloObserver); } // Track state (monitor) notifier (proto-slot). void qtractorTrack::monitorChangeNotify ( bool bOn ) { #ifdef CONFIG_DEBUG qDebug("qtractorTrack[%p]::monitorChangeNotify(%d)", this, int(bOn)); #endif // Put it in the form of an undoable command... if (m_pSession) m_pSession->execute( new qtractorTrackMonitorCommand(this, bOn)); } // Track state (record, mute, solo) notifier (proto-slot). void qtractorTrack::stateChangeNotify ( ToolType toolType, bool bOn ) { #ifdef CONFIG_DEBUG qDebug("qtractorTrack[%p]::stateChangeNotify(%d, %d)", this, int(toolType), int(bOn)); #endif // Put it in the form of an undoable command... if (m_pSession) m_pSession->execute( new qtractorTrackStateCommand(this, toolType, bOn)); } // Document element methods. bool qtractorTrack::loadElement ( qtractorDocument *pDocument, QDomElement *pElement ) { qtractorTrack::setTrackName(pElement->attribute("name")); qtractorTrack::setTrackType( qtractorTrack::trackTypeFromText(pElement->attribute("type"))); // Reset take(record) descriptor/id registry. clearTakeInfo(); // Load track children... for (QDomNode nChild = pElement->firstChild(); !nChild.isNull(); nChild = nChild.nextSibling()) { // Convert node to element... QDomElement eChild = nChild.toElement(); if (eChild.isNull()) continue; // Load (other) track properties.. if (eChild.tagName() == "properties") { for (QDomNode nProp = eChild.firstChild(); !nProp.isNull(); nProp = nProp.nextSibling()) { // Convert property node to element... QDomElement eProp = nProp.toElement(); if (eProp.isNull()) continue; if (eProp.tagName() == "input-bus") qtractorTrack::setInputBusName(eProp.text()); else if (eProp.tagName() == "output-bus") qtractorTrack::setOutputBusName(eProp.text()); else if (eProp.tagName() == "midi-omni") qtractorTrack::setMidiOmni( qtractorDocument::boolFromText(eProp.text())); else if (eProp.tagName() == "midi-channel") qtractorTrack::setMidiChannel(eProp.text().toUShort()); else if (eProp.tagName() == "midi-bank-sel-method") qtractorTrack::setMidiBankSelMethod(eProp.text().toInt()); else if (eProp.tagName() == "midi-bank") qtractorTrack::setMidiBank(eProp.text().toInt()); else if (eProp.tagName() == "midi-program") qtractorTrack::setMidiProg(eProp.text().toInt()); } } else // Load track state.. if (eChild.tagName() == "state") { for (QDomNode nState = eChild.firstChild(); !nState.isNull(); nState = nState.nextSibling()) { // Convert state node to element... QDomElement eState = nState.toElement(); if (eState.isNull()) continue; if (eState.tagName() == "mute") qtractorTrack::setMute( qtractorDocument::boolFromText(eState.text())); else if (eState.tagName() == "solo") qtractorTrack::setSolo( qtractorDocument::boolFromText(eState.text())); else if (eState.tagName() == "record") qtractorTrack::setRecord( qtractorDocument::boolFromText(eState.text())); else if (eState.tagName() == "monitor") qtractorTrack::setMonitor( qtractorDocument::boolFromText(eState.text())); else if (eState.tagName() == "gain") qtractorTrack::setGain(eState.text().toFloat()); else if (eState.tagName() == "panning") qtractorTrack::setPanning(eState.text().toFloat()); } } else if (eChild.tagName() == "view") { for (QDomNode nView = eChild.firstChild(); !nView.isNull(); nView = nView.nextSibling()) { // Convert view node to element... QDomElement eView = nView.toElement(); if (eView.isNull()) continue; if (eView.tagName() == "height") { qtractorTrack::setHeight(eView.text().toInt()); } else if (eView.tagName() == "background-color") { QColor bg; bg.setNamedColor(eView.text()); qtractorTrack::setBackground(bg); } else if (eView.tagName() == "foreground-color") { QColor fg; fg.setNamedColor(eView.text()); qtractorTrack::setForeground(fg); } } } else if (eChild.tagName() == "controllers") { // Load track controllers... qtractorTrack::loadControllers(&eChild); } else if (eChild.tagName() == "curve-file") { // Load track automation curves... qtractorTrack::loadCurveFile(&eChild, m_pCurveFile); } else // Load clips... if (eChild.tagName() == "clips" && !pDocument->isTemplate()) { for (QDomNode nClip = eChild.firstChild(); !nClip.isNull(); nClip = nClip.nextSibling()) { // Convert clip node to element... QDomElement eClip = nClip.toElement(); if (eClip.isNull()) continue; if (eClip.tagName() == "clip") { qtractorClip *pClip = NULL; switch (qtractorTrack::trackType()) { case qtractorTrack::Audio: pClip = new qtractorAudioClip(this); break; case qtractorTrack::Midi: pClip = new qtractorMidiClip(this); break; case qtractorTrack::None: default: break; } if (pClip == NULL) return false; if (!pClip->loadElement(pDocument, &eClip)) return false; qtractorTrack::addClip(pClip); } } } else // Load plugins... if (eChild.tagName() == "plugins") m_pPluginList->loadElement(pDocument, &eChild); } // Reset take(record) descriptor/id registry. clearTakeInfo(); return true; } bool qtractorTrack::saveElement ( qtractorDocument *pDocument, QDomElement *pElement ) const { pElement->setAttribute("name", qtractorTrack::trackName()); pElement->setAttribute("type", qtractorTrack::textFromTrackType(qtractorTrack::trackType())); // Reset take(record) descriptor/id registry. clearTakeInfo(); // Save track properties... QDomElement eProps = pDocument->document()->createElement("properties"); pDocument->saveTextElement("input-bus", qtractorTrack::inputBusName(), &eProps); pDocument->saveTextElement("output-bus", qtractorTrack::outputBusName(), &eProps); if (qtractorTrack::trackType() == qtractorTrack::Midi) { pDocument->saveTextElement("midi-omni", qtractorDocument::textFromBool(qtractorTrack::isMidiOmni()), &eProps); pDocument->saveTextElement("midi-channel", QString::number(qtractorTrack::midiChannel()), &eProps); if (qtractorTrack::midiBankSelMethod() >= 0) { pDocument->saveTextElement("midi-bank-sel-method", QString::number(qtractorTrack::midiBankSelMethod()), &eProps); } if (qtractorTrack::midiBank() >= 0) { pDocument->saveTextElement("midi-bank", QString::number(qtractorTrack::midiBank()), &eProps); } if (qtractorTrack::midiProg() >= 0) { pDocument->saveTextElement("midi-program", QString::number(qtractorTrack::midiProg()), &eProps); } } pElement->appendChild(eProps); // Save track state... QDomElement eState = pDocument->document()->createElement("state"); pDocument->saveTextElement("mute", qtractorDocument::textFromBool(qtractorTrack::isMute()), &eState); pDocument->saveTextElement("solo", qtractorDocument::textFromBool(qtractorTrack::isSolo()), &eState); pDocument->saveTextElement("record", qtractorDocument::textFromBool(qtractorTrack::isRecord()), &eState); pDocument->saveTextElement("monitor", qtractorDocument::textFromBool(qtractorTrack::isMonitor()), &eState); pDocument->saveTextElement("gain", QString::number(qtractorTrack::gain()), &eState); pDocument->saveTextElement("panning", QString::number(qtractorTrack::panning()), &eState); pElement->appendChild(eState); // Save track view attributes... QDomElement eView = pDocument->document()->createElement("view"); pDocument->saveTextElement("height", QString::number(qtractorTrack::height()), &eView); pDocument->saveTextElement("background-color", qtractorTrack::background().name(), &eView); pDocument->saveTextElement("foreground-color", qtractorTrack::foreground().name(), &eView); pElement->appendChild(eView); // Save track controllers... QDomElement eControllers = pDocument->document()->createElement("controllers"); qtractorTrack::saveControllers(pDocument, &eControllers); pElement->appendChild(eControllers); // Save track automation... qtractorCurveList *pCurveList = qtractorTrack::curveList(); if (pCurveList && !pCurveList->isEmpty()) { qtractorCurveFile cfile(pCurveList); QDomElement eCurveFile = pDocument->document()->createElement("curve-file"); qtractorTrack::saveCurveFile(pDocument, &eCurveFile, &cfile); pElement->appendChild(eCurveFile); } // Clips are not saved when in template mode... if (!pDocument->isTemplate()) { // Save track clips... QDomElement eClips = pDocument->document()->createElement("clips"); for (qtractorClip *pClip = qtractorTrack::clips().first(); pClip; pClip = pClip->next()) { // Create the new clip element... QDomElement eClip = pDocument->document()->createElement("clip"); if (!pClip->saveElement(pDocument, &eClip)) return false; // Add this clip... eClips.appendChild(eClip); } pElement->appendChild(eClips); } // Save track plugins... QDomElement ePlugins = pDocument->document()->createElement("plugins"); m_pPluginList->saveElement(pDocument, &ePlugins); pElement->appendChild(ePlugins); // Reset take(record) descriptor/id registry. clearTakeInfo(); return true; } // Track type textual helper methods. qtractorTrack::TrackType qtractorTrack::trackTypeFromText ( const QString& sText ) { TrackType trackType = None; if (sText == "audio") trackType = Audio; else if (sText == "midi") trackType = Midi; return trackType; } QString qtractorTrack::textFromTrackType ( TrackType trackType ) { QString sText; switch (trackType) { case Audio: sText = "audio"; break; case Midi: sText = "midi"; break; case None: default: sText = "none"; break; } return sText; } // Load track state (record, mute, solo) controllers (MIDI). void qtractorTrack::loadControllers ( QDomElement *pElement ) { qtractorMidiControl::loadControllers(pElement, m_controllers); } // Save track state (record, mute, solo) controllers (MIDI). void qtractorTrack::saveControllers ( qtractorDocument *pDocument, QDomElement *pElement ) const { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; qtractorMixer *pMixer = pMainForm->mixer(); if (pMixer == NULL) return; qtractorMixerStrip *pMixerStrip = pMixer->trackRack()->findStrip(m_pMonitor); if (pMixerStrip == NULL) return; qtractorMidiControl::Controllers controllers; if (pMidiControl->isMidiObserverMapped(m_pMonitorObserver)) { qtractorMidiControl::Controller *pController = new qtractorMidiControl::Controller; pController->name = m_pMonitorObserver->subject()->name(); pController->index = 0; // 0=MonitorObserver pController->ctype = m_pMonitorObserver->type(); pController->channel = m_pMonitorObserver->channel(); pController->param = m_pMonitorObserver->param(); pController->logarithmic = m_pMonitorObserver->isLogarithmic(); pController->feedback = m_pMonitorObserver->isFeedback(); controllers.append(pController); } qtractorMidiControlObserver *pPanObserver = pMixerStrip->meter()->panningObserver(); if (pMidiControl->isMidiObserverMapped(pPanObserver)) { qtractorMidiControl::Controller *pController = new qtractorMidiControl::Controller; pController->name = m_pMonitorObserver->subject()->name(); pController->index = 1; // 1=PanObserver pController->ctype = pPanObserver->type(); pController->channel = pPanObserver->channel(); pController->param = pPanObserver->param(); pController->logarithmic = pPanObserver->isLogarithmic(); pController->feedback = pPanObserver->isFeedback(); controllers.append(pController); } qtractorMidiControlObserver *pGainObserver = pMixerStrip->meter()->gainObserver(); if (pMidiControl->isMidiObserverMapped(pGainObserver)) { qtractorMidiControl::Controller *pController = new qtractorMidiControl::Controller; pController->name = m_pMonitorObserver->subject()->name(); pController->index = 2; // 2=GainObserver pController->ctype = pGainObserver->type(); pController->channel = pGainObserver->channel(); pController->param = pGainObserver->param(); pController->logarithmic = pGainObserver->isLogarithmic(); pController->feedback = pGainObserver->isFeedback(); controllers.append(pController); } if (pMidiControl->isMidiObserverMapped(m_pRecordObserver)) { qtractorMidiControl::Controller *pController = new qtractorMidiControl::Controller; pController->name = m_pMonitorObserver->subject()->name(); pController->index = 3; // 3=RecordObserver pController->ctype = m_pRecordObserver->type(); pController->channel = m_pRecordObserver->channel(); pController->param = m_pRecordObserver->param(); pController->logarithmic = m_pRecordObserver->isLogarithmic(); pController->feedback = m_pRecordObserver->isFeedback(); controllers.append(pController); } if (pMidiControl->isMidiObserverMapped(m_pMuteObserver)) { qtractorMidiControl::Controller *pController = new qtractorMidiControl::Controller; pController->name = m_pMonitorObserver->subject()->name(); pController->index = 4; // 4=MuteObserver pController->ctype = m_pMuteObserver->type(); pController->channel = m_pMuteObserver->channel(); pController->param = m_pMuteObserver->param(); pController->logarithmic = m_pMuteObserver->isLogarithmic(); pController->feedback = m_pMuteObserver->isFeedback(); controllers.append(pController); } if (pMidiControl->isMidiObserverMapped(m_pSoloObserver)) { qtractorMidiControl::Controller *pController = new qtractorMidiControl::Controller; pController->name = m_pMonitorObserver->subject()->name(); pController->index = 5; // 5=SoloObserver pController->ctype = m_pSoloObserver->type(); pController->channel = m_pSoloObserver->channel(); pController->param = m_pSoloObserver->param(); pController->logarithmic = m_pSoloObserver->isLogarithmic(); pController->feedback = m_pSoloObserver->isFeedback(); controllers.append(pController); } qtractorMidiControl::saveControllers(pDocument, pElement, controllers); qDeleteAll(controllers); controllers.clear(); } // Map track state (monitor, gain, pan, record, mute, solo) controllers (MIDI). void qtractorTrack::mapControllers (void) { qtractorMidiControl *pMidiControl = qtractorMidiControl::getInstance(); if (pMidiControl == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; qtractorMixer *pMixer = pMainForm->mixer(); if (pMixer == NULL) return; qtractorMixerStrip *pMixerStrip = pMixer->trackRack()->findStrip(m_pMonitor); if (pMixerStrip == NULL) return; QListIterator iter(m_controllers); while (iter.hasNext()) { qtractorMidiControl::Controller *pController = iter.next(); qtractorMidiControlObserver *pObserver = NULL; switch (pController->index) { case 0: // 0=MonitorObserver pObserver = monitorObserver(); break; case 1: // 1=PanObserver pObserver = pMixerStrip->meter()->panningObserver(); break; case 2: // 2=GainObserver pObserver = pMixerStrip->meter()->gainObserver(); break; case 3: // 3=RecordObserver pObserver = recordObserver(); break; case 4: // 4=MuteObserver pObserver = muteObserver(); break; case 5: // 5=SoloObserver pObserver = soloObserver(); break; } if (pObserver) { pObserver->setType(pController->ctype); pObserver->setChannel(pController->channel); pObserver->setParam(pController->param); pObserver->setLogarithmic(pController->logarithmic); pObserver->setFeedback(pController->feedback); pMidiControl->mapMidiObserver(pObserver); } } qDeleteAll(m_controllers); m_controllers.clear(); } // Track automation curve list accessor. qtractorCurveList *qtractorTrack::curveList (void) const { return (m_pPluginList ? m_pPluginList->curveList() : NULL); } // Track automation curve serializer accessor. qtractorCurveFile *qtractorTrack::curveFile (void) const { return m_pCurveFile; } // Track automation current curve accessor. qtractorCurve *qtractorTrack::currentCurve (void) const { qtractorCurveList *pCurveList = curveList(); return (pCurveList ? pCurveList->currentCurve() : NULL); } // Load track automation curves (monitor, gain, pan, record, mute, solo). void qtractorTrack::loadCurveFile ( QDomElement *pElement, qtractorCurveFile *pCurveFile ) { if (pCurveFile) pCurveFile->load(pElement); } // Save track automation curves (monitor, gain, pan, record, mute, solo). void qtractorTrack::saveCurveFile ( qtractorDocument *pDocument, QDomElement *pElement, qtractorCurveFile *pCurveFile ) const { if (m_pMonitor == NULL) return; if (pCurveFile == NULL) return; qtractorCurveList *pCurveList = pCurveFile->list(); if (pCurveList == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; pCurveFile->clear(); pCurveFile->setBaseDir(pSession->sessionDir()); qtractorCurve *pCurve; pCurve = monitorSubject()->curve(); if (pCurve) { qtractorCurveFile::Item *pCurveItem = new qtractorCurveFile::Item; pCurveItem->name = pCurve->subject()->name(); pCurveItem->index = 0; // 0=MonitorSubject pCurveItem->ctype = qtractorMidiEvent::CONTROLLER; pCurveItem->channel = 0; pCurveItem->param = 80; // 80=General Purpose Button 1 (on/off) pCurveItem->mode = pCurve->mode(); pCurveItem->process = pCurve->isProcess(); pCurveItem->capture = pCurve->isCapture(); pCurveItem->locked = pCurve->isLocked(); pCurveItem->logarithmic = pCurve->isLogarithmic(); pCurveItem->color = pCurve->color(); pCurveItem->subject = pCurve->subject(); pCurveFile->addItem(pCurveItem); } pCurve = m_pMonitor->panningSubject()->curve(); if (pCurve) { qtractorCurveFile::Item *pCurveItem = new qtractorCurveFile::Item; pCurveItem->name = pCurve->subject()->name(); pCurveItem->index = 1; // 1=PanningSubject pCurveItem->ctype = qtractorMidiEvent::CONTROLLER; pCurveItem->channel = 0; pCurveItem->param = 10; // 10=Pan Position (coarse) pCurveItem->mode = pCurve->mode(); pCurveItem->process = pCurve->isProcess(); pCurveItem->capture = pCurve->isCapture(); pCurveItem->locked = pCurve->isLocked(); pCurveItem->logarithmic = pCurve->isLogarithmic(); pCurveItem->color = pCurve->color(); pCurveItem->subject = pCurve->subject(); pCurveFile->addItem(pCurveItem); } pCurve = m_pMonitor->gainSubject()->curve(); if (pCurve) { qtractorCurveFile::Item *pCurveItem = new qtractorCurveFile::Item; pCurveItem->name = pCurve->subject()->name(); pCurveItem->index = 2; // 2=GainSubject pCurveItem->ctype = qtractorMidiEvent::CONTROLLER; pCurveItem->channel = 0; pCurveItem->param = 7; // 7=Volume (coarse) pCurveItem->mode = pCurve->mode(); pCurveItem->process = pCurve->isProcess(); pCurveItem->capture = pCurve->isCapture(); pCurveItem->locked = pCurve->isLocked(); pCurveItem->logarithmic = pCurve->isLogarithmic(); pCurveItem->color = pCurve->color(); pCurveItem->subject = pCurve->subject(); pCurveFile->addItem(pCurveItem); } pCurve = recordSubject()->curve(); if (pCurve) { qtractorCurveFile::Item *pCurveItem = new qtractorCurveFile::Item; pCurveItem->name = pCurve->subject()->name(); pCurveItem->index = 3; // 3=RecordSubject pCurveItem->ctype = qtractorMidiEvent::CONTROLLER; pCurveItem->channel = 0; pCurveItem->param = 81; // 81=General Purpose Button 2 (on/off) pCurveItem->mode = pCurve->mode(); pCurveItem->process = pCurve->isProcess(); pCurveItem->capture = pCurve->isCapture(); pCurveItem->locked = pCurve->isLocked(); pCurveItem->logarithmic = pCurve->isLogarithmic(); pCurveItem->color = pCurve->color(); pCurveItem->subject = pCurve->subject(); pCurveFile->addItem(pCurveItem); } pCurve = muteSubject()->curve(); if (pCurve) { qtractorCurveFile::Item *pCurveItem = new qtractorCurveFile::Item; pCurveItem->name = pCurve->subject()->name(); pCurveItem->index = 4; // 4=MuteSubject pCurveItem->ctype = qtractorMidiEvent::CONTROLLER; pCurveItem->channel = 0; pCurveItem->param = 82; // 82=General Purpose Button 3 (on/off) pCurveItem->mode = pCurve->mode(); pCurveItem->process = pCurve->isProcess(); pCurveItem->capture = pCurve->isCapture(); pCurveItem->locked = pCurve->isLocked(); pCurveItem->logarithmic = pCurve->isLogarithmic(); pCurveItem->color = pCurve->color(); pCurveItem->subject = pCurve->subject(); pCurveFile->addItem(pCurveItem); } pCurve = soloSubject()->curve(); if (pCurve) { qtractorCurveFile::Item *pCurveItem = new qtractorCurveFile::Item; pCurveItem->name = pCurve->subject()->name(); pCurveItem->index = 5; // 5=SoloSubject pCurveItem->ctype = qtractorMidiEvent::CONTROLLER; pCurveItem->channel = 0; pCurveItem->param = 83; // 83=General Purpose Button 4 (on/off) pCurveItem->mode = pCurve->mode(); pCurveItem->process = pCurve->isProcess(); pCurveItem->capture = pCurve->isCapture(); pCurveItem->locked = pCurve->isLocked(); pCurveItem->logarithmic = pCurve->isLogarithmic(); pCurveItem->color = pCurve->color(); pCurveItem->subject = pCurve->subject(); pCurveFile->addItem(pCurveItem); } if (pCurveFile->isEmpty()) return; const QString sBaseName(trackName() + "_curve"); int iClipNo = (pCurveFile->filename().isEmpty() ? 0 : 1); pCurveFile->setFilename(pSession->createFilePath(sBaseName, "mid", iClipNo)); pCurveFile->save(pDocument, pElement, pSession->timeScale()); } // Apply track automation curves (monitor, gain, pan, record, mute, solo). void qtractorTrack::applyCurveFile ( qtractorCurveFile *pCurveFile ) const { if (m_pMonitor == NULL) return; if (pCurveFile == NULL) return; if (pCurveFile->items().isEmpty()) return; qtractorCurveList *pCurveList = pCurveFile->list(); if (pCurveList == NULL) return; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; pCurveFile->setBaseDir(pSession->sessionDir()); QListIterator iter(pCurveFile->items()); while (iter.hasNext()) { qtractorCurveFile::Item *pCurveItem = iter.next(); switch (pCurveItem->index) { case 0: // 0=MonitorSubject pCurveItem->subject = monitorSubject(); break; case 1: // 1=PanSubject pCurveItem->subject = m_pMonitor->panningSubject(); break; case 2: // 2=GainSubject pCurveItem->subject = m_pMonitor->gainSubject(); break; case 3: // 3=RecordSubject pCurveItem->subject = recordSubject(); break; case 4: // 4=MuteSubject pCurveItem->subject = muteSubject(); break; case 5: // 5=SoloSubject pCurveItem->subject = soloSubject(); break; } } pCurveFile->apply(pSession->timeScale()); } // Update tracks/list-view. void qtractorTrack::updateTracks (void) { qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm == NULL) return; qtractorTracks *pTracks = pMainForm->tracks(); if (pTracks == NULL) return; pTracks->updateTrack(this); } // end of qtractorTrack.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiControlObserverForm.h0000644000175000001440000000012212067456742023767 xustar000000000000000026 mtime=1356750306.99751 26 atime=1381134670.41708 30 ctime=1381134670.417080103 qtractor-0.5.11/src/qtractorMidiControlObserverForm.h0000644000175000001440000000616312067456742023265 0ustar00rncbcusers00000000000000// qtractorMidiControlObserverForm.h // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiControlObserverForm_h #define __qtractorMidiControlObserverForm_h #include "ui_qtractorMidiControlObserverForm.h" // Forward declarartions. class qtractorMidiControlObserver; class qtractorCtlEvent; class QCloseEvent; //---------------------------------------------------------------------------- // qtractorMidiControlObserverForm -- UI wrapper form. class qtractorMidiControlObserverForm : public QDialog { Q_OBJECT public: // Pseudo-singleton instance. static qtractorMidiControlObserverForm *getInstance(); // Pseudo-constructor. static void showInstance(qtractorMidiControlObserver *pMidiObserver, QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Observer accessors. void setMidiObserver(qtractorMidiControlObserver *pMidiObserver); qtractorMidiControlObserver *midiObserver() const; // Process incoming controller event. void processEvent(const qtractorCtlEvent& ctle); // MIDI controller/observer attachment (context menu) activator. static QAction *addMidiControlAction(QWidget *pParent, QWidget *pWidget, qtractorMidiControlObserver *pMidiObserver); static void midiControlAction(QWidget *pParent, QAction *pAction); static void midiControlMenu(QWidget *pParent, const QPoint& pos); protected slots: void activateControlType(const QString&); void change(); void click(QAbstractButton *); void accept(); void reject(); void inputs(); void outputs(); void reset(); void stabilizeForm(); protected: // Constructor. qtractorMidiControlObserverForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Pseudo-destructor. void closeEvent(QCloseEvent *pCloseEvent); // Add esquisite automation menu actions... static void addMidiControlMenu( QMenu *pMenu, qtractorMidiControlObserver *pMidiObserver); private: // The Qt-designer UI struct... Ui::qtractorMidiControlObserverForm m_ui; // Target object. qtractorMidiControlObserver *m_pMidiObserver; // Instance variables. int m_iDirtyCount; int m_iDirtySetup; // Pseudo-singleton instance. static qtractorMidiControlObserverForm *g_pMidiObserverForm; }; #endif // __qtractorMidiControlObserverForm_h // end of qtractorMidiControlObserverForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorTempoAdjustForm.cpp0000644000175000001440000000012212166134117022613 xustar000000000000000027 mtime=1373157455.942698 26 atime=1381134670.83708 29 ctime=1381134670.83708011 qtractor-0.5.11/src/qtractorTempoAdjustForm.cpp0000644000175000001440000002323212166134117022105 0ustar00rncbcusers00000000000000// qtractorTempoAdjustForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorTempoAdjustForm.h" #include "qtractorAbout.h" #include "qtractorSession.h" #include "qtractorMainForm.h" #include #include #include //---------------------------------------------------------------------------- // qtractorTempoAdjustForm -- UI wrapper form. // Constructor. qtractorTempoAdjustForm::qtractorTempoAdjustForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); m_pTempoTap = new QTime(); // Initialize local time scale. m_pTimeScale = new qtractorTimeScale(); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) m_pTimeScale->copy(*pSession->timeScale()); m_ui.RangeStartSpinBox->setTimeScale(m_pTimeScale); m_ui.RangeLengthSpinBox->setTimeScale(m_pTimeScale); m_ui.TempoSpinBox->setTempo(m_pTimeScale->tempo(), false); m_ui.TempoSpinBox->setBeatsPerBar(m_pTimeScale->beatsPerBar(), false); m_ui.TempoSpinBox->setBeatDivisor(m_pTimeScale->beatDivisor(), false); m_iTempoTap = 0; m_fTempoTap = 0.0f; // Set proper time scales display format... m_ui.FormatComboBox->setCurrentIndex(int(m_pTimeScale->displayFormat())); // Initialize dirty control state (nope). m_iDirtySetup = 0; m_iDirtyCount = 0; // Try to set minimal window positioning. adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.TempoSpinBox, SIGNAL(valueChanged(float, unsigned short, unsigned short)), SLOT(tempoChanged(float, unsigned short, unsigned short))); QObject::connect(m_ui.RangeStartSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(rangeStartChanged(unsigned long))); QObject::connect(m_ui.RangeStartSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.RangeLengthSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(rangeLengthChanged(unsigned long))); QObject::connect(m_ui.RangeLengthSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.RangeBeatsSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.AdjustPushButton, SIGNAL(clicked()), SLOT(adjust())); QObject::connect(m_ui.FormatComboBox, SIGNAL(activated(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.TempoPushButton, SIGNAL(clicked()), SLOT(tempoTap())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); } // Destructor. qtractorTempoAdjustForm::~qtractorTempoAdjustForm (void) { // Don't forget to get rid of local time-scale instance... if (m_pTimeScale) delete m_pTimeScale; if (m_pTempoTap) delete m_pTempoTap; } // Range accessors. void qtractorTempoAdjustForm::setRangeStart ( unsigned long iRangeStart ) { ++m_iDirtySetup; m_ui.RangeStartSpinBox->setValue(iRangeStart, false); m_ui.RangeLengthSpinBox->setDeltaValue(true, iRangeStart); --m_iDirtySetup; } unsigned long qtractorTempoAdjustForm::rangeStart (void) const { return m_ui.RangeStartSpinBox->value(); } void qtractorTempoAdjustForm::setRangeLength ( unsigned long iRangeLength ) { ++m_iDirtySetup; m_ui.RangeLengthSpinBox->setValue(iRangeLength, false); unsigned int iRangeBeats = m_pTimeScale->beatFromFrame(iRangeLength); unsigned long q = m_pTimeScale->beatsPerBar(); iRangeBeats = q * ((iRangeBeats + (q >> 1)) / q); m_ui.RangeBeatsSpinBox->setValue(iRangeBeats); --m_iDirtySetup; } unsigned long qtractorTempoAdjustForm::rangeLength (void) const { return m_ui.RangeLengthSpinBox->value(); } unsigned short qtractorTempoAdjustForm::rangeBeats (void) const { return m_ui.RangeBeatsSpinBox->value(); } // Accept settings (OK button slot). void qtractorTempoAdjustForm::accept (void) { // Just go with dialog acceptance. QDialog::accept(); } // Reject settings (Cancel button slot). void qtractorTempoAdjustForm::reject (void) { bool bReject = true; // Check if there's any pending changes... if (m_iDirtyCount > 0) { QMessageBox::StandardButtons buttons = QMessageBox::Discard | QMessageBox::Cancel; if (m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->isEnabled()) buttons |= QMessageBox::Apply; switch (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Some settings have been changed.\n\n" "Do you want to apply the changes?"), buttons)) { case QMessageBox::Apply: accept(); return; case QMessageBox::Discard: break; default: // Cancel. bReject = false; } } if (bReject) QDialog::reject(); } // Dirty up settings. void qtractorTempoAdjustForm::changed (void) { if (m_iDirtySetup > 0) return; ++m_iDirtyCount; stabilizeForm(); } // Tempo signature has changed. void qtractorTempoAdjustForm::tempoChanged ( float /*fTempo*/, unsigned short /*iBeatsPerBar*/, unsigned short /*iBeatDivisor*/ ) { #ifdef CONFIG_DEBUG_0 qDebug("qtractorTempoAdjustForm::tempoChanged(%g, %u, %u)", fTempo, iBeatsPerBar, iBeatDivisor); #endif m_iTempoTap = 0; m_fTempoTap = 0.0f; changed(); } // Adjust delta-value spin-boxes to new anchor frame. void qtractorTempoAdjustForm::rangeStartChanged ( unsigned long iRangeStart ) { #ifdef CONFIG_DEBUG qDebug("qtractorTempoAdjustForm::rangeStartChanged(%lu)", iRangeStart); #endif m_ui.RangeLengthSpinBox->setDeltaValue(true, iRangeStart); selectChanged(); } void qtractorTempoAdjustForm::rangeLengthChanged ( unsigned long iRangeLength ) { #ifdef CONFIG_DEBUG qDebug("qtractorTempoAdjustForm::rangeLengthChanged(%lu)", iRangeLength); #endif int iRangeBeatsMax // It follows from max. tempo = 300bpm. = int(5.0f * float(iRangeLength) / float(m_pTimeScale->sampleRate())); m_ui.RangeBeatsSpinBox->setMaximum(iRangeBeatsMax); selectChanged(); } // Adjust as instructed. void qtractorTempoAdjustForm::adjust (void) { #ifdef CONFIG_DEBUG qDebug("qtractorTempoAdjustForm::adjust()"); #endif unsigned short iRangeBeats = m_ui.RangeBeatsSpinBox->value(); if (iRangeBeats < 1) return; unsigned long iRangeLength = m_ui.RangeLengthSpinBox->value(); unsigned long iBeatLength = iRangeLength / iRangeBeats; float fTempo = 60.0f * float(m_pTimeScale->sampleRate()) / float(iBeatLength); m_ui.TempoSpinBox->setTempo(fTempo, false); // m_ui.RangeLengthSpinBox->setValue(iRangeBeats * iBeatLength, false); selectChanged(); } // Adjust current selection edit/tail. void qtractorTempoAdjustForm::selectChanged (void) { #ifdef CONFIG_DEBUG qDebug("qtractorTempoAdjustForm::selectChanged()"); #endif unsigned long iRangeStart = m_ui.RangeStartSpinBox->value(); unsigned long iRangeLength = m_ui.RangeLengthSpinBox->value(); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { pSession->setEditHead(iRangeStart); pSession->setEditTail(iRangeStart + iRangeLength); } qtractorMainForm *pMainForm = qtractorMainForm::getInstance(); if (pMainForm) pMainForm->selectionNotifySlot(NULL); changed(); } // Display format has changed. void qtractorTempoAdjustForm::formatChanged ( int iDisplayFormat ) { bool bBlockSignals = m_ui.FormatComboBox->blockSignals(true); m_ui.FormatComboBox->setCurrentIndex(iDisplayFormat); qtractorTimeScale::DisplayFormat displayFormat = qtractorTimeScale::DisplayFormat(iDisplayFormat); m_ui.RangeStartSpinBox->setDisplayFormat(displayFormat); m_ui.RangeLengthSpinBox->setDisplayFormat(displayFormat); if (m_pTimeScale) m_pTimeScale->setDisplayFormat(displayFormat); m_ui.FormatComboBox->blockSignals(bBlockSignals); stabilizeForm(); } // Stabilize current form state. void qtractorTempoAdjustForm::stabilizeForm (void) { bool bValid = (m_iDirtyCount > 0); unsigned long iRangeLength = m_ui.RangeLengthSpinBox->value(); unsigned short iRangeBeats = m_ui.RangeBeatsSpinBox->value(); bValid = bValid && (iRangeLength > 0); bValid = bValid && (iRangeBeats > 0); m_ui.AdjustPushButton->setEnabled(bValid); // m_ui.OkPushButton->setEnabled(bValid); } // Tempo tap click. void qtractorTempoAdjustForm::tempoTap (void) { #ifdef CONFIG_DEBUG qDebug("qtractorTempoAdjustForm::tempoTap()"); #endif int iTimeTap = m_pTempoTap->restart(); if (iTimeTap > 200 && iTimeTap < 2000) { // Magic! m_fTempoTap += (60000.0f / float(iTimeTap)); if (++m_iTempoTap > 2) { m_fTempoTap /= float(m_iTempoTap); m_iTempoTap = 1; // Median-like averaging... m_ui.TempoSpinBox->setTempo(int(m_fTempoTap), false); } } else { m_iTempoTap = 0; m_fTempoTap = 0.0f; } } // Accepted results accessors. float qtractorTempoAdjustForm::tempo (void) const { return m_ui.TempoSpinBox->tempo(); } unsigned short qtractorTempoAdjustForm::beatsPerBar (void) const { return m_ui.TempoSpinBox->beatsPerBar(); } unsigned short qtractorTempoAdjustForm::beatDivisor (void) const { return m_ui.TempoSpinBox->beatDivisor(); } // end of qtractorTempoAdjustForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorCommand.cpp0000644000175000001440000000012312156176530021113 xustar000000000000000027 mtime=1371077976.416182 26 atime=1381134671.08808 30 ctime=1381134671.089080114 qtractor-0.5.11/src/qtractorCommand.cpp0000644000175000001440000001105012156176530020377 0ustar00rncbcusers00000000000000// qtractorCommand.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorCommand.h" #include #include //---------------------------------------------------------------------- // class qtractorCommandList - declaration. // // Constructor. qtractorCommandList::qtractorCommandList (void) { m_pLastCommand = NULL; m_commands.setAutoDelete(true); } // Destructor. qtractorCommandList::~qtractorCommandList (void) { clear(); } // Command stack cleaner. void qtractorCommandList::clear (void) { m_commands.clear(); m_pLastCommand = NULL; } // Command chain accessors. qtractorCommand *qtractorCommandList::lastCommand (void) const { return m_pLastCommand; } qtractorCommand *qtractorCommandList::nextCommand (void) const { if (m_pLastCommand) { return m_pLastCommand->next(); } else { return m_commands.first(); } } // Remove last command from command chain. void qtractorCommandList::removeLastCommand (void) { if (m_pLastCommand) { qtractorCommand *pPrevCommand = m_pLastCommand->prev(); m_commands.remove(m_pLastCommand); m_pLastCommand = pPrevCommand; } } // Special backout method (EXPERIMENTAL). void qtractorCommandList::backout ( qtractorCommand *pCommand ) { int iUpdate = 0; unsigned int flags = qtractorCommand::None; while (m_pLastCommand && m_pLastCommand != pCommand) { flags |= m_pLastCommand->flags(); m_pLastCommand->undo(); removeLastCommand(); ++iUpdate; } if (iUpdate > 0) emit updateNotifySignal(flags); } // Cannonical command methods. bool qtractorCommandList::push ( qtractorCommand *pCommand ) { // Trim the command list from current last command... qtractorCommand *pNextCommand = nextCommand(); while (pNextCommand) { qtractorCommand *pLateCommand = pNextCommand->next(); m_commands.remove(pNextCommand); pNextCommand = pLateCommand; } if (pCommand == NULL) return false; // It must be this last one... m_commands.append(pCommand); m_pLastCommand = m_commands.last(); return (m_pLastCommand != NULL); } bool qtractorCommandList::exec ( qtractorCommand *pCommand ) { bool bResult = false; // Append command... if (push(pCommand)) { // Execute operation... bResult = m_pLastCommand->redo(); // Notify commanders... emit updateNotifySignal(m_pLastCommand->flags()); } return bResult; } bool qtractorCommandList::undo (void) { bool bResult = false; if (m_pLastCommand) { // Undo operation... bResult = m_pLastCommand->undo(); // Backward one command... unsigned int flags = m_pLastCommand->flags(); m_pLastCommand = m_pLastCommand->prev(); // Notify commanders... emit updateNotifySignal(flags); } return bResult; } bool qtractorCommandList::redo (void) { bool bResult = false; // Forward one command... m_pLastCommand = nextCommand(); if (m_pLastCommand) { // Redo operation... bResult = m_pLastCommand->redo(); // Notify commanders... emit updateNotifySignal(m_pLastCommand->flags()); } return bResult; } // Command action update helper. void qtractorCommandList::updateAction ( QAction *pAction, qtractorCommand *pCommand ) const { const QRegExp rxBrackets("[\\s]+\\([^\\)]+\\)$"); pAction->setText(pAction->text().remove(rxBrackets)); pAction->setStatusTip(pAction->statusTip().remove(rxBrackets)); pAction->setToolTip(pAction->toolTip().remove(rxBrackets)); if (pCommand) { const QString sCommand = QString(pCommand->name()).remove(rxBrackets); const QString sBrackets = QString(" (%1)").arg(sCommand); pAction->setText(pAction->text() + sBrackets); pAction->setStatusTip(pAction->statusTip() + sBrackets); pAction->setToolTip(pAction->toolTip() + sBrackets); } pAction->setEnabled(pCommand != NULL); } // end of qtractorCommand.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiCursor.cpp0000644000175000001440000000012312026024607021606 xustar000000000000000027 mtime=1347955079.929716 26 atime=1381134667.10808 30 ctime=1381134667.108080051 qtractor-0.5.11/src/qtractorMidiCursor.cpp0000644000175000001440000000523012026024607021075 0ustar00rncbcusers00000000000000// qtractorMidiCursor.cpp // /**************************************************************************** Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorMidiCursor.h" #include "qtractorMidiSequence.h" //------------------------------------------------------------------------- // qtractorMidiCursor -- MIDI event cursor capsule. // Constructor. qtractorMidiCursor::qtractorMidiCursor (void) : m_pEvent(NULL), m_iTime(0) { } // Intra-sequence tick/time positioning seek. qtractorMidiEvent *qtractorMidiCursor::seek ( qtractorMidiSequence *pSeq, unsigned long iTime ) { // Plain reset... if (iTime == 0) { m_pEvent = pSeq->events().first(); } else if (iTime > m_iTime) { // Seek forward... if (m_pEvent == NULL) m_pEvent = pSeq->events().first(); while (m_pEvent && m_pEvent->next() && (m_pEvent->next())->time() < iTime) m_pEvent = m_pEvent->next(); if (m_pEvent == NULL) m_pEvent = pSeq->events().last(); } else if (iTime < m_iTime) { // Seek backward... if (m_pEvent == NULL) m_pEvent = pSeq->events().last(); while (m_pEvent && m_pEvent->time() >= iTime) m_pEvent = m_pEvent->prev(); if (m_pEvent == NULL) m_pEvent = pSeq->events().first(); } // Done. m_iTime = iTime; return m_pEvent; } // Intra-seuqnce tick/time positioning reset (seek forward). qtractorMidiEvent *qtractorMidiCursor::reset ( qtractorMidiSequence *pSeq, unsigned long iTime ) { // Reset-seek forward... if (m_iTime >= iTime) m_pEvent = NULL; if (m_pEvent == NULL) m_pEvent = pSeq->events().first(); while (m_pEvent && m_pEvent->time() + m_pEvent->duration() < iTime) m_pEvent = m_pEvent->next(); while (m_pEvent && m_pEvent->time() > iTime) m_pEvent = m_pEvent->prev(); if (m_pEvent == NULL) m_pEvent = pSeq->events().first(); // That was it... m_iTime = iTime; return m_pEvent; } // end of qtractorMidiCursor.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiConnect.cpp0000644000175000001440000000012311563576072021737 xustar000000000000000027 mtime=1305410618.253123 26 atime=1381134667.75008 30 ctime=1381134667.750080061 qtractor-0.5.11/src/qtractorMidiConnect.cpp0000644000175000001440000003366711563576072021245 0ustar00rncbcusers00000000000000// qtractorMidiConnect.cpp // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorMidiConnect.h" #include "qtractorMidiEngine.h" #include "qtractorSession.h" #include //---------------------------------------------------------------------- // qtractorMidiPortItem -- Alsa port list item. // // Constructor. qtractorMidiPortItem::qtractorMidiPortItem ( qtractorMidiClientItem *pClientItem, const QString& sPortName, int iAlsaPort ) : qtractorPortListItem(pClientItem, sPortName) { m_iAlsaPort = iAlsaPort; if (pClientItem->isReadable()) { QTreeWidgetItem::setIcon(0, qtractorMidiConnect::icon(qtractorMidiConnect::PortOut)); } else { QTreeWidgetItem::setIcon(0, qtractorMidiConnect::icon(qtractorMidiConnect::PortIn)); } } // Default destructor. qtractorMidiPortItem::~qtractorMidiPortItem (void) { } // Alsa handles accessors. int qtractorMidiPortItem::alsaClient (void) const { qtractorMidiClientItem *pClientItem = static_cast (clientItem()); return (pClientItem ? pClientItem->alsaClient() : 0); } int qtractorMidiPortItem::alsaPort (void) const { return m_iAlsaPort; } //---------------------------------------------------------------------- // qtractorMidiClientItem -- Alsa client list item. // // Constructor. qtractorMidiClientItem::qtractorMidiClientItem ( qtractorMidiClientListView *pClientListView, const QString& sClientName, int iAlsaClient ) : qtractorClientListItem(pClientListView, sClientName) { m_iAlsaClient = iAlsaClient; if (pClientListView->isReadable()) { QTreeWidgetItem::setIcon(0, qtractorMidiConnect::icon(qtractorMidiConnect::ClientOut)); } else { QTreeWidgetItem::setIcon(0, qtractorMidiConnect::icon(qtractorMidiConnect::ClientIn)); } } // Default destructor. qtractorMidiClientItem::~qtractorMidiClientItem (void) { } // Jack client accessor. int qtractorMidiClientItem::alsaClient (void) const { return m_iAlsaClient; } // Derived port finder. qtractorMidiPortItem *qtractorMidiClientItem::findPortItem ( int iAlsaPort ) { int iChildCount = QTreeWidgetItem::childCount(); for (int iChild = 0; iChild < iChildCount; ++iChild) { QTreeWidgetItem *pItem = QTreeWidgetItem::child(iChild); if (pItem->type() != qtractorConnect::PortItem) continue; qtractorMidiPortItem *pPortItem = static_cast (pItem); if (pPortItem && pPortItem->alsaPort() == iAlsaPort) return pPortItem; } return NULL; } //---------------------------------------------------------------------- // qtractorMidiClientListView -- Alsa client list view. // // Constructor. qtractorMidiClientListView::qtractorMidiClientListView( QWidget *pParent ) : qtractorClientListView(pParent) { } // Default destructor. qtractorMidiClientListView::~qtractorMidiClientListView (void) { } // Alsa sequencer accessor. snd_seq_t *qtractorMidiClientListView::alsaSeq (void) const { qtractorMidiConnect *pMidiConnect = static_cast (binding()); return (pMidiConnect ? pMidiConnect->alsaSeq() : NULL); } // Client finder by id. qtractorMidiClientItem *qtractorMidiClientListView::findClientItem ( int iAlsaClient ) { int iItemCount = QTreeWidget::topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = QTreeWidget::topLevelItem(iItem); if (pItem->type() != qtractorConnect::ClientItem) continue; qtractorMidiClientItem *pClientItem = static_cast (pItem); if (pClientItem && pClientItem->alsaClient() == iAlsaClient) return pClientItem; } return NULL; } // Client port finder by id. qtractorMidiPortItem *qtractorMidiClientListView::findClientPortItem ( int iAlsaClient, int iAlsaPort ) { qtractorMidiClientItem *pClientItem = findClientItem(iAlsaClient); if (pClientItem == NULL) return NULL; return pClientItem->findPortItem(iAlsaPort); } // Client:port refreshner. int qtractorMidiClientListView::updateClientPorts (void) { snd_seq_t *pAlsaSeq = alsaSeq(); if (pAlsaSeq == NULL) return 0; int iDirtyCount = 0; markClientPorts(0); unsigned int uiAlsaFlags; if (isReadable()) uiAlsaFlags = SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; else uiAlsaFlags = SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; snd_seq_client_info_t *pClientInfo; snd_seq_port_info_t *pPortInfo; snd_seq_client_info_alloca(&pClientInfo); snd_seq_port_info_alloca(&pPortInfo); snd_seq_client_info_set_client(pClientInfo, -1); while (snd_seq_query_next_client(pAlsaSeq, pClientInfo) >= 0) { int iAlsaClient = snd_seq_client_info_get_client(pClientInfo); if (iAlsaClient > 0) { qtractorMidiClientItem *pClientItem = findClientItem(iAlsaClient); snd_seq_port_info_set_client(pPortInfo, iAlsaClient); snd_seq_port_info_set_port(pPortInfo, -1); while (snd_seq_query_next_port(pAlsaSeq, pPortInfo) >= 0) { unsigned int uiPortCapability = snd_seq_port_info_get_capability(pPortInfo); if (((uiPortCapability & uiAlsaFlags) == uiAlsaFlags) && ((uiPortCapability & SND_SEQ_PORT_CAP_NO_EXPORT) == 0)) { QString sClientName = QString::number(iAlsaClient); sClientName += ':'; sClientName += QString::fromUtf8( snd_seq_client_info_get_name(pClientInfo)); if (isClientName(sClientName)) { int iAlsaPort = snd_seq_port_info_get_port(pPortInfo); QString sPortName = QString::number(iAlsaPort); sPortName += ':'; sPortName += QString::fromUtf8( snd_seq_port_info_get_name(pPortInfo)); if (isPortName(sPortName)) { qtractorMidiPortItem *pPortItem = NULL; if (pClientItem == NULL) { pClientItem = new qtractorMidiClientItem(this, sClientName, iAlsaClient); ++iDirtyCount; } else { pPortItem = pClientItem->findPortItem(iAlsaPort); if (sClientName != pClientItem->clientName()) { pClientItem->setClientName(sClientName); ++iDirtyCount; } } if (pClientItem) { if (pPortItem == NULL) { pPortItem = new qtractorMidiPortItem( pClientItem, sPortName, iAlsaPort); ++iDirtyCount; } else if (sPortName != pPortItem->portName()) { pPortItem->setPortName(sPortName); ++iDirtyCount; } } if (pPortItem) pPortItem->markClientPort(1); } } } } } } cleanClientPorts(0); return iDirtyCount; } //---------------------------------------------------------------------------- // qtractorMidiConnect -- Alsa connections model integrated object. // // Constructor. qtractorMidiConnect::qtractorMidiConnect ( qtractorMidiClientListView *pOListView, qtractorMidiClientListView *pIListView, qtractorConnectorView *pConnectorView ) : qtractorConnect(pOListView, pIListView, pConnectorView) { createIcons(); } // Default destructor. qtractorMidiConnect::~qtractorMidiConnect (void) { deleteIcons(); } // Local icon-set janitor methods. QIcon *qtractorMidiConnect::g_apIcons[qtractorMidiConnect::IconCount]; int qtractorMidiConnect::g_iIconsRefCount = 0; void qtractorMidiConnect::createIcons (void) { if (++g_iIconsRefCount == 1) { g_apIcons[ClientIn] = new QIcon(":/images/itemMidiClientIn.png"); g_apIcons[ClientOut] = new QIcon(":/images/itemMidiClientOut.png"); g_apIcons[PortIn] = new QIcon(":/images/itemMidiPortIn.png"); g_apIcons[PortOut] = new QIcon(":/images/itemMidiPortOut.png"); } } void qtractorMidiConnect::deleteIcons (void) { if (--g_iIconsRefCount == 0) { for (int i = 0; i < IconCount; ++i) { if (g_apIcons[i]) delete g_apIcons[i]; g_apIcons[i] = NULL; } } } // Common icon accessor (static). const QIcon& qtractorMidiConnect::icon ( int iIcon ) { return *g_apIcons[iIcon]; } // ALSA sequencer accessor. snd_seq_t *qtractorMidiConnect::alsaSeq (void) const { snd_seq_t *pAlsaSeq = NULL; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession && pSession->midiEngine()) pAlsaSeq = (pSession->midiEngine())->alsaSeq(); return pAlsaSeq; } // Connection primitive. bool qtractorMidiConnect::connectPorts ( qtractorPortListItem *pOPort, qtractorPortListItem *pIPort ) { qtractorMidiPortItem *pOMidiPort = static_cast (pOPort); qtractorMidiPortItem *pIMidiPort = static_cast (pIPort); if (pOMidiPort == NULL || pIMidiPort == NULL) return false; snd_seq_t *pAlsaSeq = alsaSeq(); if (pAlsaSeq == NULL) return false; disconnectPortsUpdate(pOPort, pIPort); snd_seq_port_subscribe_t *pAlsaSubs; snd_seq_addr_t seq_addr; snd_seq_port_subscribe_alloca(&pAlsaSubs); seq_addr.client = pOMidiPort->alsaClient(); seq_addr.port = pOMidiPort->alsaPort(); snd_seq_port_subscribe_set_sender(pAlsaSubs, &seq_addr); seq_addr.client = pIMidiPort->alsaClient(); seq_addr.port = pIMidiPort->alsaPort(); snd_seq_port_subscribe_set_dest(pAlsaSubs, &seq_addr); return (snd_seq_subscribe_port(pAlsaSeq, pAlsaSubs) >= 0); } // Disconnection primitive. bool qtractorMidiConnect::disconnectPorts ( qtractorPortListItem *pOPort, qtractorPortListItem *pIPort ) { qtractorMidiPortItem *pOMidiPort = static_cast (pOPort); qtractorMidiPortItem *pIMidiPort = static_cast (pIPort); if (pOMidiPort == NULL || pIMidiPort == NULL) return false; snd_seq_t *pAlsaSeq = alsaSeq(); if (pAlsaSeq == NULL) return false; disconnectPortsUpdate(pOPort, pIPort); snd_seq_port_subscribe_t *pAlsaSubs; snd_seq_addr_t seq_addr; snd_seq_port_subscribe_alloca(&pAlsaSubs); seq_addr.client = pOMidiPort->alsaClient(); seq_addr.port = pOMidiPort->alsaPort(); snd_seq_port_subscribe_set_sender(pAlsaSubs, &seq_addr); seq_addr.client = pIMidiPort->alsaClient(); seq_addr.port = pIMidiPort->alsaPort(); snd_seq_port_subscribe_set_dest(pAlsaSubs, &seq_addr); return (snd_seq_unsubscribe_port(pAlsaSeq, pAlsaSubs) >= 0); } // Update (clear) MIDI-buses connect lists (non-virtual). void qtractorMidiConnect::disconnectPortsUpdate ( qtractorPortListItem *pOPort, qtractorPortListItem *pIPort ) { qtractorMidiEngine *pMidiEngine = NULL; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) pMidiEngine = pSession->midiEngine(); if (pMidiEngine == NULL) return; QString sPortName; qtractorBus::BusMode busMode = qtractorBus::None; if (pOPort->clientName().section(':', 1, 1) == pMidiEngine->clientName()) { busMode = qtractorBus::Output; sPortName = pOPort->portName().section(':', 1, 1); } else if (pIPort->clientName().section(':', 1, 1) == pMidiEngine->clientName()) { busMode = qtractorBus::Input; sPortName = pIPort->portName().section(':', 1, 1); } if (busMode == qtractorBus::None) return; for (qtractorBus *pBus = pMidiEngine->buses().first(); pBus; pBus = pBus->next()) { if ((pBus->busMode() & busMode) == 0) continue; if (sPortName == pBus->busName()) { if (busMode & qtractorBus::Input) { pBus->inputs().clear(); } else { pBus->outputs().clear(); // Remember to resend all session/tracks control stuff... pMidiEngine->resetAllControllers(false); // Deferred++ } break; } } } // Update port connection references. void qtractorMidiConnect::updateConnections (void) { snd_seq_t *pAlsaSeq = alsaSeq(); if (pAlsaSeq == NULL) return; snd_seq_query_subscribe_t *pAlsaSubs; snd_seq_addr_t seq_addr; snd_seq_query_subscribe_alloca(&pAlsaSubs); // Proper type casts. qtractorMidiClientListView *pOListView = static_cast (OListView()); qtractorMidiClientListView *pIListView = static_cast (IListView()); // For each client item... int iItemCount = pOListView->topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = pOListView->topLevelItem(iItem); if (pItem->type() != qtractorConnect::ClientItem) continue; qtractorMidiClientItem *pOClient = static_cast (pItem); if (pOClient == NULL) continue; // For each port item int iChildCount = pOClient->childCount(); for (int iChild = 0; iChild < iChildCount; ++iChild) { QTreeWidgetItem *pChild = pOClient->child(iChild); if (pChild->type() != qtractorConnect::PortItem) continue; qtractorMidiPortItem *pOPort = static_cast (pChild); if (pOPort == NULL) continue; // Are there already any connections? if (pOPort->connects().count() > 0) continue; // Get port connections... snd_seq_query_subscribe_set_type(pAlsaSubs, SND_SEQ_QUERY_SUBS_READ); snd_seq_query_subscribe_set_index(pAlsaSubs, 0); seq_addr.client = pOPort->alsaClient(); seq_addr.port = pOPort->alsaPort(); snd_seq_query_subscribe_set_root(pAlsaSubs, &seq_addr); while (snd_seq_query_port_subscribers(pAlsaSeq, pAlsaSubs) >= 0) { seq_addr = *snd_seq_query_subscribe_get_addr(pAlsaSubs); qtractorMidiPortItem *pIPort = pIListView->findClientPortItem( seq_addr.client, seq_addr.port); if (pIPort) { pOPort->addConnect(pIPort); pIPort->addConnect(pOPort); } snd_seq_query_subscribe_set_index(pAlsaSubs, snd_seq_query_subscribe_get_index(pAlsaSubs) + 1); } } } } // end of qtractorMidiConnect.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiFile.h0000644000175000001440000000012312074050467020663 xustar000000000000000027 mtime=1357926711.346833 26 atime=1381134666.64408 30 ctime=1381134666.644080043 qtractor-0.5.11/src/qtractorMidiFile.h0000644000175000001440000000742712074050467020164 0ustar00rncbcusers00000000000000// qtractorMidiFile.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorMidiFile_h #define __qtractorMidiFile_h #include "qtractorMidiSequence.h" #include "qtractorMidiFileTempo.h" class qtractorTimeScale; //---------------------------------------------------------------------- // class qtractorMidiFile -- A SMF (Standard MIDI File) class. // class qtractorMidiFile { public: // Constructor. qtractorMidiFile(); // Destructor. ~qtractorMidiFile(); // Basic file open mode. enum { None = 0, Read = 1, Write = 2 }; // Open file methods. bool open(const QString& sFilename, int iMode = Read); void close(); // Open file property accessors. const QString& filename() const { return m_sFilename; } int mode() const { return m_iMode; } // Header accessors. unsigned short format() const { return m_iFormat; } unsigned short tracks() const { return m_iTracks; } unsigned short ticksPerBeat() const { return m_iTicksPerBeat; } // Tempo/time-signature map accessor. qtractorMidiFileTempo *tempoMap() const { return m_pTempoMap; } // Sequence/track readers. bool readTracks(qtractorMidiSequence **ppSeqs, unsigned short iSeqs, unsigned short iTrackChannel = 0); bool readTrack(qtractorMidiSequence *pSeq, unsigned short iTrackChannel); // Header writer. bool writeHeader(unsigned short iFormat, unsigned short iTracks, unsigned short iTicksPerBeat); // Sequence/track writers. bool writeTracks(qtractorMidiSequence **ppSeqs, unsigned short iSeqs); bool writeTrack (qtractorMidiSequence *pSeq); // All-in-one SMF file writer/creator method. static bool saveCopyFile(const QString& sNewFilename, const QString& sOldFilename, unsigned short iTrackChannel, unsigned short iFormat, qtractorMidiSequence *pSeq, qtractorTimeScale *pTimeScale = NULL, unsigned long iTimeOffset = 0); // Create filename revision. static QString createFilePathRevision( const QString& sFilename, int iRevision = 0); protected: // Read methods. int readInt (unsigned short n = 0); int readData (unsigned char *pData, unsigned short n); // Write methods. int writeInt (int val, unsigned short n = 0); int writeData (unsigned char *pData, unsigned short n); // Write tempo-time-signature node. void writeNode( qtractorMidiFileTempo::Node *pNode, unsigned long iLastTime); // Write location marker. void writeMarker( qtractorMidiFileTempo::Marker *pMarker, unsigned long iLastTime); private: // SMF instance variables. QString m_sFilename; int m_iMode; FILE *m_pFile; unsigned long m_iOffset; // Header informational data. unsigned short m_iFormat; unsigned short m_iTracks; unsigned short m_iTicksPerBeat; // Track info map. struct TrackInfo { unsigned int length; unsigned long offset; } *m_pTrackInfo; // Special tempo/time-signature map. qtractorMidiFileTempo *m_pTempoMap; }; #endif // __qtractorMidiFile_h // end of qtractorMidiFile.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorAudioConnect.cpp0000644000175000001440000000012311563576072022116 xustar000000000000000027 mtime=1305410618.253123 26 atime=1381134667.63108 30 ctime=1381134667.631080059 qtractor-0.5.11/src/qtractorAudioConnect.cpp0000644000175000001440000002634011563576072021412 0ustar00rncbcusers00000000000000// qtractorAudioConnect.cpp // /**************************************************************************** Copyright (C) 2005-2011, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAudioConnect.h" #include "qtractorAudioEngine.h" #include "qtractorSession.h" #include //---------------------------------------------------------------------- // class qtractorAudioPortItem -- Jack port list item. // // Constructor. qtractorAudioPortItem::qtractorAudioPortItem ( qtractorAudioClientItem *pClientItem, const QString& sPortName, jack_port_t *pJackPort ) : qtractorPortListItem(pClientItem, sPortName) { m_pJackPort = pJackPort; unsigned long ulPortFlags = jack_port_flags(m_pJackPort); if (ulPortFlags & JackPortIsInput) { QTreeWidgetItem::setIcon(0, qtractorAudioConnect::icon(ulPortFlags & JackPortIsPhysical ? qtractorAudioConnect::PortPhysIn : qtractorAudioConnect::PortIn)); } else { QTreeWidgetItem::setIcon(0, qtractorAudioConnect::icon(ulPortFlags & JackPortIsPhysical ? qtractorAudioConnect::PortPhysOut : qtractorAudioConnect::PortOut)); } } // Default destructor. qtractorAudioPortItem::~qtractorAudioPortItem (void) { } // Jack handles accessors. jack_client_t *qtractorAudioPortItem::jackClient (void) const { qtractorAudioClientItem *pClientItem = static_cast (clientItem()); return (pClientItem ? pClientItem->jackClient() : NULL); } jack_port_t *qtractorAudioPortItem::jackPort (void) const { return m_pJackPort; } //---------------------------------------------------------------------- // qtractorAudioClientItem -- Jack client list item. // // Constructor. qtractorAudioClientItem::qtractorAudioClientItem ( qtractorAudioClientListView *pClientListView, const QString& sClientName ) : qtractorClientListItem(pClientListView, sClientName) { if (pClientListView->isReadable()) { QTreeWidgetItem::setIcon(0, qtractorAudioConnect::icon(qtractorAudioConnect::ClientOut)); } else { QTreeWidgetItem::setIcon(0, qtractorAudioConnect::icon(qtractorAudioConnect::ClientIn)); } } // Default destructor. qtractorAudioClientItem::~qtractorAudioClientItem (void) { } // Jack client accessor. jack_client_t *qtractorAudioClientItem::jackClient (void) const { qtractorAudioClientListView *pClientListView = static_cast (QTreeWidgetItem::treeWidget()); return (pClientListView ? pClientListView->jackClient() : NULL); } //---------------------------------------------------------------------- // qtractorAudioClientListView -- Jack client list view. // // Constructor. qtractorAudioClientListView::qtractorAudioClientListView ( QWidget *pParent ) : qtractorClientListView(pParent) { } // Default destructor. qtractorAudioClientListView::~qtractorAudioClientListView (void) { } // Jack client accessor. jack_client_t *qtractorAudioClientListView::jackClient (void) const { qtractorAudioConnect *pAudioConnect = static_cast (binding()); return (pAudioConnect ? pAudioConnect->jackClient() : NULL); } // Client:port refreshner. int qtractorAudioClientListView::updateClientPorts (void) { jack_client_t *pJackClient = jackClient(); if (pJackClient == NULL) return 0; int iDirtyCount = 0; markClientPorts(0); const char **ppszClientPorts = jack_get_ports(pJackClient, 0, JACK_DEFAULT_AUDIO_TYPE, isReadable() ? JackPortIsOutput : JackPortIsInput); if (ppszClientPorts) { int iClientPort = 0; while (ppszClientPorts[iClientPort]) { const QString sClientPort = QString::fromUtf8(ppszClientPorts[iClientPort]); qtractorAudioClientItem *pClientItem = NULL; qtractorAudioPortItem *pPortItem = NULL; int iColon = sClientPort.indexOf(':'); if (iColon >= 0) { const QString sClientName = sClientPort.left(iColon); if (isClientName(sClientName)) { const QString sPortName = sClientPort.right(sClientPort.length() - iColon - 1); if (isPortName(sPortName)) { pClientItem = static_cast ( findClientItem(sClientName)); if (pClientItem) { pPortItem = static_cast ( pClientItem->findPortItem(sPortName)); } if (pClientItem == NULL) { pClientItem = new qtractorAudioClientItem(this, sClientName); ++iDirtyCount; } if (pClientItem && pPortItem == NULL) { jack_port_t *pJackPort = jack_port_by_name( pJackClient, ppszClientPorts[iClientPort]); if (pJackPort) { pPortItem = new qtractorAudioPortItem( pClientItem, sPortName, pJackPort); ++iDirtyCount; } } if (pPortItem) pPortItem->markClientPort(1); } } } ++iClientPort; } ::free(ppszClientPorts); } cleanClientPorts(0); return iDirtyCount; } //---------------------------------------------------------------------------- // qtractorAudioConnect -- Jack connections model integrated object. // // Constructor. qtractorAudioConnect::qtractorAudioConnect ( qtractorAudioClientListView *pOListView, qtractorAudioClientListView *pIListView, qtractorConnectorView *pConnectorView ) : qtractorConnect(pOListView, pIListView, pConnectorView) { createIcons(); } // Default destructor. qtractorAudioConnect::~qtractorAudioConnect (void) { deleteIcons(); } // Local icon-set janitor methods. QIcon *qtractorAudioConnect::g_apIcons[qtractorAudioConnect::IconCount]; int qtractorAudioConnect::g_iIconsRefCount = 0; void qtractorAudioConnect::createIcons (void) { if (++g_iIconsRefCount == 1) { g_apIcons[ClientIn] = new QIcon(":/images/itemAudioClientIn.png"); g_apIcons[ClientOut] = new QIcon(":/images/itemAudioClientOut.png"); g_apIcons[PortIn] = new QIcon(":/images/itemAudioPortIn.png"); g_apIcons[PortOut] = new QIcon(":/images/itemAudioPortOut.png"); g_apIcons[PortPhysIn] = new QIcon(":/images/itemAudioPortPhysIn.png"); g_apIcons[PortPhysOut] = new QIcon(":/images/itemAudioPortPhysOut.png"); } } void qtractorAudioConnect::deleteIcons (void) { if (--g_iIconsRefCount == 0) { for (int i = 0; i < IconCount; ++i) { if (g_apIcons[i]) delete g_apIcons[i]; g_apIcons[i] = NULL; } } } // Common icon accessor (static). const QIcon& qtractorAudioConnect::icon ( int iIcon ) { return *g_apIcons[iIcon]; } // JACK client accessor. jack_client_t *qtractorAudioConnect::jackClient (void) const { jack_client_t *pJackClient = NULL; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession && pSession->audioEngine()) pJackClient = (pSession->audioEngine())->jackClient(); return pJackClient; } // Connection primitive. bool qtractorAudioConnect::connectPorts ( qtractorPortListItem *pOPort, qtractorPortListItem *pIPort ) { qtractorAudioPortItem *pOAudioPort = static_cast (pOPort); qtractorAudioPortItem *pIAudioPort = static_cast (pIPort); if (pOAudioPort == NULL || pIAudioPort == NULL) return false; jack_client_t *pJackClient = jackClient(); if (pJackClient == NULL) return false; return (jack_connect(pJackClient, pOAudioPort->clientPortName().toUtf8().constData(), pIAudioPort->clientPortName().toUtf8().constData()) == 0); } // Disconnection primitive. bool qtractorAudioConnect::disconnectPorts ( qtractorPortListItem *pOPort, qtractorPortListItem *pIPort ) { qtractorAudioPortItem *pOAudioPort = static_cast (pOPort); qtractorAudioPortItem *pIAudioPort = static_cast (pIPort); if (pOAudioPort == NULL || pIAudioPort == NULL) return false; jack_client_t *pJackClient = jackClient(); if (pJackClient == NULL) return false; disconnectPortsUpdate(pOPort, pIPort); return (jack_disconnect(pJackClient, pOAudioPort->clientPortName().toUtf8().constData(), pIAudioPort->clientPortName().toUtf8().constData()) == 0); } // Update (clear) audio-buses connect lists (non-virtual). void qtractorAudioConnect::disconnectPortsUpdate ( qtractorPortListItem *pOPort, qtractorPortListItem *pIPort ) { qtractorAudioEngine *pAudioEngine = NULL; qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) pAudioEngine = pSession->audioEngine(); if (pAudioEngine == NULL) return; QString sPortName; qtractorBus::BusMode busMode = qtractorBus::None; if (pOPort->clientName() == pAudioEngine->clientName()) { busMode = qtractorBus::Output; sPortName = pOPort->portName().section('/', 0, 0); } else if (pIPort->clientName() == pAudioEngine->clientName()) { busMode = qtractorBus::Input; sPortName = pIPort->portName().section('/', 0, 0); } if (busMode == qtractorBus::None) return; for (qtractorBus *pBus = pAudioEngine->buses().first(); pBus; pBus = pBus->next()) { if ((pBus->busMode() & busMode) == 0) continue; if (sPortName == pBus->busName()) { if (busMode & qtractorBus::Input) { pBus->inputs().clear(); } else { pBus->outputs().clear(); } break; } } } // Update port connection references. void qtractorAudioConnect::updateConnections (void) { jack_client_t *pJackClient = jackClient(); if (pJackClient == NULL) return; // For each client item... int iItemCount = OListView()->topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = OListView()->topLevelItem(iItem); if (pItem->type() != qtractorConnect::ClientItem) continue; qtractorAudioClientItem *pOClient = static_cast (pItem); if (pOClient == NULL) continue; // For each port item int iChildCount = pOClient->childCount(); for (int iChild = 0; iChild < iChildCount; ++iChild) { QTreeWidgetItem *pChild = pOClient->child(iChild); if (pChild->type() != qtractorConnect::PortItem) continue; qtractorAudioPortItem *pOPort = static_cast (pChild); if (pOPort == NULL) continue; // Are there already any connections? if (pOPort->connects().count() > 0) continue; // Get port connections... const char **ppszClientPorts = jack_port_get_all_connections( pJackClient, pOPort->jackPort()); if (ppszClientPorts) { // Now, for each input client port... int iClientPort = 0; while (ppszClientPorts[iClientPort]) { qtractorPortListItem *pIPort = IListView()->findClientPortItem( ppszClientPorts[iClientPort]); if (pIPort) { pOPort->addConnect(pIPort); pIPort->addConnect(pOPort); } ++iClientPort; } ::free(ppszClientPorts); } } } } // end of qtractorAudioConnect.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditorForm.ui0000644000175000001440000000012112163602733022240 xustar000000000000000025 mtime=1372521947.2674 26 atime=1381134670.27708 30 ctime=1381134670.277080101 qtractor-0.5.11/src/qtractorMidiEditorForm.ui0000644000175000001440000013224412163602733021537 0ustar00rncbcusers00000000000000 rncbc aka Rui Nuno Capela qtractor - A MIDI/Audio multi-track sequencer. Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qtractorMidiEditorForm 0 0 840 600 MIDI Editor :/images/qtractor.png 0 0 803 29 &Track &File Select &Mode &Select I&nsert Remo&ve &Tools &Edit &View &Toolbars &Windows :/images/viewZoomTool.png &Zoom S&nap Sc&ale T&ransport &Help Qt::Horizontal 4 Qt::Horizontal 4 Qt::Horizontal 4 Qt::Horizontal 4 Qt::Horizontal 4 Qt::Horizontal 4 Qt::Horizontal 4 Qt::Horizontal 4 :/images/fileSave.png &Save Save Save Save current MIDI clip to existing file name Save &As... Save As Save as Save current MIDI clip with another file name &Unlink Unlink Unlink Unlink current MIDI clip &Inputs Track Inputs Track inputs Show current MIDI clip/track input bus connections &Outputs Track Outputs Track outputs Show current MIDI clip/track output bus connections :/images/trackProperties.png &Properties... Track Properties Track properties Edit current MIDI clip/track properties Shift+F2 :/images/clipEdit.png &Properties... Properties Properties Edit current MIDI clip properties F4 &Range Set Clip Range Clip range Set edit-range from clip extents &Loop Set Clip Loop Clip loop Set loop-range from clip extents &Close Close Close Close this MIDI clip editor :/images/editUndo.png &Undo Undo Undo Undo last edit operation Ctrl+Z :/images/editRedo.png &Redo Redo Redo Redo last edit operation Ctrl+Shift+Z :/images/editCut.png Cu&t Cut Cut Cut current selection into the local clipboard Ctrl+X :/images/editCopy.png &Copy Copy Copy Copy current selection to the local clipboard Ctrl+C :/images/editPaste.png &Paste Paste Paste Paste local clipboard contents into the current MIDI clip Ctrl+V Past&e Repeat... Paste Repeat Paste repeat Paste/repeat local clipboard contents into the current MIDI clip Ctrl+Shift+V :/images/editDelete.png &Delete Delete Delete Delete current selection Del true :/images/editModeOff.png Edit Of&f Edit Off Edit off Set edit mode off true :/images/editModeOn.png Edit &On Edit On Edit on Set edit mode on true :/images/editModeDraw.png Edit &Draw Edit draw mode Edit draw mode (notes) &All Select All Select all Select all Ctrl+A &None Select None Select none Select none Ctrl+Shift+A &Invert Select Invert Select invert Select invert Ctrl+I &Range Select Range Select range Mark range as selected Ctrl+R &Range Insert Range Insert range Insert range as selected Ctrl+Ins &Range Remove Range Remove range Remove range as selected Ctrl+Del &Quantize... Quantize Quantize Quantize selection &Transpose... Transpose Transpose Transpose selection &Normalize... Normalize Normalize Normalize selection &Randomize... Randomize Randomize Randomize selection Resi&ze... Resize Resize Resize selection Re&scale... Rescale Rescale Rescale selection T&imeshift... Timeshift Timeshift Timeshift selection true &Menubar Menubar Menubar Show/hide the menubar Ctrl+M true &Statusbar Statusbar Statusbar Show/hide the statusbar true &File File Toolbar File toolbar Show/hide the file toolbar true &Edit Edit Toolbar Edit toolbar Show/hide the edit toolbar true &View View Toolbar View toolbar Show/hide the view toolbar true &Transport Transport Toolbar Transport toolbar Show/hide the transport toolbar true &Scale Scale Toolbar Scale toolbar Show/hide the scale toolbar true Note &Duration Note Duration Note duration Whether note events are shown proportional to duration true Note &Color Note Color Note color Whether note events are colored according to pitch true &Value Color Value Color Value color Whether note events are colored according to value (velocity) true :/images/viewEvents.png &Events View events View events Show/hide the events list true :/images/viewPreview.png &Preview Notes Preview Notes Preview notes Preview notes while editing (scrub) true :/images/transportFollow.png F&ollow Playhead Follow Playhead Follow playhead Follow playhead :/images/viewZoomIn.png &In Zoom In Zoom in Zoom in Ctrl++ :/images/viewZoomOut.png &Out Zoom Out Zoom out Zoom out Ctrl+- &Reset Zoom Reset Zoom reset Zoom reset Ctrl+1 true &Horizontal Horizontal Zoom Horizontal zoom Horizontal zoom mode true &Vertical Vertical Zoom Vertical zoom Vertical zoom mode true &All All Zoom All zoom All zoom mode true &Zebra Zebra Zebra Bar zebra view mode true &Grid Grid Grid Snap grid view mode true Too&l Tips Tool tips Tool tips Floating tool tips view mode &Refresh Refresh Refresh Refresh views F5 :/images/transportBackward.png &Backward Backward Backward Transport backward Backspace true :/images/transportRewind.png Re&wind Rewind Rewind Transport rewind true :/images/transportFastForward.png F&ast Forward Fast Forward Fast forward Transport fast forward :/images/transportForward.png &Forward Forward Forward Transport forward true :/images/transportLoop.png &Loop Loop Loop Transport loop Ctrl+Shift+L Loop &Set Loop Set Loop set Transport loop set Ctrl+L :/images/transportStop.png &Stop Stop Stop Transport stop true :/images/transportPlay.png &Play Play Play Transport play/pause Space true :/images/transportRecord.png &Record Record Record Transport record true :/images/transportPunch.png &Punch Punch Punch in/out Transport punch in/out Ctrl+Shift+P Punch Se&t Punch Set Punch in/out set Transport punch in/out set Ctrl+P :/images/transportPanic.png Pa&nic Panic Panic All MIDI tracks shut off (panic) :/images/helpShortcuts.png &Shortcuts... Shortcuts Shortcuts Keyboard shortcuts &About... About About Show information about this application program About &Qt... About Qt About Qt Show information about the Qt toolkit qtractor-0.5.11/src/PaxHeaders.10084/qtractorLadspaPlugin.h0000644000175000001440000000012312073012112021544 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134671.09708 30 ctime=1381134671.098080114 qtractor-0.5.11/src/qtractorLadspaPlugin.h0000644000175000001440000001017612073012112021040 0ustar00rncbcusers00000000000000// qtractorLadspaPlugin.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorLadspaPlugin_h #define __qtractorLadspaPlugin_h #include "qtractorPlugin.h" #include //---------------------------------------------------------------------------- // qtractorLadspaPluginType -- LADSPA plugin type instance. // class qtractorLadspaPluginType : public qtractorPluginType { public: // Constructor. qtractorLadspaPluginType(qtractorPluginFile *pFile, unsigned long iIndex, qtractorPluginType::Hint typeHint = qtractorPluginType::Ladspa, const LADSPA_Descriptor *pLadspaDescriptor = NULL) : qtractorPluginType(pFile, iIndex, typeHint), m_pLadspaDescriptor(pLadspaDescriptor) {} // Destructor. ~qtractorLadspaPluginType() { close(); } // Derived methods. bool open(); void close(); // Factory method (static) static qtractorLadspaPluginType *createType( qtractorPluginFile *pFile, unsigned long iIndex); // LADSPA descriptor method (static) static const LADSPA_Descriptor *ladspa_descriptor( qtractorPluginFile *pFile, unsigned long iIndex); // Specific accessors. const LADSPA_Descriptor *ladspa_descriptor() const { return m_pLadspaDescriptor; } protected: // LADSPA descriptor itself. const LADSPA_Descriptor *m_pLadspaDescriptor; }; //---------------------------------------------------------------------------- // qtractorLadspaPlugin -- LADSPA plugin instance. // class qtractorLadspaPlugin : public qtractorPlugin { public: // Constructors. qtractorLadspaPlugin(qtractorPluginList *pList, qtractorLadspaPluginType *pLadspaType); // Destructor. ~qtractorLadspaPlugin(); // Channel/intsance number accessors. void setChannels(unsigned short iChannels); // Do the actual (de)activation. void activate(); void deactivate(); // The main plugin processing procedure. void process(float **ppIBuffer, float **ppOBuffer, unsigned int nframes); // Specific accessors. const LADSPA_Descriptor *ladspa_descriptor() const; LADSPA_Handle ladspa_handle(unsigned short iInstance) const; // Audio port numbers. unsigned long audioIn(unsigned short i) { return m_piAudioIns[i]; } unsigned long audioOut(unsigned short i) { return m_piAudioOuts[i]; } protected: // Instance variables. LADSPA_Handle *m_phInstances; // List of output control port indexes and data. unsigned long *m_piControlOuts; float *m_pfControlOuts; // List of audio port indexes. unsigned long *m_piAudioIns; unsigned long *m_piAudioOuts; }; //---------------------------------------------------------------------------- // qtractorLadspaPluginParam -- LADSPA plugin control input port instance. // class qtractorLadspaPluginParam : public qtractorPluginParam { public: // Constructors. qtractorLadspaPluginParam(qtractorLadspaPlugin *pLadspaPlugin, unsigned long iIndex); // Destructor. ~qtractorLadspaPluginParam(); // Port range hints predicate methods. bool isBoundedBelow() const; bool isBoundedAbove() const; bool isDefaultValue() const; bool isLogarithmic() const; bool isSampleRate() const; bool isInteger() const; bool isToggled() const; bool isDisplay() const; private: // Instance variables. LADSPA_PortRangeHintDescriptor m_portHints; }; #endif // __qtractorLadspaPlugin_h // end of qtractorLadspaPlugin.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorPasteRepeatForm.cpp0000644000175000001440000000012312166134117022572 xustar000000000000000027 mtime=1373157455.942698 26 atime=1381134668.06808 30 ctime=1381134668.068080066 qtractor-0.5.11/src/qtractorPasteRepeatForm.cpp0000644000175000001440000001371312166134117022066 0ustar00rncbcusers00000000000000// qtractorPasteRepeatForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorPasteRepeatForm.h" #include "qtractorAbout.h" #include "qtractorTimeScale.h" #include "qtractorSession.h" #include "qtractorOptions.h" #include #include //---------------------------------------------------------------------------- // qtractorPasteRepeatForm -- UI wrapper form. // Constructor. qtractorPasteRepeatForm::qtractorPasteRepeatForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QDialog(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::WindowModal); // Initialize dirty control state. m_pTimeScale = NULL; m_iDirtyCount = 0; // Copy from global time-scale instance... qtractorSession *pSession = qtractorSession::getInstance(); if (pSession) { m_pTimeScale = new qtractorTimeScale(*pSession->timeScale()); m_ui.RepeatPeriodSpinBox->setTimeScale(m_pTimeScale); m_ui.RepeatPeriodSpinBox->setDeltaValue(true, pSession->playHead()); } // Initialize conveniency options... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { m_ui.RepeatCountSpinBox->setValue(pOptions->iPasteRepeatCount); m_ui.RepeatPeriodCheckBox->setChecked(pOptions->bPasteRepeatPeriod); } // Choose BBT to be default format here. formatChanged(qtractorTimeScale::BBT); // Try to set minimal window positioning. adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.RepeatCountSpinBox, SIGNAL(valueChanged(int)), SLOT(changed())); QObject::connect(m_ui.RepeatPeriodCheckBox, SIGNAL(toggled(bool)), SLOT(changed())); QObject::connect(m_ui.RepeatPeriodSpinBox, SIGNAL(valueChanged(unsigned long)), SLOT(changed())); QObject::connect(m_ui.RepeatPeriodSpinBox, SIGNAL(displayFormatChanged(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.RepeatFormatComboBox, SIGNAL(activated(int)), SLOT(formatChanged(int))); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); } // Destructor. qtractorPasteRepeatForm::~qtractorPasteRepeatForm (void) { // Don't forget to get rid of local time-scale instance... if (m_pTimeScale) delete m_pTimeScale; } // Access accepted the accepted values. void qtractorPasteRepeatForm::setRepeatCount ( unsigned short iRepeatCount ) { m_ui.RepeatCountSpinBox->setValue(iRepeatCount); } unsigned short qtractorPasteRepeatForm::repeatCount (void) const { return m_ui.RepeatCountSpinBox->value(); } void qtractorPasteRepeatForm::setRepeatPeriod ( unsigned long iRepeatPeriod ) { m_ui.RepeatPeriodSpinBox->setValue(iRepeatPeriod, false); } unsigned long qtractorPasteRepeatForm::repeatPeriod (void) const { return (m_ui.RepeatPeriodCheckBox->isChecked() ? m_ui.RepeatPeriodSpinBox->value() : 0); } // Accept settings (OK button slot). void qtractorPasteRepeatForm::accept (void) { // Save settings... if (m_iDirtyCount > 0) { // Save conveniency options... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) { pOptions->iPasteRepeatCount = repeatCount(); pOptions->bPasteRepeatPeriod = (repeatPeriod() > 0); } // Reset dirty flag. m_iDirtyCount = 0; } // Just go with dialog acceptance. QDialog::accept(); } // Reject settings (Cancel button slot). void qtractorPasteRepeatForm::reject (void) { bool bReject = true; // Check if there's any pending changes... if (m_iDirtyCount > 0) { QMessageBox::StandardButtons buttons = QMessageBox::Discard | QMessageBox::Cancel; if (m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->isEnabled()) buttons |= QMessageBox::Apply; switch (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Some settings have been changed.\n\n" "Do you want to apply the changes?"), buttons)) { case QMessageBox::Apply: accept(); return; case QMessageBox::Discard: break; default: // Cancel. bReject = false; } } if (bReject) QDialog::reject(); } // Dirty up settings. void qtractorPasteRepeatForm::changed (void) { ++m_iDirtyCount; stabilizeForm(); } // Display format has changed. void qtractorPasteRepeatForm::formatChanged ( int iDisplayFormat ) { bool bBlockSignals = m_ui.RepeatFormatComboBox->blockSignals(true); m_ui.RepeatFormatComboBox->setCurrentIndex(iDisplayFormat); qtractorTimeScale::DisplayFormat displayFormat = qtractorTimeScale::DisplayFormat(iDisplayFormat); m_ui.RepeatPeriodSpinBox->setDisplayFormat(displayFormat); if (m_pTimeScale) m_pTimeScale->setDisplayFormat(displayFormat); m_ui.RepeatFormatComboBox->blockSignals(bBlockSignals); stabilizeForm(); } // Stabilize current form state. void qtractorPasteRepeatForm::stabilizeForm (void) { bool bEnabled = m_ui.RepeatPeriodCheckBox->isChecked(); m_ui.RepeatPeriodSpinBox->setEnabled(bEnabled); m_ui.RepeatFormatComboBox->setEnabled(bEnabled); m_ui.DialogButtonBox->button( QDialogButtonBox::Ok)->setEnabled(m_pTimeScale != NULL); } // end of qtractorPasteRepeatForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorShortcutForm.cpp0000644000175000001440000000012312073012112022153 xustar000000000000000027 mtime=1357648970.876129 26 atime=1381134670.67208 30 ctime=1381134670.672080107 qtractor-0.5.11/src/qtractorShortcutForm.cpp0000644000175000001440000003072212073012112021446 0ustar00rncbcusers00000000000000// qtractorShortcutForm.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorShortcutForm.h" #include "qtractorOptions.h" #include #include #include #include #include #include #include #include //------------------------------------------------------------------------- // qtractorShortcutTableItem class qtractorShortcutTableItem : public QTableWidgetItem { public: // Constructors. qtractorShortcutTableItem(const QIcon& icon, const QString& sText) : QTableWidgetItem(icon, sText) { setFlags(flags() & ~Qt::ItemIsEditable); } qtractorShortcutTableItem(const QString& sText) : QTableWidgetItem(sText) { setFlags(flags() & ~Qt::ItemIsEditable); } qtractorShortcutTableItem(const QKeySequence& shortcut) : QTableWidgetItem(shortcut.toString()) {} }; //------------------------------------------------------------------------- // qtractorShortcutTableItemEdit // Shortcut key to text event translation. void qtractorShortcutTableItemEdit::keyPressEvent ( QKeyEvent *pKeyEvent ) { int iKey = pKeyEvent->key(); Qt::KeyboardModifiers modifiers = pKeyEvent->modifiers(); if (modifiers == Qt::NoModifier) { switch (iKey) { case Qt::Key_Return: emit editingFinished(); return; case Qt::Key_Escape: emit editingCanceled(); return; } } if (iKey >= Qt::Key_Shift && iKey < Qt::Key_F1) { QLineEdit::keyPressEvent(pKeyEvent); return; } if (modifiers & Qt::ShiftModifier) iKey |= Qt::SHIFT; if (modifiers & Qt::ControlModifier) iKey |= Qt::CTRL; if (modifiers & Qt::AltModifier) iKey |= Qt::ALT; QLineEdit::setText(QKeySequence(iKey).toString()); } //------------------------------------------------------------------------- // qtractorShortcutTableItemEditor qtractorShortcutTableItemEditor::qtractorShortcutTableItemEditor ( QWidget *pParent ) : QWidget(pParent) { m_pItemEdit = new qtractorShortcutTableItemEdit(/*this*/); m_pToolButton = new QToolButton(/*this*/); m_pToolButton->setFixedWidth(18); m_pToolButton->setText("X"); QHBoxLayout *pLayout = new QHBoxLayout(); pLayout->setSpacing(0); pLayout->setMargin(0); pLayout->addWidget(m_pItemEdit); pLayout->addWidget(m_pToolButton); QWidget::setLayout(pLayout); QWidget::setFocusPolicy(Qt::StrongFocus); QWidget::setFocusProxy(m_pItemEdit); QObject::connect(m_pItemEdit, SIGNAL(editingFinished()), SLOT(finish())); QObject::connect(m_pItemEdit, SIGNAL(editingCanceled()), SLOT(cancel())); QObject::connect(m_pToolButton, SIGNAL(clicked()), SLOT(clear())); } // Shortcut text accessors. void qtractorShortcutTableItemEditor::setText ( const QString& sText ) { m_pItemEdit->setText(sText); } QString qtractorShortcutTableItemEditor::text (void) const { return m_pItemEdit->text(); } // Shortcut text clear/toggler. void qtractorShortcutTableItemEditor::clear (void) { if (m_pItemEdit->text() == m_sDefaultText) m_pItemEdit->clear(); else m_pItemEdit->setText(m_sDefaultText); m_pItemEdit->setFocus(); } // Shortcut text finish notification. void qtractorShortcutTableItemEditor::finish (void) { bool bBlockSignals = m_pItemEdit->blockSignals(true); emit editingFinished(); m_index = QModelIndex(); m_sDefaultText.clear(); m_pItemEdit->blockSignals(bBlockSignals); } // Shortcut text cancel notification. void qtractorShortcutTableItemEditor::cancel (void) { bool bBlockSignals = m_pItemEdit->blockSignals(true); m_index = QModelIndex(); m_sDefaultText.clear(); emit editingFinished(); m_pItemEdit->blockSignals(bBlockSignals); } //------------------------------------------------------------------------- // qtractorShortcutTableItemDelegate qtractorShortcutTableItemDelegate::qtractorShortcutTableItemDelegate ( qtractorShortcutForm *pShortcutForm ) : QItemDelegate(pShortcutForm->tableWidget()), m_pShortcutForm(pShortcutForm) { } // Overridden paint method. void qtractorShortcutTableItemDelegate::paint ( QPainter *pPainter, const QStyleOptionViewItem& option, const QModelIndex& index ) const { // Special treatment for action icon+text... if (index.column() == 0) { QTableWidget *pTableWidget = m_pShortcutForm->tableWidget(); QTableWidgetItem *pItem = pTableWidget->item(index.row(), 0); pPainter->save(); if (option.state & QStyle::State_Selected) { const QPalette& pal = option.palette; pPainter->fillRect(option.rect, pal.highlight().color()); pPainter->setPen(pal.highlightedText().color()); } // Draw the icon... QRect rect = option.rect; const QSize& iconSize = pTableWidget->iconSize(); pPainter->drawPixmap(1, rect.top() + ((rect.height() - iconSize.height()) >> 1), pItem->icon().pixmap(iconSize)); // Draw the text... rect.setLeft(iconSize.width() + 2); pPainter->drawText(rect, Qt::TextShowMnemonic | Qt::AlignLeft | Qt::AlignVCenter, pItem->text()); pPainter->restore(); } else { // Others do as default... QItemDelegate::paint(pPainter, option, index); } } QWidget *qtractorShortcutTableItemDelegate::createEditor ( QWidget *pParent, const QStyleOptionViewItem& /*option*/, const QModelIndex& index ) const { qtractorShortcutTableItemEditor *pItemEditor = new qtractorShortcutTableItemEditor(pParent); pItemEditor->setIndex(index); pItemEditor->setDefaultText( index.model()->data(index, Qt::DisplayRole).toString()); QObject::connect(pItemEditor, SIGNAL(editingFinished()), SLOT(commitEditor())); return pItemEditor; } void qtractorShortcutTableItemDelegate::setEditorData ( QWidget *pEditor, const QModelIndex& index ) const { qtractorShortcutTableItemEditor *pItemEditor = qobject_cast (pEditor); pItemEditor->setText( index.model()->data(index, Qt::DisplayRole).toString()); } void qtractorShortcutTableItemDelegate::setModelData ( QWidget *pEditor, QAbstractItemModel *pModel, const QModelIndex& index ) const { qtractorShortcutTableItemEditor *pItemEditor = qobject_cast (pEditor); pModel->setData(index, pItemEditor->text()); } void qtractorShortcutTableItemDelegate::commitEditor (void) { qtractorShortcutTableItemEditor *pItemEditor = qobject_cast (sender()); if (m_pShortcutForm->commitEditor(pItemEditor)) emit commitData(pItemEditor); emit closeEditor(pItemEditor); } //------------------------------------------------------------------------- // qtractorShortcutForm qtractorShortcutForm::qtractorShortcutForm ( const QList& actions, QWidget *pParent ) : QDialog(pParent) { // Setup UI struct... m_ui.setupUi(this); // Window modality (let plugin/tool windows rave around). QDialog::setWindowModality(Qt::ApplicationModal); m_iDirtyCount = 0; // m_ui.qtractorShortcutTable = new QTableWidget(0, 3, this); m_ui.ShortcutTable->setIconSize(QSize(16, 16)); m_ui.ShortcutTable->setItemDelegate( new qtractorShortcutTableItemDelegate(this)); // m_ui.ShortcutTable->setSelectionMode(QAbstractItemView::SingleSelection); // m_ui.ShortcutTable->setSelectionBehavior(QAbstractItemView::SelectRows); // m_ui.ShortcutTable->setAlternatingRowColors(true); // m_ui.ShortcutTable->setSortingEnabled(true); // m_ui.ShortcutTable->setHorizontalHeaderLabels( // QStringList() << tr("Item") << tr("Description") << tr("Shortcut")); m_ui.ShortcutTable->horizontalHeader()->setStretchLastSection(true); m_ui.ShortcutTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft); m_ui.ShortcutTable->horizontalHeader()->resizeSection(0, 120); m_ui.ShortcutTable->horizontalHeader()->resizeSection(1, 260); int iRowHeight = m_ui.ShortcutTable->fontMetrics().height() + 4; m_ui.ShortcutTable->verticalHeader()->setDefaultSectionSize(iRowHeight); m_ui.ShortcutTable->verticalHeader()->hide(); int iRow = 0; QListIterator iter(actions); while (iter.hasNext()) { QAction *pAction = iter.next(); if (pAction->objectName().isEmpty()) continue; m_ui.ShortcutTable->insertRow(iRow); m_ui.ShortcutTable->setItem(iRow, 0, new qtractorShortcutTableItem(pAction->icon(), pAction->text())); m_ui.ShortcutTable->setItem(iRow, 1, new qtractorShortcutTableItem(pAction->statusTip())); const QKeySequence& shortcut = pAction->shortcut(); const QString& sShortcutText = shortcut.toString(); m_ui.ShortcutTable->setItem(iRow, 2, new qtractorShortcutTableItem(shortcut)); m_actions.insert(pAction, iRow); if (!sShortcutText.isEmpty()) m_shortcuts.insert(sShortcutText, iRow); ++iRow; } // Restore last seen form position and extents... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) pOptions->loadWidgetGeometry(this, true); QObject::connect(m_ui.ShortcutTable, SIGNAL(itemActivated(QTableWidgetItem *)), SLOT(actionActivated(QTableWidgetItem *))); QObject::connect(m_ui.ShortcutTable, SIGNAL(itemChanged(QTableWidgetItem *)), SLOT(actionChanged(QTableWidgetItem *))); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); } qtractorShortcutForm::~qtractorShortcutForm (void) { // Store form position and extents... qtractorOptions *pOptions = qtractorOptions::getInstance(); if (pOptions) pOptions->saveWidgetGeometry(this, true); } QTableWidget *qtractorShortcutForm::tableWidget (void) const { return m_ui.ShortcutTable; } // Shortcut action finder & settler. bool qtractorShortcutForm::commitEditor ( qtractorShortcutTableItemEditor *pItemEditor ) { const QModelIndex& index = pItemEditor->index(); if (!index.isValid()) return false; const QString& sShortcutText = pItemEditor->text(); const QString& sDefaultText = pItemEditor->defaultText(); if (sShortcutText == sDefaultText) return false; if (!sShortcutText.isEmpty()) { if (m_shortcuts.contains(sShortcutText)) { QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Keyboard shortcut (%1) already assigned.") .arg(sShortcutText), QMessageBox::Cancel); pItemEditor->clear(); return false; } m_shortcuts.insert(sShortcutText, index.row()); } if (!sDefaultText.isEmpty()) m_shortcuts.remove(sDefaultText); return true; } void qtractorShortcutForm::actionActivated ( QTableWidgetItem *pItem ) { m_ui.ShortcutTable->editItem(m_ui.ShortcutTable->item(pItem->row(), 2)); } void qtractorShortcutForm::actionChanged ( QTableWidgetItem *pItem ) { const QString& sShortcutText = QKeySequence(pItem->text().trimmed()).toString(); pItem->setText(sShortcutText); ++m_iDirtyCount; } void qtractorShortcutForm::accept (void) { if (m_iDirtyCount > 0) { QHash::ConstIterator iter = m_actions.constBegin(); const QHash::ConstIterator& iter_end = m_actions.constEnd(); for ( ; iter != iter_end; ++iter) { const QString& sShortcutText = m_ui.ShortcutTable->item(iter.value(), 2)->text(); iter.key()->setShortcut(QKeySequence(sShortcutText)); } } QDialog::accept(); } void qtractorShortcutForm::reject (void) { bool bReject = true; // Check if there's any pending changes... if (m_iDirtyCount > 0) { QMessageBox::StandardButtons buttons = QMessageBox::Discard | QMessageBox::Cancel; if (m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->isEnabled()) buttons |= QMessageBox::Apply; switch (QMessageBox::warning(this, tr("Warning") + " - " QTRACTOR_TITLE, tr("Keyboard shortcuts have been changed.\n\n" "Do you want to apply the changes?"), buttons)) { case QMessageBox::Apply: accept(); return; case QMessageBox::Discard: break; default: // Cancel. bReject = false; } } if (bReject) QDialog::reject(); } // end of qtractorShortcutForm.cpp qtractor-0.5.11/src/PaxHeaders.10084/qtractorOptionsForm.h0000644000175000001440000000012312075756210021460 xustar000000000000000027 mtime=1358421128.323704 26 atime=1381134666.56708 30 ctime=1381134666.567080042 qtractor-0.5.11/src/qtractorOptionsForm.h0000644000175000001440000000632112075756210020751 0ustar00rncbcusers00000000000000// qtractorOptionsForm.h // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qtractorOptionsForm_h #define __qtractorOptionsForm_h #include "ui_qtractorOptionsForm.h" // Forward declarations... class qtractorOptions; //---------------------------------------------------------------------------- // qtractorOptionsForm -- UI wrapper form. class qtractorOptionsForm : public QDialog { Q_OBJECT public: // Constructor. qtractorOptionsForm(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); // Destructor. ~qtractorOptionsForm(); void setOptions(qtractorOptions *pOptions); qtractorOptions *options() const; protected slots: void accept(); void reject(); void changed(); void chooseMetroBarFilename(); void chooseMetroBeatFilename(); void updateMetroNoteNames(); void changeAudioMeterLevel(int iColor); void changeMidiMeterLevel(int iColor); void changeAudioMeterColor(const QString& sColor); void changeMidiMeterColor(const QString& sColor); void chooseAudioMeterColor(); void chooseMidiMeterColor(); void resetMeterColors(); void choosePluginType(int iPluginType); void changePluginPath(const QString& sPluginPath); void choosePluginPath(); void selectPluginPath(); void addPluginPath(); void removePluginPath(); void moveUpPluginPath(); void moveDownPluginPath(); void chooseLv2PresetDir(); void chooseMessagesFont(); void chooseMessagesLogPath(); void chooseSessionTemplatePath(); void stabilizeForm(); protected: // Browse for an existing audio filename. QString getOpenAudioFileName( const QString& sTitle, const QString& sFilename); // Special combo-box color item helpers. void updateColorText(QLineEdit *pLineEdit, const QColor& color); // Session format ext/suffix helpers. int sessionFormatFromExt(const QString& sSessionExt) const; QString sessionExtFromFormat(int iSessionFormat) const; private: // The Qt-designer UI struct... Ui::qtractorOptionsForm m_ui; // Instance variables... qtractorOptions *m_pOptions; int m_iDirtyCount; // Meter colors. enum { AudioMeterColors = 5, MidiMeterColors = 2 }; QColor m_audioMeterColors[AudioMeterColors]; QColor m_midiMeterColors[MidiMeterColors]; // Plug-ins path cache. QStringList m_ladspaPaths; QStringList m_dssiPaths; QStringList m_lv2Paths; QStringList m_vstPaths; }; #endif // __qtractorOptionsForm_h // end of qtractorOptionsForm.h qtractor-0.5.11/src/PaxHeaders.10084/qtractorMidiEditView.cpp0000644000175000001440000000012112203713015022042 xustar000000000000000025 mtime=1376753165.6215 26 atime=1381134671.09708 30 ctime=1381134671.097080114 qtractor-0.5.11/src/qtractorMidiEditView.cpp0000644000175000001440000004275112203713015021344 0ustar00rncbcusers00000000000000// qtractorMidiEditView.cpp // /**************************************************************************** Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qtractorAbout.h" #include "qtractorMidiEditView.h" #include "qtractorMidiEditor.h" #include "qtractorMidiEditList.h" #include "qtractorMidiEditTime.h" #include "qtractorMidiEditEvent.h" #include "qtractorMidiSequence.h" #include "qtractorSession.h" #include "qtractorOptions.h" #include #include #include #include #include #include #include //---------------------------------------------------------------------------- // qtractorMidiEditView -- MIDI sequence main view widget. // Constructor. qtractorMidiEditView::qtractorMidiEditView ( qtractorMidiEditor *pEditor, QWidget *pParent ) : qtractorScrollView(pParent) { m_pEditor = pEditor; m_eventType = qtractorMidiEvent::NOTEON; // Zoom tool widgets m_pVzoomIn = new QToolButton(this); m_pVzoomOut = new QToolButton(this); m_pVzoomReset = new QToolButton(this); m_pVzoomIn->setIcon(QIcon(":/images/viewZoomIn.png")); m_pVzoomOut->setIcon(QIcon(":/images/viewZoomOut.png")); m_pVzoomReset->setIcon(QIcon(":/images/viewZoomTool.png")); m_pVzoomIn->setAutoRepeat(true); m_pVzoomOut->setAutoRepeat(true); m_pVzoomIn->setToolTip(tr("Zoom in (vertical)")); m_pVzoomOut->setToolTip(tr("Zoom out (vertical)")); m_pVzoomReset->setToolTip(tr("Zoom reset (vertical)")); int iScrollBarExtent = qtractorScrollView::style()->pixelMetric(QStyle::PM_ScrollBarExtent); m_pVzoomReset->setFixedHeight(iScrollBarExtent); m_pVzoomOut->setFixedHeight(iScrollBarExtent); m_pVzoomIn->setFixedHeight(iScrollBarExtent); qtractorScrollView::addScrollBarWidget(m_pVzoomReset, Qt::AlignBottom); qtractorScrollView::addScrollBarWidget(m_pVzoomOut, Qt::AlignBottom); qtractorScrollView::addScrollBarWidget(m_pVzoomIn, Qt::AlignBottom); QObject::connect(m_pVzoomIn, SIGNAL(clicked()), m_pEditor, SLOT(verticalZoomInSlot())); QObject::connect(m_pVzoomOut, SIGNAL(clicked()), m_pEditor, SLOT(verticalZoomOutSlot())); QObject::connect(m_pVzoomReset, SIGNAL(clicked()), m_pEditor, SLOT(verticalZoomResetSlot())); qtractorScrollView::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); qtractorScrollView::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); qtractorScrollView::viewport()->setFocusPolicy(Qt::StrongFocus); // qtractorScrollView::viewport()->setFocusProxy(this); // qtractorScrollView::viewport()->setAcceptDrops(true); // qtractorScrollView::setDragAutoScroll(false); qtractorScrollView::setMouseTracking(true); const QFont& font = qtractorScrollView::font(); qtractorScrollView::setFont(QFont(font.family(), font.pointSize() - 1)); // QObject::connect(this, SIGNAL(contentsMoving(int,int)), // this, SLOT(updatePixmap(int,int))); // Trap for help/tool-tips and leave events. qtractorScrollView::viewport()->installEventFilter(this); } // Destructor. qtractorMidiEditView::~qtractorMidiEditView (void) { } // Scrollbar/tools layout management. void qtractorMidiEditView::setVBarGeometry ( QScrollBar& vbar, int x, int y, int w, int h ) { vbar.setGeometry(x, y, w, h - w * 2); if (m_pVzoomIn) m_pVzoomIn->setGeometry(x, y + h - w * 2, w, w); if (m_pVzoomOut) m_pVzoomOut->setGeometry(x, y + h - w, w, w); } // Update track view content height. void qtractorMidiEditView::updateContentsHeight (void) { // Do the contents resize thing... qtractorScrollView::resizeContents( qtractorScrollView::contentsWidth(), m_pEditor->editList()->contentsHeight()); // updateContents(); } // Update track view content width. void qtractorMidiEditView::updateContentsWidth ( int iContentsWidth ) { // Do the contents resize thing... qtractorTimeScale *pTimeScale = m_pEditor->timeScale(); if (pTimeScale) { qtractorMidiSequence *pSeq = m_pEditor->sequence(); if (pSeq) { unsigned long t0 = pTimeScale->tickFromFrame(m_pEditor->offset()); int x0 = pTimeScale->pixelFromFrame(m_pEditor->offset()); int w0 = pTimeScale->pixelFromTick(t0 + pSeq->duration()) - x0; if (iContentsWidth < w0) iContentsWidth = w0; } iContentsWidth += pTimeScale->pixelFromBeat( 2 * pTimeScale->beatsPerBar()) + qtractorScrollView::width(); } qtractorScrollView::resizeContents( iContentsWidth, qtractorScrollView::contentsHeight()); // Force an update on other views too... m_pEditor->editTime()->resizeContents( iContentsWidth + 100, m_pEditor->editTime()->viewport()->height()); // m_pEditor->editTime()->updateContents(); m_pEditor->editEvent()->resizeContents( iContentsWidth, m_pEditor->editEvent()->viewport()->height()); // m_pEditor->editEvent()->updateContents(); } // Local rectangular contents update. void qtractorMidiEditView::updateContents ( const QRect& rect ) { updatePixmap( qtractorScrollView::contentsX(), qtractorScrollView::contentsY()); qtractorScrollView::updateContents(rect); } // Overall contents update. void qtractorMidiEditView::updateContents (void) { updatePixmap( qtractorScrollView::contentsX(), qtractorScrollView::contentsY()); qtractorScrollView::updateContents(); } // Current event selection accessors. void qtractorMidiEditView::setEventType ( qtractorMidiEvent::EventType eventType ) { m_eventType = eventType; m_pEditor->updateContents(); } qtractorMidiEvent::EventType qtractorMidiEditView::eventType (void) const { return m_eventType; } // Resize event handler. void qtractorMidiEditView::resizeEvent ( QResizeEvent *pResizeEvent ) { qtractorScrollView::resizeEvent(pResizeEvent); // Scrollbar/tools layout management. const QSize& size = qtractorScrollView::size(); QScrollBar *pVScrollBar = qtractorScrollView::verticalScrollBar(); int w = pVScrollBar->width(); updateContents(); m_pEditor->editEventScale()->setFixedWidth( m_pEditor->width() - size.width()); m_pEditor->editEventFrame()->setFixedWidth(w); } // (Re)create the complete track view pixmap. void qtractorMidiEditView::updatePixmap ( int cx, int cy ) { QWidget *pViewport = qtractorScrollView::viewport(); int w = pViewport->width(); int h = pViewport->height(); if (w < 1 || h < 1) return; const QPalette& pal = qtractorScrollView::palette(); const QColor& rgbBase = pal.base().color(); const QColor& rgbFore = m_pEditor->foreground(); const QColor& rgbBack = m_pEditor->background(); const QColor& rgbDark = pal.mid().color(); const QColor& rgbLight = pal.midlight().color(); const QColor& rgbSharp = rgbBase.darker(110); m_pixmap = QPixmap(w, h); m_pixmap.fill(rgbBase); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; qtractorTimeScale *pTimeScale = m_pEditor->timeScale(); if (pTimeScale == NULL) return; QPainter p(&m_pixmap); p.initFrom(this); // Show that we may have clip limits... if (m_pEditor->length() > 0) { int x1 = pTimeScale->pixelFromFrame(m_pEditor->length()) - cx; if (x1 < 0) x1 = 0; if (x1 < w) p.fillRect(x1, 0, w - x1, h, rgbBase.darker(105)); } // Draw horizontal lines... p.setPen(rgbLight); // p.setBrush(rgbSharp); int h1 = m_pEditor->editList()->itemHeight(); int ch = qtractorScrollView::contentsHeight() - cy; int q = (cy / h1); int n = 127 - q; int y = q * h1 - cy; while (y < h && y < ch) { int k = (n % 12); if (k == 1 || k == 3 || k == 6 || k == 8 || k == 10) p.fillRect(0, y + 1, w, h1, rgbSharp); p.drawLine(0, y, w, y); y += h1; --n; } // Account for the editing offset: qtractorTimeScale::Cursor cursor(pTimeScale); qtractorTimeScale::Node *pNode = cursor.seekFrame(m_pEditor->offset()); unsigned long t0 = pNode->tickFromFrame(m_pEditor->offset()); int x0 = pTimeScale->pixelFromFrame(m_pEditor->offset()); int dx = x0 + cx; // Draw vertical grid lines... const QBrush zebra(QColor(0, 0, 0, 20)); pNode = cursor.seekPixel(dx); unsigned short iSnapPerBeat = (m_pEditor->isSnapGrid() ? pTimeScale->snapPerBeat() : 0); unsigned short iPixelsPerBeat = pNode->pixelsPerBeat(); unsigned int iBeat = pNode->beatFromPixel(dx); unsigned short iBar = (m_pEditor->isSnapZebra() ? pNode->barFromBeat(iBeat) : 0); int x = pNode->pixelFromBeat(iBeat) - dx; int x2 = x; while (x < w) { bool bBeatIsBar = pNode->beatIsBar(iBeat); if (bBeatIsBar) { p.setPen(rgbDark); p.drawLine(x - 1, 0, x - 1, h); if (m_pEditor->isSnapZebra() && (x > x2) && (++iBar & 1)) p.fillRect(QRect(x2, 0, x - x2 + 1, h), zebra); x2 = x; if (iBeat == pNode->beat) iPixelsPerBeat = pNode->pixelsPerBeat(); } if (bBeatIsBar || iPixelsPerBeat > 8) { p.setPen(rgbLight); p.drawLine(x, 0, x, h); } if (iSnapPerBeat > 1) { int q = iPixelsPerBeat / iSnapPerBeat; if (q > 4) { p.setPen(rgbBase.value() < 0x7f ? rgbLight.darker(105) : rgbLight.lighter(120)); for (int i = 1; i < iSnapPerBeat; ++i) { x = pTimeScale->pixelSnap(x + dx + q) - dx - 1; p.drawLine(x, 0, x, h); } } } pNode = cursor.seekBeat(++iBeat); x = pNode->pixelFromBeat(iBeat) - dx; } if (m_pEditor->isSnapZebra() && (x > x2) && (++iBar & 1)) p.fillRect(QRect(x2, 0, x - x2 + 1, h), zebra); if (y > ch) p.fillRect(0, ch, w, h - ch, rgbDark); // Draw location marker lines... qtractorTimeScale::Marker *pMarker = pTimeScale->markers().seekPixel(dx); while (pMarker) { x = pTimeScale->pixelFromFrame(pMarker->frame) - dx; if (x > w) break; p.setPen(pMarker->color); p.drawLine(x, 0, x, h); pMarker = pMarker->next(); } // // Draw the sequence events... // qtractorMidiSequence *pSeq = m_pEditor->sequence(); if (pSeq == NULL) return; pNode = cursor.seekPixel(x = dx); unsigned long iTickStart = pNode->tickFromPixel(x); pNode = cursor.seekPixel(x += w); unsigned long iTickEnd = pNode->tickFromPixel(x); // p.setPen(rgbFore); // p.setBrush(rgbBack); QColor rgbNote(rgbBack); int hue, sat, val; rgbNote.getHsv(&hue, &sat, &val); sat = 86; qtractorMidiEvent *pEvent = m_pEditor->seekEvent(iTickStart > t0 ? iTickStart - t0 : 0); while (pEvent) { unsigned long t1 = t0 + pEvent->time(); if (t1 >= iTickEnd) break; unsigned long t2 = t1 + pEvent->duration(); // Filter event type!... if (pEvent->type() == m_eventType && t2 >= iTickStart) { y = ch - h1 * (pEvent->note() + 1); if (y + h1 >= 0 && y < h) { pNode = cursor.seekTick(t1); x = pNode->pixelFromTick(t1) - x0 - cx; int w1 = pNode->pixelFromTick(t2) - x0 - cx - x; if (w1 < 5) w1 = 5; if (m_pEditor->isNoteColor()) { hue = (128 - int(pEvent->note())) << 4; if (m_pEditor->isValueColor()) sat = 64 + (int(pEvent->value()) >> 1); rgbNote.setHsv(hue, sat, val); } else if (m_pEditor->isValueColor()) { hue = (128 - int(pEvent->value())) << 1; rgbNote.setHsv(hue, sat, val); } p.fillRect(x, y, w1, h1, rgbFore); if (h1 > 3) p.fillRect(x + 1, y + 1, w1 - 4, h1 - 3, rgbNote); } } pEvent = pEvent->next(); } // Draw loop boundaries, if applicable... if (pSession->isLooping()) { const QBrush shade(QColor(0, 0, 0, 60)); p.setPen(Qt::darkCyan); x = pTimeScale->pixelFromFrame(pSession->loopStart()) - dx; if (x >= w) p.fillRect(QRect(0, 0, w, h), shade); else if (x >= 0) { p.fillRect(QRect(0, 0, x, h), shade); p.drawLine(x, 0, x, h); } x = pTimeScale->pixelFromFrame(pSession->loopEnd()) - dx; if (x < 0) p.fillRect(QRect(0, 0, w, h), shade); else if (x < w) { p.fillRect(QRect(x, 0, w - x, h), shade); p.drawLine(x, 0, x, h); } } // Draw punch boundaries, if applicable... if (pSession->isPunching()) { const QBrush shade(QColor(0, 0, 0, 60)); p.setPen(Qt::darkMagenta); x = pTimeScale->pixelFromFrame(pSession->punchIn()) - dx; if (x >= w) p.fillRect(QRect(0, 0, w, h), shade); else if (x >= 0) { p.fillRect(QRect(0, 0, x, h), shade); p.drawLine(x, 0, x, h); } x = pTimeScale->pixelFromFrame(pSession->punchOut()) - dx; if (x < 0) p.fillRect(QRect(0, 0, w, h), shade); else if (x < w) { p.fillRect(QRect(x, 0, w - x, h), shade); p.drawLine(x, 0, x, h); } } } // Draw the track view. void qtractorMidiEditView::drawContents ( QPainter *pPainter, const QRect& rect ) { // Draw viewport canvas... pPainter->drawPixmap(rect, m_pixmap, rect); m_pEditor->paintDragState(this, pPainter); // Draw special play-head line... int cx = qtractorScrollView::contentsX(); int x = m_pEditor->playHeadX() - cx; if (x >= rect.left() && x <= rect.right()) { pPainter->setPen(Qt::red); pPainter->drawLine(x, rect.top(), x, rect.bottom()); } // Draw edit-head line... x = m_pEditor->editHeadX() - cx; if (x >= rect.left() && x <= rect.right()) { pPainter->setPen(Qt::blue); pPainter->drawLine(x, rect.top(), x, rect.bottom()); } // Draw edit-tail line... x = m_pEditor->editTailX() - cx; if (x >= rect.left() && x <= rect.right()) { pPainter->setPen(Qt::blue); pPainter->drawLine(x, rect.top(), x, rect.bottom()); } } // To have main view in h-sync with edit list. void qtractorMidiEditView::contentsXMovingSlot ( int cx, int /*cy*/ ) { if (qtractorScrollView::contentsX() != cx) qtractorScrollView::setContentsPos(cx, qtractorScrollView::contentsY()); } // To have main view in v-sync with edit list. void qtractorMidiEditView::contentsYMovingSlot ( int /*cx*/, int cy ) { if (qtractorScrollView::contentsY() != cy) qtractorScrollView::setContentsPos(qtractorScrollView::contentsX(), cy); } // Focus lost event. void qtractorMidiEditView::focusOutEvent ( QFocusEvent *pFocusEvent ) { m_pEditor->focusOut(this); qtractorScrollView::focusOutEvent(pFocusEvent); } // Keyboard event handler. void qtractorMidiEditView::keyPressEvent ( QKeyEvent *pKeyEvent ) { if (!m_pEditor->keyPress(this, pKeyEvent->key(), pKeyEvent->modifiers())) qtractorScrollView::keyPressEvent(pKeyEvent); } // Handle item selection/dragging -- mouse button press. void qtractorMidiEditView::mousePressEvent ( QMouseEvent *pMouseEvent ) { // Process mouse press... // qtractorScrollView::mousePressEvent(pMouseEvent); qtractorSession *pSession = qtractorSession::getInstance(); if (pSession == NULL) return; // Which mouse state? bool bModifier = (pMouseEvent->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)); // Maybe start the drag-move-selection dance? const QPoint& pos = qtractorScrollView::viewportToContents(pMouseEvent->pos()); qtractorTimeScale *pTimeScale = m_pEditor->timeScale(); unsigned long iFrame = pTimeScale->frameSnap(m_pEditor->offset() + pTimeScale->frameFromPixel(pos.x() > 0 ? pos.x() : 0)); // We'll need options somehow... qtractorOptions *pOptions = qtractorOptions::getInstance(); switch (pMouseEvent->button()) { case Qt::LeftButton: // Only the left-mouse-button was meaningful... break; case Qt::MidButton: // Mid-button direct positioning... m_pEditor->selectAll(this, false); if (pOptions && pOptions->bMidButtonModifier) bModifier = !bModifier; // Reverse mid-button role... // Which mouse state? if (bModifier) { // Play-head positioning commit... m_pEditor->setPlayHead(iFrame); pSession->setPlayHead(m_pEditor->playHead()); } else { // Edit cursor (merge) positioning... m_pEditor->setEditHead(iFrame); m_pEditor->setEditTail(iFrame); } // Logical contents changed, just for visual feedback... m_pEditor->selectionChangeNotify(); // Fall thru... default: return; } // Remember what and where we'll be dragging/selecting... m_pEditor->dragMoveStart(this, pos, pMouseEvent->modifiers()); } // Handle item selection/dragging -- mouse pointer move. void qtractorMidiEditView::mouseMoveEvent ( QMouseEvent *pMouseEvent ) { // Process mouse move... // qtractorScrollView::mouseMoveEvent(pMouseEvent); // Are we already moving/dragging something? const QPoint& pos = qtractorScrollView::viewportToContents(pMouseEvent->pos()); m_pEditor->dragMoveUpdate(this, pos, pMouseEvent->modifiers()); } // Handle item selection/dragging -- mouse button release. void qtractorMidiEditView::mouseReleaseEvent ( QMouseEvent *pMouseEvent ) { // Process mouse release... // qtractorScrollView::mouseReleaseEvent(pMouseEvent); // Were we moving/dragging something? const QPoint& pos = qtractorScrollView::viewportToContents(pMouseEvent->pos()); m_pEditor->dragMoveCommit(this, pos, pMouseEvent->modifiers()); } // Handle zoom with mouse wheel. void qtractorMidiEditView::wheelEvent ( QWheelEvent *pWheelEvent ) { if (pWheelEvent->modifiers() & Qt::ControlModifier) { int delta = pWheelEvent->delta(); if (delta > 0) m_pEditor->zoomIn(); else m_pEditor->zoomOut(); } else qtractorScrollView::wheelEvent(pWheelEvent); } // Trap for help/tool-tip and leave events. bool qtractorMidiEditView::eventFilter ( QObject *pObject, QEvent *pEvent ) { if (m_pEditor->dragMoveFilter(this, pObject, pEvent)) return true; return qtractorScrollView::eventFilter(pObject, pEvent); } // end of qtractorMidiEditView.cpp qtractor-0.5.11/PaxHeaders.10084/TODO0000644000175000001440000000012312102155164015141 xustar000000000000000027 mtime=1359534708.011491 26 atime=1381134666.08108 30 ctime=1381134666.081080034 qtractor-0.5.11/TODO0000644000175000001440000000116112102155164014427 0ustar00rncbcusers00000000000000Qtractor - An Audio/MIDI multi-track sequencer ---------------------------------------------- Qtractor is still in some alpha stage of development, although already functional. It surely has a plenty of lurking bugs. It also lacks some features that some might find critical in the application field. All is not lost, the following are among the ones planned to be worked on in the times to come (not in any particular order): - MIDI step-recording. - Audio clip auto-crossfading. - Clip locking, muting and plug-ins. - JACK MIDI support. - OSC interface. - Scripting. - etc. etc. - Any other feature one can think of ;) qtractor-0.5.11/PaxHeaders.10084/TRANSLATORS0000644000175000001440000000012312144775565016233 xustar000000000000000027 mtime=1368652661.100498 26 atime=1381134671.24508 30 ctime=1381134671.245080116 qtractor-0.5.11/TRANSLATORS0000644000175000001440000000052312144775565015522 0ustar00rncbcusers00000000000000Czech (cs) Pavel Fric German (de) Guido Scholz French (fr) Yann Collette Italian (it) Massimo Callegari Japanese (ja) Takashi Sakamoto Russian (ru) Alexandre Prokoudine