From 9e8020719cf0b0a714e714eb0fa8ebff5e262bc5 Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Thu, 10 Dec 2015 02:53:27 +0100 Subject: [PATCH 01/90] Recovery file fixes --- include/MainWindow.h | 30 +++++++++- src/core/main.cpp | 121 ++++++++++++++++++++++++++++++++++++++--- src/gui/MainWindow.cpp | 90 ++++++++++++++++++++++++++---- 3 files changed, 219 insertions(+), 22 deletions(-) diff --git a/include/MainWindow.h b/include/MainWindow.h index 65fa83ea5b3..31089f9edaf 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -81,6 +81,29 @@ class MainWindow : public QMainWindow /// bool mayChangeProject(bool stopPlayback); + void autoSaveTimerStart() + { + m_autoSaveTimer.start( 1000 * 60 ); // 1 minute + } + + enum SessionState + { + Normal, + Recover, + Limited, + }; + + void setSession( SessionState session ) + { + m_session = session; + } + + SessionState getSession() + { + return m_session; + } + + void sessionCleanup(); void clearKeyModifiers(); @@ -131,6 +154,8 @@ public slots: void undo(); void redo(); + void autoSave(); + void runAutoSave(); protected: virtual void closeEvent( QCloseEvent * _ce ); @@ -150,7 +175,6 @@ public slots: void toggleWindow( QWidget *window, bool forceShow = false ); void refocus(); - QMdiArea * m_workspace; QWidget * m_toolBar; @@ -187,6 +211,8 @@ public slots: ToolButton * m_metronomeToggle; + SessionState m_session; + private slots: void browseHelp(); void fillTemplatesMenu(); @@ -198,8 +224,6 @@ private slots: void onToggleMetronome(); - void autoSave(); - signals: void periodicUpdate(); void initProgress(const QString &msg); diff --git a/src/core/main.cpp b/src/core/main.cpp index 6351b906201..fb3598c4de2 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #ifdef LMMS_BUILD_WIN32 @@ -61,6 +62,7 @@ #include "MemoryManager.h" #include "ConfigManager.h" #include "NotePlayHandle.h" +#include "embed.h" #include "Engine.h" #include "GuiApplication.h" #include "ImportFilter.h" @@ -644,13 +646,102 @@ int main( int argc, char * * argv ) // recover a file? QString recoveryFile = ConfigManager::inst()->recoveryFile(); - if( QFileInfo(recoveryFile).exists() && - QMessageBox::question( gui->mainWindow(), MainWindow::tr( "Project recovery" ), - MainWindow::tr( "It looks like the last session did not end properly. " - "Do you want to recover the project of this session?" ), - QMessageBox::Yes | QMessageBox::No ) == QMessageBox::Yes ) - { - fileToLoad = recoveryFile; + bool recoveryFilePresent = QFileInfo( recoveryFile ).exists() && + QFileInfo( recoveryFile ).isFile(); + bool autoSaveEnabled = + ConfigManager::inst()->value( "ui", "enableautosave" ).toInt(); + if( recoveryFilePresent ) + { + QMessageBox mb; + mb.setWindowTitle( MainWindow::tr( "Project recovery" ) ); + mb.setText( QString( + "" + "

%1

" + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + "
%2%3
%4%5
%6%7
%8%9
" + "" ).arg( + MainWindow::tr( "There is a recovery file present. " + "It looks like the last session did not end " + "properly or another instance of LMMS is " + "already running. Do you want to recover the " + "project of this session?" ), + MainWindow::tr( "Recover" ), + MainWindow::tr( "Recover the file. Please don't run " + "multiple instances of LMMS when you do this." ), + MainWindow::tr( "Ignore" ), + MainWindow::tr( "Launch LMMS as usual but with " + "automatic backup disabled to prevent the " + "present recover file from being overwritten." ), + MainWindow::tr( "Discard" ), + MainWindow::tr( "Launch a default session and delete " + "the restored files. This is not reversible." ), + MainWindow::tr( "Quit" ), + MainWindow::tr( "Shut down LMMS with no further action." ) + ) ); + + mb.setIcon( QMessageBox::Warning ); + mb.setWindowIcon( embed::getIconPixmap( "icon" ) ); + + mb.setStandardButtons( QMessageBox::Ok | + QMessageBox::Discard ); + + mb.setButtonText( QMessageBox::Ok, + MainWindow::tr( "Recover" ) ); + + QAbstractButton * recover; + QAbstractButton * discard; + QPushButton * ignore; + QPushButton * exit; + + recover = mb.QMessageBox::button( QMessageBox::Ok ); + discard = mb.QMessageBox::button( QMessageBox::Discard ); + ignore = mb.addButton( MainWindow::tr( "Ignore" ), + QMessageBox::NoRole ); + ignore->setIcon( embed::getIconPixmap( "no_entry" ) ); + exit = mb.addButton( MainWindow::tr( "Exit" ), + QMessageBox::RejectRole ); + exit->setIcon( embed::getIconPixmap( "exit" ) ); + + mb.setDefaultButton( QMessageBox::Ok ); + mb.setEscapeButton( exit ); + + mb.exec(); + if( mb.clickedButton() == discard ) + { + gui->mainWindow()->sessionCleanup(); + } + else if( mb.clickedButton() == recover ) // ::Recover + { + fileToLoad = recoveryFile; + gui->mainWindow()->setSession( MainWindow::SessionState::Recover ); + } + else if( mb.clickedButton() == ignore ) + { + if( autoSaveEnabled ) + { + gui->mainWindow()->setSession( MainWindow::SessionState::Limited ); + } + } + else // Exit + { + return 0; + } } // we try to load given file @@ -689,10 +780,13 @@ int main( int argc, char * * argv ) { // If enabled, open last project if there is one. Else, create - // a new one. + // a new one. Also skip recently opened file if limited session to + // lower the chance of opening an already opened file. if( ConfigManager::inst()-> value( "app", "openlastproject" ).toInt() && - !ConfigManager::inst()->recentlyOpenedProjects().isEmpty() ) + !ConfigManager::inst()->recentlyOpenedProjects().isEmpty() && + gui->mainWindow()->getSession() + != MainWindow::SessionState::Limited ) { QString f = ConfigManager::inst()-> recentlyOpenedProjects().first(); @@ -720,6 +814,15 @@ int main( int argc, char * * argv ) gui->mainWindow()->showMaximized(); } } + // Finally we start the auto save timer and also trigger the + // autosave one time as recover.mmp is a signal to possible other + // instances of LMMS. + if( autoSaveEnabled && + gui->mainWindow()->getSession() != MainWindow::SessionState::Limited ) + { + gui->mainWindow()->runAutoSave(); + gui->mainWindow()->autoSaveTimerStart(); + } } const int ret = app->exec(); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 97f30a1ad2d..41cf2112a20 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -79,7 +80,8 @@ MainWindow::MainWindow() : m_toolsMenu( NULL ), m_autoSaveTimer( this ), m_viewMenu( NULL ), - m_metronomeToggle( 0 ) + m_metronomeToggle( 0 ), + m_session( Normal ) { setAttribute( Qt::WA_DeleteOnClose ); @@ -201,7 +203,10 @@ MainWindow::MainWindow() : { // connect auto save connect(&m_autoSaveTimer, SIGNAL(timeout()), this, SLOT(autoSave())); - m_autoSaveTimer.start(1000 * 60); // 1 minute + // The auto save function mustn't run until there is a project + // to save or it will run over recover.mmp if you hesitate at the + // recover messagebox for a minute. It is now started in main. + // See autoSaveTimerStart() in MainWindow.h } connect( Engine::getSong(), SIGNAL( playbackStateChanged() ), @@ -650,6 +655,14 @@ void MainWindow::resetWindowTitle() { title += '*'; } + if( getSession() == Recover ) + { + title += " - " + tr( "Recover session. Please save your work!" ); + } + if( getSession() == Limited ) + { + title += " - " + tr( "Automatic backup disabled. Remember to save your work!" ); + } setWindowTitle( title + " - " + tr( "LMMS %1" ).arg( LMMS_VERSION ) ); } @@ -659,17 +672,31 @@ void MainWindow::resetWindowTitle() bool MainWindow::mayChangeProject(bool stopPlayback) { if( stopPlayback ) + { Engine::getSong()->stop(); + } - if( !Engine::getSong()->isModified() ) + if( !Engine::getSong()->isModified() && getSession() != Recover ) { return( true ); } - QMessageBox mb( tr( "Project not saved" ), - tr( "The current project was modified since " + // Separate message strings for modified and recovered files + QString messageTitleRecovered = tr( "Recovered project not saved" ); + QString messageRecovered = tr( "This project was recovered from the " + "previous session. It is currently " + "unsaved and will be lost if you don't " + "save it. Do you want to save it now?" ); + + QString messageTitleUnsaved = tr( "Project not saved" ); + QString messageUnsaved = tr( "The current project was modified since " "last saving. Do you want to save it " - "now?" ), + "now?" ); + + QMessageBox mb( ( getSession() == Recover ? + messageTitleRecovered : messageTitleUnsaved ), + ( getSession() == Recover ? + messageRecovered : messageUnsaved ), QMessageBox::Question, QMessageBox::Save, QMessageBox::Discard, @@ -683,6 +710,10 @@ bool MainWindow::mayChangeProject(bool stopPlayback) } else if( answer == QMessageBox::Discard ) { + if( getSession() == Recover ) + { + sessionCleanup(); + } return( true ); } @@ -789,6 +820,7 @@ void MainWindow::createNewProject() { Engine::getSong()->createNewProject(); } + runAutoSave(); } @@ -807,6 +839,7 @@ void MainWindow::createNewProjectFromTemplate( QAction * _idx ) Engine::getSong()->createNewProjectFromTemplate( dirBase + _idx->text() + ".mpt" ); } + runAutoSave(); } @@ -831,6 +864,7 @@ void MainWindow::openProject() setCursor( Qt::ArrowCursor ); } } + runAutoSave(); } @@ -874,6 +908,7 @@ void MainWindow::openRecentlyOpenedProject( QAction * _action ) ConfigManager::inst()->addRecentlyOpenedProject( f ); setCursor( Qt::ArrowCursor ); } + runAutoSave(); } @@ -888,6 +923,10 @@ bool MainWindow::saveProject() else { Engine::getSong()->guiSaveProject(); + if( getSession() == Recover ) + { + sessionCleanup(); + } } return( true ); } @@ -919,8 +958,11 @@ bool MainWindow::saveProjectAs() { fname += ".mpt"; } - Engine::getSong()->guiSaveProjectAs( - fname ); + Engine::getSong()->guiSaveProjectAs( fname ); + if( getSession() == Recover ) + { + sessionCleanup(); + } return( true ); } return( false ); @@ -1189,6 +1231,8 @@ void MainWindow::updateViewMenu() } + + void MainWindow::updateConfig( QAction * _who ) { QString tag = _who->data().toString(); @@ -1306,8 +1350,12 @@ void MainWindow::closeEvent( QCloseEvent * _ce ) if( mayChangeProject(true) ) { // delete recovery file - QFile::remove(ConfigManager::inst()->recoveryFile()); - _ce->accept(); + if( ConfigManager::inst()->value( "ui", "enableautosave" ).toInt() + && getSession() != Limited ) + { + sessionCleanup(); + _ce->accept(); + } } else { @@ -1318,6 +1366,16 @@ void MainWindow::closeEvent( QCloseEvent * _ce ) +void MainWindow::sessionCleanup() +{ + // delete recover session files + QFile::remove( ConfigManager::inst()->recoveryFile() ); + setSession( Normal ); +} + + + + void MainWindow::focusOutEvent( QFocusEvent * _fe ) { // when loosing focus we do not receive key-(release!)-events anymore, @@ -1459,3 +1517,15 @@ void MainWindow::autoSave() QTimer::singleShot( 10*1000, this, SLOT( autoSave() ) ); } } + + +// For the occasional auto save action that isn't run +// from the timer where we need to do extra tests. +void MainWindow::runAutoSave() +{ + if( ConfigManager::inst()->value( "ui", "enableautosave" ).toInt() && + getSession() != Limited ) + { + autoSave(); + } +} From cfa1818ba52f231eb50fd7133eb292fc30c23405 Mon Sep 17 00:00:00 2001 From: LocoMatt Date: Tue, 26 Jan 2016 23:53:03 +0100 Subject: [PATCH 02/90] Triple Oscillator GUI redesign --- data/themes/default/style.css | 4 ++-- plugins/triple_oscillator/am_active.png | Bin 989 -> 193 bytes plugins/triple_oscillator/am_inactive.png | Bin 837 -> 175 bytes plugins/triple_oscillator/artwork.png | Bin 47649 -> 20651 bytes .../triple_oscillator/exp_shape_active.png | Bin 548 -> 383 bytes .../triple_oscillator/exp_shape_inactive.png | Bin 503 -> 382 bytes plugins/triple_oscillator/fm_active.png | Bin 932 -> 189 bytes plugins/triple_oscillator/fm_inactive.png | Bin 773 -> 177 bytes plugins/triple_oscillator/logo.png | Bin 7930 -> 3827 bytes plugins/triple_oscillator/mix_active.png | Bin 1019 -> 198 bytes plugins/triple_oscillator/mix_inactive.png | Bin 879 -> 181 bytes .../moog_saw_shape_active.png | Bin 561 -> 372 bytes .../moog_saw_shape_inactive.png | Bin 504 -> 370 bytes plugins/triple_oscillator/pm_active.png | Bin 952 -> 198 bytes plugins/triple_oscillator/pm_inactive.png | Bin 802 -> 180 bytes .../triple_oscillator/saw_shape_active.png | Bin 543 -> 342 bytes .../triple_oscillator/saw_shape_inactive.png | Bin 498 -> 357 bytes .../triple_oscillator/sin_shape_active.png | Bin 581 -> 441 bytes .../triple_oscillator/sin_shape_inactive.png | Bin 538 -> 442 bytes .../triple_oscillator/square_shape_active.png | Bin 469 -> 206 bytes .../square_shape_inactive.png | Bin 426 -> 210 bytes plugins/triple_oscillator/sync_active.png | Bin 1198 -> 217 bytes plugins/triple_oscillator/sync_inactive.png | Bin 1066 -> 198 bytes .../triangle_shape_active.png | Bin 585 -> 370 bytes .../triangle_shape_inactive.png | Bin 540 -> 358 bytes .../triple_oscillator/usr_shape_active.png | Bin 546 -> 166 bytes .../triple_oscillator/usr_shape_inactive.png | Bin 501 -> 193 bytes .../white_noise_shape_active.png | Bin 588 -> 488 bytes .../white_noise_shape_inactive.png | Bin 564 -> 496 bytes 29 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 1516dece1b0..0e874a66233 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -543,8 +543,8 @@ BBTCOView { /* Plugins */ TripleOscillatorView Knob { - color: rgb(1, 32, 64); - qproperty-outerColor: rgb(0, 0, 0); + color: rgb(255, 255, 255); + qproperty-outerColor: rgb(255, 255, 255); qproperty-innerRadius: 2; qproperty-outerRadius: 7; qproperty-centerPointX: 13.0; diff --git a/plugins/triple_oscillator/am_active.png b/plugins/triple_oscillator/am_active.png index 7ba7f546cd146ea5ed1c05eb6371214bc275464a..83ca33ed8bdac26cac1191b621f46d48a20a9940 100644 GIT binary patch delta 159 zcmcc1evom3R{ehlAY8C_`D6wL2F?PH$YKTt-s>RD=%g{b0w~B{;_2(kexHLwL`J#Q z-Qhb>$j{ToF~s6@a!NwNheQdLhR#HRM#rZTVnHJR|NpNy-X)=|yjWkaa8^4Hh{2P* zd5(VrU|89ZJ6T-G@y GGywo(t2zb% delta 961 zcmV;y13vu00o@0XDt|Wsz5woGFvE-h000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k+77aUk`ps(q000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0009; zNkljhq!Ekec4yX|Q z3P2CiMfA|%G2*es;((tYe2$06z3;zb$fRZ*Tdaxv^zaJ+R`#Cr&M)8M4$nURjI_AQ z;B22ePre2q$c#Y8jZ}DnT#Nv{2)!cxJp^1L0-UbDjemy-z{%^|b$`=;-d~foO&p=L z1JZbT{`YHY*T--znpq(TU{?JztNxmS2^49tE{nrA?=n9Am&LP(mgUMkBlYNhH6SHK#I7$$|>j(N4d#pbWy5iGO& z!9ynPn1A8q7;sAHL@$Zq$r+P{Rno!=nJ%q!zI>DRaF4lkS(ThK zIVDsT)%jdU&RUgGogosg*c&iu@Q`tXldbmw_Fx9+j>`wvhYg7+}-V3)J) z57FhWL z;eUh%JYWcuTkqB4{PRc3`2+;wYzp@u^Xjd;EdBR)|DC&IM=wDW@#H0WcHXZiO-RWV zB&FJC{IbtDj(qZH$Ct)y{n2&-2@T#3p=t3pc84#3SqB^XQ$opjjP*T!?R3p80BWNv z3K!>)Yx0*c&e`;++C*FW&gy`9!Ar(v2s#>Z9H+KtN8dH00000NkvXXu0mjfG8Dn+ diff --git a/plugins/triple_oscillator/am_inactive.png b/plugins/triple_oscillator/am_inactive.png index b3b9090b5b9fa154f93d94fc832e3db971946c60..b4f3d00844d39b540eda694739f37be8d1130ae4 100644 GIT binary patch delta 141 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 IM6N<$f&!8%ZvX%Q literal 47649 zcmXt91yCE`*9{OLP$am!YtbOZy|@*JVnu_yySo*)0>!PkyF+oOXmKyap?vxMXTHh4 z?99&Y?B?x#=iYnHNtCLxEIKMNDgXdL|0pM=4%@b=%Q zpsO?mb_B&yPS*thz!>;%z>PSRnZphuyM9!XM&5)Y#6Y3p#kar!04M<;rNlKo*Uq}U z8ow;-Qan80i5y}$lvQXK+2mO+Qhv%zPJ&K+wKJ(>#UhbQX>^MHm5A7ievBuPHKtgo z+h@KSgjfhS!pS)dnV}~mnS-z>YksZLEg{zYRN+)73mJl) z@$pcN&Eg#!qb10~XFQcXI@0l+{= zF@;7+7_W73cz7b9F*7MKa0$M@33GOBlLmmqGXi|yPV3&^zhQ8JuqbPGWxTxRjQJ$z zDP%>77Ch6jQ@p00WJTY%3T~wdrGjux>dFO!;nCp53BOrLZb+qmWeuj%$(kO;?%Dwu zPl16}*p8G{Qp;dkb!-t@_ajvot5hl|9s0fI;IM6x)^2L@=i#?Pq;dt1xVgeQsIu|K z3(iIE+O-Vr4@B`Jsc$q%DNtHxyOM@RP3d4t6Ddv1hK1QE6JSBgTY$Cwj2nPq--*v=NB>Q2{5IYEl8Yc-7xaN<+65aL*nE9 zQnDT8cf=lhWQ8K%+^_vNT|H6-iESFYJ|~_22b%+

2vaHIHA6)$LfUKG4zQ~9 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 FV1i2n;$Q#( diff --git a/plugins/triple_oscillator/exp_shape_inactive.png b/plugins/triple_oscillator/exp_shape_inactive.png index 15e4d58573a50d73e1c486338463c49d714c9892..b988ba617a919bc37e6a9d3d5ccbe064d61ed1c7 100644 GIT binary patch delta 368 zcmV-$0gwLo1O5V#7k>~41^@s6$yOx<00004b3#c}2nYxWduFXme#BZ=ud)o6N+svL-sq#>f1Viz&q&-kjva2qT00Rb4a4~K2ZN`# zWgf?mFCt$jB4}ytL~C)WgpO%W>v24O|K2bhj$g~=xu;axUCrfxKE?vU#!p@C4!D2- O00000PbQi!;FzJ7=H(JNliru z-UA307aE4XC++|M0fb3JK~yNuO_JYg6HySxf3w7ZCanryBv`P}%|+E$(2Mq6z0^mk zLaJU%*cvw=G|4tQ=bRZY&dJsThZ$!0zWMjbhpTIUbAHaKsz3xB+#Sf)%`kV&4ND0# zC&tL8Z5fFOFD9=L0T958rGNNf4!C79cg&oWB9$Wpa3Byk96G*y{=~yWM+Ld7LMj3= zS&k36V-o20dt!`qU03+zzpP-Es01)`%nY+*Td>{TGairG?(TEU4a4*NW~5|{05pWm zGCX0^t~oh<&Zb>6pS{K%+;ahNqLsFTDyoWVKvn7co~BtbpPzBptbb7L(V&D7%2#3x z1swVzs6n}Fejx(0*%>0xG%JEWf>i^a5|slX1bS6MP})ChmdhLJ#XD4$i~5q=!-!h$^pxQH?o^nxN^8NNJA{Eaj6Bdj2IF5Y0y7uYQ zm&2(Xf0T$Hh2pqNQ7>NJ_O|=W$N`?D0boTzW(l+7hHcn%_Vda90h$vu)xi$NMF0Q* M07*qoM6N<$f?`S6G5`Po diff --git a/plugins/triple_oscillator/fm_active.png b/plugins/triple_oscillator/fm_active.png index b225a42f087fa68673f4fd152bac4d49e69b6f3a..0744df817d08de36d8794c2d948fc4e2c4090881 100644 GIT binary patch delta 155 zcmZ3&zL#-=R{ehlAY8C_`D6wL2F?PH$YKTt-s>RD=%g{b0w~B{;_2(kexHLwL`~?U z!MrU%AumrC#}JFt$tej59}*>08afjN8XccXhy{uK|Np< delta 904 zcmV;319$wr0i*|zDt|Wsz5woGFvE-h000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k+77hz{4z2_M000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0009F zNkl}&2Jn<5XFDh(`)bgBTk492m$c{af2HY7Z5l{u7CUkApXBd9Jq4~h)aYJ z5+H<-OeC*ul8twF`lB9)o|%pCNUa%F_q=*t?^W3+=a2R1?2H%!m|++In1KZpI_lm5 z>S7B6$N_;1s~L3>4*_>aqQwLX9g^BgJt1wN7VwJDbl%;$S}uuZ#{I)n%v!4PEkJQb zoz3wOQ3zm-jDLBhWot`aq;?SmAgp8nyo+dvg^~$1)1@t{1;ddGU?5b9dX2#N9+SES zyo(S5&(6Q$|IcEz;9cbB&%OfS-t*si_m}UH;J1&zBpsfxw_5Vv(j@0J zu}0pYR40zW6OrAKrj*$fpKV_8)*nyX897}}cL?4-cz+XN)Y*)*I3Cd_j0OrQwCW7m z+$+%lcVQ+VUr8f?KSE6v?Y^c zYCgdo4L`}7jCHI`%9$_`w@E5jpmYg&D`0>0kY}HNJyqeIpT6Vx@=t0Qie3}@FIL;EugG?Wmf--4X5-5?APaco5-;Ww9%6Y<3*rQb~PloM7UScGlD_vZs7cy+8_x3MlzzD0Wr+%@^2Vfe0M0JTEDZlt_U eB*uN0_zwfh4O+^y<@5jm002ovPDHLkU;%=gf|wKl diff --git a/plugins/triple_oscillator/fm_inactive.png b/plugins/triple_oscillator/fm_inactive.png index e5a4c534cef8e6869b2fd918013c3b0b266492a5..0481adbd6a10f70665a6b77cd7aca2bcf66f3282 100644 GIT binary patch delta 143 zcmZo=+sHUUtNuR&5H8red@=(A180FpWHAE+?{yGnbkdkz0Tg5}@$_|Nzt6!TBFnto zD6kGFWasJP7-DfcIYENenZaPvq96Z(z>p^)CFO{!U-0zg%_5O9bJau*CO%du(p6@O p@aPMdVza-Tu}zZIS(1U_m%aQqC*KX#K$93aJYD@<);T3K0RT8OF1!E$ delta 743 zcmV_CX>@2HM@dakSAh-}0007Q zNklfjN5Qd-0Zgx|p+YhO#L@Sk*xb*-62>}NxXn#2%@ju}RRj=@K5FmA1 z&~7%3op?Cdak3vi#GbL0_nnz{M&4dt>Er2?VUmCdf&d`mcfW+-ZZ~x0qo^v*IaGtk zx#(Bt?*MPBqIB<_bIfjU8Hxx8`4Jvl;_eCc;a50$9z8<3aaOub;||~yz@e^t<6Of~ zdjukQ1nth(-+#WazIJ!_xccx3MYsv~$H$L&_4)!u`0@RQvRsnq6W+c5h^hce0=SrG zMFi@`F^oa?Gr}slHXGw{#`*cPNG453;XdYx`}-NHU~NTNF4?*S&;-Gufsk_zLjjyq zL=;F6!AFoN(ncaJc*@!INv}pe^H*$xj6B}GxNSbzK@&nFbcJb-nY@udnSa{eDp zn;Bzm1oXm{tr}V^=3IaM9BDj#_L9@nvsNA?g8`GheP**iEQW##|?002ovPDHLkV1h8*S$+Tj diff --git a/plugins/triple_oscillator/logo.png b/plugins/triple_oscillator/logo.png index b179c97c8ea47694f1f2de2e88b1527d5bc24eb4..e0bc17d4398db2aec4d7e93b82a2ae3e3ccdf990 100644 GIT binary patch delta 3821 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 MPgg&ebxsLQ033)qVgLXD delta 991 zcmV<510ejy0s9A#Dt|Wsz5woGFvE-h000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k+77i5p2BYx+000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000AH zNkl&!6vsd3&YS7Xv@jr$5{!b0*ae9igUCWn0Dq$~aplgX8~-_1tX#3t z=%V=Bs3cO2Hdv5OOQD_4yXW3>T--aaeR;Wg_nY(1`JP{2dFSRWzj)~qO$Zo{$wp@X#w{fRMBVU68}UGA;oCFU+dF6U^|O33>=QBh|(% z(>T%*5dlXaNJr$C8=nF&d9=Zczkh|ebMM;6#N`P~`%~8L-bQlb=l4D<_isLD@BC%{ ze*FW^{rMfM8{ZNKC-~#-PZ;lRacTWF4Y{TwfFlAa8-HPubyt~c)z8D^#Tw&;89 zMSu2`+ziqFkaj#_X|{VTykp*dV(z%X`FmgE1U9eSVDI@g&fQ<9KYN0kW0rBt7+zyL zIU5Z?RDUh3YKe?M(msoslN=fD?Xy3g5Qh`SyANqs&fxB-DnYe!ags*dq4#Wuv-j^Z zUAxZU>6DWjKcYDy+R}@2NEsp5gq>uSjK+9ufCckFZU%Tw+1(lL{L8`ebLjGE#?wuB z;R^00xGc!HqngTQnUm@i0dCONur@NVP0ci&K z(g<$`3mt?b6~INh^%2XsKs~@6&sMZ*p;&~KC;%yeB_z)Aq*e5sXS3bXCi=P43WFly zQE?d;{|ki$EL#;NFRvv)3Qk!+^WvkhFg%1#Cp>3}bI1v|s=yRU_#attXYKCc;~xM3 N002ovPDHLkV1oFp)qDT| diff --git a/plugins/triple_oscillator/mix_inactive.png b/plugins/triple_oscillator/mix_inactive.png index 67f9b9aed2a160d1269c2b2b9884927eda3d7a4f..1615f211c92a44f6d2928155abd197df1848b1a1 100644 GIT binary patch delta 147 zcmaFQwv};$R{ehlAY8C_`D6wL2F?PH$YKTt-s>RD=%g{b0w~B{;_2(kexHLwM8jeW zN7Wmkkdvp2V~EA+JPGbKDaVX~=emKB?P@AL$<&w8KF`rl;212m4o)78&qol`;+0Q#6T9smFU delta 850 zcmV-Y1FihE0q+KoDt|Wsz5woGFvE-h000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k+784Vj4q8qC000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0008l zNkl z-jyO~i~ynlf`3X;Ba&0q83GYJf*M}Fcn-jgn`>-sJptg&n-^SUL(;U)&eLB|46lBD z&Qe-ud;1xOe}CfLyFcl4Ho1HMA;ZCd-+y~ev$ew3))Nv868o$e1Cv}x;-Y6e!YnyI z`u!fDSZle+h9wD0f*QEJ-eF~BmHquaM%j>$AN~U1!GD8CUVa0Rl+Z+S5(7xkRAj0> z2pZZ63kx-zwPe|l{#lPStn zPzA8gc~;T5W$#of6&j5uy^~{x!vT#(i^1R=Ro|00@F{*}IZIO-kCI|bw)M|^Y zuXlWHFn@`v@xBROnn)nyti9wLlN4lBm3pH|@AQ~ama)8iJ?5>ms8GzUivZ490GxA- z#v|tD=F$H#_GID$88^n5V=r=pRO-3vS)+#JnB5!ZYd#s2a}C&-n8B zfY$OV{nHcn_CC<<-U(#PWm0)gRReRy1gXlqYJa-oh1w$Dzn=kcZT?!!J2#Hoyy#5M z?(Tak)hg|Fm&7ET93RnYu28Qxqon>4z>rUZOk-<3t}$2cBvmCzDpV>J=I0l16BqO2 zu`ShEYx(x=kc(`{+S&$ruB_hpiPO^)_7C>h+`J!D&{B64#XR2L(X`gO;*6QjHOh8* z=u6BhO)3YOoO(BqkAfa1oQ%s7k>~41^@s6$yOx<00004b3#c}2nYxWd`h8jXVTkr9cA!P*z!?F9!ST(btJ9k0!cLtbu{dE5@C<^~$DBr}v5M}(EA;uIn z1mQMMJjlwBVqf{2L0SMcW#~%%V^|pTonhBa7KUkuQKOC#mbO2BXJp{x{Lg?ZkbnJU zV0izHkwKgnVtDFaTZFUuIq|1OHf9F6Mhs_@11QoA0C)6A%CL%}t^fc407*qoM6N<$ Ef|oFw8~^|S delta 528 zcmV+r0`L9w0;7aR--1^@s6y+Y^Y00006VoOIv05<@>0PbQi!;FzJ7=H(JNliru z-UA3085R+XMoRzy0lrB@K~yNuJ(4|cR8b6tKi_wUkVI%A2o(Y%Bt$_KiC>8{A%Y?e z9qa(H50=0JsHj;00?|^zG=M}A22g+*LBb3n?_U2C?Q?wWW7*ie9p~59$SHvc z1b76b29F@zi3r>(VTOC4s(*|}BeICFvb>52fDiVVQ$lD{rdZ%+5;;?9Y|Yg8bW7EL|QJbO&-pJsf0o5kUKmfyW3 zBw;Sy&ZQLotZ%XK_GuNhwAAT@a(IC4{X{3fiSIkCJb%)u+kQl8D-g)W*4b#`W< zAcs>#D>8eI0LTrVk9RTMwWq(nk;4_Kdq;*_C?SEn;SLdwRVUcT1AO+bVak6J=OA#W S(Bvin0000~41^@s6$yOx<00004b3#c}2nYxWdkeZtEkBJh;#q{_whM5je&uIfr;sVG6TcE1E!{i9(XmwoXgJ6lu}>M@SlN!f#LM&^YfXR z83OoO_4OdB=`jeCFt=VE^Zjuo$v90PbQi!;FzJ7=H(JNliru z-UA307b32_pKt&G0fk9KK~yNuO_IH9ltB>2fBSNZ@hlWBA{vs@LWPK8VR?cVZ2Ti_ zwY4)=n!+l0m=98*NX1EzSJ2`?8fSV1p_x5&~&0b>e&3`U%w`N*33xb@z zB3DG`$kW%9yhd#{ORKdew=@A>>M*kr7#lU?ktz5Bw%{?KJE@AB=KVYii_XB zI6hi1ncQS^>mCx6+%)%Qd|RG!dt-`OPv0A6eS5~`D{DM{@{F7_`}?2idqarye7>V= zYc~eXLjO)gt3we|YA}~q-M;wqv(n~L83v-65>bc%DTs&`)$;mfe*u&~D1%L45Ay&3 N002ovPDHLkV1k8!(ANL} diff --git a/plugins/triple_oscillator/pm_active.png b/plugins/triple_oscillator/pm_active.png index 1371792c0f4886c6b2be57ff56f34f9242a47afc..efe38b878e56e18323fd90ec9a99a81a19a1c669 100644 GIT binary patch delta 164 zcmdnNevEN~R{ehlAY8C_`D6wL2F?PH$YKTt-s>RD=%g{b0w~B{;_2(kexHLw*hn=g z=T|mRDA?1*F~s6@a!NwNheQdLhR#HR#)YqE{Qv(y-|g6mM=xHz5HjlN>Dgz{bJp>R zRZAlfw1)8R&}p{hyF1aOlt)>4vA$)IvmT>ypX@Ya=YxjLTnr3zqx2PHb)sGZ&1dj* L^>bP0l+XkK%UeAM delta 924 zcmV;N17rNg0k{W{Dt|Wsz5woGFvE-h000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k+77Z}%C=}xW000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0009Z zNklOK%)S6otQA-8~OK$(mrTC!@nhaS($s@2_AxnZcr`7kI>Y)qG5PL~9Cofoj z^kv=C#jCZw%ZPcVEF+duRR&Qn2aJ+?o0c*5f>y23`d6bq&^&TJEsu|0f@42N>!I`4tcPLL(X{F`t4nJ@LmUDMkkHg6+l7u5>H=O_WK+h!n#`aoi9^> zLXMs;jv*GOlM^IZ5A*(UXFl=h#j6*OByws}jxV&HB67fKWphHq#EBC>{s)3YlUSL< qCr+I3=#w#Q$TU&!XxvX delta 772 zcmV+f1N;260ip(wDt|Wsz5woGFvE-h000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k+77{bLdrQXv000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0007t zNklt zCM|`Q*V23YW?bC&w}rRpy?1(Z=gc{0MxGxW+V;*4^(X=n1OY%Ktl<;VaJFETAH&R0 zRm{?eY92QY{{i7_hEd#CRr|fNI7)zQVQ&QFpduB?G9Q~6-g}0_Q@nSquCC#n%fZxYH9Bh> z^n3q^<8wM|>%{R0Gw|MnYHIahk|3Gp1CGEJQeNqt2somB1wGh^zem8K~97c)boMy*z( zvDC!-Ssr(Odd2K1&W0f`4i0T~xqB%a;b6IJi=UOMEIRM9K{qc;HD-*)gCG-)BnO}w z(o|d0(VY>ji55T%EcHT?Xzq*fhR!i)i~CYc&G-*O?y>2-5Q!210000~41^@s6$yOx<00004b3#c}2nYxWdXG(A#ThV#p>+a zubCK%)^jif>HTI%wD^tFWf+?AjTo92oMdHKdy$o4YRC@; zHL-tqHKJ&qc0rhp;q)VBhK14C{f7-O!qWE3&x{O$T>lx^n2FNIkh<3vVY4_d>G@;e aG6nz-lsxSSy!a{r00000PbQi!;FzJ7=H(JNliru z-UA307%NctI~xE10jxkUyOF=7)iO$_M-Q4~z0;!o`( zDEKJ0V(SA~S}6De+SrSN=@j#)A)*HE*)y{&&h=uosx{xttYup_Z|TC?8nqNK1A!!9 zP-PMl31lXj!rl44w@WoM&VMYfUYAy=P?w+GbuB~f8-gnRAM~A#|x+!+t(fdF!}WZFfxN`K&CJgP!K}ak)w(v z_SP=3yK$ZMw=YPH0{yD{z!DQT?{K3jX*_Z&QY z!t%>!)WaQGCdGT?4Oc@XhJfY`NyC{4+q!*Mi_5F?sMMwu?;&I8%kY0xPmtXN5ShvE z!>?4OWBzjO1+gU?Nu62hQ2+n{07*qoM6N<$g4R3X A!~g&Q diff --git a/plugins/triple_oscillator/saw_shape_inactive.png b/plugins/triple_oscillator/saw_shape_inactive.png index 3c03438577e9db324a5b9db129563e197003b427..3d0d87b658dc5ca8d76464a22b2faf4efa34bc76 100644 GIT binary patch delta 343 zcmV-d0jU1+1LXpc7k>~41^@s6$yOx<00004b3#c}2nYxWdkeZtEkBJ=LbDhc7*v^=nJxbQ{renQ9;dS{EOf*^eG=Nsz`(%B$M??h)Tz@i z(bZtJ+1%Vv@6R8`4Gatnv(KJA*N)2q49zAc2L22T3^N!Q7&6bEJ+}d;pU^c!116oB z`JczBQ|B+@(@=<_+1S{qnSp`9iJ6(%^30PbQi!;FzJ7=H(JNliru z-UA307X*B<8jSz|0e?wEK~yNuRg$r5ltB>1fAjHKNOC5^VZg?8DI$nMuu+RdOABrN z`)n2LL_0+bPXcF*O?n|YauGrJc6R4k?A~W=c81w~Z|3bhd$@m~Tie_8T?b|$kOb7I z2tpzhL@7jwoHL8FGkP;)bAN4$8Gr$5k(NUUP*gIB2vJI=6E*@z0^<@HbO2_2oqgu@ ztCyHTE>Y|4ZhX8tFO$7{`v!o?WCJiF3cUdl!c47)kPIvUIQn+T_oG7|KY5A}=jRI| zf>MGWAi2}6WUjg*j*sUEc=r4S5-gVsB$2a|qk%o8|32*3#gh4a#(#~io9yiD;+_aW z&KXI#Cvx@%_5rgh|K#Kcr>8%;y?c*q8=H7asI6@UPRUUz^a9)+Va&dKU^?AmZ|?zM zq?GEq1VUtYq`*BPDl(xLI``bf1vfN*GJ7l z|16>vv~Hl1iHP9$pDJY?n=54mL~~F?Ap)czB3e|-MM(SweX9)QT{GCa00000NkvXX Hu0mjfVO+@M diff --git a/plugins/triple_oscillator/sin_shape_active.png b/plugins/triple_oscillator/sin_shape_active.png index 610fad0dc1d3d5c919dd34fa9062aaa20ec3b77f..f30306f68f408d4e81317888942ecc36738650de 100644 GIT binary patch delta 428 zcmV;d0aO0P1i1r{7k>~41^@s6$yOx<00004b3#c}2nYxWd6b3iI7)PtOydjZW0qU#s+2U z$(MPJ(E&-wTYoR?c38xQB)89^z3hiKL9kzSEYK&(y{LaT8$@UTbK^DEX3I(<v4E}JXa)nU z%#>L@bP|u4q_1@rCad&1?a3|Sc*JDbQzCt%vpHWS>Lph<))EE?`y^rC&tCuEVSEC1 W?Nw(WSr!EV00000PbQi!;FzJ7=H(JNliru z-UA307!cv}(mwzI0n$lCK~yNuMUp{lQ&A9wzq#)vu{ALiC2nk!x)BU0x)fZf8~6SN z|CE10Tq}qhcPiS7U38(fsECHNw$SF~-FN5CxOf#AW_i9d%sF!R{sZ5bOel*I4*?w9 z9RMst&X_yqhUJWzqpBRt=YNzU!mvNWx;?Du0uBfOg+_`LTbLW}j=N*#xJb*z5dqCcAOx%^iTyQZo42_3<{4MFp7VWr4~l@5 z9T1@%&aM*7GC>f`VK%wRXm5+6t~hr*XXWI8<4a>Sl$Z$F9TjPpe}B$EN{N$;>kPi_ zV6h^n$lCr#=2xzhG!fN^F4R&|byjIY2SxsiCoi6mmlawq&}BvU*H@aA3sk)UjXTld zWO$h$cOH?nK{Zigik}`K5^x|{hN2)N4EDA;TA#A^X9k`*p4?z{e}~j4o^$K0v8Jh) zXk4OAgT_d%m-N1DbA39V61yubh9m0HnC|EIq^2forUZyh(|%F}+;IfVG0U9)@RHfX z$KcN3^;5K}pjv=sN^v7K32D`wNpV#yJH_rhhP!WZZ^0TXyj~zUr2};GS%$P#G$&ie msu~wCGu#a`$5g@E%KimtO)s6DY~41^@s6$yOx<00004b3#c}2nYxWdA;u-?CVdk86G?@G1G3d zWtvhdmFkaUH#<(^u+^dw1hUiVaAn)c)3IRBTbkBdjzxOwO4au*%UT6?T{p2Z67F`V z;=oh2dUp>{E`Q&=1IqXH;z&3M^qh!1hYb;4Ko-KgY}Pi1;A-{u!nR3=4Xt?q?C?%0 z&K)OyFaQJOa>@?}V==kbS~dm`>UqPE*CF_;ibd4~K2oWq2jIGEv%qpR>Z^Xn{0Rn# zL^$$&E^RxR2ew7ztWapYjcf*}RO)%lVpBvn4WqYLt0t+Fu>Wf_K)GCR0FCdw|9gy2 X{zGFD7yD>Q00000NkvXXu0mjf*_XHw delta 505 zcmV0PbQi!;FzJ7=H(JNliru z-UA307A#O7gEjyF0jEhsK~yNuMUu;FQ&A9yzqwq&2WauuguYCD6x4-#1qrl>f*b#1 zH(F4-@lg|sk5;5KCZSOp;m({hN&PEET$lKG!F+^ix@}K=Nf9;ti z6-w9ZG7DQuB_=#D*?d6a*xfr4lhVES3oW;hj5RbneBq!1hk?_-!_Rsh1wwByEEG7t la%O;pfdNm~3MF<127Xn6VAt1Yih$-ac)I$ztaD0e0s!&LJthDE delta 436 zcmV;l0ZabQ0o4PL7aR--1^@s6y+Y^Y00006VoOIv05<@>0PbQi!;FzJ7=H(JNliru z-UA307&bHhSHb`Q0b)r+K~yNuZIZifRzVPjzqxm9>(28WPIm!2=@9H65eFAb9Nqk&atP@p6lL&hpg)gW+0FR%&00tnMAj!N``F3%=rHD?X9JczkFc9j$45+gREx! z`|!!vk4O^)P^HKEEe7$F~i4Co=cqAj0tsqQs9^?|+CYvWh_^y8I2c z01%z94l-iiBdFS0uG!GDP}RQnc8xF=0|_*s_Q{a}%PB(OvtedXx&L`{pB&n(R*62H zJp6op{-1pAKJ_;>;c=8l2wJo|cRrmTjUw6ZJdxd?VhG@*xbas@bO(KTP0OY&yN}N5 eZq$V`_zT8%6pn3d6%G3U0000N&PEET$lue&F+^ix@}K|n8z(mM zOqez6Q-7ySuYp0qtjGkO0PbQi!;FzJ7=H(JNliru z-UA307Z2-W!vz2U0XIoRK~yNuZIV4s1ThRopGQMQLqX480y=~QEwqTGL>voIvRi{h z2?ts(Fm~dPBAMBhAW~u%{(1HnyS%>9*=of&3}6NVNkFs8BqdTw)=H)*rSP-cF`5}C z$ETP97@%(HKBNF;D<+XCYJV+^!Z3sF=9T}>!}^H<$W8^q3`$ML!@%|9Gm;jH&D%?( zFkxy`>QtGP(SXd3*Z7bOEIYC=L`rD3nbf(nM*t8pbq2%wyb%r(5=gl;D47fZ;m+;d zJ???Kw>uYfC&KY?B7%?iEfG#B(K<&=m<@fu^HjDZi@kgR?tyA$6k!k%2xBmiIFJoI zylLN_Wt3X_%#(WywVvJO1Ni>>{3G8qIYNx4Bs`XGdu%wrxauFJDbUbGgkz{-b5xgv m>^~^8k~wcUmrXanN%jlfECkJNZaq{00000RD=%g{b0w~B{;_2(kexHLwMBUKK z=UzKdD9zKwF~s8Z+bMxu4F){U!XGQ%ZLv=HBh_=^kjN3PXT~M3qodpy*t;^E6{j}c zR1OX*?@yV0#dF)vydROZPvVla i3;e5p#%-{)gz42z)8(e@SEPVeGI+ZBxvX#_CX>@2HM@dakSAh-}000CQ zNkl3rWg=Y3s#!@%N8PM+kP{J!^j&U4I#OIP&h*aShY z0}VqA1^{CWsA5!50$MVGcrXEC3@8v76hIYG#iUInj8G9WS-@I+5P}I%)$Bu2@4%*L znowO|BQm)>-G4p9NStdyfYI!5V*oNJOtv(Dz9a+0glG`7fFN`UVuEZ>3lf#qo=j6w zKu}eT2*z1NJdwr)B+emW%=*}Ab`Fh^<_qMSb-G_XV|eKvdxLMVGJTmNbGH~Q&jYaZ z_9b?T$2sxGcRV`(8Hg}>_Xl$I9Rji3zxoyVy(*J;zJEncNLuKoGI5SZe-XvdRb8d{ z@HTN$gDA$SAs`6A7%Jl*uyO1Z2R8rX=-e%OUaU|Zoo0FZG6QQ%bksIkJAMWYW13xk z>Rvmfm!|4Zr|#yj$rWlEJLR6I^RPJ{^Wa7jYf;w(p>FVY+;k@OYW8yRP7bef&# z^Bn%`CzOD}N58Rp?o(7ey-#Ma)}rQRPL=K__t+{;u{k{64zG2t6mEeo9388VNmGkK!36EA>Cyy5+JF6{s`#`?Zs|VZ*hze@*n+Wi&fTFtc8coR zPdM=4HX6n>CQoC$$84QzhZ3@qp!iB z*rbV~yyg>WGeIMvYvv}qSH3`1u}K2HM$eC5(>QaL`qVkp7~=9Gop*2G_8Xa1D1YYS zwU4!{rwCEpZZ!iChO{fr*=!xfudb{rcneYd3Q7eqNR-Qv6^zR!s9A$%no4_`h=(*` zZ+DGIoyBMaLmmwy1e1l!w*bU}ZK5J*zJPdnNrOq6NSx1l!b=7t9*OhWGXNkCbr!-H m+D+YRV(-Bws7+C4`5!{BZ)`$A_zfZe0000RD=%g{b0w~B{;_2(kexHLwL{00a zk(w4zDA?1*F~s8Z+X;qT3<^BVyg&ZyA780p+SID!l;6|tYwh-#F+kB%PKjX>OT*pn zKhIY0xe`!2>3*5|?^BhD`^36>ue8RTFsckFb+E9(nQD3Mza`6W6abpf N;OXk;vd$@?2>^Y!Jx>4t delta 1039 zcmV+q1n~RD0jda)Dt|Wsz5woGFvE-h000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^k+77{Am5aR~`000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000A$ zNklsTQyq6885UtaDU-A{ZGB^c%^l8?5EaY zm?=<=P#Pop>&c|qyyWSVpQzUl$Y%58r{_36s`32UV~jC=wyZ~30oDqqr^f)y z6y`}JlH~FQhKEP6)}lg+yZ4Ix`RW){^+PI^e@Umaff#Eo zrP2nT=YLTwE;5;!0w6XLXM3weqj5$eF^cC|!T{PBCMI&6ot^OHw;zc{VR2H@7M2+8C)>uW1GPBLg#ZA=ho!bzfy0TB}M z6rbE5MFfn|v}{|9(VB_L90@1M$#I=VXSjooS)zh{hb+1~z#o$?k=a*V?40-r5@ zNhs9E@$nH_8;sVBj5zHq4AI{|fHoTKnt)h^Lgc1qc(+}mbFYkP5s5?rsMo3(qcO&C zP=BrP^2M*zYE_Iei02U&z!<~j8W;&ca`dhcQ?Y5O5=J`$7zQCKX!612M(|>m;e9(00>D% JPDHLkV1n`*=(hj> diff --git a/plugins/triple_oscillator/triangle_shape_active.png b/plugins/triple_oscillator/triangle_shape_active.png index e2888ac64568bbfc95a5898bcfbeb920ce7b6e59..1f89f58027f8cfbd148eea1a68e5261dfd7519f4 100644 GIT binary patch delta 356 zcmV-q0h|8G1o8rq7k>~41^@s6$yOx<00004b3#c}2nYxWd7@bcE8;=Wtd8T=I}h9+DN^ zFKeAxV0Rp_krf+Ru{#dv8b=HM{R;tDOllUBx}m*=OCwM^W;?$j00C_0H1(>rI6c`n=Qn6<1JCT)9$iDfM-_Bw9p z;|&8MNstG*!eX800000PbQi!;FzJ7=H(JNliru z-UA307#nsW3%39O0oF-GK~yNuJ(0~zRB;%EpZ9)@;8=X zx}cy{P*5R(ZL$LUfJ7uyCkxV$mSGbIb;97F^!Ch)wV zzi@}mwa1*yUM7kbUX%nfE)!65GR`94d5IMz!|pu&t4s7YU$C>ZicYlgvJF{&S|GR^ znE>X2AvAdl&0Fj&u5#t`D=r-TV0P~tKX0z!1X`3h;O^Mja;-)Rp?}eu-CHY6|N744 z{x+5>E^e(;b-MhSyGC+I7Bs4;`}lM6AUPaexap_nCY56st$*;20eZvEeatw9oX{4Gx#rXjDlqga=swjVcFs zA2IXcCHy_asuOfn(SM|bRs(EQ(fRZSD_Z>P-A1*+%qalsx~AOyLbTF!lBcqwCA$sRn{VT+yncz5WaZXcA(I01*H|P!o;eg8{9*ZPa}XM>yig=fVvq rBycy}A;NKYygtEWtSKT0GyVf$6E`;qF3xQL0000~41^@s6$yOx<00004b3#c}2nYxWdtJ%@{ADmgJd~zut#u~UVp&JJ2+M9;yIjaz~_)w zYOJDyga7pS^F9J!2oeFp7nx2c7xoR<?Gl)C{gxh)43TpErE}4EoKx1)xuw@yOA&N23reD0GjW1$CD4cj^=Ks0}jI~ qQR=Yv!6r%_)?rvB?GFF*V_X4zwo}Uf)jkIR00000PbQi!;FzJ7=H(JNliru z-UA307B;PYdQ1QS0jWtuK~yNuMUqQvQ&AAdf9H}IqhgA-_-N85SrkOE0jZ)Qh<;DE z`Z*%fv|Shr8Zc6bh{04ThC*{^&Yf{_ZsKZ&Gw1)9M|kn-wQslERI&_000(ymQgk!S z9dpBq0y8JZ$nVorDj@{cu79o*0zd$~jFdT;18#}T9W$pWBAF9bz!gD&FQ13Jd;5mz z^amLvS0!l(5DQE1t6Eu{{rbsxJmTrImkb7d7WoB%u!I5uvw|!DW{#O*<}4N$?C!r~s%4A;9;^3Fqf?c6(0{)if@5dc8dcgFe?AYt(9Wz=%FzL_P04e?aVo(L6{Xqg5H;fX{}b^g)Nv0~tC!i_ xOb!B0#R00t3Si|0nH89UyJ2Q!^fFH?`v-04E7Lc4hb{mB002ovPDHLkV1hPc<>&kwgLqf#D*pl(tDxi?Dr;B5V#`)ww`(ysvGfOsfHu@OE zm`Ifu^D8YkT6A35?)hBZzg^MFyA)4!vCoumPn^We@QzJLtmR8xK2SS@r>mdKI;Vst E070KGv;Y7A literal 546 zcmV+-0^R+IP) z0PbQi!;Am`010qNS#tmY4c7nw4c7reD4Tcy000McNliru-UA3088Nhh^B@2K0k26! zK~yNuO_I%OR8bIwzdrX)CQd?3U^M=LQBhFw5hN1d!RPTwT=*n{t1Qe;g(xa0nwV%3 z2bp`%>C@%nj$*H?ijS_chdYmTeQS$0C1eI90suo2ia-h?D&Yl%aCeT6j%dw{^_3|Y z$QtTsOtedjpy4EuN=MVrAu17~R;Lw)8HhwIjq%YrPOjYM=heI9BN15&dP8WELbK!k`0B1Atq&*b!w zYp-9h_WdJGEnr5svOyq1gSOV71<0jf$*7i@zIn+MgVb=gd4oC{gG6(7OeqD+8B^e~ zFqfRcfb7HLQcJ&nk*^PS0NB{yC7m4NeFwQe>9`U1Pp83Qmw0%6Q=-r?8w z6Y#=?=TAvp2i1{8gb<=N1tk}TP1t~KiDrL~_5D2nN>nTts6LQHU}(T*RI&foBzMAp k6T!b}$}?J2Dh-wW0V(Diq~|%A%>V!Z07*qoM6N<$f(~`+p#T5? diff --git a/plugins/triple_oscillator/usr_shape_inactive.png b/plugins/triple_oscillator/usr_shape_inactive.png index 5c1f67b10e41ab9c8f3213d4209137577be337cc..f49140656b0a52840ab73a29bd64ef518e056526 100644 GIT binary patch literal 193 zcmeAS@N?(olHy`uVBq!ia0vp^d_XL~!3HGNrubO_DYhhUcNd2LAh=-f^2tCE&H|6f zVxW%eAk65bF}ngN$X?><>&kwgLqe3vpe30(4k+a3>EaloaXvXgLD=Bm|MLet`rOot za#f<0x$m6q;rZWrk>RscoOEwb&p&=S`$LPFpSjnZvo3!pqx9?F|KqaLZ}2p(lxL}1 h;$?H`+R7zN45cp>Y z0PbQi!;Am`010qNS#tmY4c7nw4c7reD4Tcy000McNliru-UA307c^REDj@&>0fI?H zK~yNuWs*TlTTu{&zj=AxL<5GpuNu%r3R-F_MWkSVdnrY9*MbJ^t_zhkZNZRt-#w>` zd(Eb+naw$K=9`JL^G|-YvqRf75CI0;K&h6HjVzQilIi=N$A<^nh+u1Dn+SjaTr0H) z8L*0(jbw7}X-%w!5g@^A_MN-iYnIC=27>|9=@Gk={pw{RpwFVIBi07Dx7S=3(|Lcy6!(3G<-NchkE1ZI~&u6Me5Re=jYht@iy~41^@s6$yOx<00004b3#c}2nYxWdWU11Xa*eLai5CRKFs#l7>QLRt34rHVudNCXw-cfn@ZB2{qk z>8+06u(^A2!Iwpin5i&_n*gj%TL=NUCrRc(vJtk(yWvzpV{t-Z4%+w)8*`{h%v9{2 zd5MfQnH^Q`I1*4q0}7vElbBRU0gDrg?4x8QWHB|;>{P;f>#()Z_)f0PIAe_l6a!wH zrJ&O^x%J^b?N-c>D*(JY?8F=R3}^j^{O#YMCzijKX??EItHd3
Dx6D002ovPDHLkV1l=G)Rh1L delta 556 zcmV+{0@MBI1Iz@F7aR--1^@s6y+Y^Y00006VoOIv05<@>0PbQi!;FzJ7=H(JNliru z-UA3086~b;CtUyl0oh4JK~yNuO_Doq6hRb4PknkkzaHb6K_knUk8@Z65=ht?IV*6= zUI@ro02u)h8Jlo~M1*9J{K3O?x4WyW>OBJ6i0Izr>gYqMSVfDz2e*R zH-yPOPL7VLmittTeNGOK*{lu_S8($BE#f>lN6d=H7}OZ*5$CZfa{lNU^?VPLB7cG*x`M0*3lL+X zDVG$@nr^&}Z!5ZTff&o^>K9=+MXbZcj-O9okra~X%{awKJG+mst_YJIOwJ587o<^% zieUPH6k8OVOZwT8m?9~sJ91#}%Li=r8%42QgT1aWsmFwCLOI8F4cU3_V45>lB_Y+C z)HV!Gzmvx^hyhh)_kYtnXlqbq_4z%;#VNM=LrjsJ1aE-8y9QCZQ3ip7k>~41^@s6$yOx<00004b3#c}2nYxWdAL7JuR-6^egF=N9T8AP&Jn z>Y!r;F$ht?L2(t#EXJX7Kb|f(VDu)a54`Yj-t&7n@8LBG;~iREt%Ql^MaRi~er>=D z*!Pp)0bKXX@SEVp#X>*utyCJx_h1P5-`we4do=QMPUF0fw$2UmNW;1 zl9quFQ5df4e1DW|eQ9Z?uPY491G~Tq@DPRJdENpraC7rG9t%fX7O)3=GSlxU3^OYO z_nybsSU3n$^Jcc6NCcPB)ixlbxnuvwXbePR1Yez@d55V7QmC!6W09=WkR7w{>2V9(Ln?~dO=ac#tKsKAK-QMah zolfu7>nE*Zu`t=OUI}}C%4L#mpU>yl;(98Tie7wAfNGVn?Z?K>Hsg9a-rP-3gWe4H Z(tpW}mt)m2*1`Y)002ovPDHLkV1mqY)U*Hq delta 531 zcmV+u0_^?p1GEH?7aR--1^@s6y+Y^Y00006VoOIv05<@>0PbQi!;FzJ7=H(JNliru z-UA307c5BxvUdOg0l`T`K~yNuMUp#j)KCzGzk9Fkc-INZM%$AfI!YcvNdZ5Tw24Fs zJsqN=fC{8l6n3M$Hjcf?`aWhTY(jOWIWuRDKJ)tEP@nGYky#7IfP$(5y{ZVJil`td zA)>?>xw^b0Gsdt}O)&<*0Dn3t!wjN;O214M5hbOFRSd?!&CNBRKYgTaTTYHYuvnb2 znE&DA_=wZlZ!m_F<0GIC7?Y3=$`naK1PLAf?2U?QP7EX1Tm!XJ;3Y zL}mbyK2A|=@NmCky?$UmKO;%PImgc*-?_Lr$2r&kFG5O!1@IwoeSdYycwAA}x0L0G zrm2yXm`tX$ZPQ=Ma=v~2LX3eZgE@H5ZM|ePu4tMXV+@;{Tdda)s0z+GVvJPP7H!)Q zf+xl>m_x_@{yWNYgrekmL0)WNts~2Fn&yr?FNiS!;C(<-!YU9#p!1&H$rRspSZh&H z_TRq8IS0VYSBF&97HmaP5P~Pgq3zCl3{c Date: Wed, 27 Jan 2016 08:39:33 +0100 Subject: [PATCH 03/90] Fix colour of selected beat notes in Piano Roll --- src/gui/editors/PianoRoll.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index a1e25b60d20..134065e5cf0 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -785,12 +785,7 @@ void PianoRoll::drawNoteRect(QPainter & p, int x, int y, QColor col = QColor( noteCol ); - if( n->length() < 0 ) - { - //step note - col.setRgb( 0, 255, 0 ); - } - else if( n->selected() ) + if( n->selected() ) { col.setRgb( 0x00, 0x40, 0xC0 ); } From 64efd68bfdcda7e12a6c2abaf222badcb9f1c0ad Mon Sep 17 00:00:00 2001 From: Cyrille Bollu Date: Wed, 27 Jan 2016 17:03:46 +0100 Subject: [PATCH 04/90] Fixed a French translation that prevented the display of the "MIDI" and "MISC" tabs (issue 2519) --- data/locale/fr.ts | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/data/locale/fr.ts b/data/locale/fr.ts index e3b21e53820..2c1ff77dd1d 100644 --- a/data/locale/fr.ts +++ b/data/locale/fr.ts @@ -3261,11 +3261,13 @@ Vous pouvez supprimer et déplacer les canaux d'effet avec le menu contextu FUNC - FONCTIONS + "FONCTIONS" (previous translation) is too long for the limited available width. + FONCT FX - EFFETS + "EFFETS" (previous translation) is too long for the limited available width. "FX" should be understable by all + FX MIDI @@ -3811,30 +3813,6 @@ Veuillez visiter http://lmms.sf.net/wiki pour la documentation de LMMS.LMMS Project Template Modèle de projet LMMS - - Song Editor - Éditeur de morceau - - - Beat+Bassline Editor - Éditeur de motif - - - Piano Roll - Piano virtuel - - - Automation Editor - Éditeur d'automation - - - FX Mixer - Mélangeur d'effets - - - Project Notes - Notes du projet - Volume as dBV Volume en dBV From 72915b7ace72c9146532af80e88e5af6b87a49ba Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Fri, 29 Jan 2016 15:26:34 +0100 Subject: [PATCH 05/90] Fix bar display breaking at 999 --- src/gui/widgets/TimeDisplayWidget.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/gui/widgets/TimeDisplayWidget.cpp b/src/gui/widgets/TimeDisplayWidget.cpp index d6e1e5210ee..0d31a30f4a3 100644 --- a/src/gui/widgets/TimeDisplayWidget.cpp +++ b/src/gui/widgets/TimeDisplayWidget.cpp @@ -37,8 +37,8 @@ TimeDisplayWidget::TimeDisplayWidget() : QWidget(), m_displayMode( MinutesSeconds ), m_spinBoxesLayout( this ), - m_majorLCD( 3, this ), - m_minorLCD( 3, this ), + m_majorLCD( 4, this ), + m_minorLCD( 2, this ), m_milliSecondsLCD( 3, this ) { m_spinBoxesLayout.setSpacing( 0 ); @@ -137,9 +137,3 @@ void TimeDisplayWidget::mousePressEvent( QMouseEvent* mouseEvent ) } } } - - - - - - From 216143a8f57611cd66fe4f05273c5f48e39225c5 Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Sun, 31 Jan 2016 21:54:39 +0100 Subject: [PATCH 06/90] Fix bad button position in setup dialog, make the SetupDialog fixed size and EffectDialog resizeable --- include/RenameDialog.h | 2 +- src/gui/SetupDialog.cpp | 9 +++------ src/gui/widgets/RenameDialog.cpp | 14 ++++++++------ 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/include/RenameDialog.h b/include/RenameDialog.h index 8c857e15d2d..5470455d801 100644 --- a/include/RenameDialog.h +++ b/include/RenameDialog.h @@ -43,6 +43,7 @@ class RenameDialog : public QDialog protected: void keyPressEvent( QKeyEvent * _ke ); + virtual void resizeEvent(QResizeEvent * event); protected slots: @@ -58,4 +59,3 @@ protected slots: #endif - diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index 18969d46666..b894a0fe3e8 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -140,6 +140,7 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : setWindowIcon( embed::getIconPixmap( "setup_general" ) ); setWindowTitle( tr( "Setup LMMS" ) ); setModal( true ); + setFixedSize( 452, 520 ); Engine::projectJournal()->setJournalling( false ); @@ -411,8 +412,8 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : pathScroll->move( 0, 30 ); pathSelectors->resize( 360, pathsHeight - 50 ); - const int txtLength = 285; - const int btnStart = 305; + const int txtLength = 284; + const int btnStart = 297; // working-dir @@ -1526,7 +1527,3 @@ void SetupDialog::displayMIDIHelp() "controls to setup the selected " "MIDI-interface." ) ); } - - - - diff --git a/src/gui/widgets/RenameDialog.cpp b/src/gui/widgets/RenameDialog.cpp index 2e443f241bb..007d7fee0d6 100644 --- a/src/gui/widgets/RenameDialog.cpp +++ b/src/gui/widgets/RenameDialog.cpp @@ -36,6 +36,7 @@ RenameDialog::RenameDialog( QString & _string ) : m_originalString( _string ) { setWindowTitle( tr("Rename...") ); + setFixedHeight( 30 ); m_stringLE = new QLineEdit( this ); m_stringLE->setText( _string ); m_stringLE->setGeometry ( 10, 5, 220, 20 ); @@ -56,6 +57,13 @@ RenameDialog::~RenameDialog() +void RenameDialog::resizeEvent (QResizeEvent * event) { + m_stringLE->setGeometry ( 10, 5, width() - 20, 20 ); +} + + + + void RenameDialog::keyPressEvent( QKeyEvent * _ke ) { if( _ke->key() == Qt::Key_Escape ) @@ -72,9 +80,3 @@ void RenameDialog::textChanged( const QString & _new_string ) { m_stringToEdit = _new_string; } - - - - - - From de5ee5d8a3eed21a498bc154c8836ab2ebf4b539 Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Mon, 1 Feb 2016 22:44:07 +0100 Subject: [PATCH 07/90] Fix TripleOscillator modulation popups --- data/locale/ca.ts | 12 +++++----- data/locale/cs.ts | 12 +++++----- data/locale/de.ts | 12 +++++----- data/locale/en.ts | 12 +++++----- data/locale/es.ts | 12 +++++----- data/locale/fa.ts | 12 +++++----- data/locale/fr.ts | 12 +++++----- data/locale/gl.ts | 12 +++++----- data/locale/it.ts | 12 +++++----- data/locale/ja.ts | 12 +++++----- data/locale/ko.ts | 12 +++++----- data/locale/nl.ts | 12 +++++----- data/locale/pl.ts | 12 +++++----- data/locale/pt.ts | 12 +++++----- data/locale/ru.ts | 12 +++++----- data/locale/sv.ts | 12 +++++----- data/locale/uk.ts | 12 +++++----- data/locale/zh.ts | 12 +++++----- .../triple_oscillator/TripleOscillator.cpp | 24 +++++++++---------- 19 files changed, 120 insertions(+), 120 deletions(-) diff --git a/data/locale/ca.ts b/data/locale/ca.ts index f9a500abded..6d3e2bc76e1 100644 --- a/data/locale/ca.ts +++ b/data/locale/ca.ts @@ -6091,11 +6091,11 @@ Per favor, assegura't que tens permís de lectura per al fitxer i el direct TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 @@ -6107,15 +6107,15 @@ Per favor, assegura't que tens permís de lectura per al fitxer i el direct - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 @@ -6127,7 +6127,7 @@ Per favor, assegura't que tens permís de lectura per al fitxer i el direct - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 diff --git a/data/locale/cs.ts b/data/locale/cs.ts index 0fb3fc3bf75..bc88054ba89 100644 --- a/data/locale/cs.ts +++ b/data/locale/cs.ts @@ -6093,11 +6093,11 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 @@ -6109,15 +6109,15 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 @@ -6129,7 +6129,7 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 diff --git a/data/locale/de.ts b/data/locale/de.ts index f7f7f1d6410..b4930524cf1 100644 --- a/data/locale/de.ts +++ b/data/locale/de.ts @@ -6129,11 +6129,11 @@ Bitte stellen Sie sicher, dass Sie Leserechte auf diese Datei sowie das Verzeich TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 Phasenmodulation benutzen, um Oszillator 2 mit Oszillator 1 zu modulieren - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 Amplitudenmodulation benutzen, um Oszillator 2 mit Oszillator 1 zu modulieren @@ -6145,15 +6145,15 @@ Bitte stellen Sie sicher, dass Sie Leserechte auf diese Datei sowie das Verzeich Synchronisiere Oszillator 1 mit Oszillator 2 - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 Frequenzmodulation benutzen, um Oszillator 2 mit Oszillator 1 zu modulieren - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 Phasenmodulation benutzen, um Oszillator 3 mit Oszillator 2 zu modulieren - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 Amplitudenmodulation benutzen, um Oszillator 3 mit Oszillator 2 zu modulieren @@ -6165,7 +6165,7 @@ Bitte stellen Sie sicher, dass Sie Leserechte auf diese Datei sowie das Verzeich Synchronisiere Oszillator 2 mit Oszillator 3 - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 Frequenzmodulation benutzen, um Oszillator 3 mit Oszillator 2 zu modulieren diff --git a/data/locale/en.ts b/data/locale/en.ts index 7774bc923d7..2420e561e69 100644 --- a/data/locale/en.ts +++ b/data/locale/en.ts @@ -6080,11 +6080,11 @@ Please make sure you have read-permission to the file and the directory containi TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 @@ -6096,15 +6096,15 @@ Please make sure you have read-permission to the file and the directory containi - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 @@ -6116,7 +6116,7 @@ Please make sure you have read-permission to the file and the directory containi - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 diff --git a/data/locale/es.ts b/data/locale/es.ts index 020807c88ea..9154c36b73b 100644 --- a/data/locale/es.ts +++ b/data/locale/es.ts @@ -6080,11 +6080,11 @@ Please make sure you have read-permission to the file and the directory containi TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 @@ -6096,15 +6096,15 @@ Please make sure you have read-permission to the file and the directory containi - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 @@ -6116,7 +6116,7 @@ Please make sure you have read-permission to the file and the directory containi - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 diff --git a/data/locale/fa.ts b/data/locale/fa.ts index cd8d4f90571..b2c3ae332f1 100644 --- a/data/locale/fa.ts +++ b/data/locale/fa.ts @@ -6080,11 +6080,11 @@ Please make sure you have read-permission to the file and the directory containi TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 @@ -6096,15 +6096,15 @@ Please make sure you have read-permission to the file and the directory containi - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 @@ -6116,7 +6116,7 @@ Please make sure you have read-permission to the file and the directory containi - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 diff --git a/data/locale/fr.ts b/data/locale/fr.ts index 2c1ff77dd1d..d9294c35065 100644 --- a/data/locale/fr.ts +++ b/data/locale/fr.ts @@ -6613,11 +6613,11 @@ Veuillez vérifier que vous avez les droits en lecture pour ce fichier et le ré TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 Utiliser la modulation de phase pour moduler l'oscillateur 2 avec l'oscillateur 1 - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 Utiliser la modulation d'amplitude pour moduler l'oscillateur 2 avec l'oscillateur 1 @@ -6629,15 +6629,15 @@ Veuillez vérifier que vous avez les droits en lecture pour ce fichier et le ré Synchroniser l'oscillateur 1 avec l'oscillateur 2 - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 Utiliser la modulation de fréquence pour moduler l'oscillateur 2 avec l'oscillateur 1 - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 Utiliser la modulation de phase pour moduler l'oscillateur 3 avec l'oscillateur 2 - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 Utiliser la modulation d'amplitude pour moduler l'oscillateur 3 avec l'oscillateur 2 @@ -6649,7 +6649,7 @@ Veuillez vérifier que vous avez les droits en lecture pour ce fichier et le ré Synchroniser l'oscillateur 2 avec l'oscillateur 3 - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 Utiliser la modulation de fréquence pour moduler l'oscillateur 3 avec l'oscillateur 2 diff --git a/data/locale/gl.ts b/data/locale/gl.ts index 738561f236e..a89ed25ed97 100644 --- a/data/locale/gl.ts +++ b/data/locale/gl.ts @@ -6101,11 +6101,11 @@ Asegúrese de ter permiso de lectura sobre o ficheiro e o directorio que o cont TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 Empregar a modulación de fase para modular o oscilador 2 co oscilador 1 - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 Empregar a modulación de amplitude para modular o oscilador 2 co oscilador 1 @@ -6117,15 +6117,15 @@ Asegúrese de ter permiso de lectura sobre o ficheiro e o directorio que o cont Sincronizar o oscilador 1 co oscilador 2 - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 Empregar a modulación de frecuencia para modular o oscilador 2 co oscilador 1 - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 Empregar a modulación de fase para modular o oscilador 3 co oscilador 2 - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 Empregar a modulación de amplitude para modular o oscilador 3 co oscilador 2 @@ -6137,7 +6137,7 @@ Asegúrese de ter permiso de lectura sobre o ficheiro e o directorio que o cont Sincronizar o oscilador 2 co oscilador 3 - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 Empregar a modulación de frecuencia para modular o oscilador 3 co oscilador 2 diff --git a/data/locale/it.ts b/data/locale/it.ts index 39829804fc6..d27d1521afe 100644 --- a/data/locale/it.ts +++ b/data/locale/it.ts @@ -6126,11 +6126,11 @@ Assicurarsi di avere i permessi in lettura per il file e per la directory che lo TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 Usare la modulazione di fase per modulare l'oscillatore 2 con l'oscillatore 1 - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 Usare la modulazione di amplificazione per modulare l'oscillatore 2 con l'oscillatore 1 @@ -6142,15 +6142,15 @@ Assicurarsi di avere i permessi in lettura per il file e per la directory che lo Sincronizzare l'oscillatore 1 con l'oscillatore 2 - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 Usare la modulazione di frequenza per modulare l'oscillatore 2 con l'oscillatore 1 - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 Usare la modulazione di fase per modulare l'oscillatore 3 con l'oscillatore 2 - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 Usare la modulazione di amplificazione per modulare l'oscillatore 3 con l'oscillatore 2 @@ -6162,7 +6162,7 @@ Assicurarsi di avere i permessi in lettura per il file e per la directory che lo Sincronizzare l'oscillatore 2 con l'oscillatore 3 - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 Usare la modulazione di frequenza per modulare l'oscillatore 3 con l'oscillatore 2 diff --git a/data/locale/ja.ts b/data/locale/ja.ts index 41c591d3835..96cd6e89b68 100644 --- a/data/locale/ja.ts +++ b/data/locale/ja.ts @@ -6104,11 +6104,11 @@ Please make sure you have read-permission to the file and the directory containi TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 @@ -6120,15 +6120,15 @@ Please make sure you have read-permission to the file and the directory containi - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 @@ -6140,7 +6140,7 @@ Please make sure you have read-permission to the file and the directory containi - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 diff --git a/data/locale/ko.ts b/data/locale/ko.ts index 93c7a7e46e7..1f09c468122 100644 --- a/data/locale/ko.ts +++ b/data/locale/ko.ts @@ -6085,11 +6085,11 @@ Please make sure you have read-permission to the file and the directory containi TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 @@ -6101,15 +6101,15 @@ Please make sure you have read-permission to the file and the directory containi - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 @@ -6121,7 +6121,7 @@ Please make sure you have read-permission to the file and the directory containi - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 diff --git a/data/locale/nl.ts b/data/locale/nl.ts index feb2cbb5ecc..4aec33ceabb 100644 --- a/data/locale/nl.ts +++ b/data/locale/nl.ts @@ -6084,11 +6084,11 @@ Zorg ervoor dat je schrijf-bevoegdheid hebt voor deze bestanden en mapen en prob TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 @@ -6100,15 +6100,15 @@ Zorg ervoor dat je schrijf-bevoegdheid hebt voor deze bestanden en mapen en prob - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 @@ -6120,7 +6120,7 @@ Zorg ervoor dat je schrijf-bevoegdheid hebt voor deze bestanden en mapen en prob - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 diff --git a/data/locale/pl.ts b/data/locale/pl.ts index c5c2dbfe3cd..9445942c0e4 100644 --- a/data/locale/pl.ts +++ b/data/locale/pl.ts @@ -6107,11 +6107,11 @@ Upewnij się, że masz uprawnienia do odczytu tego pliku i katalogu zawierające TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 Użyj modulacji fazowej aby zmodulować oscylator 2 oscylatorem 1 - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 Użyj modulacji amplitudowej aby zmodulować oscylator 2 oscylatorem 1 @@ -6123,15 +6123,15 @@ Upewnij się, że masz uprawnienia do odczytu tego pliku i katalogu zawierające Synchronizuj oscylator 1 z oscylatorem 2 - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 Użyj modulacji częstotliwościowej aby zmodulować oscylator 2 oscylatorem 1 - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 Użyj modulacji fazowej aby zmodulować oscylator 3 oscylatorem 2 - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 Użyj modulacji amplitudowej aby zmodulować oscylator 3 oscylatorem 2 @@ -6143,7 +6143,7 @@ Upewnij się, że masz uprawnienia do odczytu tego pliku i katalogu zawierające Synchronizuj oscylator 2 z oscylatorem 3 - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 Użyj modulacji częstotliwościowej aby zmodulować oscylator 3 oscylatorem 2 diff --git a/data/locale/pt.ts b/data/locale/pt.ts index 1cab5558308..f8bf219f116 100644 --- a/data/locale/pt.ts +++ b/data/locale/pt.ts @@ -6125,7 +6125,7 @@ Por favor certifique-se que você tem permissões de leitura para o arquivo e pa Com este botão você pode modificar Ajuste bruto do oscilador %1. Você pode descer o tom do oscilador 24 semitons (2 oitavas) para cima e para baixo. Isto é útil para criar sons com um acorde. - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 Use o modulador de fase para modular o oscilador 3 com o oscilador 2 @@ -6153,11 +6153,11 @@ Por favor certifique-se que você tem permissões de leitura para o arquivo e pa Com este botão você pode ajustar o defasamento estéreo do oscilador %1. O defasador estéreo especifica o tamanho da diferença entre a defasagem entre os canais esquerdo e direito. Isto é muito bom para abrir o som. - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 Use o modulador de frequência para modular o oscilador 2 com o oscilador 1 - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 Use o modulador de fase para modular o oscilador 2 com o oscilador 1 @@ -6177,7 +6177,7 @@ Por favor certifique-se que você tem permissões de leitura para o arquivo e pa Ajuste fino direito %1: - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 Use o modulador de amplitude para modular o oscilador 2 com o oscilador 1 @@ -6193,7 +6193,7 @@ Por favor certifique-se que você tem permissões de leitura para o arquivo e pa Use ruído branco no oscilador atual. - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 Use o modulador de frequência para modular o oscilador 3 com o oscilador 2 @@ -6225,7 +6225,7 @@ Por favor certifique-se que você tem permissões de leitura para o arquivo e pa Com este botão você pode modificar o ajuste fino do oscilador %1 para o canal direito. O ajuste fino varia entre -100 centésimos e +100 centésimos. Isto é útil para criar sons 'gordos'. - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 Use o modulador de amplitude para modular o oscilador 3 com o oscilador 2 diff --git a/data/locale/ru.ts b/data/locale/ru.ts index 2ec32ca37d9..861b4353d31 100644 --- a/data/locale/ru.ts +++ b/data/locale/ru.ts @@ -6158,11 +6158,11 @@ Please make sure you have read-permission to the file and the directory containi TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 Модулировать фазу осциллятора 2 сигналом с 1 - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 Модулировать амплитуду осциллятора 2 сигналом с первого @@ -6174,15 +6174,15 @@ Please make sure you have read-permission to the file and the directory containi Синхронизировать первый осциллятор по второму - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 Модулировать частоту осциллятора 2 сигналом с 1 - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 Модулировать фазу осциллятора 3 сигналом с 2 - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 Модулировать амплитуду осциллятора 3 сигналом с 2 @@ -6194,7 +6194,7 @@ Please make sure you have read-permission to the file and the directory containi Синхронизировать осциллятор 2 и 3 - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 Модулировать частоту осциллятора 3 сигналом со 2 diff --git a/data/locale/sv.ts b/data/locale/sv.ts index 5f81fde6911..91bff1572be 100644 --- a/data/locale/sv.ts +++ b/data/locale/sv.ts @@ -6083,11 +6083,11 @@ Se till att du har läsningsrättigheter för filen och katalogen som innehålle TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 @@ -6099,15 +6099,15 @@ Se till att du har läsningsrättigheter för filen och katalogen som innehålle - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 @@ -6119,7 +6119,7 @@ Se till att du har läsningsrättigheter för filen och katalogen som innehålle - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 diff --git a/data/locale/uk.ts b/data/locale/uk.ts index 462d1ce8922..1cd14cf9e8d 100644 --- a/data/locale/uk.ts +++ b/data/locale/uk.ts @@ -6669,7 +6669,7 @@ Please make sure you have read-permission to the file and the directory containi Точне підстроювання лівого каналу осциллятора %1: - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 Модулювати фазу осциллятора 3 сигналом з 2 @@ -6697,11 +6697,11 @@ Please make sure you have read-permission to the file and the directory containi Ця ручка встановлює фазове підстроювання осциллятора %1 між каналами, тобто різницю фаз між лівим і правим каналами. Це зручно для створення розширення стереоефектів. - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 Модулювати частоту осциллятора 2 сигналом з 1 - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 Модулювати фазу осциллятора 2 сигналом з 1 @@ -6721,7 +6721,7 @@ Please make sure you have read-permission to the file and the directory containi Точна підстройка правого канала осциллятора %1: - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 Модулювати амплітуду осциллятора 2 сигналом з 1 @@ -6737,7 +6737,7 @@ Please make sure you have read-permission to the file and the directory containi Використовувати білий шум для цього осциллятора. - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 Модулювати частоту осциллятора 3 сигналом з 2 @@ -6769,7 +6769,7 @@ Please make sure you have read-permission to the file and the directory containi Ця ручка встановлює точне підстроювання для правого каналу осциллятора %1. Підстроювання задається в діапазоні від -100 сотих до +100 сотих. Це корисно для створення "насичених" звуків. - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 Модулювати амплітуду осциллятора 3 сигналом з 2 diff --git a/data/locale/zh.ts b/data/locale/zh.ts index b6704b23a8e..cf959d85bd1 100644 --- a/data/locale/zh.ts +++ b/data/locale/zh.ts @@ -6095,11 +6095,11 @@ Please make sure you have read-permission to the file and the directory containi TripleOscillatorView - Use phase modulation for modulating oscillator 2 with oscillator 1 + Use phase modulation for modulating oscillator 1 with oscillator 2 - Use amplitude modulation for modulating oscillator 2 with oscillator 1 + Use amplitude modulation for modulating oscillator 1 with oscillator 2 @@ -6111,15 +6111,15 @@ Please make sure you have read-permission to the file and the directory containi - Use frequency modulation for modulating oscillator 2 with oscillator 1 + Use frequency modulation for modulating oscillator 1 with oscillator 2 - Use phase modulation for modulating oscillator 3 with oscillator 2 + Use phase modulation for modulating oscillator 2 with oscillator 3 - Use amplitude modulation for modulating oscillator 3 with oscillator 2 + Use amplitude modulation for modulating oscillator 2 with oscillator 3 @@ -6131,7 +6131,7 @@ Please make sure you have read-permission to the file and the directory containi - Use frequency modulation for modulating oscillator 3 with oscillator 2 + Use frequency modulation for modulating oscillator 2 with oscillator 3 diff --git a/plugins/triple_oscillator/TripleOscillator.cpp b/plugins/triple_oscillator/TripleOscillator.cpp index b984d10da0a..f314c64f0b8 100644 --- a/plugins/triple_oscillator/TripleOscillator.cpp +++ b/plugins/triple_oscillator/TripleOscillator.cpp @@ -440,8 +440,8 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, pm_osc1_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_inactive" ) ); ToolTip::add( pm_osc1_btn, tr( "Use phase modulation for " - "modulating oscillator 2 with " - "oscillator 1" ) ); + "modulating oscillator 1 with " + "oscillator 2" ) ); PixmapButton * am_osc1_btn = new PixmapButton( this, NULL ); am_osc1_btn->move( mod_x + 35, mod1_y ); @@ -450,8 +450,8 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, am_osc1_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "am_inactive" ) ); ToolTip::add( am_osc1_btn, tr( "Use amplitude modulation for " - "modulating oscillator 2 with " - "oscillator 1" ) ); + "modulating oscillator 1 with " + "oscillator 2" ) ); PixmapButton * mix_osc1_btn = new PixmapButton( this, NULL ); mix_osc1_btn->move( mod_x + 70, mod1_y ); @@ -477,8 +477,8 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, fm_osc1_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "fm_inactive" ) ); ToolTip::add( fm_osc1_btn, tr( "Use frequency modulation for " - "modulating oscillator 2 with " - "oscillator 1" ) ); + "modulating oscillator 1 with " + "oscillator 2" ) ); m_mod1BtnGrp = new automatableButtonGroup( this ); m_mod1BtnGrp->addButton( pm_osc1_btn ); @@ -496,8 +496,8 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, pm_osc2_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_inactive" ) ); ToolTip::add( pm_osc2_btn, tr( "Use phase modulation for " - "modulating oscillator 3 with " - "oscillator 2" ) ); + "modulating oscillator 2 with " + "oscillator 3" ) ); PixmapButton * am_osc2_btn = new PixmapButton( this, NULL ); am_osc2_btn->move( mod_x + 35, mod2_y ); @@ -506,8 +506,8 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, am_osc2_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "am_inactive" ) ); ToolTip::add( am_osc2_btn, tr( "Use amplitude modulation for " - "modulating oscillator 3 with " - "oscillator 2" ) ); + "modulating oscillator 2 with " + "oscillator 3" ) ); PixmapButton * mix_osc2_btn = new PixmapButton( this, NULL ); mix_osc2_btn->move( mod_x + 70, mod2_y ); @@ -533,8 +533,8 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, fm_osc2_btn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "fm_inactive" ) ); ToolTip::add( fm_osc2_btn, tr( "Use frequency modulation for " - "modulating oscillator 3 with " - "oscillator 2" ) ); + "modulating oscillator 2 with " + "oscillator 3" ) ); m_mod2BtnGrp = new automatableButtonGroup( this ); From 3ffa8ac8f5363757141ea4e5cacf04eced68be00 Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Thu, 28 Jan 2016 23:19:46 +0100 Subject: [PATCH 08/90] Fix outdated copyright info, fix license not showing in the about dialog --- CMakeLists.txt | 2 +- src/core/main.cpp | 16 ++++------------ src/gui/AboutDialog.cpp | 5 ++++- src/gui/dialogs/about_dialog.ui | 4 ++-- src/lmmsversion.h.in | 2 +- 5 files changed, 12 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 407bf9887e9..228c74eb5fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ SET(PROJECT_AUTHOR "LMMS Developers") SET(PROJECT_URL "http://lmms.io") SET(PROJECT_EMAIL "lmms-devel@lists.sourceforge.net") SET(PROJECT_DESCRIPTION "${PROJECT_NAME_UCASE} - Free music production software") -SET(PROJECT_COPYRIGHT "${PROJECT_AUTHOR}, 2008-${PROJECT_YEAR}") +SET(PROJECT_COPYRIGHT "2008-${PROJECT_YEAR} ${PROJECT_AUTHOR}") SET(VERSION_MAJOR "1") SET(VERSION_MINOR "1") SET(VERSION_PATCH "3") diff --git a/src/core/main.cpp b/src/core/main.cpp index fb3598c4de2..d5beb6d9b19 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -82,14 +82,6 @@ static inline QString baseName( const QString & file ) -static std::string getCurrentYear() -{ - return QString::number( QDate::currentDate().year() ).toStdString(); -} - - - - inline void loadTranslation( const QString & tname, const QString & dir = ConfigManager::inst()->localeDir() ) { @@ -107,14 +99,14 @@ inline void loadTranslation( const QString & tname, void printVersion( char *executableName ) { printf( "LMMS %s\n(%s %s, Qt %s, %s)\n\n" - "Copyright (c) 2004-%s LMMS developers.\n\n" + "Copyright (c) %s\n\n" "This program is free software; you can redistribute it and/or\n" "modify it under the terms of the GNU General Public\n" "License as published by the Free Software Foundation; either\n" "version 2 of the License, or (at your option) any later version.\n\n" "Try \"%s --help\" for more information.\n\n", LMMS_VERSION, PLATFORM, MACHINE, QT_VERSION_STR, GCC_VERSION, - getCurrentYear().c_str(), executableName ); + LMMS_PROJECT_COPYRIGHT, executableName ); } @@ -123,7 +115,7 @@ void printVersion( char *executableName ) void printHelp() { printf( "LMMS %s\n" - "Copyright (c) 2004-%s LMMS developers.\n\n" + "Copyright (c) %s\n\n" "Usage: lmms [ -r ] [ options ]\n" " [ -u ]\n" " [ -d ]\n" @@ -157,7 +149,7 @@ void printHelp() "-v, --version Show version information and exit.\n" " --allowroot Bypass root user startup check (use with caution).\n" "-h, --help Show this usage information and exit.\n\n", - LMMS_VERSION, getCurrentYear().c_str() ); + LMMS_VERSION, LMMS_PROJECT_COPYRIGHT ); } diff --git a/src/gui/AboutDialog.cpp b/src/gui/AboutDialog.cpp index 6d39a8e46c0..69fe2b1072b 100644 --- a/src/gui/AboutDialog.cpp +++ b/src/gui/AboutDialog.cpp @@ -46,9 +46,12 @@ AboutDialog::AboutDialog(QWidget* parent) : arg( QT_VERSION_STR ). arg( GCC_VERSION ) ); + copyrightLabel->setText( copyrightLabel->text(). + arg( LMMS_PROJECT_COPYRIGHT ) ); + authorLabel->setPlainText( embed::getText( "AUTHORS" ) ); - licenseLabel->setPlainText( embed::getText( "COPYING" ) ); + licenseLabel->setPlainText( embed::getText( "LICENSE.txt" ) ); involvedLabel->setPlainText( embed::getText( "CONTRIBUTORS" ) ); } diff --git a/src/gui/dialogs/about_dialog.ui b/src/gui/dialogs/about_dialog.ui index 6d9a113373f..d6ce6ff81e2 100644 --- a/src/gui/dialogs/about_dialog.ui +++ b/src/gui/dialogs/about_dialog.ui @@ -133,9 +133,9 @@ - + - Copyright (c) 2004-2014, LMMS developers + Copyright © %1 true diff --git a/src/lmmsversion.h.in b/src/lmmsversion.h.in index 09c82ea0ffb..4f575d15421 100644 --- a/src/lmmsversion.h.in +++ b/src/lmmsversion.h.in @@ -3,4 +3,4 @@ #define LMMS_VERSION_PATCH @VERSION_PATCH@ #define LMMS_VERSION_SUFFIX "@VERSION_SUFFIX@" #define LMMS_VERSION "@VERSION@" - +#define LMMS_PROJECT_COPYRIGHT "@PROJECT_COPYRIGHT@" From d3ff3897a0efb8d485907fbe83c75cdf8360ed35 Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Tue, 2 Feb 2016 09:15:47 +0200 Subject: [PATCH 09/90] AboutDialog: make version line selectable --- src/gui/AboutDialog.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/AboutDialog.cpp b/src/gui/AboutDialog.cpp index 6d39a8e46c0..0065b6e2f36 100644 --- a/src/gui/AboutDialog.cpp +++ b/src/gui/AboutDialog.cpp @@ -45,6 +45,9 @@ AboutDialog::AboutDialog(QWidget* parent) : arg( MACHINE ). arg( QT_VERSION_STR ). arg( GCC_VERSION ) ); + versionLabel->setTextInteractionFlags( + versionLabel->textInteractionFlags() | + Qt::TextSelectableByMouse ); authorLabel->setPlainText( embed::getText( "AUTHORS" ) ); From 8b7c295fc05ddc4db05a2e803dedd97c820b65f7 Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Wed, 27 Jan 2016 17:49:24 +0100 Subject: [PATCH 10/90] Fix incorrect UI for Automation Track on Mac OS X --- data/locale/ca.ts | 100 +++++++++++------------ data/locale/cs.ts | 100 +++++++++++------------ data/locale/de.ts | 56 ++++++------- data/locale/en.ts | 56 ++++++------- data/locale/es.ts | 86 ++++++++++---------- data/locale/fa.ts | 80 +++++++++--------- data/locale/fr.ts | 116 +++++++++++++-------------- data/locale/gl.ts | 106 ++++++++++++------------ data/locale/it.ts | 108 ++++++++++++------------- data/locale/ja.ts | 106 ++++++++++++------------ data/locale/ko.ts | 76 +++++++++--------- data/locale/nl.ts | 98 +++++++++++----------- data/locale/pl.ts | 106 ++++++++++++------------ data/locale/pt.ts | 104 ++++++++++++------------ data/locale/ru.ts | 104 ++++++++++++------------ data/locale/sv.ts | 90 ++++++++++----------- data/locale/uk.ts | 86 ++++++++++---------- data/locale/zh.ts | 106 ++++++++++++------------ src/core/AutomationPattern.cpp | 7 +- src/core/Track.cpp | 39 ++++++--- src/gui/TimeLineWidget.cpp | 17 ++-- src/gui/editors/AutomationEditor.cpp | 25 ++++-- src/gui/editors/PianoRoll.cpp | 41 ++++++++-- src/gui/widgets/ProjectNotes.cpp | 86 ++++++++++++++++---- src/tracks/SampleTrack.cpp | 7 +- 25 files changed, 1019 insertions(+), 887 deletions(-) diff --git a/data/locale/ca.ts b/data/locale/ca.ts index f9a500abded..a8ebe20bafe 100644 --- a/data/locale/ca.ts +++ b/data/locale/ca.ts @@ -421,15 +421,15 @@ If you're interested in translating LMMS in another language or want to imp - Cut selected values (Ctrl+X) - Talla els valors seleccionats (Ctrl+X) + Cut selected values (%1+X) + Talla els valors seleccionats (%1+X) - Copy selected values (Ctrl+C) - Copia els valors seleccionats (Ctrl+C) + Copy selected values (%1+C) + Copia els valors seleccionats (%1+C) - Paste values from clipboard Ctrl+V) + Paste values from clipboard (%1+V) @@ -460,7 +460,7 @@ If you're interested in translating LMMS in another language or want to imp AutomationPattern - Drag a control while pressing <Ctrl> + Drag a control while pressing <%1> @@ -4870,7 +4870,7 @@ usa la roda del ratolí per a ajustar el volum d'un pas - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. @@ -4878,7 +4878,7 @@ usa la roda del ratolí per a ajustar el volum d'un pas - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. @@ -4886,16 +4886,16 @@ usa la roda del ratolí per a ajustar el volum d'un pas - Cut selected notes (Ctrl+X) - Talla les notes seleccionades (Ctrl+X) + Cut selected notes (%1+X) + Talla les notes seleccionades (%1+X) - Copy selected notes (Ctrl+C) - Copia les notes seleccionades (Ctrl+C) + Copy selected notes (%1+C) + Copia les notes seleccionades (%1+C) - Paste notes from clipboard (Ctrl+V) - Enganxa notes des del portapapers (Ctrl+V) + Paste notes from clipboard (%1+V) + Enganxa notes des del portapapers (%1+V) Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -4995,40 +4995,40 @@ Reason: "%2" &Desfés - Ctrl+Z - Ctrl+Z + %1+Z + %1+Z &Redo &Refés - Ctrl+Y - Ctrl+Y + %1+Y + %1+Y &Copy &Copia - Ctrl+C - Ctrl+C + %1+C + %1+C Cu&t &Talla - Ctrl+X - Ctrl+X + %1+X + %1+X &Paste &Enganxa - Ctrl+V - Ctrl+V + %1+V + %1+V Format Actions @@ -5039,56 +5039,56 @@ Reason: "%2" &Negreta - Ctrl+B - Ctrl+B + %1+B + %1+B &Italic Curs&iva - Ctrl+I - Ctrl+I + %1+I + %1+I &Underline &Subratllat - Ctrl+U - Ctrl+U + %1+U + %1+U &Left &Esquerra - Ctrl+L - Ctrl+L + %1+L + %1+L C&enter Cen&tre - Ctrl+E - Ctrl+E + %1+E + %1+E &Right &Dreta - Ctrl+R - Ctrl+R + %1+R + %1+R &Justify &Justifica - Ctrl+J - Ctrl+J + %1+J + %1+J &Color... @@ -5322,8 +5322,8 @@ Reason: "%2" Enganxa - Mute/unmute (<Ctrl> + middle click) - Apaga/encén (<Ctrl> + clic del mig) + Mute/unmute (<%1> + middle click) + Apaga/encén (<%1> + clic del mig) Set/clear record @@ -5925,11 +5925,11 @@ Latència: %2 ms Consell - Press <Ctrl> to disable magnetic loop points. + Press <%1> to disable magnetic loop points. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. @@ -6005,16 +6005,16 @@ Per favor, assegura't que tens permís de lectura per al fitxer i el direct Consell - Press <Ctrl> and drag to make a copy. - Pitja <Ctrl> i arrossega per a fer una còpia. + Press <%1> and drag to make a copy. + Pitja <%1> i arrossega per a fer una còpia. Current length Longitud actual - Press <Ctrl> for free resizing. - Pitja <Ctrl> per a redimensionar lliurement. + Press <%1> for free resizing. + Pitja <%1> per a redimensionar lliurement. %1:%2 (%3:%4 to %5:%6) @@ -6037,15 +6037,15 @@ Per favor, assegura't que tens permís de lectura per al fitxer i el direct Enganxa - Mute/unmute (<Ctrl> + middle click) - Apaga/encén (<Ctrl> + clic del mig) + Mute/unmute (<%1> + middle click) + Apaga/encén (<%1> + clic del mig) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. - Pitja <Ctrl> quan piquis el control de moviment per a iniciar una nova acció d'arrossegar i amollar. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + Pitja <%1> quan piquis el control de moviment per a iniciar una nova acció d'arrossegar i amollar. Actions for this track diff --git a/data/locale/cs.ts b/data/locale/cs.ts index 0fb3fc3bf75..a12e9710ec3 100644 --- a/data/locale/cs.ts +++ b/data/locale/cs.ts @@ -421,15 +421,15 @@ If you're interested in translating LMMS in another language or want to imp Kliknutím sem vyberte cubic hermite vývoj pro tento automatizační pattern. Hodnota připojeného objektu se změní po plynulé křivce a lehce přejde do vrchních a spodních bodů. - Cut selected values (Ctrl+X) - Vyjmout označené hodnoty (Ctrl+X) + Cut selected values (%1+X) + Vyjmout označené hodnoty (%1+X) - Copy selected values (Ctrl+C) - Kopírovat označené hodnoty (Ctrl+C) + Copy selected values (%1+C) + Kopírovat označené hodnoty (%1+C) - Paste values from clipboard Ctrl+V) + Paste values from clipboard (%1+V) @@ -460,8 +460,8 @@ If you're interested in translating LMMS in another language or want to imp AutomationPattern - Drag a control while pressing <Ctrl> - Ovladač táhni při stisknutém <CTRL> + Drag a control while pressing <%1> + Ovladač táhni při stisknutém <%1> Model is already connected to this pattern. @@ -4870,7 +4870,7 @@ k nastavení zesílení kroku použijte kolečko myši - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. @@ -4878,7 +4878,7 @@ k nastavení zesílení kroku použijte kolečko myši - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. @@ -4886,16 +4886,16 @@ k nastavení zesílení kroku použijte kolečko myši - Cut selected notes (Ctrl+X) - Vyjmout označené noty (Ctrl+X) + Cut selected notes (%1+X) + Vyjmout označené noty (%1+X) - Copy selected notes (Ctrl+C) - Kopírovat označené noty (Ctrl+C) + Copy selected notes (%1+C) + Kopírovat označené noty (%1+C) - Paste notes from clipboard (Ctrl+V) - Vložit noty ze schránky (Ctrl+V) + Paste notes from clipboard (%1+V) + Vložit noty ze schránky (%1+V) Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -4996,40 +4996,40 @@ Důvod: "%2" &Zpět - Ctrl+Z - Ctrl+Z + %1+Z + %1+Z &Redo &Znovu - Ctrl+Y - Ctrl+Z + %1+Y + %1+Z &Copy &Kopírovat - Ctrl+C - Ctrl+C + %1+C + %1+C Cu&t &Vyjmout - Ctrl+X - Ctrl+X + %1+X + %1+X &Paste V&ložit - Ctrl+V - Ctrl+V + %1+V + %1+V Format Actions @@ -5040,56 +5040,56 @@ Důvod: "%2" &Tučné - Ctrl+B - Ctrl+B + %1+B + %1+B &Italic &Kurzíva - Ctrl+I - Ctrl+I + %1+I + %1+I &Underline &Podtržené - Ctrl+U - Ctrl+U + %1+U + %1+U &Left Zarovnat &vlevo - Ctrl+L - Ctrl+L + %1+L + %1+L C&enter Zarovnat &na střed - Ctrl+E - Ctrl+E + %1+E + %1+E &Right Zarovnat v&pravo - Ctrl+R - Ctrl+R + %1+R + %1+R &Justify Zarovnat &do bloku - Ctrl+J - Ctrl+R + %1+J + %1+R &Color... @@ -5323,8 +5323,8 @@ Důvod: "%2" Vložit - Mute/unmute (<Ctrl> + middle click) - Ztlumit/neztlumit (<Ctrl> + prostřední klik) + Mute/unmute (<%1> + middle click) + Ztlumit/neztlumit (<%1> + prostřední klik) Set/clear record @@ -5927,11 +5927,11 @@ Zpoždění %2 ms Rada - Press <Ctrl> to disable magnetic loop points. + Press <%1> to disable magnetic loop points. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. @@ -6007,16 +6007,16 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu Rada - Press <Ctrl> and drag to make a copy. - K vytvoření kopie stiskněte <Ctrl> a táhněte myší. + Press <%1> and drag to make a copy. + K vytvoření kopie stiskněte <%1> a táhněte myší. Current length Aktuální délka - Press <Ctrl> for free resizing. - Stiskněte <Ctrl> pro volné měnění velikosti. + Press <%1> for free resizing. + Stiskněte <%1> pro volné měnění velikosti. %1:%2 (%3:%4 to %5:%6) @@ -6039,14 +6039,14 @@ Přesvědčte se prosím, že máte právo ke čtení tohoto souboru a příslu Vložit - Mute/unmute (<Ctrl> + middle click) - Ztlumit/neztlumit (<Ctrl> + prostřední klik) + Mute/unmute (<%1> + middle click) + Ztlumit/neztlumit (<%1> + prostřední klik) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. diff --git a/data/locale/de.ts b/data/locale/de.ts index f7f7f1d6410..cf40764d71a 100644 --- a/data/locale/de.ts +++ b/data/locale/de.ts @@ -423,15 +423,15 @@ Wenn Sie daran interessiert sind LMMS in eine andere Sprache zu übersetzen oder Klicken Sie hier, um kubisches, hermetisches Fortschreiten als Automationsmuster auszuwählen. Der Wert des verbundenen Objekts wird in einer nahtlosen Kurve geändert und in Spitzen und Täler übergehen. - Cut selected values (Ctrl+X) + Cut selected values (%1+X) Ausgewählte Werte ausschneiden (Strg+X) - Copy selected values (Ctrl+C) + Copy selected values (%1+C) Ausgewählte Werte kopieren (Strg+C) - Paste values from clipboard Ctrl+V) + Paste values from clipboard (%1+V) @@ -462,7 +462,7 @@ Wenn Sie daran interessiert sind LMMS in eine andere Sprache zu übersetzen oder AutomationPattern - Drag a control while pressing <Ctrl> + Drag a control while pressing <%1> Ein Steuerelement mit <Strg> hier her ziehen @@ -4907,7 +4907,7 @@ Lautstärke eines Schritts kann mit dem Mausrad geändert werden Verstimmungsmodus (Shift+T) - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. Klicken Sie hier, um den Zeichnenmodus zu aktivieren. In diesem Modus können Sie Noten hinzufügen, in der Länge ändern und verschieben. Das ist der Standardmodus, der meistens benutzt wird. Sie können auch »Umschalt+D« auf Ihrer Tastatur drücken, um in diesen Modus zu gelangen. Halten Sie in diesem Modus Strg gedrückt, um vorübergehend in den Auswahlmodus zu wechslen. @@ -4915,7 +4915,7 @@ Lautstärke eines Schritts kann mit dem Mausrad geändert werden Klicken Sie hier, um den Radiermodus zu aktivieren. In diesem Modus können Sie einzelne Noten löschen. Sie können auch »Umschalt+E« auf Ihrer Tastatur drücken, um diesen Modus zu aktivieren. - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. Klicken Sie hier, um den Auswahlmodus zu aktivieren. In diesem Modus können Sie einzelne Noten auswählen. Alternativ können Sie auch Strg im Zeichnenmodus gedrückt halten, um vorrübergehend den Auswahlmodus zu benutzen. @@ -4923,15 +4923,15 @@ Lautstärke eines Schritts kann mit dem Mausrad geändert werden Klicken Sie hier und der Verstimmungmodus wird aktivert. In diesem Modus können Sie auf eine Note klicken, um die Automations-Verstimmung zu öffnen. Sie können diese benutzen, um von einer Note in eine andere zu rutschen. Sie können auch »Umschalt+T« auf Ihrer Tastatur drücken, um diesen Modus zu aktivieren. - Cut selected notes (Ctrl+X) + Cut selected notes (%1+X) Ausgewählte Noten ausschneiden (Strg+X) - Copy selected notes (Ctrl+C) + Copy selected notes (%1+C) Ausgewählte Noten kopieren (Strg+C) - Paste notes from clipboard (Ctrl+V) + Paste notes from clipboard (%1+V) Noten aus Zwischenablage einfügen (Strg+V) @@ -5033,7 +5033,7 @@ Grund: »%2« &Rückgängig - Ctrl+Z + %1+Z Strg+Z @@ -5041,7 +5041,7 @@ Grund: »%2« Wiede&rholen - Ctrl+Y + %1+Y Strg+Y @@ -5049,7 +5049,7 @@ Grund: »%2« &Kopieren - Ctrl+C + %1+C Strg+C @@ -5057,7 +5057,7 @@ Grund: »%2« A&usschneiden - Ctrl+X + %1+X Strg+X @@ -5065,7 +5065,7 @@ Grund: »%2« &Einfügen - Ctrl+V + %1+V Strg+V @@ -5077,7 +5077,7 @@ Grund: »%2« &Fett - Ctrl+B + %1+B Strg+F @@ -5085,7 +5085,7 @@ Grund: »%2« &Kursiv - Ctrl+I + %1+I Strg+K @@ -5093,7 +5093,7 @@ Grund: »%2« &Unterstrichen - Ctrl+U + %1+U Strg+U @@ -5101,7 +5101,7 @@ Grund: »%2« &Links - Ctrl+L + %1+L Strg+L @@ -5109,7 +5109,7 @@ Grund: »%2« Z&entriert - Ctrl+E + %1+E Strg+Z @@ -5117,7 +5117,7 @@ Grund: »%2« &Rechts - Ctrl+R + %1+R Strg+R @@ -5125,7 +5125,7 @@ Grund: »%2« &Blocksatz - Ctrl+J + %1+J Strg+J @@ -5360,7 +5360,7 @@ Grund: »%2« Einfügen - Mute/unmute (<Ctrl> + middle click) + Mute/unmute (<%1> + middle click) Stumm/Laut schalten (<Strg> + Mittelklick) @@ -5963,11 +5963,11 @@ Latenz: %2 ms Tipp - Press <Ctrl> to disable magnetic loop points. + Press <%1> to disable magnetic loop points. Drücken Sie <Strg>, um magnetische Loop-Punkte zu deaktivieren. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. Halten Sie <Umschalt>, um den Anfangs-Loop-Punkt zu verschieben; Drücken Sie <Strg>, um magnetische Loop-Punkte zu deaktivieren. @@ -6043,7 +6043,7 @@ Bitte stellen Sie sicher, dass Sie Leserechte auf diese Datei sowie das Verzeich Tipp - Press <Ctrl> and drag to make a copy. + Press <%1> and drag to make a copy. <Strg> drücken und ziehen, um eine Kopie zu erstellen. @@ -6051,7 +6051,7 @@ Bitte stellen Sie sicher, dass Sie Leserechte auf diese Datei sowie das Verzeich Aktuelle Länge - Press <Ctrl> for free resizing. + Press <%1> for free resizing. Drücken Sie <Strg> für freie Größenänderung. @@ -6075,14 +6075,14 @@ Bitte stellen Sie sicher, dass Sie Leserechte auf diese Datei sowie das Verzeich Einfügen - Mute/unmute (<Ctrl> + middle click) + Mute/unmute (<%1> + middle click) Stumm/Laut schalten (<Strg> + Mittelklick) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. Drücken Sie <Strg> während des Klicks auf den Verschiebe-Griff, um eine neue Klicken und Ziehen-Aktion zu beginnen. diff --git a/data/locale/en.ts b/data/locale/en.ts index 7774bc923d7..36bbc7a91eb 100644 --- a/data/locale/en.ts +++ b/data/locale/en.ts @@ -421,15 +421,15 @@ If you're interested in translating LMMS in another language or want to imp - Cut selected values (Ctrl+X) + Cut selected values (%1+X) - Copy selected values (Ctrl+C) + Copy selected values (%1+C) - Paste values from clipboard Ctrl+V) + Paste values from clipboard (%1+V) @@ -460,7 +460,7 @@ If you're interested in translating LMMS in another language or want to imp AutomationPattern - Drag a control while pressing <Ctrl> + Drag a control while pressing <%1> @@ -4862,7 +4862,7 @@ use mouse wheel to set volume of a step - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. @@ -4870,7 +4870,7 @@ use mouse wheel to set volume of a step - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. @@ -4878,15 +4878,15 @@ use mouse wheel to set volume of a step - Cut selected notes (Ctrl+X) + Cut selected notes (%1+X) - Copy selected notes (Ctrl+C) + Copy selected notes (%1+C) - Paste notes from clipboard (Ctrl+V) + Paste notes from clipboard (%1+V) @@ -4987,7 +4987,7 @@ Reason: "%2" - Ctrl+Z + %1+Z @@ -4995,7 +4995,7 @@ Reason: "%2" - Ctrl+Y + %1+Y @@ -5003,7 +5003,7 @@ Reason: "%2" - Ctrl+C + %1+C @@ -5011,7 +5011,7 @@ Reason: "%2" - Ctrl+X + %1+X @@ -5019,7 +5019,7 @@ Reason: "%2" - Ctrl+V + %1+V @@ -5031,7 +5031,7 @@ Reason: "%2" - Ctrl+B + %1+B @@ -5039,7 +5039,7 @@ Reason: "%2" - Ctrl+I + %1+I @@ -5047,7 +5047,7 @@ Reason: "%2" - Ctrl+U + %1+U @@ -5055,7 +5055,7 @@ Reason: "%2" - Ctrl+L + %1+L @@ -5063,7 +5063,7 @@ Reason: "%2" - Ctrl+E + %1+E @@ -5071,7 +5071,7 @@ Reason: "%2" - Ctrl+R + %1+R @@ -5079,7 +5079,7 @@ Reason: "%2" - Ctrl+J + %1+J @@ -5314,7 +5314,7 @@ Reason: "%2" - Mute/unmute (<Ctrl> + middle click) + Mute/unmute (<%1> + middle click) @@ -5916,11 +5916,11 @@ Latency: %2 ms - Press <Ctrl> to disable magnetic loop points. + Press <%1> to disable magnetic loop points. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. @@ -5994,7 +5994,7 @@ Please make sure you have read-permission to the file and the directory containi - Press <Ctrl> and drag to make a copy. + Press <%1> and drag to make a copy. @@ -6002,7 +6002,7 @@ Please make sure you have read-permission to the file and the directory containi - Press <Ctrl> for free resizing. + Press <%1> for free resizing. @@ -6026,14 +6026,14 @@ Please make sure you have read-permission to the file and the directory containi - Mute/unmute (<Ctrl> + middle click) + Mute/unmute (<%1> + middle click) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. diff --git a/data/locale/es.ts b/data/locale/es.ts index 020807c88ea..ac0a5d7a280 100644 --- a/data/locale/es.ts +++ b/data/locale/es.ts @@ -421,15 +421,15 @@ If you're interested in translating LMMS in another language or want to imp - Cut selected values (Ctrl+X) + Cut selected values (%1+X) - Copy selected values (Ctrl+C) + Copy selected values (%1+C) - Paste values from clipboard Ctrl+V) + Paste values from clipboard (%1+V) @@ -460,7 +460,7 @@ If you're interested in translating LMMS in another language or want to imp AutomationPattern - Drag a control while pressing <Ctrl> + Drag a control while pressing <%1> @@ -4862,7 +4862,7 @@ use mouse wheel to set volume of a step - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. @@ -4870,7 +4870,7 @@ use mouse wheel to set volume of a step - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. @@ -4878,16 +4878,16 @@ use mouse wheel to set volume of a step - Cut selected notes (Ctrl+X) - Cortar las notas seleccionadas (Ctrl+X) + Cut selected notes (%1+X) + Cortar las notas seleccionadas (%1+X) - Copy selected notes (Ctrl+C) - Copiar las notas seleccionadas (Ctrl+C) + Copy selected notes (%1+C) + Copiar las notas seleccionadas (%1+C) - Paste notes from clipboard (Ctrl+V) - Pegar notas desde el portapapeles (Ctrl+V) + Paste notes from clipboard (%1+V) + Pegar notas desde el portapapeles (%1+V) Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -4987,40 +4987,40 @@ Reason: "%2" &Deshacer - Ctrl+Z - Ctrl+Z + %1+Z + %1+Z &Redo &Rehacer - Ctrl+Y - Ctrl+Y + %1+Y + %1+Y &Copy &Copiar - Ctrl+C - Ctrl+C + %1+C + %1+C Cu&t Cortar(&X) - Ctrl+X - Ctrl+X + %1+X + %1+X &Paste &Pegar - Ctrl+V - Ctrl+V + %1+V + %1+V Format Actions @@ -5031,56 +5031,56 @@ Reason: "%2" &Negrita - Ctrl+B - Ctrl+B + %1+B + %1+B &Italic &Cursiva - Ctrl+I - Ctrl+I + %1+I + %1+I &Underline &Subrayado - Ctrl+U - Ctrl+U + %1+U + %1+U &Left &Izquierda - Ctrl+L - Ctrl+L + %1+L + %1+L C&enter C&entrar - Ctrl+E - Ctrl+E + %1+E + %1+E &Right &Derecha - Ctrl+R - Ctrl+R + %1+R + %1+R &Justify &Justificar - Ctrl+J - Ctrl+J + %1+J + %1+J &Color... @@ -5314,7 +5314,7 @@ Reason: "%2" Pegar - Mute/unmute (<Ctrl> + middle click) + Mute/unmute (<%1> + middle click) @@ -5916,11 +5916,11 @@ Latency: %2 ms - Press <Ctrl> to disable magnetic loop points. + Press <%1> to disable magnetic loop points. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. @@ -5994,7 +5994,7 @@ Please make sure you have read-permission to the file and the directory containi - Press <Ctrl> and drag to make a copy. + Press <%1> and drag to make a copy. @@ -6002,7 +6002,7 @@ Please make sure you have read-permission to the file and the directory containi - Press <Ctrl> for free resizing. + Press <%1> for free resizing. @@ -6026,14 +6026,14 @@ Please make sure you have read-permission to the file and the directory containi Pegar - Mute/unmute (<Ctrl> + middle click) + Mute/unmute (<%1> + middle click) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. diff --git a/data/locale/fa.ts b/data/locale/fa.ts index cd8d4f90571..725bdff69cc 100644 --- a/data/locale/fa.ts +++ b/data/locale/fa.ts @@ -421,15 +421,15 @@ If you're interested in translating LMMS in another language or want to imp - Cut selected values (Ctrl+X) + Cut selected values (%1+X) - Copy selected values (Ctrl+C) + Copy selected values (%1+C) - Paste values from clipboard Ctrl+V) + Paste values from clipboard (%1+V) @@ -460,7 +460,7 @@ If you're interested in translating LMMS in another language or want to imp AutomationPattern - Drag a control while pressing <Ctrl> + Drag a control while pressing <%1> @@ -4862,7 +4862,7 @@ use mouse wheel to set volume of a step - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. @@ -4870,7 +4870,7 @@ use mouse wheel to set volume of a step - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. @@ -4878,15 +4878,15 @@ use mouse wheel to set volume of a step - Cut selected notes (Ctrl+X) + Cut selected notes (%1+X) برش نت های انتخاب شده(Ctrl+X) - Copy selected notes (Ctrl+C) + Copy selected notes (%1+C) کپی نت های انتخاب شده(Ctrl+C) - Paste notes from clipboard (Ctrl+V) + Paste notes from clipboard (%1+V) چسباندن نت ها از حافظه ی موقت(Ctrl+V) @@ -4987,40 +4987,40 @@ Reason: "%2" &واچینی - Ctrl+Z - Ctrl+Z + %1+Z + %1+Z &Redo &بازچینی - Ctrl+Y - Ctrl+Y + %1+Y + %1+Y &Copy &کپی - Ctrl+C - Ctrl+C + %1+C + %1+C Cu&t &برش - Ctrl+X - Ctrl+X + %1+X + %1+X &Paste &چسباندن - Ctrl+V - Ctrl+V + %1+V + %1+V Format Actions @@ -5031,56 +5031,56 @@ Reason: "%2" &برجسته - Ctrl+B - Ctrl+B + %1+B + %1+B &Italic &خوابیده - Ctrl+I - Ctrl+I + %1+I + %1+I &Underline &زیرخط - Ctrl+U - Ctrl+U + %1+U + %1+U &Left &چپ - Ctrl+L - Ctrl+L + %1+L + %1+L C&enter &مرکز - Ctrl+E - Ctrl+E + %1+E + %1+E &Right &راست - Ctrl+R - Ctrl+R + %1+R + %1+R &Justify &تراز - Ctrl+J - Ctrl+J + %1+J + %1+J &Color... @@ -5314,7 +5314,7 @@ Reason: "%2" چسباندن - Mute/unmute (<Ctrl> + middle click) + Mute/unmute (<%1> + middle click) @@ -5916,11 +5916,11 @@ Latency: %2 ms - Press <Ctrl> to disable magnetic loop points. + Press <%1> to disable magnetic loop points. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. @@ -5994,7 +5994,7 @@ Please make sure you have read-permission to the file and the directory containi - Press <Ctrl> and drag to make a copy. + Press <%1> and drag to make a copy. @@ -6002,7 +6002,7 @@ Please make sure you have read-permission to the file and the directory containi - Press <Ctrl> for free resizing. + Press <%1> for free resizing. @@ -6026,14 +6026,14 @@ Please make sure you have read-permission to the file and the directory containi چسباندن - Mute/unmute (<Ctrl> + middle click) + Mute/unmute (<%1> + middle click) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. diff --git a/data/locale/fr.ts b/data/locale/fr.ts index e3b21e53820..c27aace22a1 100644 --- a/data/locale/fr.ts +++ b/data/locale/fr.ts @@ -421,16 +421,16 @@ If you're interested in translating LMMS in another language or want to imp Cliquez ici pour choisir la progression cubique de Hermite pour ce motif d'automation. La valeur de l'objet connecté changera suivant une courbe lisse et adoucira les pics et les creux. - Cut selected values (Ctrl+X) - Couper les valeurs sélectionnées (Ctrl+X) + Cut selected values (%1+X) + Couper les valeurs sélectionnées (%1+X) - Copy selected values (Ctrl+C) - Copier les valeurs sélectionnées (Ctrl+C) + Copy selected values (%1+C) + Copier les valeurs sélectionnées (%1+C) - Paste values from clipboard Ctrl+V) - Coller les valeurs depuis le presse-papier (Ctrl+V) + Paste values from clipboard (%1+V) + Coller les valeurs depuis le presse-papier (%1+V) Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -464,8 +464,8 @@ If you're interested in translating LMMS in another language or want to imp AutomationPattern - Drag a control while pressing <Ctrl> - Déplacer un contrôle en appuyant sur <Ctrl> + Drag a control while pressing <%1> + Déplacer un contrôle en appuyant sur <%1> @@ -3922,11 +3922,11 @@ Veuillez visiter http://lmms.sf.net/wiki pour la documentation de LMMS.Modulation - Breath Ctrl + Breath %1 Contrôle par le souffle - Foot Ctrl + Foot %1 Contrôle par pédale @@ -5376,32 +5376,32 @@ utilisez la molette de la souris pour régler le volume d'un pasMode désaccordage (Shift+T) - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. - Cliquez ici et le mode dessin sera activé. Dans ce mode vous pourrez ajouter, redimensionner et déplacer des notes. Ceci est le mode par défaut qui est utilisé la plupart du temps. Vous pouvez aussi appuyer sur les touches 'Shift+D' de votre clavier pour activer ce mode. Dans ce mode, appuyez sur Ctrl pour passer temporairement dans le mode sélection. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. + Cliquez ici et le mode dessin sera activé. Dans ce mode vous pourrez ajouter, redimensionner et déplacer des notes. Ceci est le mode par défaut qui est utilisé la plupart du temps. Vous pouvez aussi appuyer sur les touches 'Shift+D' de votre clavier pour activer ce mode. Dans ce mode, appuyez sur %1 pour passer temporairement dans le mode sélection. Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. Cliquez ici et le mode effacement sera activé. Dans ce mode vous pourrez effacer des notes. Vous pouvez aussi appuyer sur les touches 'Shift+E' de votre clavier pour activer ce mode. - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. - Cliquez ici et le mode sélection sera activé. Dans ce mode vous pourrez sélectionner des notes. Dans ce mode, appuyez appuyer sur Ctrl pour passer temporairement en mode dessin. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. + Cliquez ici et le mode sélection sera activé. Dans ce mode vous pourrez sélectionner des notes. Dans ce mode, appuyez appuyer sur %1 pour passer temporairement en mode dessin. Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. Cliquez ici et le mode désaccordage sera activé. Dans ce mode vous pourrer cliquer sur une note pour accéder à l'automation de son désaccordage. Vous pouvez utiliser ceci pour lier des notes entre-elles. Vous pouvez aussi appuyer sur les touches 'Shift+T' de votre clavier pour activer ce mode. - Cut selected notes (Ctrl+X) - Couper les notes sélectionnées (Ctrl+X) + Cut selected notes (%1+X) + Couper les notes sélectionnées (%1+X) - Copy selected notes (Ctrl+C) - Copier les notes sélectionnées (Ctrl+C) + Copy selected notes (%1+C) + Copier les notes sélectionnées (%1+C) - Paste notes from clipboard (Ctrl+V) - Coller les notes se trouvant dans le presse-papier (Ctrl+V) + Paste notes from clipboard (%1+V) + Coller les notes se trouvant dans le presse-papier (%1+V) Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -5502,40 +5502,40 @@ Raison : "%2" &Défaire - Ctrl+Z - Ctrl+Z + %1+Z + %1+Z &Redo &Refaire - Ctrl+Y - Ctrl+Y + %1+Y + %1+Y &Copy &Copier - Ctrl+C - Ctrl+C + %1+C + %1+C Cu&t Cou&per - Ctrl+X - Ctrl+X + %1+X + %1+X &Paste Co&ller - Ctrl+V - Ctrl+V + %1+V + %1+V Format Actions @@ -5546,56 +5546,56 @@ Raison : "%2" Gr&as - Ctrl+B - Ctrl+B + %1+B + %1+B &Italic &Italique - Ctrl+I - Ctrl+I + %1+I + %1+I &Underline &Souligné - Ctrl+U - Ctrl+U + %1+U + %1+U &Left &Gauche - Ctrl+L - Ctrl+L + %1+L + %1+L C&enter C&entrer - Ctrl+E - Ctrl+E + %1+E + %1+E &Right D&roite - Ctrl+R - Ctrl+R + %1+R + %1+R &Justify &Justifier - Ctrl+J - Ctrl+J + %1+J + %1+J &Color... @@ -5829,8 +5829,8 @@ Raison : "%2" Coller - Mute/unmute (<Ctrl> + middle click) - Couper/Jouer (<Ctrl> + clic-milieu) + Mute/unmute (<%1> + middle click) + Couper/Jouer (<%1> + clic-milieu) Set/clear record @@ -6465,12 +6465,12 @@ Veuillez vérifier que vous avez les droits en lecture pour ce fichier et le ré Astuce - Press <Ctrl> to disable magnetic loop points. - Appuyez sur <Ctrl> pour désactiver les marqueur magnétiques de jeu en boucle. + Press <%1> to disable magnetic loop points. + Appuyez sur <%1> pour désactiver les marqueur magnétiques de jeu en boucle. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. - Maintenez <Shift> pour déplacer le marqueur de début de jeu en boucle. Appuyez sur <Ctrl> pour désactiver les marqueurs magnétiques de jeu en boucle. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. + Maintenez <Shift> pour déplacer le marqueur de début de jeu en boucle. Appuyez sur <%1> pour désactiver les marqueurs magnétiques de jeu en boucle. @@ -6545,16 +6545,16 @@ Veuillez vérifier que vous avez les droits en lecture pour ce fichier et le ré Astuce - Press <Ctrl> and drag to make a copy. - Appuyez sur <Ctrl> et glissez pour faire une copie. + Press <%1> and drag to make a copy. + Appuyez sur <%1> et glissez pour faire une copie. Current length Longueur actuelle - Press <Ctrl> for free resizing. - Appuyez sur <Ctrl> pour un redimensionnement libre. + Press <%1> for free resizing. + Appuyez sur <%1> pour un redimensionnement libre. %1:%2 (%3:%4 to %5:%6) @@ -6577,15 +6577,15 @@ Veuillez vérifier que vous avez les droits en lecture pour ce fichier et le ré Coller - Mute/unmute (<Ctrl> + middle click) - Couper/Jouer (<Ctrl> + clic-milieu) + Mute/unmute (<%1> + middle click) + Couper/Jouer (<%1> + clic-milieu) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. - Appuyez sur <Ctrl> en cliquant sur la poignée de déplacement pour commencer un nouveau glisser/déposer. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + Appuyez sur <%1> en cliquant sur la poignée de déplacement pour commencer un nouveau glisser/déposer. Actions for this track diff --git a/data/locale/gl.ts b/data/locale/gl.ts index 738561f236e..7b95181b9db 100644 --- a/data/locale/gl.ts +++ b/data/locale/gl.ts @@ -423,15 +423,15 @@ Se lle interesa traducir o LMMS a outro idioma ou desexa mellorar as traducións - Cut selected values (Ctrl+X) - Recortar os valores escollidos (Ctrl+X) + Cut selected values (%1+X) + Recortar os valores escollidos (%1+X) - Copy selected values (Ctrl+C) - Copiar os valores escollidos (Ctrl+C) + Copy selected values (%1+C) + Copiar os valores escollidos (%1+C) - Paste values from clipboard Ctrl+V) + Paste values from clipboard (%1+V) @@ -462,8 +462,8 @@ Se lle interesa traducir o LMMS a outro idioma ou desexa mellorar as traducións AutomationPattern - Drag a control while pressing <Ctrl> - Arrastre un control mentres ten <Ctrl> premido + Drag a control while pressing <%1> + Arrastre un control mentres ten <%1> premido Model is already connected to this pattern. @@ -4879,32 +4879,32 @@ empregue a roda do rato para modificar o volume un paso Modo de desafinación (Maiúsculas+T) - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. - Prema aquí e o activarase o modo de debuxo. Neste modo pode engadir e mover valores individuais. Este é o modo por omisión que se emprega a maior parte do tempo. Tamén pode premer «Maiúsculas+D» no teclado para activar este modo. Neste modo, manteña Ctrl para ir temporalmente ao modo de selección. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. + Prema aquí e o activarase o modo de debuxo. Neste modo pode engadir e mover valores individuais. Este é o modo por omisión que se emprega a maior parte do tempo. Tamén pode premer «Maiúsculas+D» no teclado para activar este modo. Neste modo, manteña %1 para ir temporalmente ao modo de selección. Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. Prema aquí e activarase o modo de borrado. Neste modo pódense borrar valores individuais. Tamén pode premer «Maiúsculas+E» no teclado para activar este modo. - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. - Prema aquí e activarase o modo de borrado. Neste modo pódense borrar valores individuais. Como alternativa pode premer Ctrl no modo de debuxo para empregar temporalmente o modo de selección. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. + Prema aquí e activarase o modo de borrado. Neste modo pódense borrar valores individuais. Como alternativa pode premer %1 no modo de debuxo para empregar temporalmente o modo de selección. Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. Prema aquí e actívase o modo de desafinación.Neste modo pódese premer unhanota para abrir a súa desafinación de automatización. Pódese empregar isto para escorregar entre as notas. Tamén se pode premer «Maiúsculas+T» no teclado para activar este mdo. - Cut selected notes (Ctrl+X) - Recortar as notas escollidas (Ctrl+X) + Cut selected notes (%1+X) + Recortar as notas escollidas (%1+X) - Copy selected notes (Ctrl+C) - Copiar as notas escollidas (Ctrl+C) + Copy selected notes (%1+C) + Copiar as notas escollidas (%1+C) - Paste notes from clipboard (Ctrl+V) - Apegar as notas do porta-retallos (Ctrl+V) + Paste notes from clipboard (%1+V) + Apegar as notas do porta-retallos (%1+V) Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -5005,40 +5005,40 @@ Razón: «%2» Desfa&cer - Ctrl+Z - Ctrl+Z + %1+Z + %1+Z &Redo &Refacer - Ctrl+Y - Ctrl+Y + %1+Y + %1+Y &Copy &Copiar - Ctrl+C - Ctrl+C + %1+C + %1+C Cu&t Cor&tar - Ctrl+X - Ctrl+X + %1+X + %1+X &Paste A&pegar - Ctrl+V - Ctrl+V + %1+V + %1+V Format Actions @@ -5049,56 +5049,56 @@ Razón: «%2» &Negrita - Ctrl+B - Ctrl+B + %1+B + %1+B &Italic Cursi&va - Ctrl+I - Ctrl+I + %1+I + %1+I &Underline S&ubliñado - Ctrl+U - Ctrl+U + %1+U + %1+U &Left &Esquerda - Ctrl+L - Ctrl+L + %1+L + %1+L C&enter C&entro - Ctrl+E - Ctrl+E + %1+E + %1+E &Right De&reita - Ctrl+R - Ctrl+R + %1+R + %1+R &Justify &Xustificar - Ctrl+J - Ctrl+J + %1+J + %1+J &Color... @@ -5332,8 +5332,8 @@ Razón: «%2» Apegar - Mute/unmute (<Ctrl> + middle click) - Silenciar/Darlle volume (<Ctrl> + botón central do rato) + Mute/unmute (<%1> + middle click) + Silenciar/Darlle volume (<%1> + botón central do rato) Set/clear record @@ -5935,11 +5935,11 @@ Latencia: %2 ms Suxestión - Press <Ctrl> to disable magnetic loop points. + Press <%1> to disable magnetic loop points. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. @@ -6015,16 +6015,16 @@ Asegúrese de ter permiso de lectura sobre o ficheiro e o directorio que o cont Suxestión - Press <Ctrl> and drag to make a copy. - Prema <Ctrl> e arrastre para facer unha copia. + Press <%1> and drag to make a copy. + Prema <%1> e arrastre para facer unha copia. Current length Duración actual - Press <Ctrl> for free resizing. - Prema <Ctrl> para modificar o tamaño libremente + Press <%1> for free resizing. + Prema <%1> para modificar o tamaño libremente %1:%2 (%3:%4 to %5:%6) @@ -6047,15 +6047,15 @@ Asegúrese de ter permiso de lectura sobre o ficheiro e o directorio que o cont Apegar - Mute/unmute (<Ctrl> + middle click) - Silenciar/Darlle volume (<Ctrl> + botón central do rato) + Mute/unmute (<%1> + middle click) + Silenciar/Darlle volume (<%1> + botón central do rato) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. - Prema <Ctrl> mentres ten a asa de mover premida para iniciar unha acción de arrastrar e soltar. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + Prema <%1> mentres ten a asa de mover premida para iniciar unha acción de arrastrar e soltar. Actions for this track diff --git a/data/locale/it.ts b/data/locale/it.ts index 39829804fc6..55ca5feb50e 100644 --- a/data/locale/it.ts +++ b/data/locale/it.ts @@ -424,15 +424,15 @@ Se sei interessato a tradurre LMMS o vuoi migliorare una traduzione esistente, s Clicca qui per scegliere il metodo di progressione a cubica di Hermite per questo pattern di automazione. Il valore della variabile connessa cambierà seguendo una curva morbida. - Cut selected values (Ctrl+X) - Taglia i valori selezionati (Ctrl+X) + Cut selected values (%1+X) + Taglia i valori selezionati (%1+X) - Copy selected values (Ctrl+C) - Copia i valori selezionati (Ctrl+C) + Copy selected values (%1+C) + Copia i valori selezionati (%1+C) - Paste values from clipboard Ctrl+V) + Paste values from clipboard (%1+V) @@ -463,8 +463,8 @@ Se sei interessato a tradurre LMMS o vuoi migliorare una traduzione esistente, s AutomationPattern - Drag a control while pressing <Ctrl> - Trascina un controllo tenendo premuto <Ctrl> + Drag a control while pressing <%1> + Trascina un controllo tenendo premuto <%1> Model is already connected to this pattern. @@ -4903,7 +4903,7 @@ la rotellina del mouse impostare il volume delle note Modalità intonanzione (Shift+T) - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. Cliccando qui si attiva la modalità disegno. In questa modalità è possibile aggiungere e spostare singoli valori. Questa è la modalità predefinita, che viene usata la maggior parte del tempo. Questa modalità si attiva anche premendo la combinazione di tasti 'Shift+D'. Tieni premuto Ctfl per andare temporaneamente in modalità selezione. @@ -4911,24 +4911,24 @@ la rotellina del mouse impostare il volume delle note Cliccando qui si attiva la modalità cancellazione. In questa modalità è possibile cancellare singoli valori. Questa modalità si attiva anche premendo la combinazione di tasti 'Shift+E'. - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. - Cliccando qui viene attivata la modalità selezione. Puoi selezionare le note. Puoi anche tenere premuto Ctrl durante la modalità disegno per usare la modalità selezione temporaneamente. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. + Cliccando qui viene attivata la modalità selezione. Puoi selezionare le note. Puoi anche tenere premuto %1 durante la modalità disegno per usare la modalità selezione temporaneamente. Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. Cliccando qui viene attivata la modalità intonazione. Puoi cliccare una nota per aprire la finestra di automazione dell'intonazione. Puoi usare questa modalità per fare uno slide da una nota ad un'altra. Puoi anche premere Shift+T per attivare questa modalità. - Cut selected notes (Ctrl+X) - Taglia le note selezionate (Ctrl+X) + Cut selected notes (%1+X) + Taglia le note selezionate (%1+X) - Copy selected notes (Ctrl+C) - Copia le note selezionate (Ctrl+C) + Copy selected notes (%1+C) + Copia le note selezionate (%1+C) - Paste notes from clipboard (Ctrl+V) - Incolla le note selezionate (Ctrl+V) + Paste notes from clipboard (%1+V) + Incolla le note selezionate (%1+V) Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -5029,40 +5029,40 @@ Motivo: "%2" &Annulla operazione - Ctrl+Z - Ctrl+Z + %1+Z + %1+Z &Redo &Ripeti operazione - Ctrl+Y - Ctrl+Y + %1+Y + %1+Y &Copy &Copia - Ctrl+C - Ctrl+C + %1+C + %1+C Cu&t &Taglia - Ctrl+X - Ctrl+X + %1+X + %1+X &Paste &Incolla - Ctrl+V - Ctrl+V + %1+V + %1+V Format Actions @@ -5073,56 +5073,56 @@ Motivo: "%2" &Grassetto - Ctrl+B - Ctrl+B + %1+B + %1+B &Italic &Corsivo - Ctrl+I - Ctrl+I + %1+I + %1+I &Underline &Sottolineato - Ctrl+U - Ctrl+U + %1+U + %1+U &Left &Sinistra - Ctrl+L - Ctrl+L + %1+L + %1+L C&enter &Centro - Ctrl+E - Ctrl+E + %1+E + %1+E &Right &Destra - Ctrl+R - Ctrl+R + %1+R + %1+R &Justify &Giustifica - Ctrl+J - Ctrl+J + %1+J + %1+J &Color... @@ -5356,8 +5356,8 @@ Motivo: "%2" Incolla - Mute/unmute (<Ctrl> + middle click) - Attiva/disattiva la modalità muta (<Ctrl> + tasto centrale) + Mute/unmute (<%1> + middle click) + Attiva/disattiva la modalità muta (<%1> + tasto centrale) Set/clear record @@ -5960,12 +5960,12 @@ Assicurati di avere almeno i permessi di lettura del file e prova di nuovo.Suggerimento - Press <Ctrl> to disable magnetic loop points. - Premi <Ctrl> per disabilitare i punti di loop magnetici. + Press <%1> to disable magnetic loop points. + Premi <%1> per disabilitare i punti di loop magnetici. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. - Tieni premuto <Shift> per spostare l'inizio del punto di loop; premi <Ctrl> per disabilitare i punti di loop magnetici. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. + Tieni premuto <Shift> per spostare l'inizio del punto di loop; premi <%1> per disabilitare i punti di loop magnetici. @@ -6040,16 +6040,16 @@ Assicurarsi di avere i permessi in lettura per il file e per la directory che lo Suggerimento - Press <Ctrl> and drag to make a copy. - Premere <Ctrl>, cliccare e trascinare per copiare. + Press <%1> and drag to make a copy. + Premere <%1>, cliccare e trascinare per copiare. Current length Lunghezza attuale - Press <Ctrl> for free resizing. - Premere <Ctrl> per ridimensionare liberamente. + Press <%1> for free resizing. + Premere <%1> per ridimensionare liberamente. %1:%2 (%3:%4 to %5:%6) @@ -6072,15 +6072,15 @@ Assicurarsi di avere i permessi in lettura per il file e per la directory che lo Incolla - Mute/unmute (<Ctrl> + middle click) - Attiva/disattiva la modalità muta (<Ctrl> + tasto centrale) + Mute/unmute (<%1> + middle click) + Attiva/disattiva la modalità muta (<%1> + tasto centrale) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. - Premere <Ctrl> mentre si clicca sulla maniglia per lo spostamento per iniziare una nuova azione di drag'n'drop. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + Premere <%1> mentre si clicca sulla maniglia per lo spostamento per iniziare una nuova azione di drag'n'drop. Actions for this track diff --git a/data/locale/ja.ts b/data/locale/ja.ts index 41c591d3835..c9660cf1bb1 100644 --- a/data/locale/ja.ts +++ b/data/locale/ja.ts @@ -423,15 +423,15 @@ If you're interested in translating LMMS in another language or want to imp - Cut selected values (Ctrl+X) + Cut selected values (%1+X) 選択した値を切り取り (Shift+M) - Copy selected values (Ctrl+C) - 選択した値をコピー (Ctrl+C) + Copy selected values (%1+C) + 選択した値をコピー (%1+C) - Paste values from clipboard Ctrl+V) + Paste values from clipboard (%1+V) @@ -462,8 +462,8 @@ If you're interested in translating LMMS in another language or want to imp AutomationPattern - Drag a control while pressing <Ctrl> - <Ctrl>を押しながらコントロールをドラッグしてください + Drag a control while pressing <%1> + <%1>を押しながらコントロールをドラッグしてください Model is already connected to this pattern. @@ -4881,32 +4881,32 @@ use mouse wheel to set volume of a step ディチューン モード (Shift+T) - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. - ここをクリックすると描画モードになります。描画モードでは個々のノートを追加・リサイズ・移動することができます。普段このモードをデフォルトで使用します。'Shift+D' を押してもこのモードになります。このモードではCtrlを長押しすることで一時的に選択モードにすることができます。 + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. + ここをクリックすると描画モードになります。描画モードでは個々のノートを追加・リサイズ・移動することができます。普段このモードをデフォルトで使用します。'Shift+D' を押してもこのモードになります。このモードでは%1を長押しすることで一時的に選択モードにすることができます。 Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. ここをクリックすると消去モードになります。消去モードでは個々のノートを消去することができます。'Shift+E' を押してもこのモードにすることができます。 - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. - ここをクリックすると選択モードになります。選択モードでは個々のノートを選択することができます。また、描画モード中にCtrlを長押しすることで一時的に選択モードを使用することができます。 + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. + ここをクリックすると選択モードになります。選択モードでは個々のノートを選択することができます。また、描画モード中に%1を長押しすることで一時的に選択モードを使用することができます。 Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. - Cut selected notes (Ctrl+X) - 選択したノートの切り取り (Ctrl+X) + Cut selected notes (%1+X) + 選択したノートの切り取り (%1+X) - Copy selected notes (Ctrl+C) - 選択したノートのコピー (Ctrl+C) + Copy selected notes (%1+C) + 選択したノートのコピー (%1+C) - Paste notes from clipboard (Ctrl+V) - クリップボードからノートを貼り付け (Ctrl+V) + Paste notes from clipboard (%1+V) + クリップボードからノートを貼り付け (%1+V) Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -5007,40 +5007,40 @@ Reason: "%2" 元に戻す(&U) - Ctrl+Z - Ctrl+Z + %1+Z + %1+Z &Redo やり直し(&R) - Ctrl+Y - Ctrl+Y + %1+Y + %1+Y &Copy コピー(&C) - Ctrl+C - Ctrl+C + %1+C + %1+C Cu&t 切り取り(&t) - Ctrl+X - Ctrl+X + %1+X + %1+X &Paste 貼り付け(&P) - Ctrl+V - Ctrl+V + %1+V + %1+V Format Actions @@ -5051,56 +5051,56 @@ Reason: "%2" 太字(&B) - Ctrl+B - Ctrl+B + %1+B + %1+B &Italic 斜体(&I) - Ctrl+I - Ctrl+I + %1+I + %1+I &Underline 下線(&U) - Ctrl+U - Ctrl+U + %1+U + %1+U &Left 左揃え(&L) - Ctrl+L - Ctrl+L + %1+L + %1+L C&enter 中央揃え(&e) - Ctrl+E - Ctrl+E + %1+E + %1+E &Right 右揃え(&R) - Ctrl+R - Ctrl+R + %1+R + %1+R &Justify 両端揃え(&J) - Ctrl+J - Ctrl+J + %1+J + %1+J &Color... @@ -5334,8 +5334,8 @@ Reason: "%2" 貼り付け - Mute/unmute (<Ctrl> + middle click) - ミュート/ミュート解除(<Ctrl> + 中ボタンクリック) + Mute/unmute (<%1> + middle click) + ミュート/ミュート解除(<%1> + 中ボタンクリック) Set/clear record @@ -5938,11 +5938,11 @@ Latency: %2 ms ヒント - Press <Ctrl> to disable magnetic loop points. - マグネティック ループポイントを無効化するには<Ctrl>を押してください。 + Press <%1> to disable magnetic loop points. + マグネティック ループポイントを無効化するには<%1>を押してください。 - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. @@ -6018,16 +6018,16 @@ Please make sure you have read-permission to the file and the directory containi ヒント - Press <Ctrl> and drag to make a copy. - コピーするには<Ctrl>を押しながらドラッグしてください。 + Press <%1> and drag to make a copy. + コピーするには<%1>を押しながらドラッグしてください。 Current length 現在の長さ - Press <Ctrl> for free resizing. - フリーズ解除には<Ctrl>を押してください。 + Press <%1> for free resizing. + フリーズ解除には<%1>を押してください。 %1:%2 (%3:%4 to %5:%6) @@ -6050,15 +6050,15 @@ Please make sure you have read-permission to the file and the directory containi 貼り付け - Mute/unmute (<Ctrl> + middle click) - ミュート/ミュート解除(<Ctrl> + 中ボタンクリック) + Mute/unmute (<%1> + middle click) + ミュート/ミュート解除(<%1> + 中ボタンクリック) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. - 新しいドラッグ&ドロップアクションを開始するには、移動グリップをクリック中に <Ctrl>を押してください。 + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + 新しいドラッグ&ドロップアクションを開始するには、移動グリップをクリック中に <%1>を押してください。 Actions for this track diff --git a/data/locale/ko.ts b/data/locale/ko.ts index 93c7a7e46e7..91186d45679 100644 --- a/data/locale/ko.ts +++ b/data/locale/ko.ts @@ -421,15 +421,15 @@ If you're interested in translating LMMS in another language or want to imp - Cut selected values (Ctrl+X) - 선택된 값 잘라내기 (Ctrl+X) + Cut selected values (%1+X) + 선택된 값 잘라내기 (%1+X) - Copy selected values (Ctrl+C) - 선택된 값 복사 (Ctrl+C) + Copy selected values (%1+C) + 선택된 값 복사 (%1+C) - Paste values from clipboard Ctrl+V) + Paste values from clipboard (%1+V) @@ -460,8 +460,8 @@ If you're interested in translating LMMS in another language or want to imp AutomationPattern - Drag a control while pressing <Ctrl> - <Ctrl> 누르는 동안 제어를 끌기 + Drag a control while pressing <%1> + <%1> 누르는 동안 제어를 끌기 Model is already connected to this pattern. @@ -4864,7 +4864,7 @@ use mouse wheel to set volume of a step - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. @@ -4872,7 +4872,7 @@ use mouse wheel to set volume of a step - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. @@ -4880,16 +4880,16 @@ use mouse wheel to set volume of a step - Cut selected notes (Ctrl+X) - 선택 박자를 잘라내기 (Ctrl+X) + Cut selected notes (%1+X) + 선택 박자를 잘라내기 (%1+X) - Copy selected notes (Ctrl+C) - 선택 박자를 복사 (Ctrl+C) + Copy selected notes (%1+C) + 선택 박자를 복사 (%1+C) - Paste notes from clipboard (Ctrl+V) - 클립보드에서 박자 붙여넣기 (Ctrl+V) + Paste notes from clipboard (%1+V) + 클립보드에서 박자 붙여넣기 (%1+V) Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -4990,7 +4990,7 @@ Reason: "%2" 작업 취소(&U) - Ctrl+Z + %1+Z @@ -4998,7 +4998,7 @@ Reason: "%2" 작업 재실행(&R) - Ctrl+Y + %1+Y @@ -5006,7 +5006,7 @@ Reason: "%2" 복사(&C) - Ctrl+C + %1+C @@ -5014,7 +5014,7 @@ Reason: "%2" 잘라내기(&T) - Ctrl+X + %1+X @@ -5022,7 +5022,7 @@ Reason: "%2" 붙여넣기(&P) - Ctrl+V + %1+V @@ -5034,7 +5034,7 @@ Reason: "%2" 진하게(&B) - Ctrl+B + %1+B @@ -5042,7 +5042,7 @@ Reason: "%2" 기울임(&I) - Ctrl+I + %1+I @@ -5050,7 +5050,7 @@ Reason: "%2" 밑줄(&U) - Ctrl+U + %1+U @@ -5058,7 +5058,7 @@ Reason: "%2" 왼쪽(&L) - Ctrl+L + %1+L @@ -5066,7 +5066,7 @@ Reason: "%2" 중앙(&E) - Ctrl+E + %1+E @@ -5074,7 +5074,7 @@ Reason: "%2" 오른쪽(&R) - Ctrl+R + %1+R @@ -5082,7 +5082,7 @@ Reason: "%2" 양쪽 배분(&J) - Ctrl+J + %1+J @@ -5317,8 +5317,8 @@ Reason: "%2" 붙여넣기 - Mute/unmute (<Ctrl> + middle click) - 무음/무음해제 (<Ctrl> + 중간 클릭) + Mute/unmute (<%1> + middle click) + 무음/무음해제 (<%1> + 중간 클릭) Set/clear record @@ -5921,11 +5921,11 @@ Latency: %2 ms 힌트 - Press <Ctrl> to disable magnetic loop points. + Press <%1> to disable magnetic loop points. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. @@ -5999,16 +5999,16 @@ Please make sure you have read-permission to the file and the directory containi 힌트 - Press <Ctrl> and drag to make a copy. - <Ctrl> 누르고 복사본을 만들기 위하여 끌기 + Press <%1> and drag to make a copy. + <%1> 누르고 복사본을 만들기 위하여 끌기 Current length 현재 길이 - Press <Ctrl> for free resizing. - 자유 크기 재조정하기 위하여 <Ctrl> 누르기 + Press <%1> for free resizing. + 자유 크기 재조정하기 위하여 <%1> 누르기 %1:%2 (%3:%4 to %5:%6) @@ -6031,14 +6031,14 @@ Please make sure you have read-permission to the file and the directory containi 붙여넣기 - Mute/unmute (<Ctrl> + middle click) - 무음/무음해제 (<Ctrl> + 중간 클릭) + Mute/unmute (<%1> + middle click) + 무음/무음해제 (<%1> + 중간 클릭) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. diff --git a/data/locale/nl.ts b/data/locale/nl.ts index feb2cbb5ecc..6f4a3960c3a 100644 --- a/data/locale/nl.ts +++ b/data/locale/nl.ts @@ -421,15 +421,15 @@ If you're interested in translating LMMS in another language or want to imp - Cut selected values (Ctrl+X) - Knip geselecteerde waarden (Ctrl+X) + Cut selected values (%1+X) + Knip geselecteerde waarden (%1+X) - Copy selected values (Ctrl+C) - Kopieer geselecteerde waarden (Ctrl+C) + Copy selected values (%1+C) + Kopieer geselecteerde waarden (%1+C) - Paste values from clipboard Ctrl+V) + Paste values from clipboard (%1+V) @@ -460,7 +460,7 @@ If you're interested in translating LMMS in another language or want to imp AutomationPattern - Drag a control while pressing <Ctrl> + Drag a control while pressing <%1> @@ -4863,7 +4863,7 @@ volume van de steps is met het muiswiel te veranderen - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. @@ -4871,7 +4871,7 @@ volume van de steps is met het muiswiel te veranderen - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. @@ -4879,16 +4879,16 @@ volume van de steps is met het muiswiel te veranderen - Cut selected notes (Ctrl+X) - Knip geselecteerde noten (Ctrl+X) + Cut selected notes (%1+X) + Knip geselecteerde noten (%1+X) - Copy selected notes (Ctrl+C) - Kopieer geselecteerde noten (Ctrl+C) + Copy selected notes (%1+C) + Kopieer geselecteerde noten (%1+C) - Paste notes from clipboard (Ctrl+V) - Plak noten van klembord (Ctrl+V) + Paste notes from clipboard (%1+V) + Plak noten van klembord (%1+V) Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -4988,40 +4988,40 @@ Reason: "%2" &Ongedaan maken - Ctrl+Z - Ctrl+Z + %1+Z + %1+Z &Redo &Herstellen - Ctrl+Y - Ctrl+Y + %1+Y + %1+Y &Copy &Kopieren - Ctrl+C - Ctrl+C + %1+C + %1+C Cu&t K&nippen - Ctrl+X - Ctrl+X + %1+X + %1+X &Paste &Plakken - Ctrl+V - Ctrl+V + %1+V + %1+V Format Actions @@ -5032,56 +5032,56 @@ Reason: "%2" &Vet - Ctrl+B - Ctrl+B + %1+B + %1+B &Italic &Cursief - Ctrl+I - Ctrl+I + %1+I + %1+I &Underline &Onderstrepen - Ctrl+U - Ctrl+U + %1+U + %1+U &Left &Links - Ctrl+L - Ctrl+L + %1+L + %1+L C&enter C&entreren - Ctrl+E - Ctrl+E + %1+E + %1+E &Right &Rechts - Ctrl+R - Ctrl+R + %1+R + %1+R &Justify &Uitgevuld - Ctrl+J - Ctrl+J + %1+J + %1+J &Color... @@ -5315,8 +5315,8 @@ Reason: "%2" Plakken - Mute/unmute (<Ctrl> + middle click) - Dempen/geluid aan (<Ctrl> + middelklik) + Mute/unmute (<%1> + middle click) + Dempen/geluid aan (<%1> + middelklik) Set/clear record @@ -5918,11 +5918,11 @@ Vertraging: %2 ms Tip - Press <Ctrl> to disable magnetic loop points. + Press <%1> to disable magnetic loop points. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. @@ -5998,7 +5998,7 @@ Zorg ervoor dat je schrijf-bevoegdheid hebt voor deze bestanden en mapen en prob Tip - Press <Ctrl> and drag to make a copy. + Press <%1> and drag to make a copy. @@ -6006,8 +6006,8 @@ Zorg ervoor dat je schrijf-bevoegdheid hebt voor deze bestanden en mapen en prob Huidige lengte - Press <Ctrl> for free resizing. - Druk <Ctrl> voor vrije grootteverandering. + Press <%1> for free resizing. + Druk <%1> voor vrije grootteverandering. %1:%2 (%3:%4 to %5:%6) @@ -6030,15 +6030,15 @@ Zorg ervoor dat je schrijf-bevoegdheid hebt voor deze bestanden en mapen en prob Plakken - Mute/unmute (<Ctrl> + middle click) - Dempen/geluid aan (<Ctrl> + middelklik) + Mute/unmute (<%1> + middle click) + Dempen/geluid aan (<%1> + middelklik) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. - Druk <Ctrl> tijdens klikken op move-grip om een nieuwe drag'n'drop-actie te starten. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + Druk <%1> tijdens klikken op move-grip om een nieuwe drag'n'drop-actie te starten. Actions for this track diff --git a/data/locale/pl.ts b/data/locale/pl.ts index c5c2dbfe3cd..37bf0fca1ca 100644 --- a/data/locale/pl.ts +++ b/data/locale/pl.ts @@ -427,15 +427,15 @@ Zauważone błędy i propozycje zmian tłumaczenia proszę zgłaszać na e-mail: - Cut selected values (Ctrl+X) - Wytnij zaznaczone elementy (Ctrl+X) + Cut selected values (%1+X) + Wytnij zaznaczone elementy (%1+X) - Copy selected values (Ctrl+C) - Skopiuj zaznaczone elementy (Ctrl+C) + Copy selected values (%1+C) + Skopiuj zaznaczone elementy (%1+C) - Paste values from clipboard Ctrl+V) + Paste values from clipboard (%1+V) @@ -466,8 +466,8 @@ Zauważone błędy i propozycje zmian tłumaczenia proszę zgłaszać na e-mail: AutomationPattern - Drag a control while pressing <Ctrl> - Przeciągnij trzymając wciśnięty klawisz <Ctrl> + Drag a control while pressing <%1> + Przeciągnij trzymając wciśnięty klawisz <%1> Model is already connected to this pattern. @@ -4884,32 +4884,32 @@ użyj kółka myszy aby ustawić głośność poszczególnych krokówTryb odstrojenia (Shift+T) - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. - Kliknij tutaj, aby przejść do trybu rysowania. W tym trybie możesz dodawać, przemieszczać i zmieniać rozmiar nut To domyślny tryb, który będziesz używać przez większość czasu. Możesz go aktywować z poziomu klawiatury za pomocą skrótu 'Shift+D'. Przytrzymaj klawisz 'Ctrl' aby czasowo przejść do trybu zaznaczenia. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. + Kliknij tutaj, aby przejść do trybu rysowania. W tym trybie możesz dodawać, przemieszczać i zmieniać rozmiar nut To domyślny tryb, który będziesz używać przez większość czasu. Możesz go aktywować z poziomu klawiatury za pomocą skrótu 'Shift+D'. Przytrzymaj klawisz '%1' aby czasowo przejść do trybu zaznaczenia. Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. Kliknij tutaj, aby przejść do trybu kasowania. W tym trybie możesz usuwać nuty. Możesz go aktywować z poziomu klawiatury za pomocą skrótu 'Shift+E'. - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. - Kliknij tutaj, aby przejść do trybu zaznaczania. W tym trybie możesz zaznaczać pojedyncze nuty lub całe ich grupy. Alternatywnie możesz przytrzymać klawisz 'Ctrl' w trybie rysowania aby tymczasowo przejść do trybu zaznaczania. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. + Kliknij tutaj, aby przejść do trybu zaznaczania. W tym trybie możesz zaznaczać pojedyncze nuty lub całe ich grupy. Alternatywnie możesz przytrzymać klawisz '%1' w trybie rysowania aby tymczasowo przejść do trybu zaznaczania. Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. Kliknij tutaj, aby przejść do trybu odstrojenia. W tym trybie możesz odstrajać nuty w oknie, które otworzy się po kliknięciu na nich. Ten tryb możesz aktywować z poziomu klawiatury przez wciśnięcie kombinacji 'Shift+T'. - Cut selected notes (Ctrl+X) - Wytnij zaznaczone nuty (Ctrl+X) + Cut selected notes (%1+X) + Wytnij zaznaczone nuty (%1+X) - Copy selected notes (Ctrl+C) - Skopiuj zaznaczone nuty (Ctrl+C) + Copy selected notes (%1+C) + Skopiuj zaznaczone nuty (%1+C) - Paste notes from clipboard (Ctrl+V) - Wklej nuty ze schowka (Ctrl+V) + Paste notes from clipboard (%1+V) + Wklej nuty ze schowka (%1+V) Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -5010,40 +5010,40 @@ Powód: "%2" Cofnij [&U] - Ctrl+Z - Ctrl+Z + %1+Z + %1+Z &Redo Powtórz [&R] - Ctrl+Y - Ctrl+Y + %1+Y + %1+Y &Copy &Kopiuj - Ctrl+C - Ctrl+C + %1+C + %1+C Cu&t Wy&tnij - Ctrl+X - Ctrl+X + %1+X + %1+X &Paste &Wklej - Ctrl+V - Ctrl+V + %1+V + %1+V Format Actions @@ -5054,56 +5054,56 @@ Powód: "%2" Wytłuść [&B] - Ctrl+B - Ctrl+B + %1+B + %1+B &Italic Kursywa [&I] - Ctrl+I - Ctrl+I + %1+I + %1+I &Underline Podkreślenie [&U] - Ctrl+U - Ctrl+U + %1+U + %1+U &Left Lewo [&L] - Ctrl+L - Ctrl+L + %1+L + %1+L C&enter Centrowanie [&E] - Ctrl+E - Ctrl+E + %1+E + %1+E &Right Prawo [&R] - Ctrl+R - Ctrl+R + %1+R + %1+R &Justify Justowanie [&J] - Ctrl+J - Ctrl+J + %1+J + %1+J &Color... @@ -5337,8 +5337,8 @@ Powód: "%2" Wklej - Mute/unmute (<Ctrl> + middle click) - Wycisz/anuluj wyciszenie (<Ctrl> + kliknięcie rolką myszy) + Mute/unmute (<%1> + middle click) + Wycisz/anuluj wyciszenie (<%1> + kliknięcie rolką myszy) Set/clear record @@ -5941,11 +5941,11 @@ Upewnij się, że masz przynajmniej uprawnienia odczytu tego pliku a następnie Wskazówka - Press <Ctrl> to disable magnetic loop points. + Press <%1> to disable magnetic loop points. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. @@ -6021,16 +6021,16 @@ Upewnij się, że masz uprawnienia do odczytu tego pliku i katalogu zawierające Wskazówka - Press <Ctrl> and drag to make a copy. - Naciśnij <Ctrl> i przeciągnij aby stworzyć kopię. + Press <%1> and drag to make a copy. + Naciśnij <%1> i przeciągnij aby stworzyć kopię. Current length Aktualna długość - Press <Ctrl> for free resizing. - Naciśnij <Ctrl> aby zmienić rozmiar. + Press <%1> for free resizing. + Naciśnij <%1> aby zmienić rozmiar. %1:%2 (%3:%4 to %5:%6) @@ -6053,15 +6053,15 @@ Upewnij się, że masz uprawnienia do odczytu tego pliku i katalogu zawierające Wklej - Mute/unmute (<Ctrl> + middle click) - Wycisz/anuluj wyciszenie (<Ctrl> + kliknięcie rolką myszy) + Mute/unmute (<%1> + middle click) + Wycisz/anuluj wyciszenie (<%1> + kliknięcie rolką myszy) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. - Naciśnij <Ctrl> podczas przeciągania elementu kursorem aby rozpocząć nową akcję 'przeciągnij i upuść'. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + Naciśnij <%1> podczas przeciągania elementu kursorem aby rozpocząć nową akcję 'przeciągnij i upuść'. Actions for this track diff --git a/data/locale/pt.ts b/data/locale/pt.ts index 1cab5558308..aa80670b80d 100644 --- a/data/locale/pt.ts +++ b/data/locale/pt.ts @@ -425,15 +425,15 @@ Esteban Viveros Clique aqui para selecionar progressão cúbica hermite-progressions para este sequenciador de automação. O valor do objeto conectado irá mudar em curva e suavemente entre picos e vales. - Cut selected values (Ctrl+X) - Cortar (Ctrl+X) + Cut selected values (%1+X) + Cortar (%1+X) - Copy selected values (Ctrl+C) - Copiar (Ctrl+C) + Copy selected values (%1+C) + Copiar (%1+C) - Paste values from clipboard Ctrl+V) + Paste values from clipboard (%1+V) @@ -464,8 +464,8 @@ Esteban Viveros AutomationPattern - Drag a control while pressing <Ctrl> - Arraste o controle enquanto pressiona a tecla <Ctrl> + Drag a control while pressing <%1> + Arraste o controle enquanto pressiona a tecla <%1> Model is already connected to this pattern. @@ -4882,7 +4882,7 @@ use a roda do mouse para midificar o volume de cada passo Automação para Afinação (Shift+T) - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. Clique aqui e o lápis será ativado. O lápis serve para adicionar ou mover valores simples. Ele estará ativado previamente e será utilizado a maior parte do tempo. Você pode usar 'Shift+D' no teclado para ativar o lápis. @@ -4890,7 +4890,7 @@ use a roda do mouse para midificar o volume de cada passo Clique aqui e a borracha será ativada. A borracha serve para apagar valores simples. Você pode usar 'Shif+E' no teclado para utilizar a borracha. - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. Clique aqui e modo de seleção será ativado. A borracha serve para apagar valores simples. Você pode usar 'Shif+E' no teclado para utilizar a borracha.A borracha serve para apagar valores simples. Você pode usar 'Shif+E' no teclado para utilizar a borracha. Este modo torna possível a seleção de notas. Alternativamente você pode pressionar Crtl enquanto estiver usando o lápis para utilizar o modo de seleção temporariamente. @@ -4898,16 +4898,16 @@ use a roda do mouse para midificar o volume de cada passo Clique aqui e a automação para afinação será ativada. Nela você pode clicar na nota para abrir sua automação de afinação. Você pode utilizar esta ferramenta para fazer glissandos de uma altura para outra. - Cut selected notes (Ctrl+X) - Recortar notas selecionadas (Ctrl+X) + Cut selected notes (%1+X) + Recortar notas selecionadas (%1+X) - Copy selected notes (Ctrl+C) - Copiar notas selecionadas (Ctrl+C) + Copy selected notes (%1+C) + Copiar notas selecionadas (%1+C) - Paste notes from clipboard (Ctrl+V) - Colar notas da área de transferência (Ctrl+V) + Paste notes from clipboard (%1+V) + Colar notas da área de transferência (%1+V) Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -5008,40 +5008,40 @@ Motivo: "%2" Des&fazer - Ctrl+Z - Ctrl+Z + %1+Z + %1+Z &Redo &Refazer - Ctrl+Y - Ctrl+Y + %1+Y + %1+Y &Copy &Copiar - Ctrl+C - Ctrl+C + %1+C + %1+C Cu&t Recor&tar - Ctrl+X - Ctrl+X + %1+X + %1+X &Paste C&olar - Ctrl+V - Ctrl+V + %1+V + %1+V Format Actions @@ -5052,56 +5052,56 @@ Motivo: "%2" &Negrito - Ctrl+B - Ctrl+B + %1+B + %1+B &Italic &Itálico - Ctrl+I - Ctrl+I + %1+I + %1+I &Underline S&ublinhado - Ctrl+U - Ctrl+U + %1+U + %1+U &Left &Esquerda - Ctrl+L - Ctrl+L + %1+L + %1+L C&enter C&entro - Ctrl+E - Ctrl+E + %1+E + %1+E &Right Di&reita - Ctrl+R - Ctrl+R + %1+R + %1+R &Justify &Justificar - Ctrl+J - Ctrl+J + %1+J + %1+J &Color... @@ -5339,8 +5339,8 @@ Motivo: "%2" Duplo clique para selecionar amostra - Mute/unmute (<Ctrl> + middle click) - Mudo/Não Mudo (<Ctrl> + middle click) + Mute/unmute (<%1> + middle click) + Mudo/Não Mudo (<%1> + middle click) @@ -5939,12 +5939,12 @@ Latência: %2 ms Sugestão - Press <Ctrl> to disable magnetic loop points. - Pressione <Ctrl> para desabilitar os pontos de loop magnéticos. + Press <%1> to disable magnetic loop points. + Pressione <%1> para desabilitar os pontos de loop magnéticos. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. - Pressione <Shift> para mover o começo do ponto de loop; Pressione <Ctrl> para desabilitar os pontos de loop magnéticos. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. + Pressione <Shift> para mover o começo do ponto de loop; Pressione <%1> para desabilitar os pontos de loop magnéticos. @@ -6019,16 +6019,16 @@ Por favor certifique-se que você tem permissões de leitura para o arquivo e pa Sugestão - Press <Ctrl> and drag to make a copy. - Pressione <Ctrl> e arraste para fazer uma cópia. + Press <%1> and drag to make a copy. + Pressione <%1> e arraste para fazer uma cópia. Current length Tamanho atual - Press <Ctrl> for free resizing. - Pressione <Ctrl> para redimensionar livremente. + Press <%1> for free resizing. + Pressione <%1> para redimensionar livremente. %1:%2 (%3:%4 to %5:%6) @@ -6051,15 +6051,15 @@ Por favor certifique-se que você tem permissões de leitura para o arquivo e pa Colar - Mute/unmute (<Ctrl> + middle click) + Mute/unmute (<%1> + middle click) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. - Pressione <Ctrl> enquanto clica em mover-grip para o começo, uma ação de arrastar. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + Pressione <%1> enquanto clica em mover-grip para o começo, uma ação de arrastar. Actions for this track diff --git a/data/locale/ru.ts b/data/locale/ru.ts index 2ec32ca37d9..99ec01efd9f 100644 --- a/data/locale/ru.ts +++ b/data/locale/ru.ts @@ -432,16 +432,16 @@ Oe Ai <oeai/at/symbiants/dot/com> Кубическая Эрмитова прогрессия для этого шаблона автоматизации. Кол-во подсоединенных объектов изменится по сглаженной кривой и смягчится на пиках и спадах. - Cut selected values (Ctrl+X) - Вырезать выбранные ноты (Ctrl+X) + Cut selected values (%1+X) + Вырезать выбранные ноты (%1+X) - Copy selected values (Ctrl+C) - Копировать выбранные ноты в буфер (Ctrl+C) + Copy selected values (%1+C) + Копировать выбранные ноты в буфер (%1+C) - Paste values from clipboard Ctrl+V) - Вставить запомненные значения (Ctrl+V) + Paste values from clipboard (%1+V) + Вставить запомненные значения (%1+V) Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -471,8 +471,8 @@ Oe Ai <oeai/at/symbiants/dot/com> AutomationPattern - Drag a control while pressing <Ctrl> - Тяните контроль удерживая <Ctrl> + Drag a control while pressing <%1> + Тяните контроль удерживая <%1> Model is already connected to this pattern. @@ -4933,33 +4933,33 @@ use mouse wheel to set volume of a step Режим подстраивания (Shift+T) - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. Режим рисования нот, в нём вы можете добавлять/перемещать и изменять длительность одиночных нот. Это режим по умолчанию и используется большую часть времени. -Для включения этого режима можно использовать комбинацию клавиш Shift+D, удерживайте Ctrl для временного переключения в режим выбора. +Для включения этого режима можно использовать комбинацию клавиш Shift+D, удерживайте %1 для временного переключения в режим выбора. Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. Режим стирания. В этом режиме вы можете стирать ноты. Для включения этого режима можно использовать комбинацию клавиш Shift+E. - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. - Режим выделения. В этом режиме можно выделять ноты, можно также удерживать Ctrl в режиме рисования, чтобы можно было на время войти в режим выделения. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. + Режим выделения. В этом режиме можно выделять ноты, можно также удерживать %1 в режиме рисования, чтобы можно было на время войти в режим выделения. Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. Режим подстройки. В этом режиме можно выбирать ноты для автоматизации их подстраивания. Можно использовать это для переходов нот от одной к другой. Для активации с клавиатуры <Shift+T>. - Cut selected notes (Ctrl+X) - Переместить выделенные ноты в буфер (Ctrl+X) + Cut selected notes (%1+X) + Переместить выделенные ноты в буфер (%1+X) - Copy selected notes (Ctrl+C) - Копировать выделенные ноты в буфер (Ctrl+X) + Copy selected notes (%1+C) + Копировать выделенные ноты в буфер (%1+X) - Paste notes from clipboard (Ctrl+V) - Вставить ноты из буфера (Ctrl+V) + Paste notes from clipboard (%1+V) + Вставить ноты из буфера (%1+V) Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -5060,40 +5060,40 @@ Reason: "%2" &U Отменить - Ctrl+Z - Ctrl+Z + %1+Z + %1+Z &Redo &R Повторить - Ctrl+Y - Ctrl+Y + %1+Y + %1+Y &Copy &C Копировать - Ctrl+C - Ctrl+C + %1+C + %1+C Cu&t &t Вырезать - Ctrl+X - Ctrl+X + %1+X + %1+X &Paste &P Вставить - Ctrl+V - Ctrl+V + %1+V + %1+V Format Actions @@ -5104,39 +5104,39 @@ Reason: "%2" &b Полужирный - Ctrl+B - Ctrl+B + %1+B + %1+B &Italic &i Курсив - Ctrl+I - Ctrl+I + %1+I + %1+I &Underline &U Подчеркнутый - Ctrl+U - Ctrl+U + %1+U + %1+U &Left &L По левому краю - Ctrl+L - Ctrl+L + %1+L + %1+L C&enter По &центру - Ctrl+E + %1+E @@ -5144,7 +5144,7 @@ Reason: "%2" По &правому краю - Ctrl+R + %1+R @@ -5152,7 +5152,7 @@ Reason: "%2" По &ширине - Ctrl+J + %1+J @@ -5388,8 +5388,8 @@ Reason: "%2" Вставить - Mute/unmute (<Ctrl> + middle click) - Заглушить/включить (<Ctrl> + средняя кнопка мыши) + Mute/unmute (<%1> + middle click) + Заглушить/включить (<%1> + средняя кнопка мыши) Set/clear record @@ -5992,12 +5992,12 @@ Latency: %2 ms Подсказка - Press <Ctrl> to disable magnetic loop points. - Нажмите <Ctrl>, чтобы убрать прилипание точек петли. + Press <%1> to disable magnetic loop points. + Нажмите <%1>, чтобы убрать прилипание точек петли. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. - Зажмите <Shift> чтобы сдвинуть начало точек петли; Нажмите <Ctrl>, чтобы убрать прилипание точек петли. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. + Зажмите <Shift> чтобы сдвинуть начало точек петли; Нажмите <%1>, чтобы убрать прилипание точек петли. @@ -6072,16 +6072,16 @@ Please make sure you have read-permission to the file and the directory containi Подсказка - Press <Ctrl> and drag to make a copy. - Нажмите <Ctrl> и тащите мышью, чтобы создать копию. + Press <%1> and drag to make a copy. + Нажмите <%1> и тащите мышью, чтобы создать копию. Current length Текущая длительность - Press <Ctrl> for free resizing. - Для свободного изменения размера нажмите <Ctrl>. + Press <%1> for free resizing. + Для свободного изменения размера нажмите <%1>. %1:%2 (%3:%4 to %5:%6) @@ -6104,14 +6104,14 @@ Please make sure you have read-permission to the file and the directory containi Вставить - Mute/unmute (<Ctrl> + middle click) - Тихо/громко (<Ctrl> + middle click) + Mute/unmute (<%1> + middle click) + Тихо/громко (<%1> + middle click) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. Зажмите <Сtrl> и нажимайте мышь во время движения, чтобы начать новую переброску. diff --git a/data/locale/sv.ts b/data/locale/sv.ts index 5f81fde6911..76ce9ca4463 100644 --- a/data/locale/sv.ts +++ b/data/locale/sv.ts @@ -421,16 +421,16 @@ If you're interested in translating LMMS in another language or want to imp Klicka här för att aktivera cubic hermite talföljd. Värdet följer en mjuk kurva mellan kontrollpunkter. - Cut selected values (Ctrl+X) - Klipp ut valda värden (Ctrl+X) + Cut selected values (%1+X) + Klipp ut valda värden (%1+X) - Copy selected values (Ctrl+C) - Kopiera valda värden (ctrl+C) + Copy selected values (%1+C) + Kopiera valda värden (%1+C) - Paste values from clipboard Ctrl+V) - Klistra värden (Ctrl+V) + Paste values from clipboard (%1+V) + Klistra värden (%1+V) Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -460,8 +460,8 @@ If you're interested in translating LMMS in another language or want to imp AutomationPattern - Drag a control while pressing <Ctrl> - Dra en kontroll samtidigt som du håller <Ctrl> + Drag a control while pressing <%1> + Dra en kontroll samtidigt som du håller <%1> Model is already connected to this pattern. @@ -4862,7 +4862,7 @@ use mouse wheel to set volume of a step - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. @@ -4870,7 +4870,7 @@ use mouse wheel to set volume of a step - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. @@ -4878,15 +4878,15 @@ use mouse wheel to set volume of a step - Cut selected notes (Ctrl+X) - Klipp ut valda noter(Ctrl+X) + Cut selected notes (%1+X) + Klipp ut valda noter(%1+X) - Copy selected notes (Ctrl+C) + Copy selected notes (%1+C) - Paste notes from clipboard (Ctrl+V) + Paste notes from clipboard (%1+V) @@ -4987,40 +4987,40 @@ Reason: "%2" &Ångra - Ctrl+Z - Ctrl+Z + %1+Z + %1+Z &Redo &Återställ - Ctrl+Y - Ctrl+Y + %1+Y + %1+Y &Copy &Kopiera - Ctrl+C - Ctrl+C + %1+C + %1+C Cu&t Klipp& ut - Ctrl+X - Ctrl+X + %1+X + %1+X &Paste &Klistra in - Ctrl+V - Ctrl+V + %1+V + %1+V Format Actions @@ -5031,56 +5031,56 @@ Reason: "%2" &Fet - Ctrl+B - Ctrl+B + %1+B + %1+B &Italic &Kursiv - Ctrl+I - Ctrl+I + %1+I + %1+I &Underline &Understruken - Ctrl+U - Ctrl+U + %1+U + %1+U &Left &Vänster - Ctrl+L - Ctrl+L + %1+L + %1+L C&enter C&entrera - Ctrl+E - Ctrl+E + %1+E + %1+E &Right &Höger - Ctrl+R - Ctrl+R + %1+R + %1+R &Justify - Ctrl+J - Ctrl+J + %1+J + %1+J &Color... @@ -5315,7 +5315,7 @@ Reason: "%2" Klistra in - Mute/unmute (<Ctrl> + middle click) + Mute/unmute (<%1> + middle click) @@ -5917,11 +5917,11 @@ Latency: %2 ms Ledtråd - Press <Ctrl> to disable magnetic loop points. + Press <%1> to disable magnetic loop points. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. @@ -5997,7 +5997,7 @@ Se till att du har läsningsrättigheter för filen och katalogen som innehålle Ledtråd - Press <Ctrl> and drag to make a copy. + Press <%1> and drag to make a copy. @@ -6005,7 +6005,7 @@ Se till att du har läsningsrättigheter för filen och katalogen som innehålle Aktuell längd - Press <Ctrl> for free resizing. + Press <%1> for free resizing. @@ -6029,14 +6029,14 @@ Se till att du har läsningsrättigheter för filen och katalogen som innehålle Klistra in - Mute/unmute (<Ctrl> + middle click) + Mute/unmute (<%1> + middle click) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. diff --git a/data/locale/uk.ts b/data/locale/uk.ts index 462d1ce8922..4d25ed52444 100644 --- a/data/locale/uk.ts +++ b/data/locale/uk.ts @@ -436,16 +436,16 @@ If you're interested in translating LMMS in another language or want to imp Кубічна Ермітова прогресія для цього шаблону автоматизації. Кількість приєднаних об'єктів зміниться по згладженій кривій і пом'якшиться на піках і спадах. - Cut selected values (Ctrl+X) - Вирізати вибрані ноти (Ctrl+X) + Cut selected values (%1+X) + Вирізати вибрані ноти (%1+X) - Copy selected values (Ctrl+C) - Копіювати вибрані ноти до буферу (Ctrl+C) + Copy selected values (%1+C) + Копіювати вибрані ноти до буферу (%1+C) - Paste values from clipboard (Ctrl+V) - Вставити значення з буферу (Ctrl+V) + Paste values from clipboard (%1+V) + Вставити значення з буферу (%1+V) Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -499,8 +499,8 @@ If you're interested in translating LMMS in another language or want to imp AutomationPattern - Drag a control while pressing <Ctrl> - Тягніть контроль утримуючи <Ctrl> + Drag a control while pressing <%1> + Тягніть контроль утримуючи <%1> @@ -5430,33 +5430,33 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил Режим підлаштовування (Shift+T) - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. Режим малювання нот, в ньому ви можете додавати/переміщати і змінювати тривалість одиночних нот. Це режим за замовчуванням і використовується більшу частину часу. -Для включення цього режиму можна скористатися комбінацією клавіш Shift+D, утримуйте Ctrl для тимчасового перемикання в режим вибору. +Для включення цього режиму можна скористатися комбінацією клавіш Shift+D, утримуйте %1 для тимчасового перемикання в режим вибору. Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. Режим стирання. У цьому режимі ви можете стирати ноти. Для увімкнення цього режиму можна скористатися комбінацією клавіш Shift+E. - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. - Режим виділення. У цьому режимі можна виділяти ноти, також можна утримувати Ctrl в режимі малювання, щоб на час увійти в режим виділення. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. + Режим виділення. У цьому режимі можна виділяти ноти, також можна утримувати %1 в режимі малювання, щоб на час увійти в режим виділення. Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. Режим підстроювання. У цьому режимі можна вибирати ноти для автоматизації їх підлаштування. Можна використовувати це для переходів нот від однієї до іншої. Для активації з клавіатури <Shift+T>. - Cut selected notes (Ctrl+X) - Перемістити виділені ноти до буферу (Ctrl+X) + Cut selected notes (%1+X) + Перемістити виділені ноти до буферу (%1+X) - Copy selected notes (Ctrl+C) - Копіювати виділені ноти до буферу (Ctrl+X) + Copy selected notes (%1+C) + Копіювати виділені ноти до буферу (%1+X) - Paste notes from clipboard (Ctrl+V) - Вставити ноти з буферу (Ctrl+V) + Paste notes from clipboard (%1+V) + Вставити ноти з буферу (%1+V) Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -5588,7 +5588,7 @@ Reason: "%2" &U Скасувати - Ctrl+Z + %1+Z @@ -5596,7 +5596,7 @@ Reason: "%2" &R Повторити - Ctrl+Y + %1+Y @@ -5604,7 +5604,7 @@ Reason: "%2" &C Копіювати - Ctrl+C + %1+C @@ -5612,7 +5612,7 @@ Reason: "%2" &t Вирізати - Ctrl+X + %1+X @@ -5620,7 +5620,7 @@ Reason: "%2" &P Вставити - Ctrl+V + %1+V @@ -5632,7 +5632,7 @@ Reason: "%2" Напів&жирний - Ctrl+B + %1+B @@ -5640,7 +5640,7 @@ Reason: "%2" &Курсив - Ctrl+I + %1+I @@ -5648,7 +5648,7 @@ Reason: "%2" &Підкреслити - Ctrl+U + %1+U @@ -5656,7 +5656,7 @@ Reason: "%2" По &лівому краю - Ctrl+L + %1+L @@ -5664,7 +5664,7 @@ Reason: "%2" По &центрі - Ctrl+E + %1+E @@ -5672,7 +5672,7 @@ Reason: "%2" По &правому краю - Ctrl+R + %1+R @@ -5680,7 +5680,7 @@ Reason: "%2" По &ширині - Ctrl+J + %1+J @@ -5831,8 +5831,8 @@ Reason: "%2" Виберіть запис подвійним натисненням миші - Mute/unmute (<Ctrl> + middle click) - Заглушити/включити (<Ctrl> + середня кнопка миші) + Mute/unmute (<%1> + middle click) + Заглушити/включити (<%1> + середня кнопка миші) @@ -6483,12 +6483,12 @@ Latency: %2 ms Підказка - Press <Ctrl> to disable magnetic loop points. - Натисніть <Ctrl>, щоб прибрати прилипання точок циклу. + Press <%1> to disable magnetic loop points. + Натисніть <%1>, щоб прибрати прилипання точок циклу. - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. - Зажміть <Shift> щоб змістити початок точок циклу; Натисніть <Ctrl>, щоб прибрати прилипання точок циклу. + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. + Зажміть <Shift> щоб змістити початок точок циклу; Натисніть <%1>, щоб прибрати прилипання точок циклу. @@ -6563,16 +6563,16 @@ Please make sure you have read-permission to the file and the directory containi Підказка - Press <Ctrl> and drag to make a copy. - Натисніть <Ctrl> і перетягніть, щоб створити копію. + Press <%1> and drag to make a copy. + Натисніть <%1> і перетягніть, щоб створити копію. Current length Тривалість - Press <Ctrl> for free resizing. - Для вільної зміни розміру натисніть <Ctrl>. + Press <%1> for free resizing. + Для вільної зміни розміру натисніть <%1>. %1:%2 (%3:%4 to %5:%6) @@ -6595,14 +6595,14 @@ Please make sure you have read-permission to the file and the directory containi Вставити - Mute/unmute (<Ctrl> + middle click) - Заглушити/включити (<Ctrl> + середня кнопка миші) + Mute/unmute (<%1> + middle click) + Заглушити/включити (<%1> + середня кнопка миші) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. Затисніть <Сtrl> і натискайте мишку під час руху, щоб почати нову перезбірку. diff --git a/data/locale/zh.ts b/data/locale/zh.ts index b6704b23a8e..38799c2d6ec 100644 --- a/data/locale/zh.ts +++ b/data/locale/zh.ts @@ -429,15 +429,15 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com - Cut selected values (Ctrl+X) - 剪切选定值 (Ctrl+X) + Cut selected values (%1+X) + 剪切选定值 (%1+X) - Copy selected values (Ctrl+C) - 复制选定值 (Ctrl+C) + Copy selected values (%1+C) + 复制选定值 (%1+C) - Paste values from clipboard Ctrl+V) + Paste values from clipboard (%1+V) @@ -468,8 +468,8 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com AutomationPattern - Drag a control while pressing <Ctrl> - 按住<Ctrl>拖动控制器 + Drag a control while pressing <%1> + 按住<%1>拖动控制器 Model is already connected to this pattern. @@ -4874,7 +4874,7 @@ use mouse wheel to set volume of a step - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold %1 to temporarily go into select mode. @@ -4882,7 +4882,7 @@ use mouse wheel to set volume of a step - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. @@ -4890,16 +4890,16 @@ use mouse wheel to set volume of a step - Cut selected notes (Ctrl+X) - 剪切选定音符 (Ctrl+X) + Cut selected notes (%1+X) + 剪切选定音符 (%1+X) - Copy selected notes (Ctrl+C) - 复制选定音符 (Ctrl+C) + Copy selected notes (%1+C) + 复制选定音符 (%1+C) - Paste notes from clipboard (Ctrl+V) - 从剪贴板粘贴音符 (Ctrl+V) + Paste notes from clipboard (%1+V) + 从剪贴板粘贴音符 (%1+V) Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -5000,40 +5000,40 @@ Reason: "%2" 撤销(&U) - Ctrl+Z - Ctrl+Z + %1+Z + %1+Z &Redo 重做(&R) - Ctrl+Y - Ctrl+Y + %1+Y + %1+Y &Copy 复制(&C) - Ctrl+C - Ctrl+C + %1+C + %1+C Cu&t 剪切(&T) - Ctrl+X - Ctrl+X + %1+X + %1+X &Paste 粘贴(&P) - Ctrl+V - Ctrl+V + %1+V + %1+V Format Actions @@ -5044,56 +5044,56 @@ Reason: "%2" 加粗(&B) - Ctrl+B - Ctrl+B + %1+B + %1+B &Italic 斜体(&I) - Ctrl+I - Ctrl+I + %1+I + %1+I &Underline 下划线(&U) - Ctrl+U - Ctrl+U + %1+U + %1+U &Left 左对齐(&L) - Ctrl+L - Ctrl+L + %1+L + %1+L C&enter 居中(&E) - Ctrl+E - Ctrl+E + %1+E + %1+E &Right 右对齐(&R) - Ctrl+R - Ctrl+R + %1+R + %1+R &Justify 匀齐(&J) - Ctrl+J - Ctrl+J + %1+J + %1+J &Color... @@ -5327,8 +5327,8 @@ Reason: "%2" 粘贴 - Mute/unmute (<Ctrl> + middle click) - 静音/取消静音 (<Ctrl> + 鼠标中键) + Mute/unmute (<%1> + middle click) + 静音/取消静音 (<%1> + 鼠标中键) Set/clear record @@ -5931,12 +5931,12 @@ Latency: %2 ms 提示 - Press <Ctrl> to disable magnetic loop points. - 按住 <Ctrl> 禁用磁性吸附。 + Press <%1> to disable magnetic loop points. + 按住 <%1> 禁用磁性吸附。 - Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. - 按住 <Shift> 移动起始循环点;按住 <Ctrl> 禁用磁性吸附。 + Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. + 按住 <Shift> 移动起始循环点;按住 <%1> 禁用磁性吸附。 @@ -6009,16 +6009,16 @@ Please make sure you have read-permission to the file and the directory containi 提示 - Press <Ctrl> and drag to make a copy. - 按住 <Ctrl> 并拖动以创建副本。 + Press <%1> and drag to make a copy. + 按住 <%1> 并拖动以创建副本。 Current length 当前长度 - Press <Ctrl> for free resizing. - 按住 <Ctrl> 自由调整大小。 + Press <%1> for free resizing. + 按住 <%1> 自由调整大小。 %1:%2 (%3:%4 to %5:%6) @@ -6041,15 +6041,15 @@ Please make sure you have read-permission to the file and the directory containi 粘贴 - Mute/unmute (<Ctrl> + middle click) - 静音/取消静音 (<Ctrl> + 鼠标中键) + Mute/unmute (<%1> + middle click) + 静音/取消静音 (<%1> + 鼠标中键) TrackOperationsWidget - Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. - 按住 <Ctrl> 的同时拖动移动柄复制并移动此轨道。 + Press <%1> while clicking on move-grip to begin a new drag'n'drop-action. + 按住 <%1> 的同时拖动移动柄复制并移动此轨道。 Actions for this track diff --git a/src/core/AutomationPattern.cpp b/src/core/AutomationPattern.cpp index 93934c2a2a2..9750a86136b 100644 --- a/src/core/AutomationPattern.cpp +++ b/src/core/AutomationPattern.cpp @@ -595,7 +595,12 @@ const QString AutomationPattern::name() const { return m_objects.first()->fullDisplayName(); } - return tr( "Drag a control while pressing " ); + return tr( "Drag a control while pressing <%1>" ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘"); + #else + "Ctrl"); + #endif } diff --git a/src/core/Track.cpp b/src/core/Track.cpp index 2a241b2e40e..05d3750a5ff 100644 --- a/src/core/Track.cpp +++ b/src/core/Track.cpp @@ -651,8 +651,13 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) s_textFloat->setTitle( tr( "Current position" ) ); delete m_hint; m_hint = TextFloat::displayMessage( tr( "Hint" ), - tr( "Press and drag to make " - "a copy." ), + tr( "Press <%1> and drag to make " + "a copy." ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘"), + #else + "Ctrl"), + #endif embed::getIconPixmap( "hint" ), 0 ); } else if( !m_tco->getAutoResize() ) @@ -664,8 +669,13 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) s_textFloat->setTitle( tr( "Current length" ) ); delete m_hint; m_hint = TextFloat::displayMessage( tr( "Hint" ), - tr( "Press for free " - "resizing." ), + tr( "Press <%1> for free " + "resizing." ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘"), + #else + "Ctrl"), + #endif embed::getIconPixmap( "hint" ), 0 ); } // s_textFloat->reparent( this ); @@ -933,7 +943,12 @@ void TrackContentObjectView::contextMenuEvent( QContextMenuEvent * cme ) tr( "Paste" ), m_tco, SLOT( paste() ) ); contextMenu.addSeparator(); contextMenu.addAction( embed::getIconPixmap( "muted" ), - tr( "Mute/unmute ( + middle click)" ), + tr( "Mute/unmute (<%1> + middle click)" ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘"), + #else + "Ctrl"), + #endif m_tco, SLOT( toggleMute() ) ); constructContextMenu( &contextMenu ); @@ -1569,8 +1584,13 @@ TrackOperationsWidget::TrackOperationsWidget( TrackView * parent ) : "track_op_grip" ) ); } - ToolTip::add( this, tr( "Press while clicking on move-grip " - "to begin a new drag'n'drop-action." ) ); + ToolTip::add( this, tr( "Press <%1> while clicking on move-grip " + "to begin a new drag'n'drop-action." ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘") ); + #else + "Ctrl") ); + #endif QMenu * toMenu = new QMenu( this ); toMenu->setFont( pointSize<9>( toMenu->font() ) ); @@ -1755,7 +1775,7 @@ void TrackOperationsWidget::updateMenu() toMenu->addAction( embed::getIconPixmap( "cancel", 16, 16 ), tr( "Remove this track" ), this, SLOT( removeTrack() ) ); - + if( ! m_trackView->trackContainerView()->fixedTCOs() ) { toMenu->addAction( tr( "Clear this track" ), this, SLOT( clearTrack() ) ); @@ -2738,6 +2758,3 @@ void TrackView::createTCOView( TrackContentObject * tco ) } tco->selectViewOnCreate( false ); } - - - diff --git a/src/gui/TimeLineWidget.cpp b/src/gui/TimeLineWidget.cpp index 821683187d7..a367d2bcfd8 100644 --- a/src/gui/TimeLineWidget.cpp +++ b/src/gui/TimeLineWidget.cpp @@ -324,14 +324,24 @@ void TimeLineWidget::mousePressEvent( QMouseEvent* event ) { delete m_hint; m_hint = TextFloat::displayMessage( tr( "Hint" ), - tr( "Press to disable magnetic loop points." ), + tr( "Press <%1> to disable magnetic loop points." ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘"), + #else + "Ctrl"), + #endif embed::getIconPixmap( "hint" ), 0 ); } else if( m_action == MoveLoopEnd ) { delete m_hint; m_hint = TextFloat::displayMessage( tr( "Hint" ), - tr( "Hold to move the begin loop point; Press to disable magnetic loop points." ), + tr( "Hold to move the begin loop point; Press <%1> to disable magnetic loop points." ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘"), + #else + "Ctrl"), + #endif embed::getIconPixmap( "hint" ), 0 ); } @@ -401,6 +411,3 @@ void TimeLineWidget::mouseReleaseEvent( QMouseEvent* event ) if ( m_action == SelectSongTCO ) { emit selectionFinished(); } m_action = NoAction; } - - - diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index 1c24243d4e4..74db2ba96e8 100644 --- a/src/gui/editors/AutomationEditor.cpp +++ b/src/gui/editors/AutomationEditor.cpp @@ -1199,7 +1199,7 @@ void AutomationEditor::paintEvent(QPaintEvent * pe ) //Don't bother doing/rendering anything if there is no automation points if( time_map.size() > 0 ) { - timeMap::iterator it = time_map.begin(); + timeMap::iterator it = time_map.begin(); while( it+1 != time_map.end() ) { // skip this section if it occurs completely before the @@ -1464,7 +1464,7 @@ void AutomationEditor::wheelEvent(QWheelEvent * we ) y--; } y = qBound( 0, y, m_zoomingYModel.size() - 1 ); - m_zoomingYModel.setValue( y ); + m_zoomingYModel.setValue( y ); } else if( we->modifiers() & Qt::ControlModifier && we->modifiers() & Qt::AltModifier ) { @@ -2140,11 +2140,26 @@ AutomationEditorWindow::AutomationEditorWindow() : /*DropToolBar *copyPasteActionsToolBar = addDropToolBarToTop(tr("Copy paste actions"));*/ QAction* cutAction = new QAction(embed::getIconPixmap("edit_cut"), - tr("Cut selected values (Ctrl+X)"), this); + tr("Cut selected values (%1+X)").arg( + #ifdef LMMS_BUILD_APPLE + "⌘"), this); + #else + "Ctrl"), this); + #endif QAction* copyAction = new QAction(embed::getIconPixmap("edit_copy"), - tr("Copy selected values (Ctrl+C)"), this); + tr("Copy selected values (%1+C)").arg( + #ifdef LMMS_BUILD_APPLE + "⌘"), this); + #else + "Ctrl"), this); + #endif QAction* pasteAction = new QAction(embed::getIconPixmap("edit_paste"), - tr("Paste values from clipboard (Ctrl+V)"), this); + tr("Paste values from clipboard (%1+V)").arg( + #ifdef LMMS_BUILD_APPLE + "⌘"), this); + #else + "Ctrl"), this); + #endif cutAction->setWhatsThis( tr( "Click here and selected values will be cut into the " diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index a1e25b60d20..81f59946dea 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -2434,7 +2434,7 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl ) // If shift is pressed we resize and rearrange only the selected notes // If shift + ctrl then we also rearrange all posterior notes (sticky) // If shift is pressed but only one note is selected, apply sticky - + if (shift) { // Algorithm: @@ -3986,8 +3986,13 @@ PianoRollWindow::PianoRollWindow() : "mode you can add, resize and move notes. This " "is the default mode which is used most of the time. " "You can also press 'Shift+D' on your keyboard to " - "activate this mode. In this mode, hold Ctrl to " - "temporarily go into select mode." ) ); + "activate this mode. In this mode, hold %1 to " + "temporarily go into select mode." ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘") ); + #else + "Ctrl") ); + #endif eraseAction->setWhatsThis( tr( "Click here and erase mode will be activated. In this " "mode you can erase notes. You can also press " @@ -3995,8 +4000,13 @@ PianoRollWindow::PianoRollWindow() : selectAction->setWhatsThis( tr( "Click here and select mode will be activated. " "In this mode you can select notes. Alternatively, " - "you can hold Ctrl in draw mode to temporarily use " - "select mode." ) ); + "you can hold %1 in draw mode to temporarily use " + "select mode." ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘") ); + #else + "Ctrl") ); + #endif detuneAction->setWhatsThis( tr( "Click here and detune mode will be activated. " "In this mode you can click a note to open its " @@ -4015,13 +4025,28 @@ PianoRollWindow::PianoRollWindow() : DropToolBar *copyPasteActionsToolBar = addDropToolBarToTop(tr("Copy paste controls")); QAction* cutAction = new QAction(embed::getIconPixmap("edit_cut"), - tr("Cut selected notes (Ctrl+X)"), this); + tr("Cut selected notes (%1+X)").arg( + #ifdef LMMS_BUILD_APPLE + "⌘"), this); + #else + "Ctrl"), this); + #endif QAction* copyAction = new QAction(embed::getIconPixmap("edit_copy"), - tr("Copy selected notes (Ctrl+C)"), this); + tr("Copy selected notes (%1+C)").arg( + #ifdef LMMS_BUILD_APPLE + "⌘"), this); + #else + "Ctrl"), this); + #endif QAction* pasteAction = new QAction(embed::getIconPixmap("edit_paste"), - tr("Paste notes from clipboard (Ctrl+V)"), this); + tr("Paste notes from clipboard (%1+V)").arg( + #ifdef LMMS_BUILD_APPLE + "⌘"), this); + #else + "Ctrl"), this); + #endif cutAction->setWhatsThis( tr( "Click here and the selected notes will be cut into the " diff --git a/src/gui/widgets/ProjectNotes.cpp b/src/gui/widgets/ProjectNotes.cpp index 3ee99b776db..9e345ff637a 100644 --- a/src/gui/widgets/ProjectNotes.cpp +++ b/src/gui/widgets/ProjectNotes.cpp @@ -116,31 +116,56 @@ void ProjectNotes::setupActions() a = new QAction( embed::getIconPixmap( "edit_undo" ), tr( "&Undo" ), this ); - a->setShortcut( tr( "Ctrl+Z" ) ); + a->setShortcut( tr( "%1+Z" ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘") ); + #else + "Ctrl") ); + #endif connect( a, SIGNAL( triggered() ), m_edit, SLOT( undo() ) ); tb->addAction( a ); a = new QAction( embed::getIconPixmap( "edit_redo" ), tr( "&Redo" ), this ); - a->setShortcut( tr( "Ctrl+Y" ) ); + a->setShortcut( tr( "%1+Y" ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘") ); + #else + "Ctrl") ); + #endif connect( a, SIGNAL( triggered() ), m_edit, SLOT( redo() ) ); tb->addAction( a ); a = new QAction( embed::getIconPixmap( "edit_copy" ), tr( "&Copy" ), this ); - a->setShortcut( tr( "Ctrl+C" ) ); + a->setShortcut( tr( "%1+C" ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘") ); + #else + "Ctrl") ); + #endif connect( a, SIGNAL( triggered() ), m_edit, SLOT( copy() ) ); tb->addAction( a ); a = new QAction( embed::getIconPixmap( "edit_cut" ), tr( "Cu&t" ), this ); - a->setShortcut( tr( "Ctrl+X" ) ); + a->setShortcut( tr( "%1+X" ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘") ); + #else + "Ctrl") ); + #endif connect( a, SIGNAL( triggered() ), m_edit, SLOT( cut() ) ); tb->addAction( a ); a = new QAction( embed::getIconPixmap( "edit_paste" ), tr( "&Paste" ), this ); - a->setShortcut( tr( "Ctrl+V" ) ); + a->setShortcut( tr( "%1+V" ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘") ); + #else + "Ctrl") ); + #endif connect( a, SIGNAL( triggered() ), m_edit, SLOT( paste() ) ); tb->addAction( a ); @@ -170,14 +195,24 @@ void ProjectNotes::setupActions() m_actionTextBold = new QAction( embed::getIconPixmap( "text_bold" ), tr( "&Bold" ), this ); - m_actionTextBold->setShortcut( tr( "Ctrl+B" ) ); + m_actionTextBold->setShortcut( tr( "%1+B" ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘") ); + #else + "Ctrl") ); + #endif m_actionTextBold->setCheckable( true ); connect( m_actionTextBold, SIGNAL( triggered() ), this, SLOT( textBold() ) ); m_actionTextItalic = new QAction( embed::getIconPixmap( "text_italic" ), tr( "&Italic" ), this ); - m_actionTextItalic->setShortcut( tr( "Ctrl+I" ) ); + m_actionTextItalic->setShortcut( tr( "%1+I" ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘") ); + #else + "Ctrl") ); + #endif m_actionTextItalic->setCheckable( true ); connect( m_actionTextItalic, SIGNAL( triggered() ), this, SLOT( textItalic() ) ); @@ -185,7 +220,12 @@ void ProjectNotes::setupActions() m_actionTextUnderline = new QAction( embed::getIconPixmap( "text_under" ), tr( "&Underline" ), this ); - m_actionTextUnderline->setShortcut( tr( "Ctrl+U" ) ); + m_actionTextUnderline->setShortcut( tr( "%1+U" ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘") ); + #else + "Ctrl") ); + #endif m_actionTextUnderline->setCheckable( true ); connect( m_actionTextUnderline, SIGNAL( triggered() ), this, SLOT( textUnderline() ) ); @@ -197,7 +237,12 @@ void ProjectNotes::setupActions() m_actionAlignLeft = new QAction( embed::getIconPixmap( "text_left" ), tr( "&Left" ), m_edit ); - m_actionAlignLeft->setShortcut( tr( "Ctrl+L" ) ); + m_actionAlignLeft->setShortcut( tr( "%1+L" ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘") ); + #else + "Ctrl") ); + #endif m_actionAlignLeft->setCheckable( true ); grp->addAction( m_actionAlignLeft ); @@ -205,21 +250,36 @@ void ProjectNotes::setupActions() "text_center" ), tr( "C&enter" ), m_edit ); m_actionAlignCenter->setShortcutContext( Qt::WidgetShortcut ); - m_actionAlignCenter->setShortcut( tr( "Ctrl+E" ) ); + m_actionAlignCenter->setShortcut( tr( "%1+E" ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘") ); + #else + "Ctrl") ); + #endif m_actionAlignCenter->setCheckable( true ); grp->addAction( m_actionAlignCenter ); m_actionAlignRight = new QAction( embed::getIconPixmap( "text_right" ), tr( "&Right" ), m_edit ); m_actionAlignRight->setShortcutContext( Qt::WidgetShortcut ); - m_actionAlignRight->setShortcut( tr( "Ctrl+R" ) ); + m_actionAlignRight->setShortcut( tr( "%1+R" ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘") ); + #else + "Ctrl") ); + #endif m_actionAlignRight->setCheckable( true ); grp->addAction( m_actionAlignRight ); m_actionAlignJustify = new QAction( embed::getIconPixmap( "text_block" ), tr( "&Justify" ), m_edit ); - m_actionAlignJustify->setShortcut( tr( "Ctrl+J" ) ); + m_actionAlignJustify->setShortcut( tr( "%1+J" ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘") ); + #else + "Ctrl") ); + #endif m_actionAlignJustify->setCheckable( true ); grp->addAction( m_actionAlignJustify ); @@ -409,5 +469,3 @@ void ProjectNotes::closeEvent( QCloseEvent * _ce ) } _ce->ignore(); } - - diff --git a/src/tracks/SampleTrack.cpp b/src/tracks/SampleTrack.cpp index 7cec568ad9b..2f64fd7ef2d 100644 --- a/src/tracks/SampleTrack.cpp +++ b/src/tracks/SampleTrack.cpp @@ -266,7 +266,12 @@ void SampleTCOView::contextMenuEvent( QContextMenuEvent * _cme ) tr( "Paste" ), m_tco, SLOT( paste() ) ); contextMenu.addSeparator(); contextMenu.addAction( embed::getIconPixmap( "muted" ), - tr( "Mute/unmute ( + middle click)" ), + tr( "Mute/unmute (<%1> + middle click)" ).arg( + #ifdef LMMS_BUILD_APPLE + "⌘"), + #else + "Ctrl"), + #endif m_tco, SLOT( toggleMute() ) ); contextMenu.addAction( embed::getIconPixmap( "record" ), tr( "Set/clear record" ), From aa0f7a08d64393016c2ab11ae0ba6b4853e15ed5 Mon Sep 17 00:00:00 2001 From: Colin Wallace Date: Wed, 3 Feb 2016 18:46:59 -0800 Subject: [PATCH 11/90] Move isWhiteKey, isBlackKey into Piano.h to make use of these functions in a wider scope --- include/Piano.h | 3 +++ src/core/Piano.cpp | 22 ++++++++++++++++++ src/gui/PianoView.cpp | 43 +++++++++++------------------------ src/gui/editors/PianoRoll.cpp | 22 +----------------- 4 files changed, 39 insertions(+), 51 deletions(-) diff --git a/include/Piano.h b/include/Piano.h index 48dd7f137aa..ded4de5eb9b 100644 --- a/include/Piano.h +++ b/include/Piano.h @@ -63,6 +63,9 @@ class Piano : public Model return m_midiEvProc; } + static bool isWhiteKey(int key); + static bool isBlackKey(int key); + private: static bool isValidKey( int key ) diff --git a/src/core/Piano.cpp b/src/core/Piano.cpp index d72160b5ab3..d08121b6628 100644 --- a/src/core/Piano.cpp +++ b/src/core/Piano.cpp @@ -37,9 +37,11 @@ */ #include "Piano.h" + #include "InstrumentTrack.h" #include "MidiEvent.h" #include "MidiEventProcessor.h" +#include "Note.h" /*! \brief Create a new keyboard display @@ -125,6 +127,26 @@ void Piano::handleKeyRelease( int key ) +bool Piano::isBlackKey( int key ) +{ + int keyCode = key % KeysPerOctave; + switch (keyCode) + { + case 1: + case 3: + case 6: + case 8: + case 10: + return true; + } + return false; +} + + +bool Piano::isWhiteKey( int key ) +{ + return !isBlackKey( key ); +} diff --git a/src/gui/PianoView.cpp b/src/gui/PianoView.cpp index 0f82fd70222..dacaedaa227 100644 --- a/src/gui/PianoView.cpp +++ b/src/gui/PianoView.cpp @@ -45,6 +45,7 @@ #include "PianoView.h" +#include "Piano.h" #include "CaptionMenu.h" #include "embed.h" #include "Engine.h" @@ -58,17 +59,6 @@ #include "update_event.h" -/*! The black / white order of keys as they appear on the keyboard. - */ -const Piano::KeyTypes KEY_ORDER[] = -{ -// C CIS D DIS - Piano::WhiteKey, Piano::BlackKey, Piano::WhiteKey, Piano::BlackKey, -// E F FIS G - Piano::WhiteKey, Piano::WhiteKey, Piano::BlackKey, Piano::WhiteKey, -// GIS A B H - Piano::BlackKey, Piano::WhiteKey, Piano::BlackKey, Piano::WhiteKey -} ; /*! The scale of C Major - white keys only. @@ -348,8 +338,7 @@ int PianoView::getKeyFromMouse( const QPoint & _p ) const for( int i = 0; i <= key_num; ++i ) { - if( KEY_ORDER[( m_startKey+i ) % KeysPerOctave] == - Piano::BlackKey ) + if ( Piano::isBlackKey( m_startKey+i ) ) { ++key_num; } @@ -362,17 +351,14 @@ int PianoView::getKeyFromMouse( const QPoint & _p ) const { // then do extra checking whether the mouse-cursor is over // a black key - if( key_num > 0 && KEY_ORDER[(key_num-1 ) % KeysPerOctave] == - Piano::BlackKey && + if( key_num > 0 && Piano::isBlackKey( key_num-1 ) && _p.x() % PW_WHITE_KEY_WIDTH <= ( PW_WHITE_KEY_WIDTH / 2 ) - ( PW_BLACK_KEY_WIDTH / 2 ) ) { --key_num; } - if( key_num < NumKeys - 1 && - KEY_ORDER[( key_num + 1 ) % KeysPerOctave] == - Piano::BlackKey && + if( key_num < NumKeys - 1 && Piano::isBlackKey( key_num+1 ) && _p.x() % PW_WHITE_KEY_WIDTH >= ( PW_WHITE_KEY_WIDTH - PW_BLACK_KEY_WIDTH / 2 ) ) @@ -456,8 +442,7 @@ void PianoView::mousePressEvent( QMouseEvent * _me ) { int y_diff = _me->pos().y() - PIANO_BASE; int velocity = (int)( ( float ) y_diff / - ( ( KEY_ORDER[key_num % KeysPerOctave] == - Piano::WhiteKey ) ? + ( Piano::isWhiteKey( key_num ) ? PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) * (float) m_piano->instrumentTrack()->midiPort()->baseVelocity() ); if( y_diff < 0 ) @@ -465,8 +450,7 @@ void PianoView::mousePressEvent( QMouseEvent * _me ) velocity = 0; } else if( y_diff > - ( ( KEY_ORDER[key_num % KeysPerOctave] == - Piano::WhiteKey ) ? + ( Piano::isWhiteKey( key_num ) ? PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) ) { velocity = m_piano->instrumentTrack()->midiPort()->baseVelocity(); @@ -555,7 +539,7 @@ void PianoView::mouseMoveEvent( QMouseEvent * _me ) int key_num = getKeyFromMouse( _me->pos() ); int y_diff = _me->pos().y() - PIANO_BASE; int velocity = (int)( (float) y_diff / - ( ( KEY_ORDER[key_num % KeysPerOctave] == Piano::WhiteKey ) ? + ( Piano::isWhiteKey( key_num ) ? PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) * (float) m_piano->instrumentTrack()->midiPort()->baseVelocity() ); // maybe the user moved the mouse-cursor above or under the @@ -566,7 +550,7 @@ void PianoView::mouseMoveEvent( QMouseEvent * _me ) velocity = 0; } else if( y_diff > - ( ( KEY_ORDER[key_num % KeysPerOctave] == Piano::WhiteKey ) ? + ( Piano::isWhiteKey( key_num ) ? PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) ) { velocity = m_piano->instrumentTrack()->midiPort()->baseVelocity(); @@ -751,7 +735,7 @@ int PianoView::getKeyX( int _key_num ) const while( k <= _key_num ) { - if( KEY_ORDER[k % KeysPerOctave] == Piano::WhiteKey ) + if( Piano::isWhiteKey( k ) ) { ++white_cnt; if( white_cnt > 1 ) @@ -818,7 +802,7 @@ void PianoView::paintEvent( QPaintEvent * ) QPalette::BrightText ) ); g.setColorAt( 1, QApplication::palette().color( QPalette::Active, QPalette::BrightText ) ); - if( KEY_ORDER[base_key % KeysPerOctave] == Piano::WhiteKey ) + if( Piano::isWhiteKey( base_key ) ) { p.fillRect( QRect( getKeyX( base_key ), 1, PW_WHITE_KEY_WIDTH-1, PIANO_BASE-2 ), g ); @@ -835,7 +819,7 @@ void PianoView::paintEvent( QPaintEvent * ) // draw all white keys... for( int x = 0; x < width(); ) { - while( KEY_ORDER[cur_key%KeysPerOctave] != Piano::WhiteKey ) + while( Piano::isBlackKey( cur_key ) ) { ++cur_key; } @@ -870,8 +854,7 @@ void PianoView::paintEvent( QPaintEvent * ) int white_cnt = 0; int startKey = m_startKey; - if( startKey > 0 && - KEY_ORDER[(Keys)(--startKey) % KeysPerOctave] == Piano::BlackKey ) + if( startKey > 0 && Piano::isBlackKey( (Keys)(--startKey) ) ) { if( m_piano && m_piano->isKeyPressed( startKey ) ) { @@ -886,7 +869,7 @@ void PianoView::paintEvent( QPaintEvent * ) // now draw all black keys... for( int x = 0; x < width(); ) { - if( KEY_ORDER[cur_key%KeysPerOctave] == Piano::BlackKey ) + if( Piano::isBlackKey( cur_key ) ) { // draw pressed or not pressed key, depending on // state of current key diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 3ce254c1f11..e035f027a47 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -139,27 +139,7 @@ static QString getNoteString( int key ) return s_noteStrings[key % 12] + QString::number( static_cast( key / KeysPerOctave ) ); } -static bool isBlackKey( int key ) -{ - int keyCode = key % KeysPerOctave; - switch (keyCode) - { - case 1: - case 3: - case 6: - case 8: - case 10: - return true; - } - - return false; -} - -static bool isWhiteKey( int key ) -{ - return !isBlackKey( key ); -} // used for drawing of piano PianoRoll::PianoRollKeyTypes PianoRoll::prKeyOrder[] = @@ -2691,7 +2671,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) break; } - if ( isWhiteKey( key ) ) + if ( Piano::isWhiteKey( key ) ) { // Draw note names if activated in the preferences, C notes are always drawn if ( key % 12 == 0 || drawNoteNames ) From 176e08047e328e2c0fbd257dfb1225b88964f989 Mon Sep 17 00:00:00 2001 From: Colin Wallace Date: Wed, 3 Feb 2016 18:53:05 -0800 Subject: [PATCH 12/90] Rewrite Piano::isBlackKey for clarity --- src/core/Piano.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/core/Piano.cpp b/src/core/Piano.cpp index d08121b6628..88e1f115aba 100644 --- a/src/core/Piano.cpp +++ b/src/core/Piano.cpp @@ -44,6 +44,19 @@ #include "Note.h" +/*! The black / white order of keys as they appear on the keyboard. + */ +static const Piano::KeyTypes KEY_ORDER[] = +{ +// C CIS D DIS + Piano::WhiteKey, Piano::BlackKey, Piano::WhiteKey, Piano::BlackKey, +// E F FIS G + Piano::WhiteKey, Piano::WhiteKey, Piano::BlackKey, Piano::WhiteKey, +// GIS A AIS B + Piano::BlackKey, Piano::WhiteKey, Piano::BlackKey, Piano::WhiteKey +} ; + + /*! \brief Create a new keyboard display * * \param _it the InstrumentTrack window to attach to @@ -131,17 +144,7 @@ bool Piano::isBlackKey( int key ) { int keyCode = key % KeysPerOctave; - switch (keyCode) - { - case 1: - case 3: - case 6: - case 8: - case 10: - return true; - } - - return false; + return KEY_ORDER[keyCode] == Piano::BlackKey; } From 439ab30d5152dabfe518779e3dfea2aa63ccc0ed Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Mon, 1 Feb 2016 22:34:23 +0100 Subject: [PATCH 13/90] Make the note border radius themeable, fix rendering of notes and volume/pan sliders --- data/themes/default/style.css | 2 ++ include/PianoRoll.h | 12 ++++++++-- src/gui/editors/PianoRoll.cpp | 44 ++++++++++++++++++++++++----------- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 0e874a66233..23ea03af99d 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -115,6 +115,8 @@ PianoRoll { qproperty-noteModeColor: rgb( 255, 255, 255 ); qproperty-noteColor: rgb( 119, 199, 216 ); qproperty-barColor: #4afd85; + qproperty-noteBorderRadiusX: 5; + qproperty-noteBorderRadiusY: 2; } /* main toolbar oscilloscope - can have transparent bg now */ diff --git a/include/PianoRoll.h b/include/PianoRoll.h index 92b614076f1..b6a96db93ec 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -57,6 +57,8 @@ class PianoRoll : public QWidget Q_PROPERTY( QColor noteModeColor READ noteModeColor WRITE setNoteModeColor ) Q_PROPERTY( QColor noteColor READ noteColor WRITE setNoteColor ) Q_PROPERTY( QColor barColor READ barColor WRITE setBarColor ) + Q_PROPERTY( float noteBorderRadiusX READ noteBorderRadiusX WRITE setNoteBorderRadiusX ) + Q_PROPERTY( float noteBorderRadiusY READ noteBorderRadiusY WRITE setNoteBorderRadiusY ) public: enum EditModes { @@ -109,6 +111,10 @@ class PianoRoll : public QWidget void setNoteColor( const QColor & c ); QColor barColor() const; void setBarColor( const QColor & c ); + float noteBorderRadiusX() const; + void setNoteBorderRadiusX( float b ); + float noteBorderRadiusY() const; + void setNoteBorderRadiusY( float b ); protected: @@ -126,7 +132,8 @@ class PianoRoll : public QWidget int getKey( int y ) const; static void drawNoteRect( QPainter & p, int x, int y, - int width, const Note * n, const QColor & noteCol ); + int width, const Note * n, const QColor & noteCol, + float radiusX, float radiusY ); void removeSelection(); void selectAll(); NoteVector getSelectedNotes(); @@ -349,6 +356,8 @@ protected slots: QColor m_noteModeColor; QColor m_noteColor; QColor m_barColor; + float m_noteBorderRadiusX; + float m_noteBorderRadiusY; signals: void positionChanged( const MidiTime & ); @@ -408,4 +417,3 @@ class PianoRollWindow : public Editor, SerializingObject #endif - diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 134065e5cf0..2c89a7d121a 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -209,7 +209,9 @@ PianoRoll::PianoRoll() : m_gridColor( 0, 0, 0 ), m_noteModeColor( 0, 0, 0 ), m_noteColor( 0, 0, 0 ), - m_barColor( 0, 0, 0 ) + m_barColor( 0, 0, 0 ), + m_noteBorderRadiusX( 0 ), + m_noteBorderRadiusY( 0 ) { // gui names of edit modes m_nemStr.push_back( tr( "Note Volume" ) ); @@ -759,10 +761,22 @@ QColor PianoRoll::barColor() const void PianoRoll::setBarColor( const QColor & c ) { m_barColor = c; } +float PianoRoll::noteBorderRadiusX() const +{ return m_noteBorderRadiusX; } +void PianoRoll::setNoteBorderRadiusX( float b ) +{ m_noteBorderRadiusX = b; } -void PianoRoll::drawNoteRect(QPainter & p, int x, int y, - int width, const Note * n, const QColor & noteCol ) +float PianoRoll::noteBorderRadiusY() const +{ return m_noteBorderRadiusY; } + +void PianoRoll::setNoteBorderRadiusY( float b ) +{ m_noteBorderRadiusY = b; } + + +void PianoRoll::drawNoteRect(QPainter & p, int x, int y, + int width, const Note * n, const QColor & noteCol, + float radiusX, float radiusY ) { ++x; ++y; @@ -804,15 +818,17 @@ void PianoRoll::drawNoteRect(QPainter & p, int x, int y, p.setPen( col ); p.setRenderHint(QPainter::Antialiasing); - p.drawRoundedRect( x, y, width, KEY_LINE_HEIGHT-1, 5, 2 ); + p.drawRoundedRect( QRectF ( x + 0.5, y - 0.5, width, KEY_LINE_HEIGHT ), radiusX, radiusY ); // that little tab thing on the end hinting at the user // to resize the note p.setPen( noteCol.lighter( 200 ) ); + p.setBrush( noteCol.lighter( 200 ) ); if( width > 2 ) { - p.drawLine( x + width - 3, y + 3, x + width - 3, - y + KEY_LINE_HEIGHT - 5 ); + float leftIndent = 2.5; + float vertIndent = 3.5; + p.drawRect( QRectF (x + width - leftIndent, y + vertIndent, 1, KEY_LINE_HEIGHT - (2*vertIndent + 1) ) ); } } @@ -2900,7 +2916,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) const int visible_keys = ( keyAreaBottom()-keyAreaTop() ) / KEY_LINE_HEIGHT + 2; - QPolygon editHandles; + QPolygonF editHandles; for( const Note *note : m_pattern->notes() ) { @@ -2936,7 +2952,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) // note drawNoteRect( p, x + WHITE_KEY_WIDTH, y_base - key * KEY_LINE_HEIGHT, - note_width, note, noteColor() ); + note_width, note, noteColor(), noteBorderRadiusX(), noteBorderRadiusY() ); } // draw note editing stuff @@ -2955,8 +2971,8 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) ( (float)( MaxVolume - MinVolume ) ) * ( (float)( noteEditBottom() - noteEditTop() ) ); - p.drawLine( noteEditLeft() + x, editHandleTop, - noteEditLeft() + x, noteEditBottom() ); + p.drawLine( QLineF ( noteEditLeft() + x + 0.5, editHandleTop + 0.5, + noteEditLeft() + x + 0.5, noteEditBottom() + 0.5 ) ); } else if( m_noteEditMode == NoteEditPanning ) @@ -2974,12 +2990,12 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) ( (float)( (PanningRight - PanningLeft ) ) ) * ( (float)( noteEditBottom() - noteEditTop() ) ); - p.drawLine( noteEditLeft() + x, noteEditTop() + + p.drawLine( QLineF( noteEditLeft() + x + 0.5, noteEditTop() + 0.5 + ( (float)( noteEditBottom() - noteEditTop() ) ) / 2.0f, - noteEditLeft() + x, editHandleTop ); + noteEditLeft() + x + 0.5, editHandleTop + 0.5 ) ); } - editHandles << QPoint( x + noteEditLeft(), - editHandleTop+1 ); + editHandles << QPointF ( x + noteEditLeft() + 0.5, + editHandleTop + 1.5 ); if( note->hasDetuningInfo() ) { From 8b73381517a21ba73d30cdfc9cdf9f56f0ab3d4c Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Fri, 5 Feb 2016 01:34:51 +0100 Subject: [PATCH 14/90] Make the instrument section of the sidebar themeable --- data/themes/default/style.css | 17 +++++++++++++++++ src/gui/PluginBrowser.cpp | 14 ++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 0e874a66233..df937ac6129 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -479,6 +479,23 @@ SideBar QToolButton { font-size: 12px; } +/* Instrument plugin list */ + +PluginDescList { + background-color: #5b6571; +} + +PluginDescWidget { + background-color: #e0e0e0; + color: #404040; + border: 1px solid rgb(64, 64, 64); + margin: 0px; +} + +PluginDescWidget:hover { + background-color: #e0e0e0; +} + /* font sizes for text buttons */ FxMixerView QPushButton, EffectRackView QPushButton, ControllerRackView QPushButton { diff --git a/src/gui/PluginBrowser.cpp b/src/gui/PluginBrowser.cpp index 14f99273eb5..57e823dc74d 100644 --- a/src/gui/PluginBrowser.cpp +++ b/src/gui/PluginBrowser.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "embed.h" #include "debug.h" @@ -135,21 +136,22 @@ PluginDescWidget::~PluginDescWidget() -void PluginDescWidget::paintEvent( QPaintEvent * ) +void PluginDescWidget::paintEvent( QPaintEvent * e ) { - const QColor fill_color = m_mouseOver ? QColor( 224, 224, 224 ) : - QColor( 192, 192, 192 ); QPainter p( this ); - p.fillRect( rect(), fill_color ); + // Paint everything according to the style sheet + QStyleOption o; + o.initFrom( this ); + style()->drawPrimitive( QStyle::PE_Widget, &o, &p, this ); + + // Draw the rest const int s = 16 + ( 32 * ( tLimit( height(), 24, 60 ) - 24 ) ) / ( 60 - 24 ); const QSize logo_size( s, s ); QPixmap logo = m_logo.scaled( logo_size, Qt::KeepAspectRatio, Qt::SmoothTransformation ); - p.setPen( QColor( 64, 64, 64 ) ); - p.drawRect( 0, 0, rect().right(), rect().bottom() ); p.drawPixmap( 4, 4, logo ); QFont f = p.font(); From badb6c1ca943e0c61d435e2a5bdcb40f42dec3e5 Mon Sep 17 00:00:00 2001 From: midi-pascal Date: Fri, 5 Feb 2016 11:41:25 -0500 Subject: [PATCH 15/90] Update French translation after fix of issue #2435 --- data/locale/fr.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/data/locale/fr.ts b/data/locale/fr.ts index 9f02d6ab52f..10fb548d6c5 100644 --- a/data/locale/fr.ts +++ b/data/locale/fr.ts @@ -1,6 +1,6 @@ - + AboutDialog @@ -6614,11 +6614,11 @@ Veuillez vérifier que vous avez les droits en lecture pour ce fichier et le ré TripleOscillatorView Use phase modulation for modulating oscillator 1 with oscillator 2 - Utiliser la modulation de phase pour moduler l'oscillateur 2 avec l'oscillateur 1 + Utiliser la modulation de phase pour moduler l'oscillateur 1 avec l'oscillateur 2 Use amplitude modulation for modulating oscillator 1 with oscillator 2 - Utiliser la modulation d'amplitude pour moduler l'oscillateur 2 avec l'oscillateur 1 + Utiliser la modulation d'amplitude pour moduler l'oscillateur 1 avec l'oscillateur 2 Mix output of oscillator 1 & 2 @@ -6630,15 +6630,15 @@ Veuillez vérifier que vous avez les droits en lecture pour ce fichier et le ré Use frequency modulation for modulating oscillator 1 with oscillator 2 - Utiliser la modulation de fréquence pour moduler l'oscillateur 2 avec l'oscillateur 1 + Utiliser la modulation de fréquence pour moduler l'oscillateur 1 avec l'oscillateur 2 Use phase modulation for modulating oscillator 2 with oscillator 3 - Utiliser la modulation de phase pour moduler l'oscillateur 3 avec l'oscillateur 2 + Utiliser la modulation de phase pour moduler l'oscillateur 2 avec l'oscillateur 3 Use amplitude modulation for modulating oscillator 2 with oscillator 3 - Utiliser la modulation d'amplitude pour moduler l'oscillateur 3 avec l'oscillateur 2 + Utiliser la modulation d'amplitude pour moduler l'oscillateur 2 avec l'oscillateur 3 Mix output of oscillator 2 & 3 @@ -6646,11 +6646,11 @@ Veuillez vérifier que vous avez les droits en lecture pour ce fichier et le ré Synchronize oscillator 2 with oscillator 3 - Synchroniser l'oscillateur 2 avec l'oscillateur 3 + Synchroniser l'oscillateur 2 avec l'oscillateur 3 Use frequency modulation for modulating oscillator 2 with oscillator 3 - Utiliser la modulation de fréquence pour moduler l'oscillateur 3 avec l'oscillateur 2 + Utiliser la modulation de fréquence pour moduler l'oscillateur 2 avec l'oscillateur 3 Osc %1 volume: From 6228d9ae260dd4a722487c8dff0897d745fb78ea Mon Sep 17 00:00:00 2001 From: "Kenneth Perry (thothonegan)" Date: Fri, 5 Feb 2016 14:52:28 -0600 Subject: [PATCH 16/90] If using Qt5, use Qt5LinguistTools to locate lupdate/lrelease --- CMakeLists.txt | 1 + src/CMakeLists.txt | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 228c74eb5fc..9d88b665eb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,6 +132,7 @@ IF(WANT_QT5) FIND_PACKAGE(Qt5Core REQUIRED) FIND_PACKAGE(Qt5Gui REQUIRED) + FIND_PACKAGE(Qt5LinguistTools REQUIRED) FIND_PACKAGE(Qt5Widgets REQUIRED) FIND_PACKAGE(Qt5Xml REQUIRED) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8045b86a421..fb7038c740d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -132,6 +132,11 @@ IF(LMMS_BUILD_MSYS AND CMAKE_BUILD_TYPE STREQUAL "Debug") TARGET_LINK_LIBRARIES(lmms QtCore4 QtGui4 QtXml4) ENDIF() +if (QT5) + set (QT_LUPDATE_EXECUTABLE "${Qt5_LUPDATE_EXECUTABLE}") + set (QT_LRELEASE_EXECUTABLE "${Qt5_LRELEASE_EXECUTABLE}") +endif () + # # rules for building localizations # From 45154d2e99e836efeec8532e63a4ee9a4c62ce99 Mon Sep 17 00:00:00 2001 From: "Kenneth Perry (thothonegan)" Date: Fri, 5 Feb 2016 15:08:12 -0600 Subject: [PATCH 17/90] Require linguist tools on Travis Ubuntu --- .travis/linux..install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/linux..install.sh b/.travis/linux..install.sh index 1dfcd161545..4be588ae832 100644 --- a/.travis/linux..install.sh +++ b/.travis/linux..install.sh @@ -5,7 +5,7 @@ PACKAGES="cmake libsndfile-dev fftw3-dev libvorbis-dev libogg-dev if [ $QT5 ] then - PACKAGES="$PACKAGES qtbase5-dev" + PACKAGES="$PACKAGES qtbase5-dev qttools5-dev-tools qttools5-dev" else PACKAGES="$PACKAGES libqt4-dev" fi From 59f8fbd94b6b583b55c41162b7ebf247da6dfbe1 Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Sat, 6 Feb 2016 12:17:38 +0100 Subject: [PATCH 18/90] Fix inconsistent scrollbars --- include/AutomationEditor.h | 2 +- src/gui/editors/PianoRoll.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h index c6a3c96c613..ab1130f881a 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -159,7 +159,7 @@ protected slots: } ; // some constants... - static const int SCROLLBAR_SIZE = 16; + static const int SCROLLBAR_SIZE = 14; static const int TOP_MARGIN = 16; static const int DEFAULT_Y_DELTA = 6; diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index a8eea4fdb62..0ac39f529c8 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -83,7 +83,7 @@ typedef AutomationPattern::timeMap timeMap; // some constants... const int INITIAL_PIANOROLL_HEIGHT = 480; -const int SCROLLBAR_SIZE = 16; +const int SCROLLBAR_SIZE = 14; const int PIANO_X = 0; const int WHITE_KEY_WIDTH = 64; From e24384e7325175335c2ad26359583dc5dcf984cf Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Sun, 7 Feb 2016 01:35:07 +0100 Subject: [PATCH 19/90] Make FxLine Stroke Themeable --- data/themes/default/style.css | 4 +++ include/FxLine.h | 21 ++++++++++++++ src/gui/widgets/FxLine.cpp | 53 +++++++++++++++++++++++++++++++---- 3 files changed, 73 insertions(+), 5 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 23ea03af99d..77a990a5dd6 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -492,6 +492,10 @@ FxLine { color: #e0e0e0; qproperty-backgroundActive: qlineargradient(spread:reflect, x1:0, y1:0, x2:1, y2:0, stop:0 #7b838d, stop:1 #6b7581 ); + qproperty-strokeOuterActive: rgb( 0, 0, 0 ); + qproperty-strokeOuterInactive: rgba( 0, 0, 0, 50 ); + qproperty-strokeInnerActive: rgba( 255, 255, 255, 100 ); + qproperty-strokeInnerInactive: rgba( 255, 255, 255, 50 ); } /* persistent peak markers for fx peak meters */ diff --git a/include/FxLine.h b/include/FxLine.h index 69f6a9ed0cb..6081912d431 100644 --- a/include/FxLine.h +++ b/include/FxLine.h @@ -41,6 +41,10 @@ class FxLine : public QWidget Q_OBJECT public: Q_PROPERTY( QBrush backgroundActive READ backgroundActive WRITE setBackgroundActive ) + Q_PROPERTY( QColor strokeOuterActive READ strokeOuterActive WRITE setStrokeOuterActive ) + Q_PROPERTY( QColor strokeOuterInactive READ strokeOuterInactive WRITE setStrokeOuterInactive ) + Q_PROPERTY( QColor strokeInnerActive READ strokeInnerActive WRITE setStrokeInnerActive ) + Q_PROPERTY( QColor strokeInnerInactive READ strokeInnerInactive WRITE setStrokeInnerInactive ) FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex); ~FxLine(); @@ -57,6 +61,19 @@ class FxLine : public QWidget QBrush backgroundActive() const; void setBackgroundActive( const QBrush & c ); + + QColor strokeOuterActive() const; + void setStrokeOuterActive( const QColor & c ); + + QColor strokeOuterInactive() const; + void setStrokeOuterInactive( const QColor & c ); + + QColor strokeInnerActive() const; + void setStrokeInnerActive( const QColor & c ); + + QColor strokeInnerInactive() const; + void setStrokeInnerInactive( const QColor & c ); + static const int FxLineHeight; @@ -67,6 +84,10 @@ class FxLine : public QWidget LcdWidget* m_lcd; int m_channelIndex; QBrush m_backgroundActive; + QColor m_strokeOuterActive; + QColor m_strokeOuterInactive; + QColor m_strokeInnerActive; + QColor m_strokeInnerInactive; static QPixmap * s_sendBgArrow; static QPixmap * s_receiveBgArrow; diff --git a/src/gui/widgets/FxLine.cpp b/src/gui/widgets/FxLine.cpp index ea3282a0130..620f6d62621 100644 --- a/src/gui/widgets/FxLine.cpp +++ b/src/gui/widgets/FxLine.cpp @@ -48,7 +48,11 @@ FxLine::FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex) : QWidget( _parent ), m_mv( _mv ), m_channelIndex( _channelIndex ), - m_backgroundActive( Qt::SolidPattern ) + m_backgroundActive( Qt::SolidPattern ), + m_strokeOuterActive( 0, 0, 0 ), + m_strokeOuterInactive( 0, 0, 0 ), + m_strokeInnerActive( 0, 0, 0 ), + m_strokeInnerInactive( 0, 0, 0 ) { if( ! s_sendBgArrow ) { @@ -126,11 +130,13 @@ void FxLine::drawFxLine( QPainter* p, const FxLine *fxLine, const QString& name, p->fillRect( fxLine->rect(), isActive ? fxLine->backgroundActive() : p->background() ); - - p->setPen( QColor( 255, 255, 255, isActive ? 100 : 50 ) ); + + // inner border + p->setPen( isActive ? fxLine->strokeInnerActive() : fxLine->strokeInnerInactive() ); p->drawRect( 1, 1, width-3, height-3 ); - - p->setPen( isActive ? sh_color : QColor( 0, 0, 0, 50 ) ); + + // outer border + p->setPen( isActive ? fxLine->strokeOuterActive() : fxLine->strokeOuterInactive() ); p->drawRect( 0, 0, width-1, height-1 ); // draw the mixer send background @@ -276,5 +282,42 @@ void FxLine::setBackgroundActive( const QBrush & c ) m_backgroundActive = c; } +QColor FxLine::strokeOuterActive() const +{ + return m_strokeOuterActive; +} +void FxLine::setStrokeOuterActive( const QColor & c ) +{ + m_strokeOuterActive = c; +} + +QColor FxLine::strokeOuterInactive() const +{ + return m_strokeOuterInactive; +} +void FxLine::setStrokeOuterInactive( const QColor & c ) +{ + m_strokeOuterInactive = c; +} + +QColor FxLine::strokeInnerActive() const +{ + return m_strokeInnerActive; +} + +void FxLine::setStrokeInnerActive( const QColor & c ) +{ + m_strokeInnerActive = c; +} + +QColor FxLine::strokeInnerInactive() const +{ + return m_strokeInnerInactive; +} + +void FxLine::setStrokeInnerInactive( const QColor & c ) +{ + m_strokeInnerInactive = c; +} From 76e690a1a05c14ce4b4c1b0797696d6269201767 Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Fri, 29 Jan 2016 19:43:57 +0100 Subject: [PATCH 20/90] Fixed indentation --- src/core/main.cpp | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/core/main.cpp b/src/core/main.cpp index d5beb6d9b19..d9d032c5764 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -770,33 +770,32 @@ int main( int argc, char * * argv ) } else { - - // If enabled, open last project if there is one. Else, create - // a new one. Also skip recently opened file if limited session to - // lower the chance of opening an already opened file. - if( ConfigManager::inst()-> - value( "app", "openlastproject" ).toInt() && - !ConfigManager::inst()->recentlyOpenedProjects().isEmpty() && - gui->mainWindow()->getSession() - != MainWindow::SessionState::Limited ) - { - QString f = ConfigManager::inst()-> - recentlyOpenedProjects().first(); - QFileInfo recentFile( f ); - - if ( recentFile.exists() ) - { - Engine::getSong()->loadProject( f ); + // If enabled, open last project if there is one. Else, create + // a new one. Also skip recently opened file if limited session to + // lower the chance of opening an already opened file. + if( ConfigManager::inst()-> + value( "app", "openlastproject" ).toInt() && + !ConfigManager::inst()->recentlyOpenedProjects().isEmpty() && + gui->mainWindow()->getSession() + != MainWindow::SessionState::Limited ) + { + QString f = ConfigManager::inst()-> + recentlyOpenedProjects().first(); + QFileInfo recentFile( f ); + + if ( recentFile.exists() ) + { + Engine::getSong()->loadProject( f ); + } + else + { + Engine::getSong()->createNewProject(); + } } else { Engine::getSong()->createNewProject(); } - } - else - { - Engine::getSong()->createNewProject(); - } // [Settel] workaround: showMaximized() doesn't work with // FVWM2 unless the window is already visible -> show() first @@ -806,6 +805,7 @@ int main( int argc, char * * argv ) gui->mainWindow()->showMaximized(); } } + // Finally we start the auto save timer and also trigger the // autosave one time as recover.mmp is a signal to possible other // instances of LMMS. From 1ff0650a0df2234c04831b4284a126bb4e0ca55d Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 7 Feb 2016 21:43:47 +0100 Subject: [PATCH 21/90] Removes the project lb303 which seems to have been inactive since 2008 According to the blame the project lb303 has been commented out from CMakeLists.txt on 22.07.2008. Therefore it does not seem to be actively maintained and is very likely to not even compile anymore. --- plugins/CMakeLists.txt | 1 - plugins/lb303/CMakeLists.txt | 3 - plugins/lb303/README | 87 ---- plugins/lb303/artwork.png | Bin 114428 -> 0 bytes plugins/lb303/lb303.cpp | 843 ----------------------------------- plugins/lb303/lb303.h | 271 ----------- plugins/lb303/logo.png | Bin 3468 -> 0 bytes 7 files changed, 1205 deletions(-) delete mode 100644 plugins/lb303/CMakeLists.txt delete mode 100644 plugins/lb303/README delete mode 100644 plugins/lb303/artwork.png delete mode 100644 plugins/lb303/lb303.cpp delete mode 100644 plugins/lb303/lb303.h delete mode 100644 plugins/lb303/logo.png diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 86e53b01bea..55b27b344e8 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -25,7 +25,6 @@ ADD_SUBDIRECTORY(kicker) ADD_SUBDIRECTORY(ladspa_browser) ADD_SUBDIRECTORY(LadspaEffect) ADD_SUBDIRECTORY(lb302) -#ADD_SUBDIRECTORY(lb303) ADD_SUBDIRECTORY(MidiImport) ADD_SUBDIRECTORY(MidiExport) ADD_SUBDIRECTORY(MultitapEcho) diff --git a/plugins/lb303/CMakeLists.txt b/plugins/lb303/CMakeLists.txt deleted file mode 100644 index c5dd672e3c5..00000000000 --- a/plugins/lb303/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -INCLUDE(BuildPlugin) - -BUILD_PLUGIN(lb303 lb303.cpp lb303.h MOCFILES lb303.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") diff --git a/plugins/lb303/README b/plugins/lb303/README deleted file mode 100644 index 2a8058e56d8..00000000000 --- a/plugins/lb303/README +++ /dev/null @@ -1,87 +0,0 @@ -LB303 Bass Synth - Known bugs, issues, and missing features ------------------------------------------------------------ - -2007.02.03 - First release --------------------------- - -Important note, in the current incarnation there are many behaviors, -constants, and other items that will be changed. This will result -in a change of the instrument's timbre and functionality. Therefore, -it would be wise to not make any masterpieces with the synth at -this point in time. - -BUG: - Fix the awful clicking cause by adjacent notes. This problem seems - to be caused by 'unexhausted buffers' That is, the problem manifests - itself to a greater degree when the user "buffer size" configuration - is increased to over 1024 frames or so. The problem is much less - noticable when the buffer size is set to 64 frames. - -BUG: - The synth does not make accomodations for sampling rates other than - 44100. This should be easy to fix, but I haven't gotten around to - it; nor do I have the means to test it. - -BUG: - I get segfaults now and then. Granted, I've rarely used LMMS - without also using LB302, so I do not know if the problem is actually - in the Bass Synth. I have gotten the backtraces a few times: - ... - mixer::renderNextBuffer() - mixer::nextAudioBuffer() - QOBject::activate_signal() - ??() - - and - - ... - instrumentTrack::play() - notePlayHandle() - instrumentTrack::processOutEvent() - fadeButton::activate() - QSingleShotTimer::start() - qStartTimer() - qKillTimer() - QGList::insertAt() - -TODO: - Add accent feature. This isn't as bad as it sounds, but will require - some tweaking to get right. - -TODO: - LB302 contains code for a short fixed-length default decay. If a - released note is using a user-defined VCA from the instrument - panel, then LB302 should not do anything special. However, if no - envelope is specified, then LB302 should request enough release-frames - in order to apply the built-in exponential decay. - -TODO: - The original TB303's square wave is not 50% duty cycle. The peaks are - supposed to slope down slightly. It would be nice to be able to - configure this. In fact, each waveform could have a parameter knob to - change some aspect of the wave. See lb302.cpp:643 for more info. - -TODO: - Must decide on proper action to take when a slide note is interrupted - by another slide note. Right now, the slide-from frequency is always - replaced with the prior note. However, we may wish to maintain the - current frequency in order to make the sound more continuous. - -TODO: - The default filter's distortion could use some work. - effectLib::distortion<> gets the job done, but the coefficients need - to more closely match that of lb302Filter3Pole's tanh distortion. - -TODO: - Slide decay needs a better knob mapping. sqrt()? lb302.cpp:588 - -TODO: - Consider making the slide trigger set the note to slide TO as opposed - to the note to slide FROM. I originally did FROM in order to match - the real 303. However, TO may be more intuitive. - -TODO: - Various code refactoring, as well as precomputing some values. - -TODO: - Remove one of the sawtooth waveforms in favor of the other? diff --git a/plugins/lb303/artwork.png b/plugins/lb303/artwork.png deleted file mode 100644 index 061e327358ab6d0d6b8515e8fef64a63eeb60bbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114428 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

y)q{OVVV8q}t|ruybZ5tLg*b5bCB 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

L}8z34Iy?oJZPw%8*5B+S5tb(Xsyjc6UNR_ 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 - * - * This file is part of LMMS - http://lmms.io - * - * lb303FilterIIR2 is based on the gsyn filter code by Andy Sloane. - * - * lb303Filter3Pole is based on the TB303 instrument written by - * Josep M Comajuncosas for the CSounds library - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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. - * - */ - - -#include - -#include "lb303.h" -#include "engine.h" -#include "InstrumentPlayHandle.h" -#include "InstrumentTrack.h" -#include "Knob.h" -#include "NotePlayHandle.h" -#include "templates.h" -#include "audio_port.h" - -#include "embed.cpp" - - - -// Envelope Recalculation period -#define ENVINC 64 - -// -// New config -// -#define LB_24_IGNORE_ENVELOPE -#define LB_FILTERED -//#define LB_DECAY -//#define LB_24_RES_TRICK - -#define LB_DIST_RATIO 4.0 -#define LB_24_VOL_ADJUST 3.0 -//#define LB_DECAY_NOTES - -#define LB_DEBUG - -#ifdef LB_DEBUG -#include -#endif - -// -// Old config -// - - -//#define engine::mixer()->processingSampleRate() 44100.0f - - -extern "C" -{ - -Plugin::Descriptor PLUGIN_EXPORT lb303_plugin_descriptor = -{ - STRINGIFY( PLUGIN_NAME ), - "LB303", - QT_TRANSLATE_NOOP( "pluginBrowser", - "Incomplete monophonic imitation tb303" ), - "Paul Giblock ", - 0x0100, - Plugin::Instrument, - new PluginPixmapLoader( "logo" ), - NULL -}; - -} - -// -// lb303Filter -// - -lb303Filter::lb303Filter(lb303FilterKnobState* p_fs) : - fs(p_fs), - vcf_c0(0), - vcf_e0(0), - vcf_e1(0) -{ -}; - - -void lb303Filter::recalc() -{ - vcf_e1 = exp(6.109 + 1.5876*(fs->envmod) + 2.1553*(fs->cutoff) - 1.2*(1.0-(fs->reso))); - vcf_e0 = exp(5.613 - 0.8*(fs->envmod) + 2.1553*(fs->cutoff) - 0.7696*(1.0-(fs->reso))); - vcf_e0*=M_PI/engine::mixer()->processingSampleRate(); - vcf_e1*=M_PI/engine::mixer()->processingSampleRate(); - vcf_e1 -= vcf_e0; - - vcf_rescoeff = exp(-1.20 + 3.455*(fs->reso)); -}; - - -void lb303Filter::envRecalc() -{ - vcf_c0 *= fs->envdecay; // Filter Decay. vcf_decay is adjusted for Hz and ENVINC - // vcf_rescoeff = exp(-1.20 + 3.455*(fs->reso)); moved above -}; - - -void lb303Filter::playNote() -{ - vcf_c0 = vcf_e1; -} - - -// -// lb303FilterIIR2 -// - -lb303FilterIIR2::lb303FilterIIR2(lb303FilterKnobState* p_fs) : - lb303Filter(p_fs), - vcf_d1(0), - vcf_d2(0), - vcf_a(0), - vcf_b(0), - vcf_c(1) -{ - - m_dist = new effectLib::distortion<>( 1.0, 1.0f); - -}; - - -lb303FilterIIR2::~lb303FilterIIR2() -{ - delete m_dist; -} - - -void lb303FilterIIR2::recalc() -{ - lb303Filter::recalc(); - //m_dist->setThreshold(0.5+(fs->dist*2.0)); - m_dist->setThreshold(fs->dist*75.0); -}; - - -void lb303FilterIIR2::envRecalc() -{ - float k, w; - - lb303Filter::envRecalc(); - - w = vcf_e0 + vcf_c0; // e0 is adjusted for Hz and doesn't need ENVINC - k = exp(-w/vcf_rescoeff); // Does this mean c0 is inheritantly? - - vcf_a = 2.0*cos(2.0*w) * k; - vcf_b = -k*k; - vcf_c = 1.0 - vcf_a - vcf_b; -} - - -float lb303FilterIIR2::process(const float& samp) -{ - float ret = vcf_a*vcf_d1 + vcf_b*vcf_d2 + vcf_c*samp; - // Delayed samples for filter - vcf_d2 = vcf_d1; - vcf_d1 = ret; - - if(fs->dist > 0) - ret=m_dist->nextSample(ret); - - // output = IIR2 + dry - return ret; -} - - -// -// lb303Filter3Pole -// - -lb303Filter3Pole::lb303Filter3Pole(lb303FilterKnobState *p_fs) : - lb303Filter(p_fs), - ay1(0), - ay2(0), - aout(0), - lastin(0) -{ -}; - - -void lb303Filter3Pole::recalc() -{ - // DO NOT CALL BASE CLASS - vcf_e0 = 0.000001; - vcf_e1 = 1.0; -} - - -// TODO: Try using k instead of vcf_reso -void lb303Filter3Pole::envRecalc() -{ - float w,k; - float kfco; - - lb303Filter::envRecalc(); - - // e0 is adjusted for Hz and doesn't need ENVINC - w = vcf_e0 + vcf_c0; - k = (fs->cutoff > 0.975)?0.975:fs->cutoff; - kfco = 50.f + (k)*((2300.f-1600.f*(fs->envmod))+(w) * - (700.f+1500.f*(k)+(1500.f+(k)*(engine::mixer()->processingSampleRate()/2.f-6000.f)) * - (fs->envmod)) ); - //+iacc*(.3+.7*kfco*kenvmod)*kaccent*kaccurve*2000 - - -#ifdef LB_24_IGNORE_ENVELOPE - // kfcn = fs->cutoff; - kfcn = 2.0 * kfco / engine::mixer()->processingSampleRate(); -#else - kfcn = w; -#endif - kp = ((-2.7528*kfcn + 3.0429)*kfcn + 1.718)*kfcn - 0.9984; - kp1 = kp+1.0; - kp1h = 0.5*kp1; -#ifdef LB_24_RES_TRICK - k = exp(-w/vcf_rescoeff); - kres = (((k))) * (((-2.7079*kp1 + 10.963)*kp1 - 14.934)*kp1 + 8.4974); -#else - kres = (((fs->reso))) * (((-2.7079*kp1 + 10.963)*kp1 - 14.934)*kp1 + 8.4974); -#endif - value = 1.0+( (fs->dist) *(1.5 + 2.0*kres*(1.0-kfcn))); // ENVMOD was DIST -} - - -float lb303Filter3Pole::process(const float& samp) -{ - float ax1 = lastin; - float ay11 = ay1; - float ay31 = ay2; - lastin = (samp) - tanh(kres*aout); - ay1 = kp1h * (lastin+ax1) - kp*ay1; - ay2 = kp1h * (ay1 + ay11) - kp*ay2; - aout = kp1h * (ay2 + ay31) - kp*aout; - - return tanh(aout*value)*LB_24_VOL_ADJUST/(1.0+fs->dist); -} - - -// -// LBSynth -// - -lb303Synth::lb303Synth( InstrumentTrack * _InstrumentTrack ) : - instrument( _InstrumentTrack, &lb303_plugin_descriptor ), - vcf_cut_knob( 0.75f, 0.0f, 1.5f, 0.005f, this, tr( "VCF Cutoff Frequency" ) ), - vcf_res_knob( 0.75f, 0.0f, 1.25f, 0.005f, this, tr( "VCF Resonance" ) ), - vcf_mod_knob( 0.1f, 0.0f, 1.0f, 0.005f, this, tr( "VCF Envelope Mod" ) ), - vcf_dec_knob( 0.1f, 0.0f, 1.0f, 0.005f, this, tr( "VCF Envelope Decay" ) ), - dist_knob( 0.0f, 0.0f, 1.0f, 0.01f, this, tr( "Distortion" ) ), - wave_knob( 0.0f, 0.0f, 5.0f, 1.0f, this, tr( "Waveform" ) ), - slide_dec_knob( 0.6f, 0.0f, 1.0f, 0.005f, this, tr( "Slide Decay" ) ), - slideToggle( false, this, tr( "Slide" ) ), - accentToggle( false, this, tr( "Accent" ) ), - deadToggle( false, this, tr( "Dead" ) ), - db24Toggle( false, this, tr( "24dB/oct Filter" ) ) - -{ - - connect( engine::mixer(), SIGNAL( sampleRateChanged( ) ), - this, SLOT ( filterChanged( ) ) ); - - connect( &vcf_cut_knob, SIGNAL( dataChanged( ) ), - this, SLOT ( filterChanged( ) ) ); - - connect( &vcf_res_knob, SIGNAL( dataChanged( ) ), - this, SLOT ( filterChanged( ) ) ); - - connect( &vcf_mod_knob, SIGNAL( dataChanged( ) ), - this, SLOT ( filterChanged( ) ) ); - - connect( &vcf_dec_knob, SIGNAL( dataChanged( ) ), - this, SLOT ( filterChanged( ) ) ); - - connect( &db24Toggle, SIGNAL( dataChanged( ) ), - this, SLOT ( db24Toggled( ) ) ); - - connect( &dist_knob, SIGNAL( dataChanged( ) ), - this, SLOT ( filterChanged( ))); - - - // SYNTH - - vco_inc = 0.0; - vco_c = 0; - vco_k = 0; - - vco_slide = 0; vco_slideinc = 0; - vco_slidebase = 0; - - fs.cutoff = 0; - fs.envmod = 0; - fs.reso = 0; - fs.envdecay = 0; - fs.dist = 0; - - vcf_envpos = ENVINC; - - // Start VCA on an attack. - vca_mode = 3; - vca_a = 0; - - //vca_attack = 1.0 - 0.94406088; - vca_attack = 1.0 - 0.96406088; - vca_decay = 0.99897516; - - vco_shape = SAWTOOTH; - - // Experimenting with a0 between original (0.5) and 1.0 - vca_a0 = 0.5; - vca_a = 9; - vca_mode = 3; - - vcf = new lb303FilterIIR2(&fs); - - sample_cnt = 0; - release_frame = 1<<24; - catch_frame = 0; - catch_decay = 0; - - recalcFilter(); - - last_offset = 0; - - new_freq = -1; - current_freq = -1; - delete_freq = -1; - - instrumentPlayHandle * iph = new instrumentPlayHandle( this ); - engine::mixer()->addPlayHandle( iph ); - - filterChanged(); -} - - -lb303Synth::~lb303Synth() -{ - delete vcf; -} - - -void lb303Synth::saveSettings( QDomDocument & _doc, - QDomElement & _this ) -{ - vcf_cut_knob.saveSettings( _doc, _this, "vcf_cut" ); - vcf_res_knob.saveSettings( _doc, _this, "vcf_res" ); - vcf_mod_knob.saveSettings( _doc, _this, "vcf_mod" ); - vcf_dec_knob.saveSettings( _doc, _this, "vcf_dec" ); - - wave_knob.saveSettings( _doc, _this, "shape"); - dist_knob.saveSettings( _doc, _this, "dist"); - slide_dec_knob.saveSettings( _doc, _this, "slide_dec"); - - slideToggle.saveSettings( _doc, _this, "slide"); - deadToggle.saveSettings( _doc, _this, "dead"); - db24Toggle.saveSettings( _doc, _this, "db24"); -} - - -void lb303Synth::loadSettings( const QDomElement & _this ) -{ - vcf_cut_knob.loadSettings( _this, "vcf_cut" ); - vcf_res_knob.loadSettings( _this, "vcf_res" ); - vcf_mod_knob.loadSettings( _this, "vcf_mod" ); - vcf_dec_knob.loadSettings( _this, "vcf_dec" ); - - dist_knob.loadSettings( _this, "dist"); - wave_knob.loadSettings( _this, "shape"); - slide_dec_knob.loadSettings( _this, "slide_dec"); - - slideToggle.loadSettings( _this, "slide"); - deadToggle.loadSettings( _this, "dead"); - db24Toggle.loadSettings( _this, "db24"); - - filterChanged(); -} - -// TODO: Split into one function per knob. envdecay doesn't require -// recalcFilter. -void lb303Synth::filterChanged() -{ - fs.cutoff = vcf_cut_knob.value(); - fs.reso = vcf_res_knob.value(); - fs.envmod = vcf_mod_knob.value(); - fs.dist = LB_DIST_RATIO*dist_knob.value(); - - float d = 0.2 + (2.3*vcf_dec_knob.value()); - - d *= engine::mixer()->processingSampleRate(); // d *= smpl rate - fs.envdecay = pow(0.1, 1.0/d * ENVINC); // decay is 0.1 to the 1/d * ENVINC - // vcf_envdecay is now adjusted for both - // sampling rate and ENVINC - recalcFilter(); -} - - -void lb303Synth::db24Toggled() -{ - delete vcf; - if(db24Toggle.value()) { - vcf = new lb303Filter3Pole(&fs); - } - else { - vcf = new lb303FilterIIR2(&fs); - } - recalcFilter(); -} - - - -QString lb303Synth::nodeName() const -{ - return( lb303_plugin_descriptor.name ); -} - - -void lb303Synth::recalcFilter() -{ - vcf->recalc(); - - vcf_envpos = ENVINC; // Trigger filter update in process() -} - -inline int MIN(int a, int b) { - return (aprocessingSampleRate(); // TODO: Use actual sampling rate. -} - -int lb303Synth::process(sampleFrame *outbuf, const Uint32 size) -{ - unsigned int i; - float w; - float samp; - - if( delete_freq == current_freq ) { - // Normal release - delete_freq = -1; - vca_mode = 1; - } - - if( new_freq > 0.0f ) { - lb303Note note; - note.vco_inc = GET_INC( true_freq ); - note.dead = deadToggle.value(); - initNote(¬e); - - current_freq = new_freq; - - new_freq = -1.0f; - } - - - - // TODO: NORMAL RELEASE - // vca_mode = 1; - - for(i=0;i= ENVINC) { - vcf->envRecalc(); - - vcf_envpos = 0; - - if (vco_slide) { - vco_inc=vco_slidebase-vco_slide; - // Calculate coeff from dec_knob on knob change. - vco_slide*= 0.9+(slide_dec_knob.value()*0.0999); // TODO: Adjust for Hz and ENVINC - - } - } - - - sample_cnt++; - vcf_envpos++; - - int decay_frames = 128; - - // update vco - vco_c += vco_inc; - - if(vco_c > 0.5) - vco_c -= 1.0; - - /*LB303 - if (catch_decay > 0) { - if (catch_decay < decay_frames) { - catch_decay++; - } - }*/ - - switch(int(rint(wave_knob.value()))) { - case 0: vco_shape = SAWTOOTH; break; - case 1: vco_shape = INVERTED_SAWTOOTH; break; - case 2: vco_shape = TRIANGLE; break; - case 3: vco_shape = SQUARE; break; - case 4: vco_shape = ROUND_SQUARE; break; - case 5: vco_shape = MOOG; break; - default: vco_shape = SAWTOOTH; break; - } - - // add vco_shape_param the changes the shape of each curve. - // merge sawtooths with triangle and square with round square? - switch (vco_shape) { - case SAWTOOTH: // p0: curviness of line - vco_k = vco_c; // Is this sawtooth backwards? - break; - - case INVERTED_SAWTOOTH: // p0: curviness of line - vco_k = -vco_c; // Is this sawtooth backwards? - break; - - case TRIANGLE: // p0: duty rev.saw<->triangle<->saw p1: curviness - vco_k = (vco_c*2.0)+0.5; - if (vco_k>0.5) - vco_k = 1.0- vco_k; - break; - - case SQUARE: // p0: slope of top - vco_k = (vco_c<0)?0.5:-0.5; - break; - - case ROUND_SQUARE: // p0: width of round - vco_k = (vco_c<0)?(sqrtf(1-(vco_c*vco_c*4))-0.5):-0.5; - break; - - case MOOG: // Maybe the fall should be exponential/sinsoidal instead of quadric. - // [-0.5, 0]: Rise, [0,0.25]: Slope down, [0.25,0.5]: Low - vco_k = (vco_c*2.0)+0.5; - if (vco_k>1.0) { - vco_k = -0.5 ; - } - else if (vco_k>0.5) { - w = 2.0*(vco_k-0.5)-1.0; - vco_k = 0.5 - sqrtf(1.0-(w*w)); - } - vco_k *= 2.0; // MOOG wave gets filtered away - break; - } - - // Write out samples. - samp = vcf->process(vco_k) * vca_a; - - /* - float releaseFrames = desiredReleaseFrames(); - samp *= (releaseFrames - catch_decay)/releaseFrames; - */ - //LB303 samp *= (float)(decay_frames - catch_decay)/(float)decay_frames; - - for(int c=0; c=release_frame) { - vca_mode=1; - } - */ - - // Handle Envelope - if(vca_mode==0) { - vca_a+=(vca_a0-vca_a)*vca_attack; - if(sample_cnt>=0.5*engine::mixer()->processingSampleRate()) - vca_mode = 2; - } - else if(vca_mode == 1) { - vca_a *= vca_decay; - - // the following line actually speeds up processing - if(vca_a < (1/65536.0)) { - vca_a = 0; - vca_mode = 3; - } - } - - } - return 1; -} - - -/* Prepares the active LB303 note. I separated this into a function because it - * needs to be called onplayNote() when a new note is started. It also needs - * to be called from process() when a prior edge-to-edge note is done releasing. - */ - -void lb303Synth::initNote( lb303Note *n) -{ - catch_decay = 0; - - vco_inc = n->vco_inc; - - // Always reset vca on non-dead notes, and - // Only reset vca on decaying(decayed) and never-played - if(n->dead == 0 || (vca_mode==1 || vca_mode==3)) { - //printf(" good\n"); - sample_cnt = 0; - vca_mode = 0; - // LB303: - //vca_a = 0; - } - else { - vca_mode = 2; - } - - // Initiate Slide - // TODO: Break out into function, should be called again on detuneChanged - if (vco_slideinc) { - vco_slide = vco_inc-vco_slideinc; // Slide amount - vco_slidebase = vco_inc; // The REAL frequency - vco_slideinc = 0; // reset from-note - } - else { - vco_slide = 0; - } - // End break-out - - // Slide-from note, save inc for next note - if (slideToggle.value()) { - vco_slideinc = vco_inc; // May need to equal vco_slidebase+vco_slide if last note slid - } - - - recalcFilter(); - - if(n->dead ==0){ - // Swap next two blocks?? - vcf->playNote(); - // Ensure envelope is recalculated - vcf_envpos = ENVINC; - - // Double Check - //vca_mode = 0; - //vca_a = 0.0; - } -} - - -void lb303Synth::playNote( NotePlayHandle * _n, - sampleFrame * _working_buffer ) -{ - if( _n->arpBaseNote() ) - { - //return; - } - - // Currently have release/decay disabled - // Start the release decay if this is the first release period. - //if (_n->released() && catch_decay == 0) - // catch_decay = 1; - - bool decay_note = false; - - release_frame = _n->framesLeft() - desiredReleaseFrames(); - - - if(deadToggle.value() == 0 && decay_note) { - } - /// Start a new note. - else if( _n->totalFramesPlayed() == 0 ) { - new_freq = _n->unpitchedFrequency(); - true_freq = _n->frequency(); - _n->m_pluginData = this; - } - - // Check for slide - if( _n->unpitchedFrequency() == current_freq ) { - true_freq = _n->frequency(); - - if( slideToggle.value() ) { - vco_slidebase = GET_INC( true_freq ); // The REAL frequency - } - else { - vco_inc = GET_INC( true_freq ); - } - } -} - - - -void lb303Synth::play( sampleFrame * _working_buffer ) -{ - //printf("."); - const fpp_t frames = engine::mixer()->framesPerPeriod(); - - process( _working_buffer, frames); - instrumentTrack()->processAudioBuffer( _working_buffer, frames, - NULL ); -} - - - -void lb303Synth::deleteNotePluginData( NotePlayHandle * _n ) -{ - //printf("GONE\n"); - if( _n->unpitchedFrequency() == current_freq ) - { - delete_freq = current_freq; - } -} - - -PluginView * lb303Synth::instantiateView( QWidget * _parent ) -{ - return( new lb303SynthView( this, _parent ) ); -} - - -lb303SynthView::lb303SynthView( Instrument * _instrument, QWidget * _parent ) : - InstrumentView( _instrument, _parent ) -{ - // GUI - m_vcfCutKnob = new Knob( knobBright_26, this ); - m_vcfCutKnob->move( 75, 130 ); - m_vcfCutKnob->setHintText( tr( "Cutoff Freq:" ) + " ", "" ); - m_vcfCutKnob->setLabel( tr("CUT") ); - - m_vcfResKnob = new Knob( knobBright_26, this ); - m_vcfResKnob->move( 120, 130 ); - m_vcfResKnob->setHintText( tr( "Resonance:" ) + " ", "" ); - m_vcfResKnob->setLabel( tr("RES") ); - - m_vcfModKnob = new Knob( knobBright_26, this ); - m_vcfModKnob->move( 165, 130 ); - m_vcfModKnob->setHintText( tr( "Env Mod:" ) + " ", "" ); - m_vcfModKnob->setLabel( tr("ENV MOD") ); - - m_vcfDecKnob = new Knob( knobBright_26, this ); - m_vcfDecKnob->move( 210, 130 ); - m_vcfDecKnob->setHintText( tr( "Decay:" ) + " ", "" ); - m_vcfDecKnob->setLabel( tr("DEC") ); - - m_slideToggle = new LedCheckBox( "Slide", this ); - m_slideToggle->move( 10, 180 ); - - m_accentToggle = new LedCheckBox( "Accent", this ); - m_accentToggle->move( 10, 200 ); - m_accentToggle->setDisabled(true); - - m_deadToggle = new LedCheckBox( "Dead", this ); - m_deadToggle->move( 10, 220 ); - - m_db24Toggle = new LedCheckBox( "24dB/oct", this ); - m_db24Toggle->setWhatsThis( - tr( "303-es-que, 24dB/octave, 3 pole filter" ) ); - m_db24Toggle->move( 10, 150); - - - m_slideDecKnob = new Knob( knobBright_26, this ); - m_slideDecKnob->move( 210, 75 ); - m_slideDecKnob->setHintText( tr( "Slide Decay:" ) + " ", "" ); - m_slideDecKnob->setLabel( tr( "SLIDE")); - - m_distKnob = new Knob( knobBright_26, this ); - m_distKnob->move( 210, 190 ); - m_distKnob->setHintText( tr( "DIST:" ) + " ", "" ); - m_distKnob->setLabel( tr( "DIST")); - - - m_waveKnob = new Knob( knobBright_26, this ); - m_waveKnob->move( 120, 75 ); - m_waveKnob->setHintText( tr( "WAVE:" ) + " ", "" ); - m_waveKnob->setLabel( tr( "WAVE")); - - - setAutoFillBackground( true ); - QPalette pal; - pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( - "artwork" ) ); - setPalette( pal ); -} - - -lb303SynthView::~lb303SynthView() -{ -} - - -void lb303SynthView::modelChanged() -{ - lb303Synth * syn = castModel(); - - m_vcfCutKnob->setModel( &syn->vcf_cut_knob ); - m_vcfResKnob->setModel( &syn->vcf_res_knob ); - m_vcfDecKnob->setModel( &syn->vcf_dec_knob ); - m_vcfModKnob->setModel( &syn->vcf_mod_knob ); - m_slideDecKnob->setModel( &syn->slide_dec_knob ); - - m_distKnob->setModel( &syn->dist_knob ); - m_waveKnob->setModel( &syn->wave_knob ); - - m_slideToggle->setModel( &syn->slideToggle ); - m_accentToggle->setModel( &syn->accentToggle ); - m_deadToggle->setModel( &syn->deadToggle ); - m_db24Toggle->setModel( &syn->db24Toggle ); -} - - - -extern "C" -{ - -// necessary for getting instance out of shared lib -Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) -{ - - return( new lb303Synth( - static_cast( _data ) ) ); -} - - -} - - diff --git a/plugins/lb303/lb303.h b/plugins/lb303/lb303.h deleted file mode 100644 index 893cd0acd71..00000000000 --- a/plugins/lb303/lb303.h +++ /dev/null @@ -1,271 +0,0 @@ -/* - * lb303.h - declaration of class lb303 which is a bass synth attempting to - * emulate the Roland TB303 bass synth - * - * Copyright (c) 2006-2008 Paul Giblock - * - * This file is part of LMMS - http://lmms.io - * - * lb303FilterIIR2 is based on the gsyn filter code by Andy Sloane. - * - * lb303Filter3Pole is based on the TB303 instrument written by - * Josep M Comajuncosas for the CSounds library - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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 _LB303_H_ -#define _LB303_H_ - -#include "effect_lib.h" -#include "Instrument.h" -#include "InstrumentView.h" -#include "LedCheckbox.h" -#include "Knob.h" -#include "Mixer.h" - -class lb303SynthView; -class NotePlayHandle; - -class lb303FilterKnobState -{ - public: - float cutoff; - float reso; - float envmod; - float envdecay; - float dist; -}; - - -class lb303Filter -{ - public: - lb303Filter(lb303FilterKnobState* p_fs); - virtual ~lb303Filter() {}; - - virtual void recalc(); - virtual void envRecalc(); - virtual float process(const float& samp)=0; - virtual void playNote(); - - protected: - lb303FilterKnobState *fs; - - // Filter Decay - float vcf_c0; // c0=e1 on retrigger; c0*=ed every sample; cutoff=e0+c0 - float vcf_e0, // e0 and e1 for interpolation - vcf_e1; - float vcf_rescoeff; // Resonance coefficient [0.30,9.54] -}; - -class lb303FilterIIR2 : public lb303Filter -{ - public: - lb303FilterIIR2(lb303FilterKnobState* p_fs); - virtual ~lb303FilterIIR2(); - - virtual void recalc(); - virtual void envRecalc(); - virtual float process(const float& samp); - - protected: - float vcf_d1, // d1 and d2 are added back into the sample with - vcf_d2; // vcf_a and b as coefficients. IIR2 resonance - // loop. - - // IIR2 Coefficients for mixing dry and delay. - float vcf_a, // Mixing coefficients for the final sound. - vcf_b, // - vcf_c; - - effectLib::monoToStereoAdaptor > * m_dist_fx; - effectLib::distortion<> * m_dist; -}; - - -class lb303Filter3Pole : public lb303Filter -{ - public: - lb303Filter3Pole(lb303FilterKnobState* p_fs); - - //virtual void recalc(); - virtual void envRecalc(); - virtual void recalc(); - virtual float process(const float& samp); - - protected: - float kfcn, - kp, - kp1, - kp1h, - kres; - float ay1, - ay2, - aout, - lastin, - value; -}; - - - -class lb303Note -{ -public: - float vco_inc; - bool dead; -}; - - -class lb303Synth : public Instrument -{ - Q_OBJECT -public: - lb303Synth( InstrumentTrack * _instrument_track ); - virtual ~lb303Synth(); - - virtual void play( sampleFrame * _working_buffer ); - virtual void playNote( NotePlayHandle * _n, - sampleFrame * _working_buffer ); - virtual void deleteNotePluginData( NotePlayHandle * _n ); - - - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); - - virtual QString nodeName() const; - - virtual f_cnt_t desiredReleaseFrames() const - { - return 0; //4048; - } - - virtual PluginView * instantiateView( QWidget * _parent ); - -private: - - void initNote(lb303Note *note); - - -private: - FloatModel vcf_cut_knob; - FloatModel vcf_res_knob; - FloatModel vcf_mod_knob; - FloatModel vcf_dec_knob; - - FloatModel vco_fine_detune_knob; - - FloatModel dist_knob; - FloatModel wave_knob; - FloatModel slide_dec_knob; - - BoolModel slideToggle; - BoolModel accentToggle; - BoolModel deadToggle; - BoolModel db24Toggle; - - -public slots: - void filterChanged(); - void db24Toggled(); - -private: - // Oscillator - float vco_inc, // Sample increment for the frequency. Creates Sawtooth. - vco_k, // Raw oscillator sample [-0.5,0.5] - vco_c; // Raw oscillator sample [-0.5,0.5] - - float vco_slide, //* Current value of slide exponential curve. Nonzero=sliding - vco_slideinc, //* Slide base to use in next node. Nonzero=slide next note - vco_slidebase; //* The base vco_inc while sliding. - - float vco_detune; - - enum vco_shape_t { SAWTOOTH, INVERTED_SAWTOOTH, SQUARE, TRIANGLE, MOOG, ROUND_SQUARE }; - vco_shape_t vco_shape; - - // User settings - lb303FilterKnobState fs; - lb303Filter *vcf; - - int release_frame; - - - // More States - int vcf_envpos; // Update counter. Updates when >= ENVINC - - float vca_attack, // Amp attack - vca_decay, // Amp decay - vca_a0, // Initial amplifier coefficient - vca_a; // Amplifier coefficient. - - // Envelope State - int vca_mode; // 0: attack, 1: decay, 2: idle, 3: never played - - // My hacks - int sample_cnt; - - int last_offset; - - int catch_frame; - int catch_decay; - - float new_freq; - float current_freq; - float delete_freq; - float true_freq; - - void recalcFilter(); - - int process(sampleFrame *outbuf, const Uint32 size); - - friend class lb303SynthView; - -} ; - - -class lb303SynthView : public InstrumentView -{ - Q_OBJECT -public: - lb303SynthView( Instrument * _instrument, - QWidget * _parent ); - virtual ~lb303SynthView(); - -private: - virtual void modelChanged(); - - Knob * m_vcfCutKnob; - Knob * m_vcfResKnob; - Knob * m_vcfDecKnob; - Knob * m_vcfModKnob; - - Knob * m_vcoFineDetuneKnob; - - Knob * m_distKnob; - Knob * m_waveKnob; - Knob * m_slideDecKnob; - - LedCheckBox * m_slideToggle; - LedCheckBox * m_accentToggle; - LedCheckBox * m_deadToggle; - LedCheckBox * m_db24Toggle; - -} ; - -#endif diff --git a/plugins/lb303/logo.png b/plugins/lb303/logo.png deleted file mode 100644 index 22c99d1e46e1c58aa1642a6283a27aa00ae57fd7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3468 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 us?~zl Date: Mon, 8 Feb 2016 19:44:50 +0100 Subject: [PATCH 22/90] Get rid of hardcoded colors in the Piano Roll and Automation Editor --- data/themes/default/style.css | 11 ++++-- include/AutomationEditor.h | 4 ++ include/PianoRoll.h | 22 ++++++++++- src/gui/editors/AutomationEditor.cpp | 9 ++++- src/gui/editors/PianoRoll.cpp | 58 ++++++++++++++++++++++------ 5 files changed, 86 insertions(+), 18 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 23ea03af99d..0826618c76a 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -16,15 +16,14 @@ AutomationEditor { color: #e0e0e0; qproperty-vertexColor: #ff77af; qproperty-gridColor: #808080; + qproperty-crossColor: rgb( 255, 51, 51 ); qproperty-graphColor: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(153, 175, 255, 250), stop:1 rgba(153, 175, 255, 100)); - /*#99afff;*/ qproperty-scaleColor: qlineargradient(spread:reflect, x1:0, y1:0.5, x2:1, y2:0.5, stop:0 #333, stop:1 #202020); - /*rgb( 32, 32, 32 );*/ } /* text box */ @@ -114,9 +113,15 @@ PianoRoll { qproperty-gridColor: rgb( 128, 128, 128 ); qproperty-noteModeColor: rgb( 255, 255, 255 ); qproperty-noteColor: rgb( 119, 199, 216 ); - qproperty-barColor: #4afd85; qproperty-noteBorderRadiusX: 5; qproperty-noteBorderRadiusY: 2; + qproperty-selectedNoteColor: rgb( 0, 64, 192 ); + qproperty-barColor: #4afd85; + qproperty-markedSemitoneColor: rgba( 40, 40, 40, 200 ); + /* Text on the white piano keys */ + qproperty-textColor: rgb( 0, 0, 0 ); + qproperty-textColorLight: rgb( 128, 128, 128); + qproperty-textShadow: rgb( 240, 240, 240 ); } /* main toolbar oscilloscope - can have transparent bg now */ diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h index c6a3c96c613..4d1583a2351 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -55,6 +55,7 @@ class AutomationEditor : public QWidget, public JournallingObject Q_PROPERTY(QColor vertexColor READ vertexColor WRITE setVertexColor) Q_PROPERTY(QBrush scaleColor READ scaleColor WRITE setScaleColor) Q_PROPERTY(QBrush graphColor READ graphColor WRITE setGraphColor) + Q_PROPERTY(QColor crossColor READ crossColor WRITE setCrossColor) public: void setCurrentPattern(AutomationPattern * new_pattern); @@ -80,10 +81,12 @@ class AutomationEditor : public QWidget, public JournallingObject QBrush graphColor() const; QColor vertexColor() const; QBrush scaleColor() const; + QColor crossColor() const; void setGridColor(const QColor& c); void setGraphColor(const QBrush& c); void setVertexColor(const QColor& c); void setScaleColor(const QBrush& c); + void setCrossColor(const QColor& c); enum EditModes { @@ -237,6 +240,7 @@ protected slots: QBrush m_graphColor; QColor m_vertexColor; QBrush m_scaleColor; + QColor m_crossColor; friend class AutomationEditorWindow; diff --git a/include/PianoRoll.h b/include/PianoRoll.h index b6a96db93ec..e874c802e0b 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -59,6 +59,11 @@ class PianoRoll : public QWidget Q_PROPERTY( QColor barColor READ barColor WRITE setBarColor ) Q_PROPERTY( float noteBorderRadiusX READ noteBorderRadiusX WRITE setNoteBorderRadiusX ) Q_PROPERTY( float noteBorderRadiusY READ noteBorderRadiusY WRITE setNoteBorderRadiusY ) + Q_PROPERTY( QColor selectedNoteColor READ selectedNoteColor WRITE setSelectedNoteColor ) + Q_PROPERTY( QColor textColor READ textColor WRITE setTextColor ) + Q_PROPERTY( QColor textColorLight READ textColorLight WRITE setTextColorLight ) + Q_PROPERTY( QColor textShadow READ textShadow WRITE setTextShadow ) + Q_PROPERTY( QColor markedSemitoneColor READ markedSemitoneColor WRITE setMarkedSemitoneColor ) public: enum EditModes { @@ -115,6 +120,16 @@ class PianoRoll : public QWidget void setNoteBorderRadiusX( float b ); float noteBorderRadiusY() const; void setNoteBorderRadiusY( float b ); + QColor selectedNoteColor() const; + void setSelectedNoteColor( const QColor & c ); + QColor textColor() const; + void setTextColor( const QColor & c ); + QColor textColorLight() const; + void setTextColorLight( const QColor & c ); + QColor textShadow() const; + void setTextShadow( const QColor & c ); + QColor markedSemitoneColor() const; + void setMarkedSemitoneColor( const QColor & c ); protected: @@ -133,7 +148,7 @@ class PianoRoll : public QWidget int getKey( int y ) const; static void drawNoteRect( QPainter & p, int x, int y, int width, const Note * n, const QColor & noteCol, - float radiusX, float radiusY ); + float radiusX, float radiusY, const QColor & selCol ); void removeSelection(); void selectAll(); NoteVector getSelectedNotes(); @@ -358,6 +373,11 @@ protected slots: QColor m_barColor; float m_noteBorderRadiusX; float m_noteBorderRadiusY; + QColor m_selectedNoteColor; + QColor m_textColor; + QColor m_textColorLight; + QColor m_textShadow; + QColor m_markedSemitoneColor; signals: void positionChanged( const MidiTime & ); diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index 74db2ba96e8..b7190632f13 100644 --- a/src/gui/editors/AutomationEditor.cpp +++ b/src/gui/editors/AutomationEditor.cpp @@ -105,7 +105,8 @@ AutomationEditor::AutomationEditor() : m_gridColor( 0,0,0 ), m_graphColor( Qt::SolidPattern ), m_vertexColor( 0,0,0 ), - m_scaleColor( Qt::SolidPattern ) + m_scaleColor( Qt::SolidPattern ), + m_crossColor( 0, 0, 0 ) { connect( this, SIGNAL( currentPatternChanged() ), this, SLOT( updateAfterPatternChange() ), @@ -251,6 +252,8 @@ QColor AutomationEditor::vertexColor() const { return m_vertexColor; } QBrush AutomationEditor::scaleColor() const { return m_scaleColor; } +QColor AutomationEditor::crossColor() const +{ return m_crossColor; } void AutomationEditor::setGridColor( const QColor & c ) { m_gridColor = c; } void AutomationEditor::setGraphColor( const QBrush & c ) @@ -259,6 +262,8 @@ void AutomationEditor::setVertexColor( const QColor & c ) { m_vertexColor = c; } void AutomationEditor::setScaleColor( const QBrush & c ) { m_scaleColor = c; } +void AutomationEditor::setCrossColor( const QColor & c ) +{ m_crossColor = c; } @@ -972,7 +977,7 @@ inline void AutomationEditor::drawCross( QPainter & p ) / (float)( m_maxLevel - m_minLevel ) ) : grid_bottom - ( level - m_bottomLevel ) * m_y_delta; - p.setPen( QColor( 0xFF, 0x33, 0x33 ) ); + p.setPen( crossColor() ); p.drawLine( VALUES_WIDTH, (int) cross_y, width(), (int) cross_y ); p.drawLine( mouse_pos.x(), TOP_MARGIN, mouse_pos.x(), height() - SCROLLBAR_SIZE ); diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index a8eea4fdb62..20f764e3d83 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -211,7 +211,12 @@ PianoRoll::PianoRoll() : m_noteColor( 0, 0, 0 ), m_barColor( 0, 0, 0 ), m_noteBorderRadiusX( 0 ), - m_noteBorderRadiusY( 0 ) + m_noteBorderRadiusY( 0 ), + m_selectedNoteColor( 0, 0, 0 ), + m_textColor( 0, 0, 0 ), + m_textColorLight( 0, 0, 0 ), + m_textShadow( 0, 0, 0 ), + m_markedSemitoneColor( 0, 0, 0 ) { // gui names of edit modes m_nemStr.push_back( tr( "Note Volume" ) ); @@ -773,10 +778,39 @@ float PianoRoll::noteBorderRadiusY() const void PianoRoll::setNoteBorderRadiusY( float b ) { m_noteBorderRadiusY = b; } +QColor PianoRoll::selectedNoteColor() const +{ return m_selectedNoteColor; } + +void PianoRoll::setSelectedNoteColor( const QColor & c ) +{ m_selectedNoteColor = c; } + +QColor PianoRoll::textColor() const +{ return m_textColor; } + +void PianoRoll::setTextColor( const QColor & c ) +{ m_textColor = c; } + +QColor PianoRoll::textColorLight() const +{ return m_textColorLight; } + +void PianoRoll::setTextColorLight( const QColor & c ) +{ m_textColorLight = c; } + +QColor PianoRoll::textShadow() const +{ return m_textShadow; } + +void PianoRoll::setTextShadow( const QColor & c ) +{ m_textShadow = c; } + +QColor PianoRoll::markedSemitoneColor() const +{ return m_markedSemitoneColor; } + +void PianoRoll::setMarkedSemitoneColor( const QColor & c ) +{ m_markedSemitoneColor = c; } void PianoRoll::drawNoteRect(QPainter & p, int x, int y, int width, const Note * n, const QColor & noteCol, - float radiusX, float radiusY ) + float radiusX, float radiusY, const QColor & selCol ) { ++x; ++y; @@ -801,7 +835,7 @@ void PianoRoll::drawNoteRect(QPainter & p, int x, int y, if( n->selected() ) { - col.setRgb( 0x00, 0x40, 0xC0 ); + col = QColor( selCol ); } // adjust note to make it a bit faded if it has a lower volume @@ -2609,7 +2643,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) } p.fillRect( WHITE_KEY_WIDTH + 1, y - KEY_LINE_HEIGHT / 2, width() - 10, KEY_LINE_HEIGHT, - QColor( 40, 40, 40, 200 ) ); + markedSemitoneColor() ); } @@ -2717,16 +2751,16 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) QPoint textStart( WHITE_KEY_WIDTH - 18, key_line_y ); textStart += QPoint( 0, yCorrectionForNoteLabels ); - p.setPen( QColor( 240, 240, 240 ) ); + p.setPen( textShadow() ); p.drawText( textStart + QPoint( 1, 1 ), noteString ); // The C key is painted darker than the other ones if ( key % 12 == 0 ) { - p.setPen( QColor( 0, 0, 0 ) ); + p.setPen( textColor() ); } else { - p.setPen( QColor( 128, 128, 128 ) ); + p.setPen( textColorLight() ); } p.drawText( textStart, noteString ); } @@ -2952,7 +2986,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) // note drawNoteRect( p, x + WHITE_KEY_WIDTH, y_base - key * KEY_LINE_HEIGHT, - note_width, note, noteColor(), noteBorderRadiusX(), noteBorderRadiusY() ); + note_width, note, noteColor(), noteBorderRadiusX(), noteBorderRadiusY(), selectedNoteColor() ); } // draw note editing stuff @@ -2962,7 +2996,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) QColor color = barColor().lighter( 30 + ( note->getVolume() * 90 / MaxVolume ) ); if( note->selected() ) { - color.setRgb( 0x00, 0x40, 0xC0 ); + color = selectedNoteColor(); } p.setPen( QPen( color, NOTE_EDIT_LINE_WIDTH ) ); @@ -2977,10 +3011,10 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) } else if( m_noteEditMode == NoteEditPanning ) { - QColor color( noteColor() ); + QColor color = noteColor(); if( note->selected() ) { - color.setRgb( 0x00, 0x40, 0xC0 ); + color = selectedNoteColor(); } p.setPen( QPen( color, NOTE_EDIT_LINE_WIDTH ) ); @@ -3032,7 +3066,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) MidiTime::ticksPerTact() ) - x; int y = (int) y_base - sel_key_start * KEY_LINE_HEIGHT; int h = (int) y_base - sel_key_end * KEY_LINE_HEIGHT - y; - p.setPen( QColor( 0, 64, 192 ) ); + p.setPen( selectedNoteColor() ); p.setBrush( Qt::NoBrush ); p.drawRect( x + WHITE_KEY_WIDTH, y, w, h ); From 2dd403e53b414006fe9fe7e322b241dd120d0d46 Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Sun, 7 Feb 2016 00:27:33 +0100 Subject: [PATCH 23/90] Rename note volume into note velocity --- data/locale/ca.ts | 8 ++++---- data/locale/cs.ts | 8 ++++---- data/locale/de.ts | 8 ++++---- data/locale/en.ts | 8 ++++---- data/locale/es.ts | 8 ++++---- data/locale/fa.ts | 8 ++++---- data/locale/fr.ts | 10 +++++----- data/locale/gl.ts | 8 ++++---- data/locale/it.ts | 10 +++++----- data/locale/ja.ts | 8 ++++---- data/locale/ko.ts | 8 ++++---- data/locale/nl.ts | 8 ++++---- data/locale/pl.ts | 8 ++++---- data/locale/pt.ts | 8 ++++---- data/locale/ru.ts | 8 ++++---- data/locale/sv.ts | 8 ++++---- data/locale/uk.ts | 8 ++++---- data/locale/zh.ts | 8 ++++---- src/gui/editors/PianoRoll.cpp | 6 +++--- src/gui/widgets/InstrumentMidiIOView.cpp | 2 +- src/tracks/Pattern.cpp | 2 +- 21 files changed, 79 insertions(+), 79 deletions(-) diff --git a/data/locale/ca.ts b/data/locale/ca.ts index d1478efd769..0bdc647b700 100644 --- a/data/locale/ca.ts +++ b/data/locale/ca.ts @@ -2775,7 +2775,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity @@ -4603,7 +4603,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step pica dos cops per a obrir aquest patró al rotlle de piano usa la roda del ratolí per a ajustar el volum d'un pas @@ -4767,7 +4767,7 @@ usa la roda del ratolí per a ajustar el volum d'un pas - Note Volume + Note Velocity @@ -4799,7 +4799,7 @@ usa la roda del ratolí per a ajustar el volum d'un pas - Volume: %1% + Velocity: %1% diff --git a/data/locale/cs.ts b/data/locale/cs.ts index 1039d8cce46..488bd866a3e 100644 --- a/data/locale/cs.ts +++ b/data/locale/cs.ts @@ -2775,7 +2775,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity @@ -4603,7 +4603,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step dvojitým kliknutím otevřete tento pattern v piano-roll k nastavení zesílení kroku použijte kolečko myši @@ -4767,7 +4767,7 @@ k nastavení zesílení kroku použijte kolečko myši Zámek noty - Note Volume + Note Velocity @@ -4799,7 +4799,7 @@ k nastavení zesílení kroku použijte kolečko myši - Volume: %1% + Velocity: %1% diff --git a/data/locale/de.ts b/data/locale/de.ts index e6b08c27c41..d0ed6b3ab64 100644 --- a/data/locale/de.ts +++ b/data/locale/de.ts @@ -2795,7 +2795,7 @@ Sie können FX Kanäle im Kontextmenü entfernen und verschieben, welches durch BENUTZERDEFINIERTE GRUNDLAUTSTÄRKE - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity Geben Sie die Lautstärken-Normalisationsbasis für MIDI-basierende Instrumente bei einer Notenlautstärke von 100% an @@ -4640,7 +4640,7 @@ PM bedeutet Phasen-Modulation: Die Phase von Oszillator 3 wird durch Oszillator PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step Doppelklick, um dieses Pattern im Piano-Roll zu öffnen Lautstärke eines Schritts kann mit dem Mausrad geändert werden @@ -4804,7 +4804,7 @@ Lautstärke eines Schritts kann mit dem Mausrad geändert werden Notenraster - Note Volume + Note Velocity Noten-Lautstärke @@ -4836,7 +4836,7 @@ Lautstärke eines Schritts kann mit dem Mausrad geändert werden Kein Akkord - Volume: %1% + Velocity: %1% Lautstärke: %1% diff --git a/data/locale/en.ts b/data/locale/en.ts index 494d7e21160..a8b528feb29 100644 --- a/data/locale/en.ts +++ b/data/locale/en.ts @@ -2774,7 +2774,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity @@ -4596,7 +4596,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step @@ -4759,7 +4759,7 @@ use mouse wheel to set volume of a step - Note Volume + Note Velocity @@ -4791,7 +4791,7 @@ use mouse wheel to set volume of a step - Volume: %1% + Velocity: %1% diff --git a/data/locale/es.ts b/data/locale/es.ts index c6165ebcec7..9be4e004ff0 100644 --- a/data/locale/es.ts +++ b/data/locale/es.ts @@ -2774,7 +2774,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity @@ -4596,7 +4596,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step @@ -4759,7 +4759,7 @@ use mouse wheel to set volume of a step - Note Volume + Note Velocity @@ -4791,7 +4791,7 @@ use mouse wheel to set volume of a step - Volume: %1% + Velocity: %1% diff --git a/data/locale/fa.ts b/data/locale/fa.ts index 89030f04870..7593cb57e0d 100644 --- a/data/locale/fa.ts +++ b/data/locale/fa.ts @@ -2774,7 +2774,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity @@ -4596,7 +4596,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step @@ -4759,7 +4759,7 @@ use mouse wheel to set volume of a step - Note Volume + Note Velocity @@ -4791,7 +4791,7 @@ use mouse wheel to set volume of a step - Volume: %1% + Velocity: %1% diff --git a/data/locale/fr.ts b/data/locale/fr.ts index 10fb548d6c5..ab22441c61a 100644 --- a/data/locale/fr.ts +++ b/data/locale/fr.ts @@ -2922,7 +2922,7 @@ Vous pouvez supprimer et déplacer les canaux d'effet avec le menu contextu VÉLOCITÉ DE BASE PERSONNALISÉE - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity Spécifiez la vélocité normalisée de base des instruments MIDI pour un volume de note de 100% @@ -5087,7 +5087,7 @@ Le mode PM signifie modulation de phase: la phase de l'oscillateur 3 est mo PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step double-cliquer pour ouvrir ce motif dans le piano virtuel utilisez la molette de la souris pour régler le volume d'un pas @@ -5251,7 +5251,7 @@ utilisez la molette de la souris pour régler le volume d'un pasVérouiller la note - Note Volume + Note Velocity Volume de note @@ -5283,8 +5283,8 @@ utilisez la molette de la souris pour régler le volume d'un pasPas d'accord - Volume: %1% - Volume: %1% + Velocity: %1% + Velocity: %1% Panning: %1% left diff --git a/data/locale/gl.ts b/data/locale/gl.ts index da59462fcbc..9ee1f1d4cf7 100644 --- a/data/locale/gl.ts +++ b/data/locale/gl.ts @@ -2789,7 +2789,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity @@ -4612,7 +4612,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step faga duplo clic para abrir este padrón na pianola empregue a roda do rato para modificar o volume un paso @@ -4776,7 +4776,7 @@ empregue a roda do rato para modificar o volume un paso Bloqueo de notas - Note Volume + Note Velocity Volume das notas @@ -4808,7 +4808,7 @@ empregue a roda do rato para modificar o volume un paso - Volume: %1% + Velocity: %1% diff --git a/data/locale/it.ts b/data/locale/it.ts index b27ddb6ce10..6f47bb1ae11 100644 --- a/data/locale/it.ts +++ b/data/locale/it.ts @@ -2795,7 +2795,7 @@ Puoi rimuovere e muovere i canali con il menù contestuale, cliccando con il tas VELOCITY BASE PERSONALIZZATA - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity Specifica la normalizzazione della velocity per strumenti MIDI al volume della nota 100% @@ -4636,7 +4636,7 @@ Vi sono due forme speciali: "Random" e "Random morbido" sono PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step un doppio click apre questo pattern nel piano-roll la rotellina del mouse impostare il volume delle note @@ -4800,7 +4800,7 @@ la rotellina del mouse impostare il volume delle note Note lock - Note Volume + Note Velocity Volume Note @@ -4832,8 +4832,8 @@ la rotellina del mouse impostare il volume delle note - Accordi - Volume: %1% - Volume: %1% + Velocity: %1% + Velocity: %1% Panning: %1% left diff --git a/data/locale/ja.ts b/data/locale/ja.ts index f8a15806cfa..c082d910d92 100644 --- a/data/locale/ja.ts +++ b/data/locale/ja.ts @@ -2790,7 +2790,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity @@ -4614,7 +4614,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step ダプルクリックでこのパターンをピアノロールで開きます マウスホイールでステップの音量をセットします @@ -4778,7 +4778,7 @@ use mouse wheel to set volume of a step ノートをロック - Note Volume + Note Velocity ノートの音量 @@ -4810,7 +4810,7 @@ use mouse wheel to set volume of a step - Volume: %1% + Velocity: %1% 音量: %1% diff --git a/data/locale/ko.ts b/data/locale/ko.ts index a18e0854233..2f6a3f8c77e 100644 --- a/data/locale/ko.ts +++ b/data/locale/ko.ts @@ -2774,7 +2774,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity @@ -4597,7 +4597,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step 피아노-롤에서 이 패턴을 열기위해 이중 클릭 한 단계 볼륨을 설정하기위하여 마우스 휠 사용 @@ -4761,7 +4761,7 @@ use mouse wheel to set volume of a step 박자 잠금 - Note Volume + Note Velocity @@ -4793,7 +4793,7 @@ use mouse wheel to set volume of a step - Volume: %1% + Velocity: %1% diff --git a/data/locale/nl.ts b/data/locale/nl.ts index 1763789196c..20e063048cf 100644 --- a/data/locale/nl.ts +++ b/data/locale/nl.ts @@ -2774,7 +2774,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity @@ -4596,7 +4596,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step dubbel-klik om deze pattern in Piano-Roll te openen volume van de steps is met het muiswiel te veranderen @@ -4760,7 +4760,7 @@ volume van de steps is met het muiswiel te veranderen - Note Volume + Note Velocity @@ -4792,7 +4792,7 @@ volume van de steps is met het muiswiel te veranderen - Volume: %1% + Velocity: %1% diff --git a/data/locale/pl.ts b/data/locale/pl.ts index 152188f2c8d..b78dfe68a0b 100644 --- a/data/locale/pl.ts +++ b/data/locale/pl.ts @@ -2793,7 +2793,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity @@ -4617,7 +4617,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step Podwójne kliknięcie otwiera pattern w Edytorze Pianolowym użyj kółka myszy aby ustawić głośność poszczególnych kroków @@ -4781,7 +4781,7 @@ użyj kółka myszy aby ustawić głośność poszczególnych krokówBlokada nuty - Note Volume + Note Velocity Głośność Nuty @@ -4813,7 +4813,7 @@ użyj kółka myszy aby ustawić głośność poszczególnych kroków - Volume: %1% + Velocity: %1% diff --git a/data/locale/pt.ts b/data/locale/pt.ts index bbfe78f8a4c..96c791c7d83 100644 --- a/data/locale/pt.ts +++ b/data/locale/pt.ts @@ -2791,7 +2791,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity @@ -4631,7 +4631,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step duplo clique para abrir esta sequência no Editor de notas MDll use a roda do mouse para midificar o volume de cada passo @@ -4771,7 +4771,7 @@ use a roda do mouse para midificar o volume de cada passo Panorâmico da nota - Note Volume + Note Velocity Volume da nota @@ -4811,7 +4811,7 @@ use a roda do mouse para midificar o volume de cada passo Por favor abra um a sequência com um duplo clique sobre ela! - Volume: %1% + Velocity: %1% diff --git a/data/locale/ru.ts b/data/locale/ru.ts index 61a0e5bfc87..3ecafb55c03 100644 --- a/data/locale/ru.ts +++ b/data/locale/ru.ts @@ -2809,7 +2809,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri ПРОИЗВОЛЬНАЯ БАЗОВАЯ СКОРОСТЬ - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity Опрделяет базовую скорость нормальизации для MiDi инструментов при громкости ноты 100% @@ -4666,7 +4666,7 @@ PM (ФМ) режим значит фазовая модуляция: Осцил PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step Чтобы открыть эту мелодию в нотном редакторе, дважды на нём щёлкните Используйте колёсико мыши для установки громкости отдельного такта @@ -4830,7 +4830,7 @@ use mouse wheel to set volume of a step Фиксация нот - Note Volume + Note Velocity Громкость нот @@ -4862,7 +4862,7 @@ use mouse wheel to set volume of a step Убрать аккорды - Volume: %1% + Velocity: %1% Громкость %1% diff --git a/data/locale/sv.ts b/data/locale/sv.ts index 4b09c927212..ef6a85c5a42 100644 --- a/data/locale/sv.ts +++ b/data/locale/sv.ts @@ -2774,7 +2774,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity @@ -4596,7 +4596,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step @@ -4759,7 +4759,7 @@ use mouse wheel to set volume of a step - Note Volume + Note Velocity @@ -4791,7 +4791,7 @@ use mouse wheel to set volume of a step - Volume: %1% + Velocity: %1% diff --git a/data/locale/uk.ts b/data/locale/uk.ts index 8b0bbc3af51..98d43370ffb 100644 --- a/data/locale/uk.ts +++ b/data/locale/uk.ts @@ -2974,7 +2974,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri СВОЯ БАЗОВА ШВИДКІСТЬ - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity Визначає базову швидкість нормальізаціі для MiDi інструментів при гучності ноти 100% @@ -5186,7 +5186,7 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил Видалити такти - use mouse wheel to set volume of a step + use mouse wheel to set velocity of a step використовуйте колесо миші для встановлення кроку гучності @@ -5318,7 +5318,7 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил Стереофонія нот - Note Volume + Note Velocity Гучність нот @@ -5350,7 +5350,7 @@ PM (ФМ) режим означає Фазова Модуляція: Осцил Відкрийте шаблон за допомогою подвійного клацання мишею! - Volume: %1% + Velocity: %1% Гучність %1% diff --git a/data/locale/zh.ts b/data/locale/zh.ts index 0c40398363a..fd772feca7d 100644 --- a/data/locale/zh.ts +++ b/data/locale/zh.ts @@ -2783,7 +2783,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri - Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Specify the velocity normalization base for MIDI-based instruments at 100% note velocity @@ -4607,7 +4607,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView double-click to open this pattern in piano-roll -use mouse wheel to set volume of a step +use mouse wheel to set velocity of a step 双击在钢琴窗中打开此片段 使用鼠标滑轮设置此音阶的音量 @@ -4771,7 +4771,7 @@ use mouse wheel to set volume of a step - Note Volume + Note Velocity 音符音量 @@ -4803,7 +4803,7 @@ use mouse wheel to set volume of a step - Volume: %1% + Velocity: %1% 音量:%1% diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index a8eea4fdb62..f3ffa57b34b 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -214,7 +214,7 @@ PianoRoll::PianoRoll() : m_noteBorderRadiusY( 0 ) { // gui names of edit modes - m_nemStr.push_back( tr( "Note Volume" ) ); + m_nemStr.push_back( tr( "Note Velocity" ) ); m_nemStr.push_back( tr( "Note Panning" ) ); QSignalMapper * signalMapper = new QSignalMapper( this ); @@ -490,7 +490,7 @@ void PianoRoll::showVolTextFloat(volume_t vol, const QPoint &pos, int timeout) { //! \todo display velocity for MIDI-based instruments // possibly dBV values too? not sure if it makes sense for note volumes... - showTextFloat( tr("Volume: %1%").arg( vol ), pos, timeout ); + showTextFloat( tr("Velocity: %1%").arg( vol ), pos, timeout ); } @@ -3575,7 +3575,7 @@ void PianoRoll::enterValue( NoteVector* nv ) { bool ok; int new_val; - new_val = QInputDialog::getInt( this, "Piano roll: note volume", + new_val = QInputDialog::getInt( this, "Piano roll: note velocity", tr( "Please enter a new value between %1 and %2:" ). arg( MinVolume ).arg( MaxVolume ), (*nv)[0]->getVolume(), diff --git a/src/gui/widgets/InstrumentMidiIOView.cpp b/src/gui/widgets/InstrumentMidiIOView.cpp index f2747fe7dd2..bf9483b4dd1 100644 --- a/src/gui/widgets/InstrumentMidiIOView.cpp +++ b/src/gui/widgets/InstrumentMidiIOView.cpp @@ -147,7 +147,7 @@ InstrumentMidiIOView::InstrumentMidiIOView( QWidget* parent ) : baseVelocityLayout->setContentsMargins( 8, 18, 8, 8 ); baseVelocityLayout->setSpacing( 6 ); - QLabel* baseVelocityHelp = new QLabel( tr( "Specify the velocity normalization base for MIDI-based instruments at note volume 100%" ) ); + QLabel* baseVelocityHelp = new QLabel( tr( "Specify the velocity normalization base for MIDI-based instruments at 100% note velocity" ) ); baseVelocityHelp->setWordWrap( true ); baseVelocityHelp->setFont( pointSize<8>( baseVelocityHelp->font() ) ); diff --git a/src/tracks/Pattern.cpp b/src/tracks/Pattern.cpp index b7ae0d1b758..c32d6a2cadb 100644 --- a/src/tracks/Pattern.cpp +++ b/src/tracks/Pattern.cpp @@ -706,7 +706,7 @@ PatternView::PatternView( Pattern* pattern, TrackView* parent ) : setFixedHeight( parentWidget()->height() - 2 ); ToolTip::add( this, - tr( "use mouse wheel to set volume of a step" ) ); + tr( "use mouse wheel to set velocity of a step" ) ); setStyle( QApplication::style() ); } From ca8f80d44f9690fdf7a42da1307ed68b0b2f45ae Mon Sep 17 00:00:00 2001 From: Lukas W Date: Thu, 11 Feb 2016 11:58:42 +1300 Subject: [PATCH 24/90] Fix loading relative file path samples Closes #2412 --- include/FileBrowser.h | 2 +- include/SampleBuffer.h | 2 +- src/core/SampleBuffer.cpp | 22 +++++++++++++--------- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/include/FileBrowser.h b/include/FileBrowser.h index a73a00801b9..d9847cf911a 100644 --- a/include/FileBrowser.h +++ b/include/FileBrowser.h @@ -201,7 +201,7 @@ class FileItem : public QTreeWidgetItem QString fullName() const { - return QFileInfo(m_path, text(0)).absoluteFilePath(); + return QDir::cleanPath(m_path) + "/" + text(0); } inline FileTypes type( void ) const diff --git a/include/SampleBuffer.h b/include/SampleBuffer.h index e627ca5c5c2..dbb2f71ace6 100644 --- a/include/SampleBuffer.h +++ b/include/SampleBuffer.h @@ -253,7 +253,7 @@ class EXPORT SampleBuffer : public QObject, public sharedObject } static QString tryToMakeRelative( const QString & _file ); - static QString tryToMakeAbsolute( const QString & _file ); + static QString tryToMakeAbsolute(const QString & file); public slots: diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 6dff51abba2..e44b246e548 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -1414,20 +1414,24 @@ QString SampleBuffer::tryToMakeRelative( const QString & _file ) -QString SampleBuffer::tryToMakeAbsolute( const QString & _file ) +QString SampleBuffer::tryToMakeAbsolute(const QString& file) { - if( QFileInfo( _file ).isAbsolute() ) - { - return _file; - } + QFileInfo f(file); - QString f = ConfigManager::inst()->userSamplesDir() + _file; - if( QFileInfo( f ).exists() ) + if(f.isRelative()) { - return f; + f = QFileInfo(ConfigManager::inst()->userSamplesDir() + file); + + if(! f.exists()) + { + f = QFileInfo(ConfigManager::inst()->factorySamplesDir() + file); + } } - return ConfigManager::inst()->factorySamplesDir() + _file; + if (f.exists()) { + return f.absoluteFilePath(); + } + return file; } From 3bbe0e3e150268bb9f923ae8a04e501511c378d4 Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Thu, 28 Jan 2016 10:37:53 +0100 Subject: [PATCH 25/90] Only lmms projects allowed in recent file list. Increase recent file memmory to 50 --- src/core/ConfigManager.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/core/ConfigManager.cpp b/src/core/ConfigManager.cpp index 114a12202a9..85125ed59be 100644 --- a/src/core/ConfigManager.cpp +++ b/src/core/ConfigManager.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -253,16 +254,18 @@ void ConfigManager::createWorkingDir() -void ConfigManager::addRecentlyOpenedProject( const QString & _file ) +void ConfigManager::addRecentlyOpenedProject( const QString & file ) { - if( !_file.endsWith( ".mpt", Qt::CaseInsensitive ) ) + QFileInfo recentFile( file ); + if( recentFile.suffix().toLower() == "mmp" || + recentFile.suffix().toLower() == "mmpz" ) { - m_recentlyOpenedProjects.removeAll( _file ); - if( m_recentlyOpenedProjects.size() > 30 ) + m_recentlyOpenedProjects.removeAll( file ); + if( m_recentlyOpenedProjects.size() > 50 ) { m_recentlyOpenedProjects.removeLast(); } - m_recentlyOpenedProjects.push_front( _file ); + m_recentlyOpenedProjects.push_front( file ); ConfigManager::inst()->saveConfigFile(); } } From b7d5b2ddf56ab7778ea6b6b335f54af90749f296 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Sat, 13 Feb 2016 09:23:59 +1300 Subject: [PATCH 26/90] Fix #2558 --- include/FileBrowser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/FileBrowser.h b/include/FileBrowser.h index d9847cf911a..a73a00801b9 100644 --- a/include/FileBrowser.h +++ b/include/FileBrowser.h @@ -201,7 +201,7 @@ class FileItem : public QTreeWidgetItem QString fullName() const { - return QDir::cleanPath(m_path) + "/" + text(0); + return QFileInfo(m_path, text(0)).absoluteFilePath(); } inline FileTypes type( void ) const From 0721b49a1c4e815329283309ee06318e5d23123d Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Sun, 14 Feb 2016 00:40:33 +0100 Subject: [PATCH 27/90] Show Main Window before loading/importing project --- src/core/main.cpp | 71 +++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 42 deletions(-) diff --git a/src/core/main.cpp b/src/core/main.cpp index d9d032c5764..d8b1536c76c 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -736,15 +736,18 @@ int main( int argc, char * * argv ) } } - // we try to load given file - if( !fileToLoad.isEmpty() ) + // first show the Main Window and then try to load given file + + // [Settel] workaround: showMaximized() doesn't work with + // FVWM2 unless the window is already visible -> show() first + gui->mainWindow()->show(); + if( fullscreen ) { - gui->mainWindow()->show(); - if( fullscreen ) - { - gui->mainWindow()->showMaximized(); - } + gui->mainWindow()->showMaximized(); + } + if( !fileToLoad.isEmpty() ) + { if( fileToLoad == recoveryFile ) { Engine::getSong()->createNewProjectFromTemplate( fileToLoad ); @@ -761,49 +764,33 @@ int main( int argc, char * * argv ) { return EXIT_SUCCESS; } - - gui->mainWindow()->show(); - if( fullscreen ) - { - gui->mainWindow()->showMaximized(); - } } - else + // If enabled, open last project if there is one. Else, create + // a new one. Also skip recently opened file if limited session to + // lower the chance of opening an already opened file. + else if( ConfigManager::inst()-> + value( "app", "openlastproject" ).toInt() && + !ConfigManager::inst()-> + recentlyOpenedProjects().isEmpty() && + gui->mainWindow()->getSession() != + MainWindow::SessionState::Limited ) { - // If enabled, open last project if there is one. Else, create - // a new one. Also skip recently opened file if limited session to - // lower the chance of opening an already opened file. - if( ConfigManager::inst()-> - value( "app", "openlastproject" ).toInt() && - !ConfigManager::inst()->recentlyOpenedProjects().isEmpty() && - gui->mainWindow()->getSession() - != MainWindow::SessionState::Limited ) - { - QString f = ConfigManager::inst()-> - recentlyOpenedProjects().first(); - QFileInfo recentFile( f ); + QString f = ConfigManager::inst()-> + recentlyOpenedProjects().first(); + QFileInfo recentFile( f ); - if ( recentFile.exists() ) - { - Engine::getSong()->loadProject( f ); - } - else - { - Engine::getSong()->createNewProject(); - } + if ( recentFile.exists() ) + { + Engine::getSong()->loadProject( f ); } else { Engine::getSong()->createNewProject(); } - - // [Settel] workaround: showMaximized() doesn't work with - // FVWM2 unless the window is already visible -> show() first - gui->mainWindow()->show(); - if( fullscreen ) - { - gui->mainWindow()->showMaximized(); - } + } + else + { + Engine::getSong()->createNewProject(); } // Finally we start the auto save timer and also trigger the From ff1f5165426a920a34f5957303e00feec5e8d8bd Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Sun, 14 Feb 2016 11:40:07 +0100 Subject: [PATCH 28/90] Change spacing on hovered items in the context menus --- data/themes/default/style.css | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 29e70974420..71d4292d61f 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -69,14 +69,12 @@ QMenu { QMenu::separator { height: 1px; background: #8d8d8d; - margin-left: 5px; - margin-right: 5px; } QMenu::item { color: black; - padding: 2px 32px 2px 20px; - margin:3px; + padding: 2px 35px 2px 23px; + margin: 3px 0px 3px 0px; } QMenu::item:selected { From 87dce6d2f4dd9d9c966eb8f3515fe1acf2c12889 Mon Sep 17 00:00:00 2001 From: Fastigium Date: Tue, 16 Feb 2016 13:17:20 +0100 Subject: [PATCH 29/90] Make PresetPreviewPlayHandle thread affinity matter --- include/PresetPreviewPlayHandle.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/PresetPreviewPlayHandle.h b/include/PresetPreviewPlayHandle.h index 0ebed9c8977..aa9610a1427 100644 --- a/include/PresetPreviewPlayHandle.h +++ b/include/PresetPreviewPlayHandle.h @@ -38,6 +38,11 @@ class EXPORT PresetPreviewPlayHandle : public PlayHandle PresetPreviewPlayHandle( const QString& presetFile, bool loadByPlugin = false, DataFile *dataFile = 0 ); virtual ~PresetPreviewPlayHandle(); + virtual inline bool affinityMatters() const + { + return true; + } + virtual void play( sampleFrame* buffer ); virtual bool isFinished() const; From da8040764f6edbd53292c429b27b64bc21709955 Mon Sep 17 00:00:00 2001 From: Fastigium Date: Tue, 16 Feb 2016 13:27:41 +0100 Subject: [PATCH 30/90] Require explicit types when removing PlayHandles in the Mixer This fixes a few deadlocks where a PresetPreviewPlayHandle would be removed by the creation of a new PresetPreviewPlayHandle. --- include/Mixer.h | 2 +- include/PlayHandle.h | 9 ++++----- plugins/GigPlayer/GigPlayer.cpp | 4 +++- plugins/carlabase/carla.cpp | 2 +- plugins/opl2/opl2instrument.cpp | 4 +++- plugins/sf2_player/sf2_player.cpp | 4 +++- plugins/vestige/vestige.cpp | 4 +++- plugins/zynaddsubfx/ZynAddSubFx.cpp | 4 +++- src/core/Mixer.cpp | 4 ++-- src/tracks/BBTrack.cpp | 4 +++- src/tracks/InstrumentTrack.cpp | 5 ++++- src/tracks/SampleTrack.cpp | 2 +- 12 files changed, 31 insertions(+), 17 deletions(-) diff --git a/include/Mixer.h b/include/Mixer.h index 3128c65b666..b8d2dec7c58 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -224,7 +224,7 @@ class EXPORT Mixer : public QObject return m_playHandles; } - void removePlayHandles( Track * _track, bool removeIPHs = true ); + void removePlayHandlesOfTypes( Track * _track, const quint8 types ); bool hasNotePlayHandles(); diff --git a/include/PlayHandle.h b/include/PlayHandle.h index ea66cc65ceb..73eda3ae50b 100644 --- a/include/PlayHandle.h +++ b/include/PlayHandle.h @@ -40,11 +40,10 @@ class PlayHandle : public ThreadableJob public: enum Types { - TypeNotePlayHandle, - TypeInstrumentPlayHandle, - TypeSamplePlayHandle, - TypePresetPreviewHandle, - TypeCount + TypeNotePlayHandle = 0x01, + TypeInstrumentPlayHandle = 0x02, + TypeSamplePlayHandle = 0x04, + TypePresetPreviewHandle = 0x08 } ; typedef Types Type; diff --git a/plugins/GigPlayer/GigPlayer.cpp b/plugins/GigPlayer/GigPlayer.cpp index 1f81f151e28..dedfe0edeaf 100644 --- a/plugins/GigPlayer/GigPlayer.cpp +++ b/plugins/GigPlayer/GigPlayer.cpp @@ -101,7 +101,9 @@ GigInstrument::GigInstrument( InstrumentTrack * _instrument_track ) : GigInstrument::~GigInstrument() { - Engine::mixer()->removePlayHandles( instrumentTrack() ); + Engine::mixer()->removePlayHandlesOfTypes( instrumentTrack(), + PlayHandle::TypeNotePlayHandle + | PlayHandle::TypeInstrumentPlayHandle ); freeInstance(); } diff --git a/plugins/carlabase/carla.cpp b/plugins/carlabase/carla.cpp index de65aa1e3bb..ad1b683a69f 100644 --- a/plugins/carlabase/carla.cpp +++ b/plugins/carlabase/carla.cpp @@ -188,7 +188,7 @@ CarlaInstrument::CarlaInstrument(InstrumentTrack* const instrumentTrack, const D CarlaInstrument::~CarlaInstrument() { - Engine::mixer()->removePlayHandles( instrumentTrack() ); + Engine::mixer()->removePlayHandlesOfTypes(instrumentTrack(), PlayHandle::TypeNotePlayHandle | PlayHandle::TypeInstrumentPlayHandle); if (fHost.resourceDir != NULL) { diff --git a/plugins/opl2/opl2instrument.cpp b/plugins/opl2/opl2instrument.cpp index 46e56eb3d13..54493bf92e8 100644 --- a/plugins/opl2/opl2instrument.cpp +++ b/plugins/opl2/opl2instrument.cpp @@ -217,7 +217,9 @@ opl2instrument::opl2instrument( InstrumentTrack * _instrument_track ) : opl2instrument::~opl2instrument() { delete theEmulator; - Engine::mixer()->removePlayHandles( instrumentTrack() ); + Engine::mixer()->removePlayHandlesOfTypes( instrumentTrack(), + PlayHandle::TypeNotePlayHandle + | PlayHandle::TypeInstrumentPlayHandle ); delete [] renderbuffer; } diff --git a/plugins/sf2_player/sf2_player.cpp b/plugins/sf2_player/sf2_player.cpp index 8d633d6d378..50a39c34952 100644 --- a/plugins/sf2_player/sf2_player.cpp +++ b/plugins/sf2_player/sf2_player.cpp @@ -157,7 +157,9 @@ sf2Instrument::sf2Instrument( InstrumentTrack * _instrument_track ) : sf2Instrument::~sf2Instrument() { - Engine::mixer()->removePlayHandles( instrumentTrack() ); + Engine::mixer()->removePlayHandlesOfTypes( instrumentTrack(), + PlayHandle::TypeNotePlayHandle + | PlayHandle::TypeInstrumentPlayHandle ); freeFont(); delete_fluid_synth( m_synth ); delete_fluid_settings( m_settings ); diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 5ce5f468bec..a4836ff9364 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -102,7 +102,9 @@ vestigeInstrument::~vestigeInstrument() knobFModel = NULL; } - Engine::mixer()->removePlayHandles( instrumentTrack() ); + Engine::mixer()->removePlayHandlesOfTypes( instrumentTrack(), + PlayHandle::TypeNotePlayHandle + | PlayHandle::TypeInstrumentPlayHandle ); closePlugin(); } diff --git a/plugins/zynaddsubfx/ZynAddSubFx.cpp b/plugins/zynaddsubfx/ZynAddSubFx.cpp index 2a9f60224c0..ad1e8ff90be 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/ZynAddSubFx.cpp @@ -144,7 +144,9 @@ ZynAddSubFxInstrument::ZynAddSubFxInstrument( ZynAddSubFxInstrument::~ZynAddSubFxInstrument() { - Engine::mixer()->removePlayHandles( instrumentTrack() ); + Engine::mixer()->removePlayHandlesOfTypes( instrumentTrack(), + PlayHandle::TypeNotePlayHandle + | PlayHandle::TypeInstrumentPlayHandle ); m_pluginMutex.lock(); delete m_plugin; diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 19744064199..92124a66093 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -665,13 +665,13 @@ void Mixer::removePlayHandle( PlayHandle * _ph ) -void Mixer::removePlayHandles( Track * _track, bool removeIPHs ) +void Mixer::removePlayHandlesOfTypes( Track * _track, const quint8 types ) { lockPlayHandleRemoval(); PlayHandleList::Iterator it = m_playHandles.begin(); while( it != m_playHandles.end() ) { - if( ( *it )->isFromTrack( _track ) && ( removeIPHs || ( *it )->type() != PlayHandle::TypeInstrumentPlayHandle ) ) + if( ( *it )->isFromTrack( _track ) && ( ( *it )->type() & types ) ) { ( *it )->audioPort()->removePlayHandle( ( *it ) ); if( ( *it )->type() == PlayHandle::TypeNotePlayHandle ) diff --git a/src/tracks/BBTrack.cpp b/src/tracks/BBTrack.cpp index 45210b05f4e..7b10016bf6a 100644 --- a/src/tracks/BBTrack.cpp +++ b/src/tracks/BBTrack.cpp @@ -387,7 +387,9 @@ BBTrack::BBTrack( TrackContainer* tc ) : BBTrack::~BBTrack() { - Engine::mixer()->removePlayHandles( this ); + Engine::mixer()->removePlayHandlesOfTypes( this, + PlayHandle::TypeNotePlayHandle + | PlayHandle::TypeInstrumentPlayHandle ); const int bb = s_infoMap[this]; Engine::getBBTrackContainer()->removeBB( bb ); diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 545c82c012c..e1f7f4b416e 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -430,7 +430,10 @@ void InstrumentTrack::silenceAllNotes( bool removeIPH ) lock(); // invalidate all NotePlayHandles linked to this track m_processHandles.clear(); - Engine::mixer()->removePlayHandles( this, removeIPH ); + Engine::mixer()->removePlayHandlesOfTypes( this, removeIPH + ? PlayHandle::TypeNotePlayHandle + | PlayHandle::TypeInstrumentPlayHandle + : PlayHandle::TypeNotePlayHandle ); unlock(); } diff --git a/src/tracks/SampleTrack.cpp b/src/tracks/SampleTrack.cpp index 2f64fd7ef2d..4858a04dc60 100644 --- a/src/tracks/SampleTrack.cpp +++ b/src/tracks/SampleTrack.cpp @@ -446,7 +446,7 @@ SampleTrack::SampleTrack( TrackContainer* tc ) : SampleTrack::~SampleTrack() { - Engine::mixer()->removePlayHandles( this ); + Engine::mixer()->removePlayHandlesOfTypes( this, PlayHandle::TypeSamplePlayHandle ); } From ca7c90a99cfd27be8740497936f6a82f77ac922c Mon Sep 17 00:00:00 2001 From: Fastigium Date: Tue, 16 Feb 2016 13:31:17 +0100 Subject: [PATCH 31/90] Add mixer lock to EffectChain::clear to prevent a race condition --- src/core/EffectChain.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/core/EffectChain.cpp b/src/core/EffectChain.cpp index 5580ab14ab2..d3af38573c1 100644 --- a/src/core/EffectChain.cpp +++ b/src/core/EffectChain.cpp @@ -79,6 +79,8 @@ void EffectChain::loadSettings( const QDomElement & _this ) { clear(); + // TODO This method should probably also lock the mixer + m_enabledModel.setValue( _this.attribute( "enabled" ).toInt() ); const int plugin_cnt = _this.attribute( "numofeffects" ).toInt(); @@ -264,10 +266,14 @@ void EffectChain::clear() { emit aboutToClear(); + Engine::mixer()->lock(); + m_enabledModel.setValue( false ); for( int i = 0; i < m_effects.count(); ++i ) { delete m_effects[i]; } m_effects.clear(); + + Engine::mixer()->unlock(); } From 9d1867c7ebf729d4ad59efef249876a4e0c39dff Mon Sep 17 00:00:00 2001 From: Fastigium Date: Tue, 16 Feb 2016 13:34:13 +0100 Subject: [PATCH 32/90] Make Mixer::removePlayHandle check m_newPlayHandles, too This fixes a problem where a PresetPreviewPlayHandle would be put in m_newPlayHandles to be added, then "removed" before it was actually added, leaving it dangling. --- src/core/Mixer.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 92124a66093..012144a2cd5 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -642,12 +642,32 @@ void Mixer::removePlayHandle( PlayHandle * _ph ) { lockPlayHandleRemoval(); _ph->audioPort()->removePlayHandle( _ph ); + bool removedFromList = false; + // Check m_newPlayHandles first because doing it the other way around + // creates a race condition + m_playHandleMutex.lock(); PlayHandleList::Iterator it = - qFind( m_playHandles.begin(), - m_playHandles.end(), _ph ); + qFind( m_newPlayHandles.begin(), + m_newPlayHandles.end(), _ph ); + if( it != m_newPlayHandles.end() ) + { + m_newPlayHandles.erase( it ); + removedFromList = true; + } + m_playHandleMutex.unlock(); + // Now check m_playHandles + it = qFind( m_playHandles.begin(), + m_playHandles.end(), _ph ); if( it != m_playHandles.end() ) { m_playHandles.erase( it ); + removedFromList = true; + } + // Only deleting PlayHandles that were actually found in the list + // "fixes crash when previewing a preset under high load" + // (See tobydox's 2008 commit 4583e48) + if ( removedFromList ) + { if( _ph->type() == PlayHandle::TypeNotePlayHandle ) { NotePlayHandleManager::release( (NotePlayHandle*) _ph ); From 1c0d329dfb93938d1c439eebb48c6dc2f16d6c45 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Tue, 16 Feb 2016 14:27:44 -0500 Subject: [PATCH 33/90] Bump version for 1.2 RC1 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d88b665eb4..1fe5abc83ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ SET(PROJECT_DESCRIPTION "${PROJECT_NAME_UCASE} - Free music production software" SET(PROJECT_COPYRIGHT "2008-${PROJECT_YEAR} ${PROJECT_AUTHOR}") SET(VERSION_MAJOR "1") SET(VERSION_MINOR "1") -SET(VERSION_PATCH "3") +SET(VERSION_PATCH "90") #SET(VERSION_SUFFIX "") SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") IF(VERSION_SUFFIX) From d3d97b3275e8be9c58625719e01d4b40c1ade52d Mon Sep 17 00:00:00 2001 From: Yann Collette Date: Wed, 17 Feb 2016 20:47:53 +0100 Subject: [PATCH 34/90] Change the link of carlabase to SHARED and explicitly link carlarack and carlapatchbay to carlabase. --- cmake/modules/BuildPlugin.cmake | 11 ++++++++--- plugins/carlabase/CMakeLists.txt | 2 +- plugins/carlapatchbay/CMakeLists.txt | 3 ++- plugins/carlarack/CMakeLists.txt | 3 ++- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/cmake/modules/BuildPlugin.cmake b/cmake/modules/BuildPlugin.cmake index 05f1f77ce90..7fa7c4cb51b 100644 --- a/cmake/modules/BuildPlugin.cmake +++ b/cmake/modules/BuildPlugin.cmake @@ -1,10 +1,10 @@ # BuildPlugin.cmake - Copyright (c) 2008 Tobias Doerffel # # description: build LMMS-plugin -# usage: BUILD_PLUGIN( MOCFILES EMBEDDED_RESOURCES UICFILES ) +# usage: BUILD_PLUGIN( MOCFILES EMBEDDED_RESOURCES UICFILES LINK ) MACRO(BUILD_PLUGIN PLUGIN_NAME) - CMAKE_PARSE_ARGUMENTS(PLUGIN "" "" "MOCFILES;EMBEDDED_RESOURCES;UICFILES" ${ARGN}) + CMAKE_PARSE_ARGUMENTS(PLUGIN "" "" "MOCFILES;EMBEDDED_RESOURCES;UICFILES;LINK" ${ARGN}) SET(PLUGIN_SOURCES ${PLUGIN_UNPARSED_ARGUMENTS}) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/src/gui) @@ -45,7 +45,12 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME) SET(QT_LIBRARIES "${QT_OVERRIDE_LIBRARIES}") ENDIF() - ADD_LIBRARY(${PLUGIN_NAME} MODULE ${PLUGIN_SOURCES} ${plugin_MOC_out}) + IF ("${PLUGIN_LINK}" STREQUAL "SHARED") + ADD_LIBRARY(${PLUGIN_NAME} SHARED ${PLUGIN_SOURCES} ${plugin_MOC_out}) + ELSE () + ADD_LIBRARY(${PLUGIN_NAME} MODULE ${PLUGIN_SOURCES} ${plugin_MOC_out}) + ENDIF () + IF(QT5) TARGET_LINK_LIBRARIES(${PLUGIN_NAME} Qt5::Widgets Qt5::Xml) ENDIF() diff --git a/plugins/carlabase/CMakeLists.txt b/plugins/carlabase/CMakeLists.txt index ca6ab5fa1d0..8fdde2ec51f 100644 --- a/plugins/carlabase/CMakeLists.txt +++ b/plugins/carlabase/CMakeLists.txt @@ -3,7 +3,7 @@ if(LMMS_HAVE_CARLA) INCLUDE_DIRECTORIES(${CARLA_INCLUDE_DIRS}) LINK_DIRECTORIES(${CARLA_LIBRARY_DIRS}) LINK_LIBRARIES(${CARLA_LIBRARIES}) - BUILD_PLUGIN(carlabase carla.cpp carla.h MOCFILES carla.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") + BUILD_PLUGIN(carlabase carla.cpp carla.h MOCFILES carla.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png" LINK SHARED) SET_TARGET_PROPERTIES(carlabase PROPERTIES SKIP_BUILD_RPATH TRUE BUILD_WITH_INSTALL_RPATH TRUE diff --git a/plugins/carlapatchbay/CMakeLists.txt b/plugins/carlapatchbay/CMakeLists.txt index 878415ea0ea..d9aa6b32102 100644 --- a/plugins/carlapatchbay/CMakeLists.txt +++ b/plugins/carlapatchbay/CMakeLists.txt @@ -2,7 +2,8 @@ if(LMMS_HAVE_CARLA) ADD_DEFINITIONS(-DCARLA_PLUGIN_PATCHBAY -DCARLA_PLUGIN_SYNTH) INCLUDE(BuildPlugin) INCLUDE_DIRECTORIES(${CARLA_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/../carlabase") - LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/../carlabase") + LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/../carlabase" + ${CARLA_LIBRARY_DIRS}) LINK_LIBRARIES(carlabase) BUILD_PLUGIN(carlapatchbay carlapatchbay.cpp EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") endif(LMMS_HAVE_CARLA) diff --git a/plugins/carlarack/CMakeLists.txt b/plugins/carlarack/CMakeLists.txt index 2655fa89be7..1834b23715e 100644 --- a/plugins/carlarack/CMakeLists.txt +++ b/plugins/carlarack/CMakeLists.txt @@ -2,7 +2,8 @@ if(LMMS_HAVE_CARLA) ADD_DEFINITIONS(-DCARLA_PLUGIN_RACK -DCARLA_PLUGIN_SYNTH) INCLUDE(BuildPlugin) INCLUDE_DIRECTORIES(${CARLA_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/../carlabase") - LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/../carlabase") + LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/../carlabase" + ${CARLA_LIBRARY_DIRS}) LINK_LIBRARIES(carlabase) BUILD_PLUGIN(carlarack carlarack.cpp EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") endif(LMMS_HAVE_CARLA) From 76f6b1863276fc956d79ceb547440da813b10832 Mon Sep 17 00:00:00 2001 From: Fastigium Date: Thu, 18 Feb 2016 20:27:44 +0100 Subject: [PATCH 35/90] Drop PresetPreviewPlayHandle's shared buffer system Instead, add the NotePlayHandle used for previewing directly to the mixer. This fixes two preview problems, namely the shared buffer being released by the NotePlayHandle but still being pulled in by the AudioPort resulting in distortions, and certain previews being cut off at mouse release even if a release was set in the envelope. --- src/core/PresetPreviewPlayHandle.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/core/PresetPreviewPlayHandle.cpp b/src/core/PresetPreviewPlayHandle.cpp index 4b8b4997044..633f03a3fb6 100644 --- a/src/core/PresetPreviewPlayHandle.cpp +++ b/src/core/PresetPreviewPlayHandle.cpp @@ -118,6 +118,8 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, { s_previewTC->lockData(); + setUsesBuffer( false ); + if( s_previewTC->previewNote() != NULL ) { s_previewTC->previewNote()->mute(); @@ -185,6 +187,8 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, s_previewTC->setPreviewNote( m_previewNote ); + Engine::mixer()->addPlayHandle( m_previewNote ); + s_previewTC->unlockData(); Engine::projectJournal()->setJournalling( j ); } @@ -201,7 +205,7 @@ PresetPreviewPlayHandle::~PresetPreviewPlayHandle() // then set according state s_previewTC->setPreviewNote( NULL ); } - NotePlayHandleManager::release( m_previewNote ); + m_previewNote->noteOff(); s_previewTC->unlockData(); } @@ -210,7 +214,8 @@ PresetPreviewPlayHandle::~PresetPreviewPlayHandle() void PresetPreviewPlayHandle::play( sampleFrame * _working_buffer ) { - m_previewNote->play( _working_buffer ); + // Do nothing; the preview instrument is played by m_previewNote, which + // has been added to the mixer } From eec6c5b4f035168c0c5c6a63d1713665c6e66acd Mon Sep 17 00:00:00 2001 From: Lukas W Date: Fri, 19 Feb 2016 12:04:36 +1300 Subject: [PATCH 36/90] Clean up some path separator mess --- plugins/stk/mallets/mallets.cpp | 3 +-- src/core/ConfigManager.cpp | 30 ++++++++++++------------------ src/gui/SetupDialog.cpp | 16 ++++++++-------- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/plugins/stk/mallets/mallets.cpp b/plugins/stk/mallets/mallets.cpp index 632f88fd556..44b43830a64 100644 --- a/plugins/stk/mallets/mallets.cpp +++ b/plugins/stk/mallets/mallets.cpp @@ -79,8 +79,7 @@ malletsInstrument::malletsInstrument( InstrumentTrack * _instrument_track ): m_presetsModel(this), m_spreadModel(0, 0, 255, 1, this, tr( "Spread" )), m_filesMissing( !QDir( ConfigManager::inst()->stkDir() ).exists() || - !QFileInfo( ConfigManager::inst()->stkDir() + QDir::separator() - + "sinewave.raw" ).exists() ) + !QFileInfo( ConfigManager::inst()->stkDir() + "/sinewave.raw" ).exists() ) { // ModalBar m_presetsModel.addItem( tr( "Marimba" ) ); diff --git a/src/core/ConfigManager.cpp b/src/core/ConfigManager.cpp index 85125ed59be..89128aa826f 100644 --- a/src/core/ConfigManager.cpp +++ b/src/core/ConfigManager.cpp @@ -36,13 +36,13 @@ #include "GuiApplication.h" -static inline QString ensureTrailingSlash( const QString & _s ) +static inline QString ensureTrailingSlash( const QString & s ) { - if( _s.right( 1 ) != QDir::separator() ) + if(s.at(s.length()-1) != '/') { - return _s + QDir::separator(); + return s + '/'; } - return _s; + return s; } @@ -50,13 +50,11 @@ ConfigManager * ConfigManager::s_instanceOfMe = NULL; ConfigManager::ConfigManager() : - m_lmmsRcFile( QDir::home().absolutePath() + QDir::separator() + - ".lmmsrc.xml" ), - m_workingDir( QDir::home().absolutePath() + QDir::separator() + - "lmms" + QDir::separator() ), + m_lmmsRcFile( QDir::home().absolutePath() +"/.lmmsrc.xml" ), + m_workingDir( QDir::home().absolutePath() + "/lmms/"), m_dataDir( "data:/" ), m_artworkDir( defaultArtworkDir() ), - m_vstDir( m_workingDir + "vst" + QDir::separator() ), + m_vstDir( m_workingDir + "vst/" ), m_flDir( QDir::home().absolutePath() ), m_gigDir( m_workingDir + GIG_PATH ), m_sf2Dir( m_workingDir + SF2_PATH ), @@ -400,11 +398,7 @@ void ConfigManager::loadConfigFile() { m_artworkDir = defaultArtworkDir(); } - if( m_artworkDir.right( 1 ) != - QDir::separator() ) - { - m_artworkDir += QDir::separator(); - } + m_artworkDir = ensureTrailingSlash(m_artworkDir); } setWorkingDir( value( "paths", "workingdir" ) ); @@ -433,18 +427,18 @@ void ConfigManager::loadConfigFile() } - if( m_vstDir.isEmpty() || m_vstDir == QDir::separator() || + if( m_vstDir.isEmpty() || m_vstDir == QDir::separator() || m_vstDir == "/" || !QDir( m_vstDir ).exists() ) { #ifdef LMMS_BUILD_WIN32 QString programFiles = QString::fromLocal8Bit( getenv( "ProgramFiles" ) ); - m_vstDir = programFiles + QDir::separator() + "VstPlugins" + QDir::separator(); + m_vstDir = programFiles + "/VstPlugins/"; #else m_vstDir = m_workingDir + "plugins/vst/"; #endif } - if( m_flDir.isEmpty() || m_flDir == QDir::separator() ) + if( m_flDir.isEmpty() || m_flDir == QDir::separator() || m_flDir == "/") { m_flDir = ensureTrailingSlash( QDir::home().absolutePath() ); } @@ -455,7 +449,7 @@ void ConfigManager::loadConfigFile() } #ifdef LMMS_HAVE_STK - if( m_stkDir.isEmpty() || m_stkDir == QDir::separator() || + if( m_stkDir.isEmpty() || m_stkDir == QDir::separator() || m_stkDir == "/" || !QDir( m_stkDir ).exists() ) { #if defined(LMMS_BUILD_WIN32) diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index b894a0fe3e8..4c64fac1173 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -1003,18 +1003,18 @@ void SetupDialog::accept() ConfigManager::inst()->setValue( "app", "language", m_lang ); - ConfigManager::inst()->setWorkingDir( m_workingDir ); - ConfigManager::inst()->setVSTDir( m_vstDir ); - ConfigManager::inst()->setGIGDir( m_gigDir ); - ConfigManager::inst()->setSF2Dir( m_sf2Dir ); - ConfigManager::inst()->setArtworkDir( m_artworkDir ); - ConfigManager::inst()->setFLDir( m_flDir ); - ConfigManager::inst()->setLADSPADir( m_ladDir ); + ConfigManager::inst()->setWorkingDir(QDir::fromNativeSeparators(m_workingDir)); + ConfigManager::inst()->setVSTDir(QDir::fromNativeSeparators(m_vstDir)); + ConfigManager::inst()->setGIGDir(QDir::fromNativeSeparators(m_gigDir)); + ConfigManager::inst()->setSF2Dir(QDir::fromNativeSeparators(m_sf2Dir)); + ConfigManager::inst()->setArtworkDir(QDir::fromNativeSeparators(m_artworkDir)); + ConfigManager::inst()->setFLDir(QDir::fromNativeSeparators(m_flDir)); + ConfigManager::inst()->setLADSPADir(QDir::fromNativeSeparators(m_ladDir)); #ifdef LMMS_HAVE_FLUIDSYNTH ConfigManager::inst()->setDefaultSoundfont( m_defaultSoundfont ); #endif #ifdef LMMS_HAVE_STK - ConfigManager::inst()->setSTKDir( m_stkDir ); + ConfigManager::inst()->setSTKDir(QDir::fromNativeSeparators(m_stkDir)); #endif ConfigManager::inst()->setBackgroundArtwork( m_backgroundArtwork ); From cde1bcc350419163be16e0dc9957219aed1a0ca3 Mon Sep 17 00:00:00 2001 From: Colin Wallace Date: Thu, 18 Feb 2016 20:16:08 -0800 Subject: [PATCH 37/90] Fix #2588 by making Alt+Right shortcut mirror the Alt+Left shortcut; Alt+Right sets the PianoRoll to edit the *next* pattern in the song editor; Alt+Left = previous. --- src/gui/editors/PianoRoll.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 85ef9339bc2..a8c70c6a9ea 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -1081,7 +1081,8 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke ) } else if( ke->modifiers() & Qt::AltModifier) { - Pattern * p = m_pattern->previousPattern(); + // switch to editing a pattern adjacent to this one in the song editor + Pattern * p = direction > 0 ? m_pattern->nextPattern() : m_pattern->previousPattern(); if(p != NULL) { setCurrentPattern(p); From bda6c7e2b8e5a5ffa79711b5025b616dd10ad833 Mon Sep 17 00:00:00 2001 From: Ben Bryan Date: Fri, 19 Feb 2016 00:05:49 -0600 Subject: [PATCH 38/90] Fix equalizer labels for #2583 --- plugins/Eq/EqControlsDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/Eq/EqControlsDialog.cpp b/plugins/Eq/EqControlsDialog.cpp index ee91ca8f4a2..2b65907402f 100644 --- a/plugins/Eq/EqControlsDialog.cpp +++ b/plugins/Eq/EqControlsDialog.cpp @@ -105,7 +105,7 @@ EqControlsDialog::EqControlsDialog( EqControls *controls ) : } m_resKnob->setVolumeKnob(false); m_resKnob->setModel( m_parameterWidget->getBandModels( i )->res ); - if(i > 1 && i < 6) { m_resKnob->setHintText( tr( "Bandwidth: " ) , " Octave" ); } + if(i > 0 && i < 7) { m_resKnob->setHintText( tr( "Bandwidth: " ) , tr( " Octave" ) ); } else { m_resKnob->setHintText( tr( "Resonance : " ) , "" ); } m_freqKnob = new Knob( knobBright_26, this ); From d5259292c91ab58ea382fcae4d4267fd7c278f90 Mon Sep 17 00:00:00 2001 From: Steffen Baranowsky Date: Tue, 5 Jan 2016 15:25:25 +0100 Subject: [PATCH 39/90] New GUI for the native EQ plugin --- plugins/Eq/12dB.png | Bin 0 -> 1029 bytes plugins/Eq/12dBoff.png | Bin 0 -> 958 bytes plugins/Eq/24dB.png | Bin 0 -> 1059 bytes plugins/Eq/24dBoff.png | Bin 0 -> 990 bytes plugins/Eq/48dB.png | Bin 0 -> 1075 bytes plugins/Eq/48dBoff.png | Bin 0 -> 1012 bytes plugins/Eq/ActiveAnalyse.png | Bin 0 -> 935 bytes plugins/Eq/ActiveAnalyseoff.png | Bin 0 -> 846 bytes plugins/Eq/ActiveHP.png | Bin 0 -> 992 bytes plugins/Eq/ActiveHPoff.png | Bin 0 -> 905 bytes plugins/Eq/ActiveHS.png | Bin 0 -> 968 bytes plugins/Eq/ActiveHSoff.png | Bin 0 -> 883 bytes plugins/Eq/ActiveLP.png | Bin 0 -> 990 bytes plugins/Eq/ActiveLPoff.png | Bin 0 -> 896 bytes plugins/Eq/ActiveLS.png | Bin 0 -> 983 bytes plugins/Eq/ActiveLSoff.png | Bin 0 -> 909 bytes plugins/Eq/ActivePeak.png | Bin 0 -> 1064 bytes plugins/Eq/ActivePeakoff.png | Bin 0 -> 998 bytes plugins/Eq/CMakeLists.txt | 4 +- plugins/Eq/EqControls.cpp | 43 +- plugins/Eq/EqControls.h | 17 +- plugins/Eq/EqControlsDialog.cpp | 297 ++++++++--- plugins/Eq/EqControlsDialog.h | 36 +- plugins/Eq/EqCurve.cpp | 818 +++++++++++++++++++++++++++++++ plugins/Eq/EqCurve.h | 209 ++++++++ plugins/Eq/EqEffect.cpp | 4 +- plugins/Eq/EqFader.h | 21 +- plugins/Eq/EqLayout1BG.png | Bin 0 -> 52487 bytes plugins/Eq/EqParameterWidget.cpp | 278 +++++------ plugins/Eq/EqParameterWidget.h | 100 ++-- plugins/Eq/EqSpectrumView.h | 63 ++- plugins/Eq/artwork.png | Bin 27905 -> 0 bytes plugins/Eq/bandLabel1.png | Bin 0 -> 413 bytes plugins/Eq/bandLabel1on.png | Bin 0 -> 457 bytes plugins/Eq/bandLabel2.png | Bin 0 -> 487 bytes plugins/Eq/bandLabel2on.png | Bin 0 -> 544 bytes plugins/Eq/bandLabel3.png | Bin 0 -> 488 bytes plugins/Eq/bandLabel3on.png | Bin 0 -> 537 bytes plugins/Eq/bandLabel4.png | Bin 0 -> 467 bytes plugins/Eq/bandLabel4on.png | Bin 0 -> 525 bytes plugins/Eq/bandLabel5.png | Bin 0 -> 458 bytes plugins/Eq/bandLabel5on.png | Bin 0 -> 515 bytes plugins/Eq/bandLabel6.png | Bin 0 -> 525 bytes plugins/Eq/bandLabel6on.png | Bin 0 -> 605 bytes plugins/Eq/bandLabel7.png | Bin 0 -> 446 bytes plugins/Eq/bandLabel7on.png | Bin 0 -> 499 bytes plugins/Eq/bandLabel8.png | Bin 0 -> 540 bytes plugins/Eq/bandLabel8on.png | Bin 0 -> 614 bytes plugins/Eq/circle1.png | Bin 0 -> 1030 bytes plugins/Eq/handle1.png | Bin 0 -> 1174 bytes plugins/Eq/handle1inactive.png | Bin 0 -> 734 bytes plugins/Eq/handle2.png | Bin 0 -> 1483 bytes plugins/Eq/handle2inactive.png | Bin 0 -> 942 bytes plugins/Eq/handle3.png | Bin 0 -> 1459 bytes plugins/Eq/handle3inactive.png | Bin 0 -> 920 bytes plugins/Eq/handle4.png | Bin 0 -> 1344 bytes plugins/Eq/handle4inactive.png | Bin 0 -> 818 bytes plugins/Eq/handle5.png | Bin 0 -> 1421 bytes plugins/Eq/handle5inactive.png | Bin 0 -> 918 bytes plugins/Eq/handle6.png | Bin 0 -> 1506 bytes plugins/Eq/handle6inactive.png | Bin 0 -> 944 bytes plugins/Eq/handle7.png | Bin 0 -> 1511 bytes plugins/Eq/handle7inactive.png | Bin 0 -> 833 bytes plugins/Eq/handle8.png | Bin 0 -> 1429 bytes plugins/Eq/handle8inactive.png | Bin 0 -> 948 bytes plugins/Eq/handlehover.png | Bin 0 -> 967 bytes 66 files changed, 1538 insertions(+), 352 deletions(-) create mode 100644 plugins/Eq/12dB.png create mode 100644 plugins/Eq/12dBoff.png create mode 100644 plugins/Eq/24dB.png create mode 100644 plugins/Eq/24dBoff.png create mode 100644 plugins/Eq/48dB.png create mode 100644 plugins/Eq/48dBoff.png create mode 100644 plugins/Eq/ActiveAnalyse.png create mode 100644 plugins/Eq/ActiveAnalyseoff.png create mode 100644 plugins/Eq/ActiveHP.png create mode 100644 plugins/Eq/ActiveHPoff.png create mode 100644 plugins/Eq/ActiveHS.png create mode 100644 plugins/Eq/ActiveHSoff.png create mode 100644 plugins/Eq/ActiveLP.png create mode 100644 plugins/Eq/ActiveLPoff.png create mode 100644 plugins/Eq/ActiveLS.png create mode 100644 plugins/Eq/ActiveLSoff.png create mode 100644 plugins/Eq/ActivePeak.png create mode 100644 plugins/Eq/ActivePeakoff.png create mode 100644 plugins/Eq/EqCurve.cpp create mode 100644 plugins/Eq/EqCurve.h create mode 100644 plugins/Eq/EqLayout1BG.png delete mode 100644 plugins/Eq/artwork.png create mode 100644 plugins/Eq/bandLabel1.png create mode 100644 plugins/Eq/bandLabel1on.png create mode 100644 plugins/Eq/bandLabel2.png create mode 100644 plugins/Eq/bandLabel2on.png create mode 100644 plugins/Eq/bandLabel3.png create mode 100644 plugins/Eq/bandLabel3on.png create mode 100644 plugins/Eq/bandLabel4.png create mode 100644 plugins/Eq/bandLabel4on.png create mode 100644 plugins/Eq/bandLabel5.png create mode 100644 plugins/Eq/bandLabel5on.png create mode 100644 plugins/Eq/bandLabel6.png create mode 100644 plugins/Eq/bandLabel6on.png create mode 100644 plugins/Eq/bandLabel7.png create mode 100644 plugins/Eq/bandLabel7on.png create mode 100644 plugins/Eq/bandLabel8.png create mode 100644 plugins/Eq/bandLabel8on.png create mode 100644 plugins/Eq/circle1.png create mode 100644 plugins/Eq/handle1.png create mode 100644 plugins/Eq/handle1inactive.png create mode 100644 plugins/Eq/handle2.png create mode 100644 plugins/Eq/handle2inactive.png create mode 100644 plugins/Eq/handle3.png create mode 100644 plugins/Eq/handle3inactive.png create mode 100644 plugins/Eq/handle4.png create mode 100644 plugins/Eq/handle4inactive.png create mode 100644 plugins/Eq/handle5.png create mode 100644 plugins/Eq/handle5inactive.png create mode 100644 plugins/Eq/handle6.png create mode 100644 plugins/Eq/handle6inactive.png create mode 100644 plugins/Eq/handle7.png create mode 100644 plugins/Eq/handle7inactive.png create mode 100644 plugins/Eq/handle8.png create mode 100644 plugins/Eq/handle8inactive.png create mode 100644 plugins/Eq/handlehover.png diff --git a/plugins/Eq/12dB.png b/plugins/Eq/12dB.png new file mode 100644 index 0000000000000000000000000000000000000000..650a9b7ed9944e2b10e2c24b5f68c480f34b801f GIT binary patch literal 1029 zcmV+g1p51lP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00V7FL_t(Y$Gw(Ih+IV!hQE5< zZU+TH4dj6fgNouJ8-oEKlaL4_gBl$Z9{~k%s}O_EM4iMSCW_)Zg5pk0R#5_?Bt{92 zj6@_^jAUuD(v{JfboZ?~$3<1&?sl>;F?hL$zPG4*{_|J;=dU)8Om0wP48viK!5F|8 z41j_1bjeFm$_=Whf~cbZ2ycvG!}>dL-r=mpxj~E;krNv;09DoU%Sh6cWDp{xn3$Vi z$Y9o4yt8=k3EtsD2DZ)?mKkgqXc({$CaOpQh;^cl2@@l#iZLdGdFSxnQ&pZSctY@a z?{Lmyt!;pY*)3-UBAHE$iP}btHO-s`%sET&jw*Ostw2>}K<5geF<5Kh63kFVB(us( zm#FKQ=L0H=h-5HZz*+f{iFL(e%L+WI=J@?BMm9nNbE_$==t67Tr&)LGvB;1I`- zzC#r}&O2siKjPbyXL#y~ady5qHM)u-sKVk>hbnjg9^Jl|3x6(h-L+$E8ehl6mb<|i ztO1P8U1Y7{WwC?h(*NWg>!zq9W{?`H;6}pXJuItFz2Yti5F=UmZKe#ZI?T zU(N$5CVIUZSD2#Uwe*5ElQURKg0n(2hF{K}W8=gt0Gysb*i^b_<{5VH{e<0nK4#U* z8?t*OVeFcU$*DJ3antoYw_{6_-)wvAe%&;_j&_mu*jS5pt0DwXD81Jhv|ZlRA_GsX z>quSartWlmEG>2Ebb55UJ&vFF8L!H~Fq7o&FHI|&$1bm_Qvr=5c~!ypZ6?;)&-&Gi zDlrMpr7N)dHo{^00000NkvXXu0mjfBMIDQ literal 0 HcmV?d00001 diff --git a/plugins/Eq/12dBoff.png b/plugins/Eq/12dBoff.png new file mode 100644 index 0000000000000000000000000000000000000000..8e5b61599822c5bf19afb34f132a62b0fae89b6a GIT binary patch literal 958 zcmV;v13~e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00SmTL_t(Y$Gw)#ZX87r$A4Ab zV_8I2kR|&8Y+i0TL?Mn1#7N|V zIXar1uHw+Wv%5x-_=xDkcF(B0e)F%dURhaLbp!+f5kv%OpP{VE`US(m#}L!uz43PBYOp`BGFL!~GN z#)xA)&q#ONy+9mGi6n-Q07np_NKq34F$O{igb)du)v3yuvJ4ZE>>@^rz%k3Jk{L+_ zNr@)!KtzZXSWqQ|K#Wy^#^Tap9OcEzT2HaC6)hM2I4wQd}4!F=k*^sHlb! zY#6l(WsG2!NXbSZ&uZ0-%t2arscHrmmu8ibD#kol6;)OJbsZzOzWt{4N(^J3(QIFk zoQ*+wJoF^pxr8 zX*!(_7cN``fe3==sKyQsp3pSe=UU>qzP8Thl})+6A||J_u1aQ#(VF7 zkk9BSwmUnwxp((2tE($*bw>WiI63*92YU~A`<-_u-v4oO!fQ)Qt+MfP^X5k!|9Z^c z{XLeJm$P!8$f#jY72!&}#{Ge1AyW}dq$}=htkWqVk~>i%y9P{GcyOQ+_0J(=S#gj^KBh* gI66A~U;Y;S39&XmH~A$_MF0Q*07*qoM6N<$f>|xN6aWAK literal 0 HcmV?d00001 diff --git a/plugins/Eq/24dB.png b/plugins/Eq/24dB.png new file mode 100644 index 0000000000000000000000000000000000000000..1543f94edad542d523765ed155d659c95801cb60 GIT binary patch literal 1059 zcmV+;1l;?HP)4bZ4EO*502y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00WCjL_t(Y$Gw(KXk1kk$A9?`R=qIMadVaq6(sl{w=&QhQX^Z!Fh+X7U#OLvWS$}m@cTQ=5JOcjZwNG zLJX1VnYjdJoy9wg_nyK#e35{yvzcWA>jmlsTm}EQNQJg{RRdD9Z%sTn01-YYm)+ z8LEgRR%z)XRTa{FKt&Oe1ZFdsFC0aY*fq)`u`3+jIjrsO-D+lOpG1@pBcV#g0f=Z? z(il_0#*hS&#gPCD%CewQ7BrhBjYf)Qv&_GXp8FIxZF`JHey_~M_U1JPe3Ew($@4G0 z!|Yc-GIGl`JaFF#W#Ma;zISYz*8W3$J2Sa*6-7{mg~c{y;Q<)AZ7-+(SfKx`J~nUK z$d;k2z!DZ10ksm_Nyr&m5*TzGKBwO?~nWciuYzz{OYG zQ;+}h>u+3l?PaVVIA@he-#_vM2lm~~kz>>Km`xs&dSv2-w|V&f?Ob@l`G^Q2ii+^v z=aYQ@#X$gmm_3-JF3Lq4*73pdS^jJ<)#?)w0Ah%AIu$N6MZs(C1qFWkd7iPmo&w<0 zkDkR@AsB;G5R;OGD0QWK#&@uL@2l+I^9lp&)+YCeLf@K_;nBxA@7%MwV{E9-Z*JXw zy>8yLk!F^5Utfb}qogQ2Mee=YpzZ3W7U_CoRRyXlHFbNb!{Xu+?RJOuQirLJzs9T5 zHOwff`*YKZrm=t4)G>pG6?s*`FWXG0lAkSCFRFwnI2ZqwU3EGMFjSEk1yRK>9|={6 zwQ-6lA;^C-;wsRo0#%5aSq2L+)`>LxnXAss5fefn#MlLsm{g}4kZhc1^6->iX45ls d|I6QkzW{3Od#sh#S+)QG002ovPDHLkV1g~0>lgq4 literal 0 HcmV?d00001 diff --git a/plugins/Eq/24dBoff.png b/plugins/Eq/24dBoff.png new file mode 100644 index 0000000000000000000000000000000000000000..419a091ba505e370aaf6df7a8df636731490571e GIT binary patch literal 990 zcmV<410np0P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00TxzL_t(Y$Gw)ZZyZGwhrjn` z*0KvLwq#eK3L;ptqq7v6AcZ0^62zt;{{T=2g$k&!oj(B*yCWh9Xl*$t*d*zJ$`nMg zgk3nT6?B!O^Uiw|Gq<;Plmdu2>279cXXo4B@6CI2(&@}P0)l`DB7!v6Pz#X6)_l5(Pn32&!lZ zO{*#yDn&8SBDQ#*k?y#AfjE{DNem$Yjvz#lq9z1l41^E}ArdsJQgQ3O2tBh1J=C-P+s_OZEjNJU{%f^)$ zTFz)*Uy!^Tg{1{*aOv_KA%yaPvc0{{k9RltVsYt&i&*CT`g!0PHM z&khe69v)_DYKrOU84!pdh~{|AOwVxf;#>Ui{dZiRdmAnB>~_2S_UkVIsA>b+-TjmG zwY3JKBA5uz4iC9@?PKLfS}Tf!|7K}Gcq#5*w|Q(ljd0cytT4<$F4a?aIn6?rv-_JKJfpQ`?qwyIp>|caJOc3&*V5+1cUSJKq4X zytLSi|Mm1Kubn;1`1ts9oAmniPk8_8RkpW(Z^qPH-aoj1pSig?CMG6ICCIyMacP;Q z?Erwt~H2woQYH%XmRBBi=1 z#BPS;M0axWOexp1W7)5$q<>tlQmU!z0!#^W!yO|131Ub}15mR6R)|xb6e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00WyzL_t(Y$Gw(ch?G?r#((F} z_szBx1pNW6tAZlv!kY@AKel9GY=4x+h4LbhD3XjUV%KUF!B`?KQ0T&RV<9CLwnVHf zQ;T9_!KkYxLb|B7K)cY`ZFatM-nWZ$=9}5pn@SqyWxhF_d7tx~^E}TP^Kk!4HOA0g z))uhG3z`B9D0o!1rie!LLMXC@nA)u-lV-lEm4(~l> z=_w0OQFy#}IA^ie)R^M#`*61zrOBzA?vJBPKMvs=n6os)@zv_#3`({4#qkNnMm1Z&=1BpPlB<=0dGL5dk2ENUK%h zGE)@1W-n+xIibfWI4cBW*s^(mP0#H?MA`DpIzmhhw+%nW*6r`Gb=v`!FS{zGM-+N5 zE9oD2g=??5lE*i!uKSzy>+aURRV(Pp((dhT(93Qv)}R|m9RYHE>ACRSCTs*VMY;4f>KjxAbpg!KRb002ovPDHLkV1m(%{SN>D literal 0 HcmV?d00001 diff --git a/plugins/Eq/48dBoff.png b/plugins/Eq/48dBoff.png new file mode 100644 index 0000000000000000000000000000000000000000..37f0f5ff80eeb987123fe4c3879590d49c575a35 GIT binary patch literal 1012 zcmVe zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00Ue}L_t(Y$Gw)%Z&gJU$3N%H z+@_lbyJ%#M5t{(P1XF?wD~1|LaUlstT`4Topk)R4AAmdg(f$b-HQ{xmmPAdgDG*s$ z7m}LTromk$v`H5wuXoOIG1L3rD`BA$-{Q@@d2{EJ@Av$eEBp69?+6G2B8Ujm{Dv|s z^T&J~yldh(?%??gFY6J3UAvw^RZ*2ZiXy5F7`Ddk)PnFl-vYQ9=7yPJ=9n2vON&H7 zP!)nI8bULwN`^{N40I8@c%G5&xO;&(mJ&$}ApwpcM3JH<1Y!(?5C|a>G^uTRw{PD9VC3LIMn_-nQ3cR$ zw+SHtFf}#B!;KC4`}-Ll9%j#;y&w=l5Y6#eUtec_{+GroE%Cf_=V#t}`yBwj`tl17 zAASXZ#l=6EZnYYSieMr<+}Pms>5sVg=RI!B++gp%eSi?9D-O4A&N2GZD6Q7@94F1O zdhO^@zWwHFR#sLxapKJ;CNncLjE^7V>76^deCe~i-|~NxlUK77BO^_9YIkBSFE7(- zT?gRPix-;ppJr!y_q~&xJavlM*&mzr)dvrFcK2=u2L~TX(us*Pym9>>C;y;_ltwXtX`W9^X4G|E>NNM7 z2#%Zg)Jv1L?qJ5)*sFYg?HXpzkt1W6835zQUT1o`#dNF1jvY^7<@u_rn7n$0fq?-I z9eOdJk0S>Tyx`9b4^vf6x7plmv$bd|^!rX9& z$kqliB&7~0*?()qsm=;5Up2TBy}*Rhp)Eg@p2QVn*)cQ2-E+*$9I$f3YHplQ^zzKN ib;Mz5Y4Lw~E%+O?7F33Y|958q0000e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00R$6L_t(Y$Gw(Ki=0Ie$A4A* zGV@h}5W&dmvI`+ZkOgr=f|s0?tVF~}JV*{A5g{JjJt#r(8w3Ih9z3Y0xU!(2m;EO0 z%skyy9{PEiiBUX6AEv13?&|-)s;j!5NA_RYb`fD+R0I(~1OX7}|2^?>oc;&yxP!Ul zk4Y2}wztj^Vj!pz!X%qcG+>d5)ZKf{257A|i5az2j!#Y-nFi(d`(N_er*DyBAf`sF zLHj5h**eiW;Xr2YSWi&8N>?gU3hs`GG_n{1069l;ilh{YF%W{Hsw2^QbbpNs%vv<1 zR5~q)%4jo^g`kZrMP{=^&XH@^@AB=#j~bx}ssc}l40p_0RPE?0U00et;O3ZFBhxjq zlp;AtW;yZQ*B=v8AclbIl)IhFxA^IYqqWFdp3Iz5E2V4B0hoC^(psCtB8+4qDA%sv zCFexWiCIp}=b728$$Xyq<q1ZrMc{fjD4DINm za%t~9a-X}LA~^+8id@*aN$T^OQslRv?{Cu##z^c>AolYyD9^t5CLt;pc5b4>wNV|h27Cc@^R5beSMHz#nF^wcit^0!Z;VMF zfX1;Xzn^^3&kYqUfQ(oODF5;~{q?JVTtB~c1ArGUzWuj0+Iq~?cv=>Peh>ij$^Q7qBh0L?Rv)o&Q19=;U<^}X z&DkE`TV&oEDNst?*u3frrBqg30iavc=eKT*Tfda=8Lvv1od^?0EG3;o5jL+7J6*eeHv(5m&<f1EAZxqNFJ59^CXx3RzL3Z<*mYM47*-QV@Ydk5ZE$A2P+_YVB({;o&&*3*tY zIUvUP)L${B6uMH|%hP*e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00Op2L_t(Y$Gw(qk`zS{hM&x; z>bVCV0GGQkqDN3f{|JV{euM0;ivnt(96>!2dywg_Onzi_^~?qs{y;mTCbRPEowu_l zYvkt5j~xL)Km-v%`W~9r^!GdtzNI*hJ9vEH&7KjsapNOY6;%l-il}yAnB{fU2H~O4 z0B(l4VP=>)X2#Xk8?qp%3V;9gCwD&mjHHUD6u=UI$jt5?^xOl|9d~aaj@3#PL#Tiw z2w5c90OXuVDUnhpX|Pk3EoK2GBJqk?7=dFJtg0DR1*w%OA`lUjEwGdlITuRFyng)$ z!!R(Efz>du8dj`Uv4&yj`f6CQYH`CbP=WyNK^ikv<@Z;w$SHNuoHHdykx~lZegClQr4%mC z&$@pG$*mRhp%YaELHh}BV0XW~hbHCO8$7)PlKUI~KQtxdqq{`{ZF{;Xw$EWC4{#*;0>kGPlm_^{_i{}vph)Pd7Iy_kH zve@VSqy2-Ocxm-|450kW=kVzGAN?oCM*y5X{o%ba>bt+sCfj7N_@TNxhX?zM-52}y z`1=pO4PUF*eZkCeyO!hzfVsDk)An2PopyK5&z|CLynOL|nT_UvqstK8N~$4it+A%5 z?`L^(e6;MZ`K=nCe{naykXsvPpiYdKZLp~&P1DFUO^mJBIF8Le@y-1QeLwrBY3%vG z{rXEE#BPS;s5_X?Om>sTapLmF3&zc62W+$1aB+UNfOY?FeytN$Yp`=*Z||1hUa!6N z@IP6%*K6O~yXD#2Ay}_JLFd8wp{^LSCM)hv_I5RZwHsDZvk!cE#%-N(xVn1tzx*wD Y3zHe@It^S#MF0Q*07*qoM6N<$g5|}GT>t<8 literal 0 HcmV?d00001 diff --git a/plugins/Eq/ActiveHP.png b/plugins/Eq/ActiveHP.png new file mode 100644 index 0000000000000000000000000000000000000000..3534c799823b42fa640c6bb0c82d636741649f11 GIT binary patch literal 992 zcmV<610Vc}P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00T%#L_t(Y$Gw)%Yh6_k$3Jt< zxi9~Lc2R5$lwwV)ZiLv@THT6SxKt1~BI3f08xdPjK?U82NCm|o2>t*?7vio7sT2Z& zMl`lWT-5vvN!~kWW?Y6iEIqvFBEob85kvqH1VEtO zUH5RDc7i+ZVD9+7NFu`Gy>}2(B!)nYli1rtEi5ttb@z5x#Z=BOwS^H@A5G&Cdb&@V)1!nAPWG<`h**uFV0Mc^#=L zp)#WiqKTsdRErj2%UPA=tkI(MW$HMVhzW(eSZ@>Eu=U@4ljVsqUcJwf(PcBeY$ys@H=~Sy* zjUn+5$Hmok&YrpZhTlK?^b*fJ^$2RlFTeiD#pR#+eK?StXrGx`H6E{0H8XzO*kXC* zXTJROMa=w0%E#PrGmafS%-rlDhQrLx?ueb8VXF%`ByYRmOya#mI@t#fkmPDZ&f%5_=y$0#eKTqvbp zbFRNvRZ3Aztr@kG+?g1rTHBSn#BR>)ZMQNUj>d+3(606`^`xoky6%vAn<=^aS#L96 zeS3)`M{Z$fcXU&BH5ygGk`-0MDzloDi;j)c%sIU{PYA;H_VDJ6IF~xsqK#PtE2`r{ z-UM>{>>)x7Y;W)Wt5-}Zg`zqEGc}3`?geYc`Cq;~ZJOETwT=JfZ^7TA;I_W}1#?gU O0000e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00QwzL_t(Y$Gw(Kk`qS|g}=-y zU0_0l6(OyVV1^ZrIe~{IKlTxT4S#nq-r7C`_91`;u)q-puVIOrU{?IJ<_5I7GQFr$ zcWcHI4hV-kLaLG~yI#MSnXg(dUi{V(5ClXJ5v2PKWme{=Tn;{%IF37b{=&=u5rMO3 z=cp>Gl1EWQwF8FDcpSArc%E+n+zfNW%rJAzjKjlsL_ts$f+`w9H>yeomBJVpAP(?6 zL%QSc1;nwGNMZ;Ha0DTW6gD9cV<3b;2$7(fovI9&WiS!R645gP$1Jl-W+W9PCE6T; zh!81YL6r~!F^&poERt^WD5o>)SY^pHwK*PebKDg~h$5g;Bn*)lGhk+@s0KuY)oR7F zr%wR5e&gnV89kUKQnDV%Gg~zy;~6}t6aWvm0y4PnbBy( zXw;R5WDJ%r5Zqua}(P-DNhLF`Lc!@%~Tz{@VkNj*fCn z>|;ZSXc+7z+O>{?AUfB$>-auVsGz4zkw>(zW;&8j~?>k#h=u5eJsDam1ikM z7B?yHo0%R|g}SZ*m`{KA<3|sv>zc`A!hEs7%t$G*zrWw*Pk_k3 zTvfGXcW>|1^@B^7`0n5UGvmXD_blHmbFcf!*yvjoRpLr@ef;=|YPsar?K@l5ce46( z{N$Sn|wM_HrwB2GJ?TSqw9k?q97|0F1|D)@{4RYTK?( zHgyMD_H{EHC%P9_DP=z^o4$Viik+Pu)=l%pc9l{~+iqB<%+4XQ2@pe4>YjAISRkS_ z>*ni>I2CD&oVXLcfCmgC fc=+yrc`f)Gey(2=_&>NB00000NkvXXu0mjf$BdED literal 0 HcmV?d00001 diff --git a/plugins/Eq/ActiveHS.png b/plugins/Eq/ActiveHS.png new file mode 100644 index 0000000000000000000000000000000000000000..c4a5546da44e87ae998ef1e3e54e8886bd818bb8 GIT binary patch literal 968 zcmV;(12_DMP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00S^dL_t(Y$Gw)#t6W78#edb^ zcgFY^xKno;bRmKela06$(IgO1aN)wQhaVe3P$ak!UAi;!OniipY;+?;32sFRJP;*8 zUN$2B4a&>R?dmEQ)py>!d~FOiQ{2nko;r1^Pn|n*?72fOBCJOeK?D#%00jEoEtli; z54htF=8oSGMMOCC#KYv0$tjWZUhFR-5{vACx_iH}FKKJG7iKhVT;ARZu#^)eCrT*{ zB~yj~PC0d!0k#gb4mg3CJJtcTHmWv66?aEO0<7drDTUdrFdGWPP$(snb0Vd*0$OKx zGb=C)HmZ%96iKq$vjWRGF_g?~D9q;rvsnP<+yO;MN#GXDaK|iIMe7>1YU~Hx95V~B z)WOP-8HQjtpAEro$dsH(Y47YNW@pY`V(Z)w+-Y6d`XE}`8Y!3&g6QH1zyKS10V|dE zYB#_7p5Lzg!7o35j#-Fe94i2|2D8O-WOsMD$}0jTlyybD&a9PBj8;6_7e`=Gh;sQBI$kq;`Dbs z^w?{>^~UqOvvG7?`IsAS79(JWne{pJo)>UP-e_<{8BL9iSDxj{_9myk zyvWtx|3v#URi$a%+nPm9xz_V1+;PHYR2!`|ni{n>#;T~sb?lNpzx6&JeSD5umD;~w z-?vy+c6XO7mm{hTYu1h0N$%_!X0u2zR>rZi94m{($Z{F6Sd2V)|9u>O@)2Hr^Rs== z{{Cl|etU3nbUO^NLYbw6#4jYle#8 qu2?tDyZQ38b!L~hcm9{Z1^)uu@tV0bw!B{e0000e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00P@dL_t(Y$Gw)la$H3ag}?3@ z=?Ro6vz?ogt4w6PJOJh8?mnb|X^`}CQW>(^fi1Ox#QLLymHMK?{h*AP6EL`UjEkD*{)pTt!t; zmEMaYsuM7b{Vr-kL?4d;;f{yn?zji;&hhbcsvxKeMHMY&>Q$wKN-_o(hzq>vkP$>g zf&^}ci6a;g2tpM}Hl>njiuDhXCp zDWy>BUV_#P>6k~knAyathfJ;Y^+0$Kp&&vP0hJ74snps5J3~da%wS{IM0oP#5B_}m zl*`)Pd+*{Ns5>I`oXJ8QrBrGulpS^~03Scz@b`-seDdjMlj52g0A>wq#?TsPXJ@GP z-xs8-QAl>0PwAkglzt3e5=`3ST15oITmh}?h|Ee2z=hm&)`279@HtRJfCnvKQ%%-vL?4P{R z0|<09(b>x!H}4WQ>rb1<@7%q|Z@>OB&+W_)!@zcXMjM7afTx{-25FpWm}ZS;Mr%fE z1FbcN)_Ok-92^{Q_1ZOl{^>`CVV>V^x3ty)M1&wFBMx_hphhGsv+if3%|zg?sMtBX zx_R?e%#3fo{_0XeynW{mZr0faR5C9nj-(4j1a5w*5g#4h;OOYa#YQ})AyY#HH4;on zhxWe7Ud9#UJ!0-%Fg5Z-;CaJpH_n%OdG_175^#L{{D1jd@DH4{Q@sGgCer`_002ov JPDHLkV1jq=k=g(N literal 0 HcmV?d00001 diff --git a/plugins/Eq/ActiveLP.png b/plugins/Eq/ActiveLP.png new file mode 100644 index 0000000000000000000000000000000000000000..37c2ca869b5ee7b88fff5764627b81481130995a GIT binary patch literal 990 zcmV<410np0P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00TxzL_t(Y$Gw)pYh6VY#(!sK z?u-5dl@e@|m?|}Ctq5XlX{_B=T!}~v>cWC_=_1gD6{;xs7j)5rv_e-3F2t2uQYmB^ zkyxz@vHlP7&CEG2&fNQ6+Egrv!#mvf9&^ukzH`6x&6QVAt(b@~9YF*UKm-90Xy0~S zhS5G?h8d_Cc26V`VdeRQ#1x4k5aT3v7U79SCZJ~4uIxx!t4>0dS}M0Twj3 zh$apPbg-@!FsQUu``poUT)VOcz{QV0=j!D(%*+{y3ro$&xej?nAh^7nNK*9Hr9jtt zTT^TAsEgeB?N3g>{Rx{JmpHt0|lnIYi*+U;g00;w&Nb3Kl?GUN?rco4WdV|NI#a zEzJ*=K4_g-J;HbEn;cl2<)2n^kMS7+P@F3;$?mMS=?evEn zdtr$u7WSg5Z4RyF1q_0rTyL!rBI7<{MaGBU*8-os?Rl@ zKVXL8Hd9Ka)=Di(&XsX4l;YQM_F=s@#%qrp8ZOzcaUQ4>^||dCeg8HdC_uSuX@Nqf{lv`mgP3|NcFE z@zqVvoqdJz*qN7H{gF5`2g{`n#;IzQq7QAv$6q{zs%Z2vVLju;nKoq%aoiU?)}ZN~Xu9-cbQ?AFHC|MFV!H%eTF{OsYHqyPW_ M07*qoM6N<$f+1YbfB*mh literal 0 HcmV?d00001 diff --git a/plugins/Eq/ActiveLPoff.png b/plugins/Eq/ActiveLPoff.png new file mode 100644 index 0000000000000000000000000000000000000000..3b570fadf9195f3772158f05f6f93ff51ddc9914 GIT binary patch literal 896 zcmV-`1AqL9P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00QVqL_t(Y$Gw)pk`zS{hQG|J zet~tC*@*GP>@vd%Z*sxilN!4yuK~ORa0Q=0y{NAM9Mq#=gq-Bc!0t_=-(k8kIb?ND z53qz9h80m$HPv19&;MuUUn5tpeBuZQ0wRbAGJJ%4ao;~|x zV08NG6>ZzHx3|Y)vE=5h+wbJZY&IKMPp20UtAMpqdbR@O_qjpek55jR%|1qJfuGkF z%O$JT3#QWxe5mE2T0H9I)2ml$nn;YC(va34YKMnMeE;3I%;)>;?(W8(>MZ?U2NWDP z->MgP+o~Hgqm(kt$GuC@J0)%v^UX>ml;-!QaVa0(Yw+7eZA|L&-Zz` zT2V@emC;#l)y^P0)i|qRmRkMZr|>yNJ(kwpnM@`Cy#DJoA5A6!TF-Se94EV1R;7fW zZB@UbQvSAG?de zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00TcsL_t(Y$Gw(MYn)XS#((GB zduNjI3%FC4wYX432rd*A6k2ql5Xd40W2lmyAa|GMvG z82tlgm_akc?y4vvti5oK5CcJ#5EgZM2yZO105!Az&8eofwneo@EtT7M4joK`5`z+B zB*j2X4y-{tO9xv9S_T}zni;JFlw8TBBBfwvh=_y55Qs4{8bwAal2RnbKnRMe&ViQM z-OCDEb2g<^vKB;TzGe;EU&k?(JQPD+u~ z2dK4@QkqY@z4HZMA1If%F3{RS7&#YITv*MFoa?-=2&l`uizEg@2z}D#jALN3y27Xf zrxf{W?<0Qt`FH;O>mNqRw?Fn{NGTAa5<(!xfChEjh@b+9x{Fl(Y{uinWHNT41SLdQ zY8+G>l-*A+vA+2kF-HGCxO#_O8hV}TKX_GDfo^KmUV^BivbcGuXP$nNoy%`>{`qaL zfBBuS)5X1R6X|_>Fs#4xlD+!!vphCgVRd!PWHM&5I%Yghq~w+uCOt!poO|xQGsSeU ze}$uePx#@-Ux}VE?h&y0d3h<;8cl$v_kdl!ag%F%xA=^S$TXsLFIboAAlF(OK^sMcV9=x?!RL6Jth5|E48?}OR2QldQcnDj74D9 z*1eJlLC8JVYHf^0ah{DkA716fwevjn#N$k-v%5@PJ7_u8*9_tiGbMYTsmenWWOL&+ zHr8L^_+)lwT+L<}9&V&6c4-Mj@qvHn$aW2eqA(z^jb+A(FypeT* zg#2h8F{KnrtqZVLU3F%K)`Rm=K0Mnpv)gwL|CiT-{{TPGgu@Q-xK;oF002ovPDHLk FV1lDI#VY^+ literal 0 HcmV?d00001 diff --git a/plugins/Eq/ActiveLSoff.png b/plugins/Eq/ActiveLSoff.png new file mode 100644 index 0000000000000000000000000000000000000000..234d03fbeb46466df6dd184e67e770d754a0eaf7 GIT binary patch literal 909 zcmV;819JR{P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00Q+%L_t(Y$Gw)zl2kGDwn4$ofUL=Z3)f z^A}K6RHgQ!h-wFhP5&}#gUCAG0AvJ_K|~OdLezIyP0SG5lg4mddY zaDvys!f}r+P*%1Yfe7`?WFn4IjJtR5Q6}s%lTu0#^5YNR^W@267K_8KxXMZq8IcC$ z9;nv%f}k6Pt7ucCl0Zbwb18*k7}{CZ&nKVWY(_-b z+uI{azI*r(1orp$n=;$^xf9_;1n$n?FJ2&5uDqX@-o3;yyu~og7-j>rVd&thrGuT- z?tl5kneT4hzQbyD%F{oeV!5NJ>Is|OWh5y%sj1zzT>inM<&wqWA&bQ!;m+vJIF78> zYgVfjtJSJ|jX@1Mt(VN`bwflCK4o`&e9WWelFvS`tRjMVX?^#`NFcF|iEh0tSg%LM z(W^+z$cQeWP5b?~U%7efHts%=e&9Y5zKsc&@Vs# z#D$9&na}5p({w@^&0E-`akW;y=JDe^vW*5 z*i4W>+`EEaXT+zcr>{0*A1lL_PBO7e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00WRoL_t(Y$Gw)#YgAVl#((GI z&LsE;xHK*`Ru_d}G*qNT`=KZ(ij^idA*RtT+J!DfP;h5Aia3$PCUjBgrXUteODPhB zfV3zjt4LS=1r0NE&&S)vIdf;?Bs=kPUuL+R^FHtM-sgSJRVR*(ic*T+&`O~cpcD!~ zLH@VtB?$Qj5kw%0Aa8_KN-;XJ3u6sNYmDi}#v)Q;rMjRZl7HEdG=$iV7zsY`Y-Kfp zX```5W38pI23sUxZFFXtzE>|)Cx_e z6$cQbq?U$&PRvMx$l^$V39QHkD5aQN_=Ue;tnqyLZUr`d`8&S<;Wwtg`~(q6j8qa< z6v4SrM$jfu*6voV}KeMo-% z>CY|Q;l;}Rs?sgQSP5b8$jp{`&YnJmMWAu#8wLkzY}+=#;9#A>fg1IC!Ti#%>>Zh5 zcKR4!&z#s2?9Tn4xi|NS>B&!-{Nf1hwxii9X*S!eueWHnN`C+2FRbKQkSx_sl_5l? zCqCw@sn2--;AK7-dynB=Lw#WXtp3Zrxko%-zDw|d(s@FRRj%Ir8WDtKGu{V62m~K- zE^YKau=wCA*KaQ2obQY4Hi zS|vMoZ0Eq}FjKR)X|+n)?eu(V_BIDbhuOJfdwQPtm8HWuzag&(*pAJ3m;9__Gf@N| zBF3cYKY!*h!3Pe0_-)m~@y|cv{F%cvn`NI}m1Sb?T_A)=6v1|m1m{C#oG}XC$37!I zb#jbTC&xAz@qg>B&5hXk)K(udvkc}#sFWsIAjZ9&BgT7=51|VdL&PhEh$m*_e4B@7 i>}B?BW%ZqW7W@x2Gn@Kx2$3xS0000e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00T}*L_t(Y$Gw)zZd6AQhQF$A zd+F6=Vd?_LxQ36UpEWktHnh0L*lC zWzjunj!nEn8L8*=Y4z#v{8iO|ADN#1(h(2@L=X|Axrf@T{WE?J-s(7xJ9zoS>v%-q z{P{^#6;&x$QAD)?!{BBU?znq}IN1!7j9`Ex2vMY}34s^`Ap}B*1TE@RrKPOEM5Kg>p(1c{E~+eNOa(C` zl^KW#kqQf{gb;{vq(Wm2=^&4Cwz5W537J|d^8wF}yMhQ&1XOAWLnOumED9CX(7?Lg zJ@&iZhO@Y|#M0985S9(IJOp`Bt2rY=$(gi@BZNo{fpALQ?%pnczkSQ?J9it{!|g3z zyx3=Dd8MjSL=sX#W*OD8z98tJ!d0|Zq@tlfi@LzO<6~YQ9B^}eqZtb!aC3cw*9Ql@ zJ3elWM>Mq75^c7Qf*{)7V}jHw)SAx+_wRA-`i={OwFx3jOiYwqnUS-RbH>d0 z=ly$RZf@RRzWnn{bNJ@l@6fuz&oq!)g+KlH!>ea8$TbR#ll?RPV~K37wLDil19hr#R>L$)Br{SnQtFdZqSNUx zIW@)h)+YUazX{X!)+UovQ*=5VQc88ckp|GZuIG&7ME9!7toYf9-LI$^BErJ_0%pb^ zzyH>R@T<$0S(sm--|L;QE3-sO1C>_PIYb5%BqL@+kmZkzcxGmnnVH!WM*N}o;lGV| zkcJvg+=+v-6{ +#include +#include EqControlsDialog::EqControlsDialog( EqControls *controls ) : @@ -45,113 +43,223 @@ EqControlsDialog::EqControlsDialog( EqControls *controls ) : m_controls = controls; setAutoFillBackground( true ); QPalette pal; - pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) ); + pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "EqLayout1BG" ) ); setPalette( pal ); - setFixedSize( 350, 275 ); - m_inSpec = new EqSpectrumView( &controls->m_inFftBands, this); - m_inSpec->move( 51, 2 ); + setFixedSize( 500, 500 ); + QGridLayout * mainLayout = new QGridLayout( this ); + + m_inSpec = new EqSpectrumView( &controls->m_inFftBands, this ); + mainLayout->addWidget( m_inSpec, 0, 1, 1, 8 ); m_inSpec->color = QColor( 238, 154, 120, 80 ); - m_outSpec = new EqSpectrumView( &controls->m_outFftBands, this); - m_outSpec->move( 51, 2 ); - m_outSpec->color = QColor(145, 205, 22, 80); + + m_outSpec = new EqSpectrumView( &controls->m_outFftBands, this ); + m_outSpec->color = QColor( 145, 205, 22, 80 ); + mainLayout->addWidget( m_outSpec, 0, 1, 1, 8 ); + m_parameterWidget = new EqParameterWidget( this , controls ); - m_parameterWidget->move( 51, 2 ); - - setBand( 0, &controls->m_hpActiveModel, &controls->m_hpFeqModel, &controls->m_hpResModel, 0, QColor(255 ,255, 255), tr( "HP" ) ,0,0); - setBand( 1, &controls->m_lowShelfActiveModel, &controls->m_lowShelfFreqModel, &controls->m_lowShelfResModel, &controls->m_lowShelfGainModel, QColor(255 ,255, 255), tr( "Low Shelf" ), &controls->m_lowShelfPeakL , &controls->m_lowShelfPeakR ); - setBand( 2, &controls->m_para1ActiveModel, &controls->m_para1FreqModel, &controls->m_para1BwModel, &controls->m_para1GainModel, QColor(255 ,255, 255), tr( "Peak 1" ), &controls->m_para1PeakL, &controls->m_para1PeakR ); - setBand( 3, &controls->m_para2ActiveModel, &controls->m_para2FreqModel, &controls->m_para2BwModel, &controls->m_para2GainModel, QColor(255 ,255, 255), tr( "Peak 2" ), &controls->m_para2PeakL, &controls->m_para2PeakR ); - setBand( 4, &controls->m_para3ActiveModel, &controls->m_para3FreqModel, &controls->m_para3BwModel, &controls->m_para3GainModel, QColor(255 ,255, 255), tr( "Peak 3" ), &controls->m_para3PeakL, &controls->m_para3PeakR ); - setBand( 5, &controls->m_para4ActiveModel, &controls->m_para4FreqModel, &controls->m_para4BwModel, &controls->m_para4GainModel, QColor(255 ,255, 255), tr( "Peak 4" ), &controls->m_para4PeakL, &controls->m_para4PeakR ); - setBand( 6, &controls->m_highShelfActiveModel, &controls->m_highShelfFreqModel, &controls->m_highShelfResModel, &controls->m_highShelfGainModel, QColor(255 ,255, 255), tr( "High Shelf" ), &controls->m_highShelfPeakL, &controls->m_highShelfPeakR ); - setBand( 7, &controls->m_lpActiveModel, &controls->m_lpFreqModel, &controls->m_lpResModel, 0, QColor(255 ,255, 255), tr( "LP" ) ,0,0); - int cw = width()/8; //the chanel width in pixels - int ko = ( cw * 0.5 ) - ((new Knob( knobBright_26, 0 ))->width() * 0.5 ); - - m_inGainFader = new EqFader( &controls->m_inGainModel, tr( "In Gain" ), this, &controls->m_inPeakL, &controls->m_inPeakR); - m_inGainFader->move( 10, 5 ); - m_inGainFader->setDisplayConversion( false ); - m_inGainFader->setHintText( tr( "Gain" ), "dBv"); + mainLayout->addWidget( m_parameterWidget, 0, 1, 1, 8 ); + setBand( 0, &controls->m_hpActiveModel, &controls->m_hpFeqModel, &controls->m_hpResModel, 0, QColor(255 ,255, 255), tr( "HP" ) ,0,0, &controls->m_hp12Model, &controls->m_hp24Model, &controls->m_hp48Model,0,0,0); + setBand( 1, &controls->m_lowShelfActiveModel, &controls->m_lowShelfFreqModel, &controls->m_lowShelfResModel, &controls->m_lowShelfGainModel, QColor(255 ,255, 255), tr( "Low Shelf" ), &controls->m_lowShelfPeakL , &controls->m_lowShelfPeakR,0,0,0,0,0,0 ); + setBand( 2, &controls->m_para1ActiveModel, &controls->m_para1FreqModel, &controls->m_para1BwModel, &controls->m_para1GainModel, QColor(255 ,255, 255), tr( "Peak 1" ), &controls->m_para1PeakL, &controls->m_para1PeakR,0,0,0,0,0,0 ); + setBand( 3, &controls->m_para2ActiveModel, &controls->m_para2FreqModel, &controls->m_para2BwModel, &controls->m_para2GainModel, QColor(255 ,255, 255), tr( "Peak 2" ), &controls->m_para2PeakL, &controls->m_para2PeakR,0,0,0,0,0,0 ); + setBand( 4, &controls->m_para3ActiveModel, &controls->m_para3FreqModel, &controls->m_para3BwModel, &controls->m_para3GainModel, QColor(255 ,255, 255), tr( "Peak 3" ), &controls->m_para3PeakL, &controls->m_para3PeakR,0,0,0,0,0,0 ); + setBand( 5, &controls->m_para4ActiveModel, &controls->m_para4FreqModel, &controls->m_para4BwModel, &controls->m_para4GainModel, QColor(255 ,255, 255), tr( "Peak 4" ), &controls->m_para4PeakL, &controls->m_para4PeakR,0,0,0,0,0,0 ); + setBand( 6, &controls->m_highShelfActiveModel, &controls->m_highShelfFreqModel, &controls->m_highShelfResModel, &controls->m_highShelfGainModel, QColor(255 ,255, 255), tr( "High Shelf" ), &controls->m_highShelfPeakL, &controls->m_highShelfPeakR,0,0,0,0,0,0 ); + setBand( 7, &controls->m_lpActiveModel, &controls->m_lpFreqModel, &controls->m_lpResModel, 0, QColor(255 ,255, 255), tr( "LP" ) ,0,0,0,0,0, &controls->m_lp12Model, &controls->m_lp24Model, &controls->m_lp48Model); + m_inGainFader = new EqFader( &controls->m_inGainModel, tr( "In Gain" ), this, + &controls->m_inPeakL, &controls->m_inPeakR ); - m_outGainFader = new EqFader( &controls->m_outGainModel, tr( "Out Gain" ), this, &controls->m_outPeakL, &controls->m_outPeakR ); - m_outGainFader->move( 315, 5 ); - m_outGainFader->setDisplayConversion( false ); - m_outGainFader->setHintText( tr( "Gain" ), "dBv"); - //gain faders + mainLayout->addWidget( m_inGainFader, 0, 0 ); + m_inGainFader->setDisplayConversion( false ); + m_inGainFader->setHintText( tr( "Gain" ), "dBv"); - int fo = (cw * 0.5) - (m_outGainFader->width() * 0.5 ); + m_outGainFader = new EqFader( &controls->m_outGainModel, tr( "Out Gain" ), this, + &controls->m_outPeakL, &controls->m_outPeakR ); + mainLayout->addWidget( m_outGainFader, 0, 9 ); + m_outGainFader->setDisplayConversion( false ); + m_outGainFader->setHintText( tr( "Gain" ), "dBv" ); - for( int i = 1; i < m_parameterWidget->bandCount() - 1; i++) + // Gain Fader for each Filter exepts the pass filter + for( int i = 1; i < m_parameterWidget->bandCount() - 1; i++ ) { - m_gainFader = new EqFader( m_parameterWidget->getBandModels(i)->gain, tr( "" ), this ,m_parameterWidget->getBandModels( i )->peakL, m_parameterWidget->getBandModels( i )->peakR ); - m_gainFader->move( cw * i + fo , 123 ); + m_gainFader = new EqFader( m_parameterWidget->getBandModels( i )->gain, tr( "" ), this, + m_parameterWidget->getBandModels( i )->peakL, m_parameterWidget->getBandModels( i )->peakR ); + mainLayout->addWidget( m_gainFader, 2, i+1 ); + mainLayout->setAlignment( m_gainFader, Qt::AlignHCenter ); m_gainFader->setMinimumHeight(80); m_gainFader->resize(m_gainFader->width() , 80); m_gainFader->setDisplayConversion( false ); m_gainFader->setHintText( tr( "Gain") , "dB"); } - - for( int i = 0; i < m_parameterWidget->bandCount() ; i++) + + //Control Button and Knobs for each Band + for( int i = 0; i < m_parameterWidget->bandCount() ; i++ ) { m_resKnob = new Knob( knobBright_26, this ); - if(i ==0 || i == 7) - { - m_resKnob->move( cw * i + ko , 190 ); - } else - { - m_resKnob->move( cw * i + ko , 205 ); - } + mainLayout->setRowMinimumHeight( 4, 33 ); + mainLayout->addWidget( m_resKnob, 5, i+1 ); + mainLayout->setAlignment( m_resKnob, Qt::AlignHCenter ); m_resKnob->setVolumeKnob(false); m_resKnob->setModel( m_parameterWidget->getBandModels( i )->res ); if(i > 1 && i < 6) { m_resKnob->setHintText( tr( "Bandwidth: " ) , " Octave" ); } else { m_resKnob->setHintText( tr( "Resonance : " ) , "" ); } m_freqKnob = new Knob( knobBright_26, this ); - if( i == 0 || i == 7 ) - { - m_freqKnob->move( cw * i + ko, 222 ); - } else - { - m_freqKnob->move(cw * i + ko, 235 ); - } + mainLayout->addWidget( m_freqKnob, 3, i+1 ); + mainLayout->setAlignment( m_freqKnob, Qt::AlignHCenter ); m_freqKnob->setVolumeKnob( false ); m_freqKnob->setModel( m_parameterWidget->getBandModels( i )->freq ); m_freqKnob->setHintText( tr( "Frequency:" ), "Hz" ); - m_activeBox = new LedCheckBox( m_parameterWidget->getBandModels( i )->name , this , "" , LedCheckBox::Green ); - m_activeBox->move( cw * i + fo + 3, 260 ); + // adds the Number Active buttons + m_activeBox = new PixmapButton( this, NULL ); + m_activeBox->setCheckable(true); + m_activeBox->setModel( m_parameterWidget->getBandModels( i )->active ); + + QString iconActiveFileName = "bandLabel" + QString::number(i+1) + "on"; + QString iconInactiveFileName = "bandLabel" + QString::number(i+1); + m_activeBox->setActiveGraphic( PLUGIN_NAME::getIconPixmap( iconActiveFileName.toLatin1() ) ); + m_activeBox->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( iconInactiveFileName.toLatin1() ) ); + + mainLayout->addWidget( m_activeBox, 1, i+1 ); + mainLayout->setAlignment( m_activeBox, Qt::AlignHCenter ); + m_activeBox->setModel( m_parameterWidget->getBandModels( i )->active ); + + // adds the symbols active buttons + m_activeBox = new PixmapButton( this, NULL ); + m_activeBox->setCheckable(true); + m_activeBox->setModel( m_parameterWidget->getBandModels( i )->active ); + switch (i) + { + case 0: + m_activeBox->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "ActiveHP" ) ); + m_activeBox->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "ActiveHPoff" ) ); + break; + case 1: + m_activeBox->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "ActiveLS" ) ); + m_activeBox->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "ActiveLSoff" ) ); + break; + case 6: + m_activeBox->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "ActiveHS" ) ); + m_activeBox->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "ActiveHSoff" ) ); + break; + case 7: + m_activeBox->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "ActiveLP" ) ); + m_activeBox->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "ActiveLPoff" ) ); + break; + default: + m_activeBox->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "ActivePeak" ) ); + m_activeBox->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "ActivePeakoff" ) ); + } + + mainLayout->addWidget( m_activeBox, 7, i+1 ); + mainLayout->setAlignment( m_activeBox, Qt::AlignHCenter); m_activeBox->setModel( m_parameterWidget->getBandModels( i )->active ); + + // Connects the knobs, Faders and buttons with the curve graphic + QObject::connect( m_parameterWidget->getBandModels( i )->freq , SIGNAL( dataChanged() ), m_parameterWidget, SLOT ( updateView() ) ); + if ( m_parameterWidget->getBandModels( i )->gain ) QObject::connect( m_parameterWidget->getBandModels( i )->gain, SIGNAL( dataChanged() ), m_parameterWidget, SLOT ( updateView() )); + QObject::connect( m_parameterWidget->getBandModels( i )->res, SIGNAL( dataChanged() ), m_parameterWidget , SLOT ( updateView() ) ); + QObject::connect( m_parameterWidget->getBandModels( i )->active, SIGNAL( dataChanged() ), m_parameterWidget , SLOT ( updateView() ) ); + + m_parameterWidget->changeHandle( i ); } + + // adds the buttons for Spectrum analyser on/off + m_inSpecB = new PixmapButton(this, NULL); + m_inSpecB->setActiveGraphic( PLUGIN_NAME::getIconPixmap( + "ActiveAnalyse" ) ); + m_inSpecB->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( + "ActiveAnalyseoff" ) ); + m_inSpecB->setCheckable(true); + m_inSpecB->setModel( &controls->m_analyseInModel ); + + m_outSpecB = new PixmapButton(this, NULL); + m_outSpecB->setActiveGraphic( PLUGIN_NAME::getIconPixmap( + "ActiveAnalyse" ) ); + m_outSpecB->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( + "ActiveAnalyseoff" ) ); + m_outSpecB->setCheckable(true); + m_outSpecB->setModel( &controls->m_analyseOutModel ); + mainLayout->addWidget( m_inSpecB, 1, 0 ); + mainLayout->addWidget( m_outSpecB, 1, 9 ); + mainLayout->setAlignment( m_inSpecB, Qt::AlignHCenter ); + mainLayout->setAlignment( m_outSpecB, Qt::AlignHCenter ); + //hp filter type + m_hp12Box = new PixmapButton( this , NULL ); + m_hp12Box->setModel( m_parameterWidget->getBandModels( 0 )->hp12 ); + m_hp12Box->setActiveGraphic( PLUGIN_NAME::getIconPixmap( + "12dB" ) ); + m_hp12Box->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( + "12dBoff" ) ); - m_hp12Box = new LedCheckBox( tr( "12dB" ), this , "" , LedCheckBox::Green ); - m_hp12Box->move( cw*0 + ko, 170 ); - m_hp12Box->setModel( &controls->m_hp12Model ); - m_hp24Box = new LedCheckBox( tr( "24dB" ), this , "" , LedCheckBox::Green ); - m_hp24Box->move( cw*0 + ko, 150 ); - m_hp24Box->setModel( &controls->m_hp24Model ); + m_hp24Box = new PixmapButton( this , NULL ); + m_hp24Box->setModel(m_parameterWidget->getBandModels( 0 )->hp24 ); - m_hp48Box = new LedCheckBox( tr( "48dB" ), this , "" , LedCheckBox::Green ); - m_hp48Box->move( cw*0 + ko, 130 ); - m_hp48Box->setModel( &controls->m_hp48Model ); + + m_hp24Box->setActiveGraphic( PLUGIN_NAME::getIconPixmap( + "24dB" ) ); + m_hp24Box->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( + "24dBoff" ) ); + + m_hp48Box = new PixmapButton( this , NULL ); + m_hp48Box->setModel( m_parameterWidget->getBandModels(0)->hp48 ); + + m_hp48Box->setActiveGraphic( PLUGIN_NAME::getIconPixmap( + "48dB" ) ); + m_hp48Box->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( + "48dBoff" ) ); //LP filter type + m_lp12Box = new PixmapButton( this , NULL ); + mainLayout->addWidget( m_lp12Box, 2,1 ); + m_lp12Box->setModel( m_parameterWidget->getBandModels( 7 )->lp12 ); + m_lp12Box->setActiveGraphic( PLUGIN_NAME::getIconPixmap( + "12dB" ) ); + m_lp12Box->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( + "12dBoff" ) ); + + m_lp24Box = new PixmapButton( this , NULL ); + m_lp24Box->setModel( m_parameterWidget->getBandModels( 7 )->lp24 ); + m_lp24Box->setActiveGraphic( PLUGIN_NAME::getIconPixmap( + "24dB" ) ); + m_lp24Box->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( + "24dBoff" ) ); + + m_lp48Box = new PixmapButton( this , NULL ); + m_lp48Box->setModel( m_parameterWidget->getBandModels( 7 )->lp48 ); + m_lp48Box->setActiveGraphic( PLUGIN_NAME::getIconPixmap( + "48dB" ) ); + m_lp48Box->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( + "48dBoff" ) ); + // the curve has to change its appearance + QObject::connect( m_parameterWidget->getBandModels( 0 )->hp12 , SIGNAL ( dataChanged() ), m_parameterWidget, SLOT( updateView())); + QObject::connect( m_parameterWidget->getBandModels( 0 )->hp24 , SIGNAL ( dataChanged() ), m_parameterWidget, SLOT( updateView())); + QObject::connect( m_parameterWidget->getBandModels( 0 )->hp48 , SIGNAL ( dataChanged() ), m_parameterWidget, SLOT( updateView())); + + QObject::connect( m_parameterWidget->getBandModels( 7 )->lp12 , SIGNAL ( dataChanged() ), m_parameterWidget, SLOT( updateView())); + QObject::connect( m_parameterWidget->getBandModels( 7 )->lp24 , SIGNAL ( dataChanged() ), m_parameterWidget, SLOT( updateView())); + QObject::connect( m_parameterWidget->getBandModels( 7 )->lp48 , SIGNAL ( dataChanged() ), m_parameterWidget, SLOT( updateView())); - m_lp12Box = new LedCheckBox( tr( "12dB"), this , "" , LedCheckBox::Green ); - m_lp12Box->move( cw*7 + ko -5 , 170 ); - m_lp12Box->setModel( &controls->m_lp12Model ); - m_lp24Box = new LedCheckBox( tr( "24dB"), this , "" , LedCheckBox::Green ); - m_lp24Box->move( cw*7 + ko - 5, 150 ); - m_lp24Box->setModel( &controls->m_lp24Model ); - m_lp48Box = new LedCheckBox( tr( "48dB"), this , "" , LedCheckBox::Green ); - m_lp48Box->move( cw*7 + ko - 5, 130 ); - m_lp48Box->setModel( &controls->m_lp48Model ); + QVBoxLayout * hpGrpBtnLayout = new QVBoxLayout; + hpGrpBtnLayout->addWidget( m_hp12Box ); + hpGrpBtnLayout->addWidget( m_hp24Box ); + hpGrpBtnLayout->addWidget( m_hp48Box ); + + QVBoxLayout * lpGrpBtnLayout = new QVBoxLayout; + lpGrpBtnLayout->addWidget( m_lp12Box ); + lpGrpBtnLayout->addWidget( m_lp24Box ); + lpGrpBtnLayout->addWidget( m_lp48Box ); + + mainLayout->addLayout( hpGrpBtnLayout, 2, 1, Qt::AlignCenter ); + mainLayout->addLayout( lpGrpBtnLayout, 2, 8, Qt::AlignCenter ); automatableButtonGroup *lpBtnGrp = new automatableButtonGroup(this,tr ( "lp grp" ) ); - lpBtnGrp->addButton( m_lp12Box); + lpBtnGrp->addButton( m_lp12Box ); lpBtnGrp->addButton( m_lp24Box ); lpBtnGrp->addButton( m_lp48Box ); lpBtnGrp->setModel( &m_controls->m_lpTypeModel, false); @@ -162,11 +270,46 @@ EqControlsDialog::EqControlsDialog( EqControls *controls ) : hpBtnGrp->addButton( m_hp48Box ); hpBtnGrp->setModel( &m_controls->m_hpTypeModel,false); + mainLayout->setAlignment( Qt::AlignTop ); + for (int i = 0 ; i < 10; i++) + { + mainLayout->setColumnMinimumWidth(i, 50); + } + + mainLayout->setAlignment( m_inGainFader, Qt::AlignHCenter ); + mainLayout->setAlignment( m_outGainFader, Qt::AlignHCenter ); + mainLayout->setRowMinimumHeight( 0,200 ); + mainLayout->setRowMinimumHeight( 1, 40 ); + mainLayout->setRowMinimumHeight(6,15); + mainLayout->setContentsMargins( 0, 11, 0, 0 ); + mainLayout->setAlignment(m_inSpec, Qt::AlignCenter ); + mainLayout->setAlignment(m_outSpec, Qt::AlignCenter ); + + m_freqLabel = new QLabel(this); + m_freqLabel->setText("- " + tr( "Frequency")+ " -" ); + m_freqLabel->move( 217 , 377 ); + + m_resLabel1 = new QLabel(this); + m_resLabel1->setText("- " + tr( "Resonance")+ " -" ); + m_resLabel1->move( 62 , 444 ); + + m_resLabel2 = new QLabel(this); + m_resLabel2->setText("- " + tr( "Resonance")+ " -" ); + m_resLabel2->move( 365 , 444 ); + + m_bandWidthLabel = new QLabel(this); + m_bandWidthLabel->setText("- " + tr( "Bandwidth")+ " -" ); + m_bandWidthLabel->move( 215 , 444 ); + + setLayout(mainLayout); } + + + void EqControlsDialog::mouseDoubleClickEvent(QMouseEvent *event) { - m_originalHeight = parentWidget()->height() == 150 ? m_originalHeight : parentWidget()->height() ; - parentWidget()->setFixedHeight( parentWidget()->height() == m_originalHeight ? 150 : m_originalHeight ); + m_originalHeight = parentWidget()->height() == 283 ? m_originalHeight : parentWidget()->height() ; + parentWidget()->setFixedHeight( parentWidget()->height() == m_originalHeight ? 283 : m_originalHeight ); update(); } diff --git a/plugins/Eq/EqControlsDialog.h b/plugins/Eq/EqControlsDialog.h index f0bf4a993bd..09984fe4d61 100644 --- a/plugins/Eq/EqControlsDialog.h +++ b/plugins/Eq/EqControlsDialog.h @@ -31,8 +31,11 @@ #include "LedCheckbox.h" #include "EqParameterWidget.h" #include "MainWindow.h" -#include "qpushbutton.h" #include "EqSpectrumView.h" +#include "PixmapButton.h" +#include +#include + class EqControls; @@ -50,27 +53,33 @@ class EqControlsDialog : public EffectControlDialog private: EqControls * m_controls; - Fader* m_inGainFader; Fader* m_outGainFader; Fader* m_gainFader; Knob* m_resKnob; Knob* m_freqKnob; - LedCheckBox* m_activeBox; - LedCheckBox* m_lp12Box; - LedCheckBox* m_lp24Box; - LedCheckBox* m_lp48Box; - LedCheckBox* m_hp12Box; - LedCheckBox* m_hp24Box; - LedCheckBox* m_hp48Box; + PixmapButton* m_inSpecB; + PixmapButton* m_outSpecB; + PixmapButton* m_activeBox; + PixmapButton* m_lp12Box; + PixmapButton* m_lp24Box; + PixmapButton* m_lp48Box; + PixmapButton* m_hp12Box; + PixmapButton* m_hp24Box; + PixmapButton* m_hp48Box; LedCheckBox* m_analyzeBox; EqParameterWidget* m_parameterWidget; EqSpectrumView* m_inSpec; EqSpectrumView* m_outSpec; + QLabel* m_freqLabel; + QLabel* m_resLabel1; + QLabel* m_resLabel2; + QLabel* m_bandWidthLabel; + virtual void mouseDoubleClickEvent(QMouseEvent *event); - EqBand* setBand( int index, BoolModel* active, FloatModel* freq, FloatModel* res, FloatModel* gain, QColor color, QString name, float* peakL, float* peakR) + EqBand* setBand( int index, BoolModel* active, FloatModel* freq, FloatModel* res, FloatModel* gain, QColor color, QString name, float* peakL, float* peakR, BoolModel *hp12, BoolModel *hp24, BoolModel *hp48, BoolModel *lp12, BoolModel *lp24, BoolModel *lp48 ) { EqBand* filterModels = m_parameterWidget->getBandModels( index ); filterModels->active = active; @@ -80,10 +89,17 @@ class EqControlsDialog : public EffectControlDialog filterModels->gain = gain; filterModels->peakL = peakL; filterModels->peakR = peakR; + filterModels->hp12 = hp12; + filterModels->hp24 = hp24; + filterModels->hp48 = hp48; + filterModels->lp12 = lp12; + filterModels->lp24 = lp24; + filterModels->lp48 = lp48; return filterModels; } int m_originalHeight; + }; diff --git a/plugins/Eq/EqCurve.cpp b/plugins/Eq/EqCurve.cpp new file mode 100644 index 00000000000..54d9b82e7ca --- /dev/null +++ b/plugins/Eq/EqCurve.cpp @@ -0,0 +1,818 @@ +/* + * EqCurve.cpp - declaration of EqCurve and EqHandle classes. + * + * Copyright (c) 2015 Steffen Baranowsky + * + * This file is part of LMMS - http://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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. + * + */ + +#include "EqCurve.h" +#include "lmms_math.h" +#include "Effect.h" +#include "embed.h" + +EqHandle::EqHandle( int num, int x, int y ) +{ + PI = LD_PI; + m_numb = num; + setMouseHover( false ); + m_width = x; + m_heigth = y; + m_mousePressed = false; + m_active = false; + setFlag( ItemIsMovable ); + setFlag( ItemSendsGeometryChanges ); + setAcceptHoverEvents( true ); + float totalHeight = 36; + m_pixelsPerUnitHeight = ( m_heigth ) / ( totalHeight ); + m_handleMoved = false; + QObject::connect( this,SIGNAL( positionChanged() ) , this, SLOT( handleMoved() ) ); +} + + + + +QRectF EqHandle::boundingRect() const +{ + return QRectF( -11, -11, 23, 23 ); +} + + + + +void EqHandle::handleMoved() +{ + m_handleMoved = true; +} + + + + +void EqHandle::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget ) +{ + painter->setRenderHint( QPainter::Antialiasing, true) ; + if ( m_mousePressed ) + { + emit positionChanged(); + + } + + // graphics for the handles + QString fileName = "handle" + QString::number(m_numb+1); + if ( !isActiveHandle() ) { fileName = fileName + "inactive"; } + QPixmap circlePixmap = PLUGIN_NAME::getIconPixmap( fileName.toLatin1() ); + painter->drawPixmap( -12, -12, circlePixmap ); + + // on mouse hover draw an info box and change the pixmap of the handle + if ( isMouseHover() ) + { + // keeps the info box in view + float rectX = -40; + float rectY = -40; + if ( EqHandle::y() < 40 ) + { + rectY = rectY + 40 - EqHandle::y(); + } + if ( EqHandle::x() < 40 ) + { + rectX = rectX + 40 - EqHandle::x(); + } + if ( EqHandle::x() > m_width - 40 ) + { + rectX = rectX - (40 - (m_width - EqHandle::x() ) ); + } + + painter->drawPixmap( -12, -12, PLUGIN_NAME::getIconPixmap( "handlehover" ) ); + QRectF textRect = QRectF ( rectX, rectY, 80, 30 ); + QRectF textRect2 = QRectF ( rectX+1, rectY+1, 80, 30 ); + QString freq = QString::number( xPixelToFreq(EqHandle::x() )) ; + QString res; + if ( getType() < 3 || getType() > 3 ) + { + res = tr( "Reso: ") + QString::number( getResonance() ); + } + else + { + res = tr( "BW: " ) + QString::number( getResonance() ); + } + + painter->setPen( QColor( 255, 255, 255 ) ); + painter->drawRect( textRect ); + painter->fillRect( textRect, QBrush( QColor( 128, 128, 255 , 64 ) ) ); + + painter->setPen ( QColor( 0, 0, 0 ) ); + painter->drawText( textRect2, Qt::AlignCenter, + QString( tr( "Freq: " ) + freq + "\n" + res ) ); + painter->setPen( QColor( 255, 255, 255 ) ); + painter->drawText( textRect, Qt::AlignCenter, + QString( tr( "Freq: " ) + freq + "\n" + res ) ); + } +} + + + + +QPainterPath EqHandle::getCurvePath() +{ + QPainterPath path; + float y = m_heigth*0.5; + for ( float x=0 ; x < m_width; x++ ) + { + if ( m_type == 1 ) y = getLowCutCurve( x ); + if ( m_type == 2 ) y = getLowShelfCurve( x ); + if ( m_type == 3 ) y = getPeakCurve( x ); + if ( m_type == 4 ) y = getHighShelfCurve( x ); + if ( m_type == 5 ) y = getHighCutCurve( x ); + if ( x==0 ) path.moveTo( x, y ); // sets the begin of Path + path.lineTo( x, y ); + } + return path; +} + + + + + +float EqHandle::getPeakCurve(float x) +{ + double freqZ = xPixelToFreq( EqHandle::x() ); + const int SR = Engine::mixer()->processingSampleRate(); + double w0 = 2* PI * freqZ / SR ; + double c = cosf( w0 ); + double s = sinf( w0 ); + double Q = getResonance(); + double A = pow( 10, yPixelToGain(EqHandle::y()) / 40 ); + double alpha = s * sinh( log( 2 ) / 2 * Q * w0 / sinf( w0 ) ); + double a0, a1, a2, b0, b1, b2; // coeffs to calculate + + //calc coefficents + b0 = 1 + alpha*A; + b1 = -2*c; + b2 = 1 - alpha*A; + a0 = 1 + alpha/A; + a1 = -2*c; + a2 = 1 - alpha/A; + + //normalise + b0 /= a0; + b1 /= a0; + b2 /= a0; + a1 /= a0; + a2 /= a0; + a0 = 1; + + double w; + double PHI; + double gain; + double freq = xPixelToFreq( x ); + w = 2*PI * freq / SR; + PHI = pow( sin( w/2 ), 2 )*4; + gain = 10* log10( pow( b0 + b1 + b2 , 2 ) + + ( b0 * b2 * PHI - ( b1*(b0+b2 )+ 4*b0*b2 ) ) *PHI ) + - 10*log10( pow( 1+ a1+ a2 ,2 ) + ( 1* a2 * PHI - ( a1 * ( 1+ a2 ) +4 *1 * a2 ) ) *PHI ); + float y= gainToYPixel( gain ); + return y; +} + + + + +float EqHandle::getHighShelfCurve( float x ) +{ + double freqZ = xPixelToFreq( EqHandle::x() ); + const int SR = Engine::mixer()->processingSampleRate(); + double w0 = 2 * PI * freqZ / SR; + double c = cosf( w0 ); + double s = sinf( w0 ); + double A = pow( 10, yPixelToGain( EqHandle::y() ) * 0.025 ); + double beta = sqrt( A ) / m_resonance; + double a0, a1, a2, b0, b1, b2; // coeffs to calculate + + //calc coefficents + b0 = A *( ( A +1 ) + ( A - 1 ) * c + beta * s); + b1 = -2 * A * ( ( A - 1 ) + ( A + 1 ) * c ); + b2 = A * ( ( A + 1 ) + ( A - 1 ) * c - beta * s); + a0 = ( A + 1 ) - ( A - 1 ) * c + beta * s; + a1 = 2 * ( ( A - 1 ) - ( A + 1 ) * c ); + a2 = ( A + 1) - ( A - 1 ) * c - beta * s; + //normalise + b0 /= a0; + b1 /= a0; + b2 /= a0; + a1 /= a0; + a2 /= a0; + a0 = 1; + + double w; + double PHI; + double gain; + double freq = xPixelToFreq( x ); + w = 2* PI * freq / SR ; + PHI = pow(sin( w/2 ), 2 ) * 4; + gain = 10* log10( pow( b0 + b1 + b2 , 2 ) + + ( b0 * b2 * PHI - ( b1*( b0+b2 )+ 4*b0*b2 ) ) *PHI ) + - 10*log10( pow(1+ a1+ a2 ,2 ) + ( 1* a2 * PHI - ( a1 * ( 1 + a2 ) + 4 * 1 * a2) ) *PHI ); + float y= gainToYPixel( gain ); + return y; +} + + + + +float EqHandle::getLowShelfCurve( float x ) +{ + double freqZ = xPixelToFreq( EqHandle::x() ); + const int SR = Engine::mixer()->processingSampleRate(); + double w0 = 2 * PI * freqZ / SR ; + double c = cosf( w0 ); + double s = sinf( w0 ); + double A = pow( 10, yPixelToGain( EqHandle::y() ) / 40 ); + double beta = sqrt( A ) / m_resonance; + double a0, a1, a2, b0, b1, b2; // coeffs to calculate + + //calc coefficents + b0 = A * ( ( A+1 ) - ( A-1 ) * c + beta * s ); + b1 = 2 * A * ( ( A - 1 ) - ( A + 1 ) * c) ; + b2 = A * ( ( A + 1 ) - ( A - 1 ) * c - beta * s); + a0 = ( A + 1 ) + ( A - 1 ) * c + beta * s; + a1 = -2 * ( ( A - 1 ) + ( A + 1 ) * c ); + a2 = ( A + 1 ) + ( A - 1) * c - beta * s; + + //normalise + b0 /= a0; + b1 /= a0; + b2 /= a0; + a1 /= a0; + a2 /= a0; + a0 = 1; + + double w; + double PHI; + double gain; + double freq = xPixelToFreq( x ); + w = 2* PI * freq / SR ; + PHI = pow( sin( w/2 ), 2 ) * 4; + gain = 10 * log10( pow( b0 + b1 + b2 , 2 ) + + ( b0 * b2 * PHI - ( b1 * ( b0+b2 ) + 4 * b0 * b2 ) ) *PHI ) + - 10 * log10( pow( 1 + a1 + a2, 2 ) + ( 1 * a2 * PHI - ( a1 * ( 1 + a2 ) + 4 * 1 * a2 ) ) * PHI ); + float y= gainToYPixel( gain ); + return y; +} + + + + +float EqHandle::getLowCutCurve( float x ) +{ + double freqZ = xPixelToFreq( EqHandle::x() ); + const int SR = Engine::mixer()->processingSampleRate(); + double w0 = 2 * PI * freqZ / SR ; + double c = cosf( w0 ); + double s = sinf( w0 ); + double resonance = getResonance(); + double A = pow( 10, yPixelToGain( EqHandle::y() ) / 20); + double alpha = s / 2 * sqrt ( ( A +1/A ) * ( 1 / resonance -1 ) +2 ); + double a0, a1, a2, b0, b1, b2; // coeffs to calculate + + b0 = ( 1 + c ) * 0.5; + b1 = ( -( 1 + c ) ); + b2 = ( 1 + c ) * 0.5; + a0 = 1 + alpha; + a1 = ( -2 * c ); + a2 = 1 - alpha; + //normalise + b0 /= a0; + b1 /= a0; + b2 /= a0; + a1 /= a0; + a2 /= a0; + a0 = 1; + + double w; + double PHI; + double gain; + double freq = xPixelToFreq( x ); + w = 2 * PI * freq / SR ; + PHI = pow( sin( w/2), 2 ) * 4; + gain = 10 * log10( pow( b0 + b1 + b2 , 2 ) + + ( b0 * b2 * PHI - ( b1 * ( b0 + b2 ) + 4 * b0 * b2 ) ) * PHI ) + - 10 * log10( pow( 1 + a1 + a2, 2 ) + ( 1 * a2 * PHI - ( a1 * ( 1 + a2 ) + 4 * 1 * a2 ) ) * PHI ); + + if ( m_hp24 ) + { + gain = gain + 10 * log10( pow( b0 + b1 + b2 , 2 ) + + ( b0 * b2 * PHI - ( b1 * ( b0 + b2 ) + 4 * b0 * b2 ) ) * PHI ) + - 10 * log10( pow( 1 + a1 + a2, 2 ) + ( 1 * a2 * PHI - ( a1 * ( 1 + a2 ) + 4 * 1 * a2 ) ) * PHI ); + + } + + if ( m_hp48 ) + { + gain = gain + 10 * log10( pow( b0 + b1 + b2 , 2 ) + + ( b0 * b2 * PHI - ( b1 * ( b0 + b2 ) + 4 * b0 * b2 ) ) * PHI ) + - 10 * log10( pow( 1 + a1 + a2, 2 ) + ( 1 * a2 * PHI - ( a1 * ( 1 + a2 ) + 4 * 1 * a2 ) ) * PHI ); + + gain = gain + ( 10 * log10( pow( b0 + b1 + b2 , 2 ) + + ( b0 * b2 * PHI - ( b1 * ( b0 + b2 ) + 4 * b0 * b2 ) ) * PHI ) + - 10 * log10( pow( 1 + a1 + a2, 2 ) + ( 1 * a2 * PHI - ( a1 * ( 1 + a2 ) + 4 * 1 * a2 ) ) * PHI )); + + } + + float y= gainToYPixel( gain ); + return y; +} + + + + +float EqHandle::getHighCutCurve( float x ) +{ + double freqZ = xPixelToFreq( EqHandle::x() ); + const int SR = Engine::mixer()->processingSampleRate(); + double w0 = 2 * PI * freqZ / SR ; + double c = cosf( w0 ); + double s = sinf( w0 ); + double resonance = getResonance(); + double A = pow( 10, yPixelToGain(EqHandle::y() ) / 20 ); + double alpha = s / 2 * sqrt ( ( A + 1 / A ) * ( 1 / resonance -1 ) +2 ); + double a0, a1, a2, b0, b1, b2; // coeffs to calculate + + + b0 = ( 1 - c ) * 0.5; + b1 = 1 - c; + b2 = ( 1 - c ) * 0.5; + a0 = 1 + alpha; + a1 = -2 * c; + a2 = 1 - alpha; + + //normalise + b0 /= a0; + b1 /= a0; + b2 /= a0; + a1 /= a0; + a2 /= a0; + a0 = 1; + + double w; + double PHI; + double gain; + double freq = xPixelToFreq( x ); + w = 2 * PI * freq / SR ; + PHI = pow(sin( w/2),2 )*4; + + gain = 10 * log10( pow( b0 + b1 + b2 , 2 ) + + ( b0 * b2 * PHI - ( b1 * ( b0 + b2 ) + 4 * b0 * b2 ) ) * PHI ) + - 10 * log10( pow( 1 + a1 + a2, 2 ) + ( 1 * a2 * PHI - ( a1 * ( 1 + a2 ) + 4 * 1 * a2 ) ) * PHI ); + + if ( m_lp24 ) + { + gain = gain + ( 10 * log10( pow( b0 + b1 + b2 , 2 ) + + ( b0 * b2 * PHI - ( b1 * ( b0 + b2 ) + 4 * b0 * b2 ) ) * PHI ) + - 10 * log10( pow( 1 + a1 + a2, 2 ) + ( 1 * a2 * PHI - ( a1 * ( 1 + a2 ) + 4 * 1 * a2 ) ) * PHI ) ); + + } + + if ( m_lp48 ) + { + gain = gain + ( 10 * log10( pow( b0 + b1 + b2 , 2 ) + + ( b0 * b2 * PHI - ( b1 * ( b0 + b2 ) + 4 * b0 * b2 ) ) * PHI ) + - 10 * log10( pow( 1 + a1 + a2, 2 ) + ( 1 * a2 * PHI - ( a1 * ( 1 + a2 ) + 4 * 1 * a2 ) ) * PHI ) ); + + gain = gain + ( 10 * log10( pow( b0 + b1 + b2 , 2 ) + + ( b0 * b2 * PHI - ( b1 * ( b0 + b2 ) + 4 * b0 * b2 ) ) * PHI ) + - 10 * log10( pow( 1 + a1 + a2, 2 ) + ( 1 * a2 * PHI - ( a1 * ( 1 + a2 ) + 4 * 1 * a2 ) ) * PHI ) ); + } + + + float y= gainToYPixel( gain ); + return y; +} + + + + + +float EqHandle::getResonance() +{ + return m_resonance; +} + + + + +int EqHandle::getNum() +{ + return m_numb; +} + + + + +void EqHandle::setType(int t) +{ + EqHandle::m_type = t; +} + + + + +void EqHandle::setResonance(float r) +{ + EqHandle::m_resonance = r; +} + + + + +bool EqHandle::isMouseHover() +{ + return m_mouseHover; +} + + + + +void EqHandle::setMouseHover(bool d) +{ + m_mouseHover = d; +} + + + + +int EqHandle::getType() +{ + return m_type; +} + + + + +bool EqHandle::isActiveHandle() +{ + return m_active; +} + + + + +void EqHandle::setHandleActive( bool a ) +{ + EqHandle::m_active = a; +} + + + + +void EqHandle::setHandleMoved( bool a ) +{ + m_handleMoved = a; +} + + + + +bool EqHandle::getHandleMoved() +{ + return m_handleMoved; +} + + + + +void EqHandle::sethp12() +{ + m_hp12 = true; + m_hp24 = false; + m_hp48 = false; +} + + + + +void EqHandle::sethp24() +{ + m_hp12 = false; + m_hp24 = true; + m_hp48 = false; +} + + + + +void EqHandle::sethp48() +{ + m_hp12 = false; + m_hp24 = false; + m_hp48 = true; +} + + + + +void EqHandle::setlp12() +{ + m_lp12 = true; + m_lp24 = false; + m_lp48 = false; +} + + + + +void EqHandle::setlp24() +{ + m_lp12 = false; + m_lp24 = true; + m_lp48 = false; +} + + + + +void EqHandle::setlp48() +{ + m_lp12 = false; + m_lp24 = false; + m_lp48 = true; +} + + + + +void EqHandle::mousePressEvent( QGraphicsSceneMouseEvent *event ) +{ + m_mousePressed = true; + QGraphicsItem::mousePressEvent( event ); +} + + + + +void EqHandle::mouseReleaseEvent( QGraphicsSceneMouseEvent *event ) +{ + m_mousePressed = false; + QGraphicsItem::mouseReleaseEvent( event ); +} + + + + +void EqHandle::wheelEvent( QGraphicsSceneWheelEvent *wevent ) +{ + float highestBandwich; + if ( m_type < 3 || m_type > 3 ) + { + highestBandwich = 10; + } + else + { + highestBandwich = 4; + } + + int numDegrees = wevent->delta() / 120; + float numSteps = 0; + if ( wevent->modifiers() == Qt::ControlModifier ) + { + numSteps = numDegrees * 0.01; + } + else + { + numSteps = numDegrees * 0.15; + } + + if ( wevent->orientation() == Qt::Vertical ) + { + m_resonance = m_resonance + ( numSteps ); + + if ( m_resonance < 0.1 ) + { + m_resonance = 0.1; + } + + if ( m_resonance > highestBandwich ) + { + m_resonance = highestBandwich; + } + emit positionChanged(); + } + wevent->accept(); +} + + + + +void EqHandle::hoverEnterEvent( QGraphicsSceneHoverEvent *hevent ) +{ + setMouseHover( true ); +} + + + + +void EqHandle::hoverLeaveEvent( QGraphicsSceneHoverEvent *hevent ) +{ + setMouseHover( false ); +} + + + + +QVariant EqHandle::itemChange( QGraphicsItem::GraphicsItemChange change, const QVariant &value ) +{ + if ( change == ItemPositionChange ) + { + // pass filter don't move in y direction + if ( EqHandle::m_type == 1 || EqHandle::m_type == 5 ) + { + float newX = value.toPointF().x(); + if ( newX < 0 ) + { + newX = 0; + } + if ( newX > m_width ) + { + newX = m_width; + } + return QPointF(newX, m_heigth/2); + } + } + + QPointF newPos = value.toPointF(); + QRectF rect = QRectF( 0, 0, m_width, m_heigth ); + if ( !rect.contains( newPos ) ) + { + // Keep the item inside the scene rect. + newPos.setX( qMin( rect.right(), qMax( newPos.x(), rect.left() ) ) ); + newPos.setY( qMin( rect.bottom(), qMax( newPos.y(), rect.top() ) ) ); + return newPos; + } + return QGraphicsItem::itemChange( change, value ); +} + + + + +// ---------------------------------------------------------------------- +// +// Class EqCurve +// +// Every Handle calculates its own curve. +// But EqCurve generates an average curve. +// +// ---------------------------------------------------------------------- + +EqCurve::EqCurve( QList *handle, int x, int y ) +{ + m_width = x; + m_heigth = y; + m_handle = handle; + m_alpha = 0; +} + + + + +QRectF EqCurve::boundingRect() const +{ + return QRect( 0, 0, m_width, m_heigth ); +} + + + + +void EqCurve::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget ) +{ + painter->setRenderHint( QPainter::Antialiasing, true ); + + //Computes the main curve + //if a band is active the curve will be computed by averaging the curves of each band + QMap mainCurve; + for ( int x = 0; x < m_width ; x++ ) + { + mainCurve[x] = 0; + } + int activeHandles=0; + for ( int thatHandle = 0; thatHandlecount(); thatHandle++ ) + { + if ( m_handle->at(thatHandle)->isActiveHandle() == true ) + { + activeHandles++; + } + } + for ( int thatHandle = 0; thatHandlecount(); thatHandle++ ) + { + if ( m_handle->at(thatHandle)->isActiveHandle() == true ) + { + for ( int x = 0; x < m_width ; x=x+1 ) + { + if ( m_handle->at( thatHandle )->getType() == 1 ) + { + mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getLowCutCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) ); + } + if ( m_handle->at(thatHandle)->getType() == 2 ) + { + mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getLowShelfCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) ); + } + if ( m_handle->at( thatHandle )->getType() == 3 ) + { + mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getPeakCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) ); + } + if ( m_handle->at( thatHandle )->getType() == 4 ) + { + mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getHighShelfCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) ); + } + if ( m_handle->at(thatHandle)->getType() == 5 ) + { + mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getHighCutCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) ); + } + } + } + } + + QPainterPath mCurve; + //compute a QPainterPath + for ( int x = 0; x < m_width ; x++ ) + { + mainCurve[x] = ( ( mainCurve[x] / activeHandles ) ) - ( m_heigth/2 ); + if ( x==0 ) + { + mCurve.moveTo( x, mainCurve[x] ); + } + mCurve.lineTo( x, mainCurve[x] ); + } + //and paint it with Pathstroker + QPainterPathStroker stroke; + QPainterPath strokeP; + stroke.setWidth( 2 ); + strokeP = stroke.createStroke( mCurve ); + painter->fillPath( strokeP, QBrush( Qt::white ) ); + + // if mouse hover a handle, m_alpha counts up slow for blend in the filled EQ curve + // todo: a smarter way of this "if-monster" + QColor curveColor; + if ( m_handle->at( 0 )->isMouseHover() + || m_handle->at( 1 )->isMouseHover() + || m_handle->at( 2 )->isMouseHover() + || m_handle->at( 3 )->isMouseHover() + || m_handle->at( 4 )->isMouseHover() + || m_handle->at( 5 )->isMouseHover() + || m_handle->at( 6 )->isMouseHover() + || m_handle->at( 7 )->isMouseHover() + ) + { + if ( m_alpha < 40 ) + m_alpha = m_alpha + 10; + } + else + { + if ( m_alpha > 0 ) + m_alpha = m_alpha - 10; + } + + //draw on mouse hover the curve of hovered filter + for ( int i = 0; i < m_handle->count(); i++ ) + { + if ( m_handle->at(i)->isMouseHover() ) + { + switch ( i+1 ) + { + case 1: curveColor = QColor( 163, 23, 23, 10*m_alpha/4 );break; + case 2: curveColor = QColor( 229,108,0, 10*m_alpha/4 );break; + case 3: curveColor = QColor( 255,240,0, 10*m_alpha/4 );break; + case 4: curveColor = QColor( 12, 255, 0, 10*m_alpha/4 );break; + case 5: curveColor = QColor( 0, 252, 255, 10*m_alpha/4 );break; + case 6: curveColor = QColor( 59, 96, 235, 10*m_alpha/4 );break; + case 7: curveColor = QColor( 112, 73, 255, 10*m_alpha/4 );break; + case 8: curveColor = QColor( 255, 71, 227, 10*m_alpha/4 ); + } + QPen pen ( curveColor); + pen.setWidth( 2 ); + painter->setPen( pen ); + painter->drawPath( m_handle->at( i )->getCurvePath() ); + } + } + // draw on mouse hover the EQ curve filled. with m_alpha it blends in and out smooth + QPainterPath cPath; + cPath.addPath( mCurve ); + cPath.lineTo( cPath.currentPosition().x(), m_heigth ); + cPath.lineTo( cPath.elementAt( 0 ).x , m_heigth ); + painter->fillPath( cPath, QBrush ( QColor( 255,255,255, m_alpha ) ) ); + +} diff --git a/plugins/Eq/EqCurve.h b/plugins/Eq/EqCurve.h new file mode 100644 index 00000000000..65d9aa81eec --- /dev/null +++ b/plugins/Eq/EqCurve.h @@ -0,0 +1,209 @@ +/* + * EqCurve.h - defination of EqCurve and EqHandle classes. + * +* Copyright (c) 2015 Steffen Baranowsky + * + * This file is part of LMMS - http://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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 EQCURVE_H +#define EQCURVE_H + +#include +#include +#include +#include "lmms_math.h" + + +enum{ + highpass=1, + lowshelf, + para, + highshelf, + lowpass +}; + + + + + +// implements the Eq_Handle to control a band +class EqHandle : public QGraphicsObject +{ + Q_OBJECT +public: + EqHandle( int num, int x, int y ); + void paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget ); + QPainterPath getCurvePath(); + float getPeakCurve( float x ); + float getHighShelfCurve( float x ); + float getLowShelfCurve( float x ); + float getLowCutCurve( float x ); + float getHighCutCurve( float x ); + float getResonance(); + int getNum(); + int getType(); + void setType( int t ); + void setResonance( float r ); + bool isMouseHover(); + void setMouseHover( bool d ); + bool isActiveHandle(); + void setHandleActive( bool a ); + void setHandleMoved(bool a); + bool getHandleMoved(); + void sethp12(); + void sethp24(); + void sethp48(); + void setlp12(); + void setlp24(); + void setlp48(); +private: + long double PI; + float m_pixelsPerUnitWidth; + float m_pixelsPerUnitHeight; + float m_scale; + bool m_hp12; + bool m_hp24; + bool m_hp48; + bool m_lp12; + bool m_lp24; + bool m_lp48; + bool m_mouseHover; + bool m_active; + int m_type, m_numb; + float m_resonance; + float m_width, m_heigth; + bool m_mousePressed; + bool m_handleMoved; + QRectF boundingRect() const; + + + + + inline float freqToXPixel( float freq ) + { + float min = log ( 27) / log( 10 ); + float max = log ( 20000 )/ log( 10 ); + float range = max - min; + return ( log( freq ) / log( 10 ) - min ) / range * m_width; + } + + + + + inline float xPixelToFreq( float x ) + { + float min = log ( 27) / log( 10 ); + float max = log ( 20000 ) / log( 10 ); + float range = max - min; + return pow( 10 , x * ( range / m_width ) + min ); + } + + + + + inline float gainToYPixel( float gain ) + { + return ( m_heigth ) - ( gain * m_pixelsPerUnitHeight ) - ( ( m_heigth ) * 0.5 ); + } + + + + + inline float yPixelToGain( float y ) + { + return ( ( 0.5 * m_heigth ) - y ) / m_pixelsPerUnitHeight; + } + + + + +signals: + void positionChanged(); +private slots: + void handleMoved(); + + +protected: + void mousePressEvent( QGraphicsSceneMouseEvent *event ); + void mouseReleaseEvent( QGraphicsSceneMouseEvent *event ); + void wheelEvent( QGraphicsSceneWheelEvent *wevent ); + void hoverEnterEvent( QGraphicsSceneHoverEvent *hevent ); + void hoverLeaveEvent( QGraphicsSceneHoverEvent *hevent ); + QVariant itemChange( GraphicsItemChange change, const QVariant &value ); +}; + + + +class EqCurve : public QGraphicsObject +{ + Q_OBJECT +public: + EqCurve( QList *handle, int x, int y ); + QList *m_handle; + QRectF boundingRect() const; + void paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget ); +private: + int m_width, m_heigth; + int m_alpha; + + float m_pixelsPerUnitHeight; + float m_scale; + + + + + inline float freqToXPixel( float freq ) + { + float min = log ( 27) / log( 10 ); + float max = log ( 20000 ) / log( 10 ); + float range = max - min; + return ( log( freq ) / log( 10 ) - min ) / range * m_width; + } + + + + + inline float xPixelToFreq( float x ) + { + float min = log ( 27) / log( 10 ); + float max = log ( 20000 ) / log( 10 ); + float range = max - min; + return pow( 10 , x * ( range / m_width ) + min ); + } + + + + + inline float gainToYPixel( float gain ) + { + return ( m_heigth ) - ( gain * m_pixelsPerUnitHeight ) - ( ( m_heigth ) * 0.5 ); + } + + + + + inline float yPixelToGain( float y ) + { + return ( ( 0.5 * m_heigth ) - y ) / m_pixelsPerUnitHeight; + } + +}; + +#endif // EQCURVE_H diff --git a/plugins/Eq/EqEffect.cpp b/plugins/Eq/EqEffect.cpp index 01830ce10fd..2abfc0711b9 100644 --- a/plugins/Eq/EqEffect.cpp +++ b/plugins/Eq/EqEffect.cpp @@ -188,7 +188,7 @@ bool EqEffect::processAudioBuffer(sampleFrame *buf, const fpp_t frames) const int sampleRate = Engine::mixer()->processingSampleRate(); sampleFrame m_inPeak = { 0, 0 }; - if(m_eqControls.m_analyseIn ) + if(m_eqControls.m_analyseInModel.value( true ) ) { m_eqControls.m_inFftBands.analyze( buf, frames ); } @@ -326,7 +326,7 @@ bool EqEffect::processAudioBuffer(sampleFrame *buf, const fpp_t frames) m_eqControls.m_outPeakR = m_eqControls.m_outPeakR < outPeak[1] ? outPeak[1] : m_eqControls.m_outPeakR; checkGate( outSum / frames ); - if(m_eqControls.m_analyseOut ) + if(m_eqControls.m_analyseOutModel.value( true ) ) { m_eqControls.m_outFftBands.analyze( buf, frames ); setBandPeaks( &m_eqControls.m_outFftBands , ( int )( sampleRate * 0.5 ) ); diff --git a/plugins/Eq/EqFader.h b/plugins/Eq/EqFader.h index 0e1ae986aa7..05d411f3a81 100644 --- a/plugins/Eq/EqFader.h +++ b/plugins/Eq/EqFader.h @@ -27,9 +27,9 @@ #include "EffectControls.h" #include "MainWindow.h" #include "GuiApplication.h" -#include "qwidget.h" #include "TextFloat.h" -#include "qlist.h" +#include +#include @@ -39,8 +39,8 @@ class EqFader : public Fader public: Q_OBJECT public: - EqFader( FloatModel * model, const QString & name, QWidget * parent, float* lPeak, float* rPeak ) : - Fader( model, name, parent) + EqFader( FloatModel * model, const QString & name, QWidget * parent, QPixmap * back, QPixmap * leds, QPixmap * knob, float* lPeak, float* rPeak ) : + Fader( model, name, parent, back, leds, knob ) { setMinimumSize( 23, 116 ); setMaximumSize( 23, 116 ); @@ -53,6 +53,19 @@ class EqFader : public Fader setPeak_R( 0 ); } + EqFader( FloatModel * model, const QString & name, QWidget * parent, float* lPeak, float* rPeak ) : + Fader( model, name, parent ) + { + setMinimumSize( 23, 116 ); + setMaximumSize( 23, 116 ); + resize( 23, 116 ); + m_lPeak = lPeak; + m_rPeak = rPeak; + connect( gui->mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( updateVuMeters() ) ); + m_model = model; + setPeak_L( 0 ); + setPeak_R( 0 ); + } diff --git a/plugins/Eq/EqLayout1BG.png b/plugins/Eq/EqLayout1BG.png new file mode 100644 index 0000000000000000000000000000000000000000..482fcf116477cf4fb1ff6856e93d4508a33e074c GIT binary patch literal 52487 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%0A0?ji=Pp#g0TiCrt#9&6el9LoMHSCa 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 V%G + * Copyright (c) 2015 Steffen Baranowsky * * This file is part of LMMS - http://lmms.io * @@ -23,34 +24,55 @@ */ #include "EqParameterWidget.h" -#include "QPainter" -#include "qwidget.h" #include "lmms_math.h" -#include "MainWindow.h" -#include "QMouseEvent" #include "EqControls.h" +#include +#include +#include + EqParameterWidget::EqParameterWidget( QWidget *parent, EqControls * controls ) : QWidget( parent ), m_bands ( 0 ), - m_selectedBand ( 0 ) + m_displayWidth ( 400 ), + m_displayHeigth ( 200 ), + m_notFirst ( false ), + m_controls ( controls ) + { m_bands = new EqBand[8]; - resize( 250, 116 ); - // connect( Engine::mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( update() ) ); - QTimer *timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(update())); - timer->start(100); - float totalLength = log10( 21000 ); - m_pixelsPerUnitWidth = width( ) / totalLength ; - float totalHeight = 80; - m_pixelsPerUnitHeight = (height() - 4) / ( totalHeight ); - m_scale = 1.5; + resize( m_displayWidth, m_displayHeigth ); + float totalHeight = 36; // gain range from -18 to +18 + m_pixelsPerUnitHeight = m_displayHeigth / totalHeight; m_pixelsPerOctave = freqToXPixel( 10000 ) - freqToXPixel( 5000 ); - m_controls = controls; - tf = new TextFloat(); - tf->hide(); + //GraphicsScene and GraphicsView stuff + m_scene = new QGraphicsScene(); + m_scene->setSceneRect( 0, 0, m_displayWidth, m_displayHeigth ); + m_view = new QGraphicsView(this); + m_view->setStyleSheet( "border-style: none; background: transparent;"); + m_view->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); + m_view->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); + m_view->setScene( m_scene ); + + //adds the handles + m_handleList = new QList; + for ( int i = 0; i < bandCount(); i++ ) + { + m_handle = new EqHandle ( i, m_displayWidth, m_displayHeigth ); + m_handleList->append( m_handle ); + m_handle->setZValue(1); + m_scene->addItem( m_handle ); + } + + //adds the curve widget + m_eqcurve = new EqCurve( m_handleList, m_displayWidth, m_displayHeigth ); + m_scene->addItem( m_eqcurve ); + for ( int i = 0; i < bandCount(); i++ ) + { + // if the data of handle position has changed update the models + QObject::connect( m_handleList->at( i ) ,SIGNAL( positionChanged() ), this ,SLOT( updateModels() ) ); + } } @@ -58,7 +80,7 @@ EqParameterWidget::EqParameterWidget( QWidget *parent, EqControls * controls ) : EqParameterWidget::~EqParameterWidget() { - if(m_bands) + if( m_bands ) { delete[] m_bands; m_bands = 0; @@ -68,174 +90,122 @@ EqParameterWidget::~EqParameterWidget() -void EqParameterWidget::paintEvent( QPaintEvent *event ) +void EqParameterWidget::updateView() { - QPainter painter( this ); - //Draw Frequecy maker lines - painter.setPen( QPen( QColor( 100, 100, 100, 200 ), 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin ) ); - for( int x = 20 ; x < 100; x += 10) - { - painter.drawLine( freqToXPixel( x ) , 0, freqToXPixel( x ) , height() ); - } - for( int x = 100 ; x < 1000; x += 100) - { - painter.drawLine( freqToXPixel( x ) , 0, freqToXPixel( x ) , height() ); - } - for( int x = 1000 ; x < 11000; x += 1000) - { - painter.drawLine( freqToXPixel( x ) , 0, freqToXPixel( x ) , height() ); - } - //draw 0dB line - painter.drawLine(0, gainToYPixel( 0 ) , width(), gainToYPixel( 0 ) ); - for( int i = 0 ; i < bandCount() ; i++ ) { - m_bands[i].color.setAlpha( m_bands[i].active->value() ? activeAplha() : inactiveAlpha() ); - painter.setPen( QPen( m_bands[i].color, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin ) ); - float x = freqToXPixel( m_bands[i].freq->value() ); - float y = height() * 0.5; - float gain = 1; - if( m_bands[i].gain ) - { - gain = m_bands[i].gain->value(); - } - y = gainToYPixel( gain ); - float bw = m_bands[i].freq->value() * m_bands[i].res->value(); - m_bands[i].x = x; m_bands[i].y = y; - const int radius = 7; - painter.drawEllipse( x - radius , y - radius, radius * 2 ,radius * 2 ); - QString msg = QString ( "%1" ).arg ( QString::number (i + 1) ); - painter.drawText(x - ( radius * 0.5 ), y + ( radius * 0.85 ), msg ); - painter.setPen( QPen( m_bands[i].color, 1, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin ) ); - if( i == 0 || i == bandCount() - 1 ) + if ( m_handleList->at( i )->getHandleMoved() == false ) //prevents a short circuit between handle and data model { - painter.drawLine(x , y, x, y - (m_bands[i].res->value() * 4 ) ); + //sets the band on active if a fader or a knob is moved + bool hover= false; // prevents an action if handle is moved + for ( int j = 0; j < bandCount(); j++ ) + { + if ( m_handleList->at(j)->isMouseHover() ) hover = true; + } + if ( !hover ) + { + if ( sender() == m_bands[i].gain ) m_bands[i].active->setValue( true ); + if ( sender() == m_bands[i].freq ) m_bands[i].active->setValue( true ); + if ( sender() == m_bands[i].res ) m_bands[i].active->setValue( true ); + } + + changeHandle(i); } else { - painter.drawLine(freqToXPixel(m_bands[i].freq->value()-(bw * 0.5)),y,freqToXPixel(m_bands[i].freq->value()+(bw * 0.5)),y); + m_handleList->at( i )->setHandleActive( m_bands[i].active->value() ); + m_handleList->at( i )->setHandleMoved( false ); } } -} - - - -void EqParameterWidget::mousePressEvent( QMouseEvent *event ) -{ - m_oldX = event->x(); m_oldY = event->y(); - m_selectedBand = selectNearestHandle( event->x(), event->y() ); - m_mouseAction = none; - if ( event->button() == Qt::LeftButton ) m_mouseAction = drag; - if ( event->button() == Qt::RightButton ) m_mouseAction = res; + m_notFirst = true; + if ( m_bands[0].hp12->value() ) m_handleList->at( 0 )->sethp12(); + if ( m_bands[0].hp24->value() ) m_handleList->at( 0 )->sethp24(); + if ( m_bands[0].hp48->value() ) m_handleList->at( 0 )->sethp48(); + if ( m_bands[7].lp12->value() ) m_handleList->at( 7 )->setlp12(); + if ( m_bands[7].lp24->value() ) m_handleList->at( 7 )->setlp24(); + if ( m_bands[7].lp48->value() ) m_handleList->at( 7 )->setlp48(); } -void EqParameterWidget::mouseReleaseEvent( QMouseEvent *event ) +void EqParameterWidget::changeHandle( int i ) { - m_selectedBand = 0; - m_mouseAction = none; - const int inXmin = 228; - const int inXmax = 250; - const int inYmin = 20; - const int inYmax = 30; - - const int outXmin = 228; - const int outXmax = 250; - const int outYmin = 30; - const int outYmax = 40; - - if(event->x() > inXmin && event->x() < inXmax && event->y() > inYmin && event->y() < inYmax ) + //fill x, y, and bw with data from model + float x = freqToXPixel( m_bands[i].freq->value() ); + float y = m_handleList->at( i )->y(); + //for pass filters there is no gain model + if( m_bands[i].gain ) { - m_controls->m_analyseIn = !m_controls->m_analyseIn; + float gain = m_bands[i].gain->value(); + y = gainToYPixel( gain ); } + float bw = m_bands[i].res->value(); - if(event->x() > outXmin && event->x() < outXmax && event->y() > outYmin && event->y() < outYmax ) + // set the handle position, filter type for each handle + switch ( i ) { - m_controls->m_analyseOut = !m_controls->m_analyseOut; + case 0 : + m_handleList->at( i )->setType( highpass ); + m_handleList->at( i )->setPos( x, m_displayHeigth/2 ); + break; + case 1: + m_handleList->at( i )->setType( lowshelf ); + m_handleList->at( i )->setPos( x, y ); + break; + case 2: + m_handleList->at( i )->setType( para ); + m_handleList->at( i )->setPos( x, y ); + break; + case 3: + m_handleList->at( i )->setType( para ); + m_handleList->at( i )->setPos( x, y ); + break; + case 4: + m_handleList->at( i )->setType( para ); + m_handleList->at( i )->setPos( x, y ); + break; + case 5: + m_handleList->at( i )->setType( para ); + m_handleList->at( i )->setPos( x, y ); + break; + case 6: + m_handleList->at( i )->setType( highshelf ); + m_handleList->at( i )->setPos( x, y ); + break; + case 7: + m_handleList->at( i )->setType( lowpass ); + m_handleList->at( i )->setPos( QPointF( x, m_displayHeigth/2 ) ); + break; } - tf->hide(); -} - - - - -void EqParameterWidget::mouseMoveEvent( QMouseEvent *event ) -{ - int deltaX = event->x() - m_oldX; - int deltaR = event->y() - m_oldY; - m_oldX = event->x(); m_oldY = event->y(); - if(m_selectedBand && m_selectedBand->active->value() ) + // set resonance/bandwidth for each handle + if ( m_handleList->at( i )->getResonance() != bw ) { - switch ( m_mouseAction ) { - case none : - break; - case drag: - if( m_selectedBand->freq ) m_selectedBand->freq->setValue( xPixelToFreq( m_oldX ) ); - if( m_selectedBand->gain )m_selectedBand->gain->setValue( yPixelToGain( m_oldY ) ); - break; - case res: - if( m_selectedBand->res )m_selectedBand->res->incValue( ( deltaX) * resPixelMultiplyer() ); - if( m_selectedBand->res )m_selectedBand->res->incValue( (-deltaR) * resPixelMultiplyer() ); - break; - default: - break; - } - } - if( m_oldX > 0 && m_oldX < width() && m_oldY > 0 && m_oldY < height() ) - { - tf->setText( QString::number(xPixelToFreq( m_oldX )) + tr( "Hz ") ); - tf->show(); - const int x = event->x() > width() * 0.5 ? - m_oldX - tf->width() : - m_oldX; - tf->moveGlobal(this, QPoint( x, m_oldY - tf->height() ) ); + m_handleList->at( i )->setResonance( bw ); } -} - - - -void EqParameterWidget::mouseDoubleClickEvent( QMouseEvent *event ) -{ - EqBand* selected = selectNearestHandle( event->x() , event->y() ); - if( selected ) - { - selected->active->setValue( selected->active->value() ? 0 : 1 ); - } + // and the active status + m_handleList->at( i )->setHandleActive( m_bands[i].active->value() ); + m_handleList->at( i )->update(); + m_eqcurve->update(); } -EqBand* EqParameterWidget::selectNearestHandle( const int x, const int y ) +void EqParameterWidget::updateModels() { - EqBand* selectedModel = 0; - float* distanceToHandles = new float[bandCount()]; - //calc distance to each handle - for( int i = 0 ; i < bandCount() ; i++ ) - { - int xOffset = m_bands[i].x - x; - int yOffset = m_bands[i].y - y; - distanceToHandles[i] = fabs( sqrt( ( xOffset * xOffset ) + ( yOffset * yOffset ) ) ); - } - //select band - int shortestBand = 0; - for ( int i = 1 ; i < bandCount() ; i++ ) - { - if ( distanceToHandles [i] < distanceToHandles[shortestBand] ){ - shortestBand = i; - } - } - if(distanceToHandles[shortestBand] < maxDistanceFromHandle() ) + for ( int i=0 ; i < bandCount(); i++ ) { - selectedModel = &m_bands[shortestBand]; + m_bands[i].freq->setValue( xPixelToFreq( m_handleList->at(i)->x() ) ); + if( m_bands[i].gain ) m_bands[i].gain->setValue( yPixelToGain( m_handleList->at(i)->y() ) ); + m_bands[i].res->setValue( m_handleList->at( i )->getResonance() ); + //sets the band on active if the handle is moved + if ( sender() == m_handleList->at( i ) ) m_bands[i].active->setValue( true ); } - delete[] distanceToHandles; - return selectedModel; + m_eqcurve->update(); } diff --git a/plugins/Eq/EqParameterWidget.h b/plugins/Eq/EqParameterWidget.h index eb83ec96202..c503858aad7 100644 --- a/plugins/Eq/EqParameterWidget.h +++ b/plugins/Eq/EqParameterWidget.h @@ -2,6 +2,7 @@ * eqparameterwidget.cpp - defination of EqParameterWidget class. * * Copyright (c) 2014 David French +* Copyright (c) 2015 Steffen Baranowsky * * This file is part of LMMS - http://lmms.io * @@ -26,8 +27,13 @@ #ifndef EQPARAMETERWIDGET_H #define EQPARAMETERWIDGET_H #include +#include +#include +#include #include "EffectControls.h" #include "TextFloat.h" +#include "EqCurve.h" + class EqControls; @@ -40,6 +46,12 @@ public : FloatModel* res; FloatModel* freq; BoolModel* active; + BoolModel* hp12; + BoolModel* hp24; + BoolModel* hp48; + BoolModel* lp12; + BoolModel* lp24; + BoolModel* lp48; QColor color; int x; int y; @@ -58,16 +70,13 @@ class EqParameterWidget : public QWidget public: explicit EqParameterWidget( QWidget *parent = 0, EqControls * controls = 0); ~EqParameterWidget(); - const int bandCount() - { - return 8; - } + QList *m_handleList; + void changeHandle(int i); - - const int maxDistanceFromHandle() + const int bandCount() { - return 20; + return 8; } @@ -79,88 +88,65 @@ class EqParameterWidget : public QWidget } - - - const int activeAplha() - { - return 200; - } - - - - - const int inactiveAlpha() - { - return 100; - } - - - - - const float resPixelMultiplyer() - { - return 100; - } - - -signals: - -public slots: - -protected: - virtual void paintEvent ( QPaintEvent * event ); - virtual void mousePressEvent(QMouseEvent * event ); - virtual void mouseReleaseEvent(QMouseEvent * event); - virtual void mouseMoveEvent(QMouseEvent * event); - virtual void mouseDoubleClickEvent(QMouseEvent * event); - private: + EqBand *m_bands; + int m_displayWidth, m_displayHeigth; + bool m_notFirst; EqControls *m_controls; + + QGraphicsView *m_view; + QGraphicsScene *m_scene; + EqHandle *m_handle; + EqCurve *m_eqcurve; + float m_pixelsPerUnitWidth; float m_pixelsPerUnitHeight; float m_pixelsPerOctave; float m_scale; - EqBand* m_selectedBand; - TextFloat *tf; - EqBand* selectNearestHandle( const int x, const int y ); - enum MouseAction { none, drag, res } m_mouseAction; - int m_oldX, m_oldY; - int *m_xGridBands; - inline int freqToXPixel( float freq ) + inline float freqToXPixel( float freq ) { - return ( log10( freq ) * m_pixelsPerUnitWidth * m_scale ) - ( width() * 0.5 ); + float min = log ( 27) / log( 10 ); + float max = log ( 20000 )/ log( 10 ); + float range = max - min; + return ( log( freq ) / log( 10 ) - min ) / range * m_displayWidth; } - inline float xPixelToFreq( int x ) + + inline float xPixelToFreq( float x ) { - return pow( 10, ( x + ( width() * 0.5 ) ) / ( m_pixelsPerUnitWidth * m_scale ) ); + float min = log ( 27 ) / log( 10 ); + float max = log ( 20000 ) / log( 10 ); + float range = max - min; + return pow( 10 , x * ( range / m_displayWidth ) + min ); } - inline int gainToYPixel( float gain ) + inline float gainToYPixel( float gain ) { - return ( height() - 3) - ( gain * m_pixelsPerUnitHeight ) - ( (height() -3 ) * 0.5); + return m_displayHeigth - ( gain * m_pixelsPerUnitHeight ) - ( m_displayHeigth * 0.5 ); } - inline float yPixelToGain( int y ) + inline float yPixelToGain( float y ) { - return ( ( 0.5 * height() ) - y) / m_pixelsPerUnitHeight; + return ( ( 0.5 * m_displayHeigth ) - y ) / m_pixelsPerUnitHeight; } +private slots: + void updateModels(); + void updateView(); }; - #endif // EQPARAMETERWIDGET_H diff --git a/plugins/Eq/EqSpectrumView.h b/plugins/Eq/EqSpectrumView.h index 30693739964..1d9ad5ea23b 100644 --- a/plugins/Eq/EqSpectrumView.h +++ b/plugins/Eq/EqSpectrumView.h @@ -23,13 +23,13 @@ #ifndef EQSPECTRUMVIEW_H #define EQSPECTRUMVIEW_H -#include "qpainter.h" -//#include "eqeffect.h" -#include "qwidget.h" +#include +#include #include "fft_helpers.h" #include "Engine.h" + const int MAX_BANDS = 2048; class EqAnalyser @@ -54,7 +54,7 @@ class EqAnalyser m_active ( true ) { m_inProgress=false; - m_specBuf = (fftwf_complex *) fftwf_malloc( ( FFT_BUFFER_SIZE + 1 ) * sizeof( fftwf_complex ) ); + m_specBuf = ( fftwf_complex * ) fftwf_malloc( ( FFT_BUFFER_SIZE + 1 ) * sizeof( fftwf_complex ) ); m_fftPlan = fftwf_plan_dft_r2c_1d( FFT_BUFFER_SIZE*2, m_buffer, m_specBuf, FFTW_MEASURE ); clear(); } @@ -121,6 +121,8 @@ class EqAnalyser ( int )( LOWEST_FREQ * ( FFT_BUFFER_SIZE + 1 ) / ( float )( m_sr / 2 ) ), ( int )( HIGHEST_FREQ * ( FFT_BUFFER_SIZE + 1) / ( float )( m_sr / 2 ) ) ); m_energy = maximum( m_bands, MAX_BANDS ) / maximum( m_buffer, FFT_BUFFER_SIZE ); + + m_framesFilledUp = 0; m_inProgress = false; m_active = false; @@ -139,16 +141,20 @@ class EqSpectrumView : public QWidget QWidget( _parent ), m_sa( b ) { - setFixedSize( 250, 116 ); + setFixedSize( 400, 200 ); QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(update())); - timer->start(2000); + timer->start(100); setAttribute( Qt::WA_TranslucentBackground, true ); m_skipBands = MAX_BANDS * 0.5; - float totalLength = log10( 21000); - m_pixelsPerUnitWidth = width( ) / totalLength ; + float totalLength = log10( 20000 ); + m_pixelsPerUnitWidth = width( ) / totalLength ; m_scale = 1.5; color = QColor( 255, 255, 255, 255 ); + for ( int i=0 ; i < MAX_BANDS ; i++ ) + { + m_bandHeight.append( 0 ); + } } @@ -168,7 +174,7 @@ class EqSpectrumView : public QWidget { m_sa->m_active = isVisible(); const int fh = height(); - const int LOWER_Y = -60; // dB + const int LOWER_Y = -36; // dB QPainter p( this ); p.setPen( QPen( color, 1, Qt::SolidLine, Qt::RoundCap, Qt::BevelJoin ) ); const float e = m_sa->m_energy; @@ -183,13 +189,28 @@ class EqSpectrumView : public QWidget } pp = QPainterPath(); float * b = m_sa->m_bands; - int h; + float h; pp.moveTo( 0,height() ); for( int x = 0; x < MAX_BANDS; ++x, ++b ) { - h = (int)( fh * 2.0 / 3.0 * ( 20 * ( log10 ( *b / e ) ) - LOWER_Y ) / (-LOWER_Y ) ); - if( h < 0 ) h = 0; else if( h >= fh ) continue; - pp.lineTo( freqToXPixel(bandToFreq( x ) ), fh-h ); + h = ( fh * 2.0 / 3.0 * ( 20 * ( log10( *b / e ) ) - LOWER_Y ) / (-LOWER_Y ) ); + if( h < 0 ) + { + h = 0; + } + else if( h >= fh ) + { + continue; + } + if (h > m_bandHeight.at(x)) + { + m_bandHeight[x] = h; + } + else + { + m_bandHeight[x] = m_bandHeight[x] -1; + } + pp.lineTo( freqToXPixel( bandToFreq( x ) ), fh - m_bandHeight.at( x ) ); } pp.lineTo( width(), height() ); pp.closeSubpath(); @@ -205,21 +226,29 @@ class EqSpectrumView : public QWidget return ( log10( band - m_skipBands ) * m_pixelsPerUnitWidth * m_scale ); } + + + inline float bandToFreq ( int index ) { return index * m_sa->m_sr / (MAX_BANDS * 2 ); } - inline int freqToXPixel( float freq ) + + + inline float freqToXPixel( float freq ) { - return ( log10( freq ) * m_pixelsPerUnitWidth * m_scale ) - ( width() * 0.5 ); + float min = log ( 27) / log( 10 ); + float max = log ( 20000 )/ log( 10 ); + float range = max - min; + return ( log( freq ) / log( 10 ) - min ) / range * width(); } + private: float m_pixelsPerUnitWidth; float m_scale; int m_skipBands; + QList m_bandHeight; } ; - - #endif // EQSPECTRUMVIEW_H diff --git a/plugins/Eq/artwork.png b/plugins/Eq/artwork.png deleted file mode 100644 index 33fa4960defbf65b02db84e0b812bec717e4e0c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27905 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%0A?-KV-lr7 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 Hu0mjf8ekH` diff --git a/plugins/Eq/bandLabel1.png b/plugins/Eq/bandLabel1.png new file mode 100644 index 0000000000000000000000000000000000000000..402a9f3ab38dc7d9493916512ba6a5caf356aaf5 GIT binary patch literal 413 zcmV;O0b>4%P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{009L_L_t(o!|j#JYQr!PMeo>> zZJCC;c~G)#z9sbkKOkL%G|-Y}YdtJa7l9_wP32mK7M-O)9PXWw4I~nYL?V$0g0|ad zo=PSF;AyjoE_&JRkWE?Rq%tw|;%s(@)p7wM!r}D@W9;}cDJ7PRIqF&g0KE4<5(UZ1 zqCnH!qplUQ?ApGycKjOG>qq2y{_VVN_4o^7t%Y+Ar;jtVz6!K9<0pH2KcVY75E14N z4FG_dp-qHj-g^)cib8(POdA8{i0@1(HK@X2vZ}n1>A148yvX{#58A|FnUn%TTz1Mi z2WE~ZtEy`7yne zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00A*cL_t(o!|jznOT$1IhkuvU zpodmU{hP!n26QWQ(W$r?Tpaywj)I%Jn>hIe1XnAl@!BdynlzZGxj0yi;?!^#Q0|$I zgYew@%lqB|3WY+UP$#i$ZbklA_D>KGYWtE~IHXDoBZ8^|&9mgkE zV7*AZY_2{9Z)Xjw_ACJ4^({r`F%nyuxipQf<}x~Dh7iC_Ev zLm<9E`p+?fFv0o7E$&$^xMQLC201;u#vq762tjMx0swH%!8)P%$_7CKfM8*s!Z1G1 z*n5ibo@Vmq%rUEZgnlS@sBLrRYyJJ-Ns+CLWSn#OOk!pA+9W77M&0>>I7#KnenvQy zdlB1Kwa_pZk~voK<{0}TK0LboJMY>5m6gf|oIqMVuPB%V00000NkvXXu0mjf(fPb9 literal 0 HcmV?d00001 diff --git a/plugins/Eq/bandLabel2.png b/plugins/Eq/bandLabel2.png new file mode 100644 index 0000000000000000000000000000000000000000..dfcbadb686f354889dd3ff1db3152cdc695d49ac GIT binary patch literal 487 zcmVe zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00B=)L_t(o!|j#ZPQpMChCkSr z7Ge+dfT!q%J`3^v9{>{(l(W!Er7fjiC`MyE5Ec?mzsudp{5z9>W}%>i%7P$7(<+Qc6XsEbu4|keAHBS|T#_p`k0KVGm@LZx zh~wn#ZV|`w-MAJ4aGW{-d7kqynaX$L8sBpg2$EuTK;`?Ph}*#sQw^l4Tj)yB=wp z?q*%7ih}#Goxl5^ d{a>-Y@(i_`Y-pJ6eGmWu002ovPDHLkV1jpP&aD6d literal 0 HcmV?d00001 diff --git a/plugins/Eq/bandLabel2on.png b/plugins/Eq/bandLabel2on.png new file mode 100644 index 0000000000000000000000000000000000000000..62c668c0031d3267ca4409c93cfd3248c2b96dfd GIT binary patch literal 544 zcmV+*0^j|KP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00D?eL_t(o!|jzxFGEojfIm;4 zYU62Hw5p+au@F*0NJLDDB1j|_Hn#o}OLlf*BeCd0f(3~XO$gT+q?c(b3V-$%q_}r!S?I%m7fOs#zBW4i1pCETg6}LngsaheA`m zow8B|vq>g=|HSJ08NS_1v9jK-3L4!dpU#SlObmEb46?+AFDR~zmO|sVcWo_Bu`k=& z4&ksBu()!>?*0wsPKD9o8USR2Bv$4R+;Vo|BN|Hpa2|}k-vvW4vE7(T@h$@BY%2#K znM|>~b|StT0VE0fyQ^^5+IV?MGVk5z_%tG3rWE8cGFXknt`H7CGPmI8;+G}NNT#~1 z4E3p)@@0J6A-qe6BoaySL*3}M)6?PN`T3RE`91uByXeWv#6+S`OiXS5z4cq0o#e^6X%l49AZcZlWtJZkd>rmSm2q-< i6OsJi&r?&Grn~{RdT{|nDDLn80000P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00B@*L_t(o!|jz_Z-OushTo0~ z<)a8r7v1jWZ!!D-KfqmVyPOIYkbf1$=K|dm1PBWRM-~<+V%*>JUl%v003HRv$Co>psEhgT7yyw zpRul&i@jM{nkJZ}$yrS)h21XeE$h8A&vk#)q?ElySIOL8WI+(%ev+DhXK(Kx-M+># zNBSLU7zWsEcjhk$Ap}Y(WO?4z9LF&eBOwG2vnd$!KnMWe zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00DtXL_t(o!|jzzOF}^ufWNN! zsCc6|uYSu9naNzE; z(rhuHppd;OvU8B;_#`J*wzSZX#bT(4$xaip(}b~6M>ujNu8il&$EvyDNW0jRoyKk{ z7D^mNv)nzrAUjPgFZuycP{hjO7x%<3?g20vwRFnnkKFcNTC8j`=wf2bRS|oBDY3bg zBpgYLefn*!Oe@Y!6+s8Ld`AlE7|jU~c+zaA$KxF=h1iwcvkW)d)vYVq}Bf z>XLG~%tkm#G#YNu=_B^FRB) bvYPS+@iJ{oR1YI900000NkvXXu0mjft1{#9 literal 0 HcmV?d00001 diff --git a/plugins/Eq/bandLabel4.png b/plugins/Eq/bandLabel4.png new file mode 100644 index 0000000000000000000000000000000000000000..b6c9b6e035f79b3cf92db5a1b6f62846f58688b1 GIT binary patch literal 467 zcmeAS@N?(olHy`uVBq!ia0vp^(m<@i!3HGxts29C6kC$Fy9>jA5L~c#`DCC7XMsm# zF#`j)FbFd;%$g$s6l5>)^mS#w&ne5J#G`&t3S@v}iEBiObAE1aYF-J0b5UwyNotBh zd1gt5g1e`0KzJjcI0FNtwWo_?NW|f{QxE1fIf%IS^PDkQ7PdO9F?8|$q+kE#6DHr9 zrRQ_ht0}={SB6t=mXgM#We?YIBwBpFSIZL+3;`X-Qa;THQ#EFEd;IaLtN&$9x2d^n zLel2#y&zJtt~oW5;mq@Vm%^BRK3<)#c?^9S57h0q*R=9hTYBWPOv}f)4s)DCER0VZ zeY~T1$l%7?NpI?Qbe@{ZsrVsAT#@D9tHS7Eerl@>_eFxBOBO2G2=Tt{*e; zEu6#X<$2BVz@_+wOU|?@-^)Aw``oX+dQsVj3JxcI%Sb z9QjpXacISbTZfFI?x*{697Hl=?TD_|G2%Y*quqn!(f6&t;uc GLK6Vln8#cI literal 0 HcmV?d00001 diff --git a/plugins/Eq/bandLabel4on.png b/plugins/Eq/bandLabel4on.png new file mode 100644 index 0000000000000000000000000000000000000000..22f99e626265e0c44fc9f57dd0de58d813d47d47 GIT binary patch literal 525 zcmeAS@N?(olHy`uVBq!ia0vp^(m<@i!3HGxts29C6kC$Fy9>jA5L~c#`DCC7XMsm# zF#`j)FbFd;%$g$s6l5>)^mS#w&ne5JBw;Ikt{NyLS>hT|;+&tGo0?a`;9QiNSdyBe zP@Y+mq2TW68xY>eC(gjYSnBEG7!q;#?bP$$hZ1Ct$*206XGZyU7b#VqkbPzULd3bF zZid1m`!sibS?g;nITkewPL$>G=bp2R$3ItU$(B-qXNrq%K3h;R|MB;ywf66S*WUYH z$*2Sdi&j3FykyNw(H^FTttC~@7N|$I-9K$s#kIK3+VIpxjb|=r+$9+fd_1XqYt=hD zopZ)Ok(Nj)1_LR{fZe-(t4DWj)R67sXk`jpd--ajgkJSAeFF`-9>?bG3q!+i&Dt%l za)>qXRCmHnhP-znCA(^~*Su8g;rkJIVp|LLCzu4OvSk)dT=^#ByV N44$rjF6*2Ung9UE+!6o) literal 0 HcmV?d00001 diff --git a/plugins/Eq/bandLabel5.png b/plugins/Eq/bandLabel5.png new file mode 100644 index 0000000000000000000000000000000000000000..b1d942333f541bdbb9ff5a04e23dc36c6d8f3e39 GIT binary patch literal 458 zcmV;*0X6=KP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00A;dL_t(o!|j#rO2aS|hTkTK zexzwvnVUlq#a+wr{x4uE(}^NXXkELuwDE`F2ClkdT2S)*Jt zdR~k%MA1NR^pyf`?-t;k!*OgJMFY65`(tQ+mBy;7kfs@)o?o^*CF=GMvYW!XuJy?* z%fje*_?bK+j`3*N`hFdBW`UFl!vJ9z?5)RfqOY?cl#R7GPOwf>eVwgVuLz`se zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00C=BL_t(o!|j#9O9DX{#oxN? zY-)}hsf!|ME+r}kK}67{Ll)5~=-8oae@&;LQ-_XSy7doqtAj)+6>1)Way3b61+{Iv z=|!PncA=Qxao)h=y>Ivi;BYt`4u|tAgnWL}a>`5sfTX6`Zd9#Q;BvA?N6n<4UJOtf z2m6a7wfB!Mj!p{fl4)^etoEWCY->y=#+yCY4R$q3qJWtg1pqW#9h{yO(d(J^JP<80 z1>zO~01BPJ&ej~lL61FV>G|nlO38)UxPraiEEG!Enn|KCa$bZ;SXqj)efpoKg~Q`( zcs*`JR3BECV~D7e0DyQbz`jPy0*p={<;ORiUpx%Xsh`-pK}>VFx4Ydhc4jgWvAv#z z8uCIE1t^qYV=Xbz>kWh5%rdDUa+xr4nea&crl_+^wvY~v)ox2V?#eB8$u6&+kWGaU zRehj-8U4PAMze!LQAg?imF?EA*4n7n+JEyu`@d$6@(n80RX0|Bdz=6O002ovPDHLk FV1oXg)&~Fp literal 0 HcmV?d00001 diff --git a/plugins/Eq/bandLabel6.png b/plugins/Eq/bandLabel6.png new file mode 100644 index 0000000000000000000000000000000000000000..a574db58532369f853376c5ee28637403f5f2973 GIT binary patch literal 525 zcmV+o0`mQdP)@02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00DJLL_t(o!|j#bPQpMCh0k`k zrL=%;MJmQv`loqB=cClW6{(()ayYjGR8t-;-r@Zhi%)ankIBzfO8H2cz$_R2h$jX=ecM! z>R^oR)zU0e=SIWSnH~} z0fkY7!C-Wr2B}mGSXLDPKt$jg$Nk+c7-Lv2mzahT;y6(QtJiAV2GKOwwzU_pX__EO zn9b+EpEJ{}eESjCbJRE!`nLN9!x55X1}Pwp29HNT<^vvrBt(B z?aq(uTzssRhUVqv=6-g>Kp*8SjuW`WHK=jiv};J6NK%YqObM1(ZUF!|y~PToN%&k+P;1i|?4oM-e P00000NkvXXu0mjfsY=|v literal 0 HcmV?d00001 diff --git a/plugins/Eq/bandLabel6on.png b/plugins/Eq/bandLabel6on.png new file mode 100644 index 0000000000000000000000000000000000000000..f67a2517a50bff49fa82d77a75f79dc9120856c4 GIT binary patch literal 605 zcmV-j0;2tiP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00G5GL_t(o!|j#LOB+ELhacD7 zux3}2t`^Zot*(+54=uEyp@R{Qf7}?AN(-UoM?(+O) z3deE9ACTT|jlqF10JiO-1r?sm-$qs>ip45xZ@2mIIWI;w8twANiXt(5{fhV8)2%Zb zAEsKXlT7XZ{XOfCbo_CX$yh{8vUWY-jh9wZeEd?NQgMim7|g{-0O&MSF)~Ft37>ek zgH!+6x0Byb%2u-*V%pWO_h;-*FS0D51r?_64|((1?17kMpS~7}-Mt3D#CRVQ<9)xq z^E#0elkC-6mVBXd=9=reyjb}`I#Uvp%(Ch%EWYR7ScDsMuGgTslfVUvcL)Fg02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00AaRL_t(o!|j#bPQpMCM$b~p zRxHpKMWT1|EX4PJ08CWG%AW?>CY1hoVM4+UmfCHi*>knYe#yyBW@bU7(P%Up%~^=? z_#v-L)&#g8jg*TXCleZVma$e@vq;Esdh|W_WF`zF{P+3qUnX0vA2Yk%u9`AhmOOdC z-|yLMgKEn7^gKPD7a_R29U`S9NfKr=pEOOYZ;(9C8Qu(#Qj%pEZ~mO5fT)zL@42+w z7XU1lE8;j-)B2Vrahx6iK@buIp_(}pLNK_#LI^>crYx3AbwlmC4yI`Wuv&kRWw{!e zVHotf9RT7uW?P`mOUpdhq0#t`uGgRHcB5e!*!JaNc*7`CC+l|X!>cwW%U4)t+xFpn oZmXZYu3o0EfAc^4zp`5S0w=RuNyyr%V*mgE07*qoM6N<$f+Fa*g#Z8m literal 0 HcmV?d00001 diff --git a/plugins/Eq/bandLabel7on.png b/plugins/Eq/bandLabel7on.png new file mode 100644 index 0000000000000000000000000000000000000000..fc04379254fdf69f390af39941ff359465fb3605 GIT binary patch literal 499 zcmVe zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00CP`L_t(o!|j#5OF~f?#((O) z6?nrSH4`n!zR01X5Bj2LkcOI~vA?S+Xo-fPAZUn&K!_T{!pcx1j35OwHMMSJgAlZ+ zndd@rf73af2Oi$%yyrcjqobpvqoea93_jmNQ7bbEpv&VCZWN6~Flrg2re;z#qRCMw zb5kAVW4cSRy?6cl%G%q^6*aMkbbVrU*p;&9PpLc?mx=nsxVCZjZQs~nVs&Kzo7GG@ z^UBul71h_F}V|QPmH2_CsW{Z(_P}e%ei^+XBF$|CYx@PE6~&oC;&ZP5?sT zWL5W6lbIwLS@LybG#bbkR1S`!;vV(PxQiA`69E2`82Q4x7&FBzGcxD^Ad$=w2*$;Y ztJw)RvRslLpWaif@t>$@)~v{Q`>g<^o(tSWli~*Pkk^jMRFVaP@tUiu%B-)a^=lmp p*Irds<7$2L{BQne|JO`YJ^|?+THvhhjLiT5002ovPDHLkV1hl9)&~Fp literal 0 HcmV?d00001 diff --git a/plugins/Eq/bandLabel8.png b/plugins/Eq/bandLabel8.png new file mode 100644 index 0000000000000000000000000000000000000000..9f971840a37255a698c52390c2f48ad80b7ddbd3 GIT binary patch literal 540 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 QX#fBK07*qoM6N<$f*099kN^Mx literal 0 HcmV?d00001 diff --git a/plugins/Eq/handle2.png b/plugins/Eq/handle2.png new file mode 100644 index 0000000000000000000000000000000000000000..51c1df2906d376ba43e584c1b0c67b5cc430f6e5 GIT binary patch literal 1483 zcmV;+1vL7JP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00lEiL_t(Y$F-GPh+S75#(!(= zwJ+y>&Sa)N=A5Rq6Y-FVjhXf#MDmcT2^J(stRQF*eDSF;Y5OX^`JnhD7!0H@2AXIH zD#E0WG$v>(Z8O!BfYrpLGo5R4?&s{Y_g;G~AI?mZwh?^s|F~G|TmReleeiz_@vuV+ ziai93D3ha1jyygt3JE}jp+m?jP43bJLVigszK#8_;P$5oP7+Y1Op!-g6BORiJbEqV zvm1t5BFX!TK{dn5GX-uwZCI;p(x*#@F6(SC5C-!p@GamR6{_6{c3g7Vy^wOSm&Ml^ ztW{XyAgskIfpimOE+srN$s1p`d{Ee+$v;?TKzI8C@jxrGOj6sdQGLZQdtLL?Fhe@< z(2*rgBvz{NT}L8(2PbQBG6`ybj`zM>&G75Zz5k+9Q&FA039uXf5ryP=Qhi-zOaolQgcRE<0c`Wbb^5jpt_=&?IAjMlznh zN4crUzt-oALy2x_bbCb7Zi~eCYx4a0`6GAkY`n0t(tPpCmA`)D*=N5t)#;$yZ7*rH z+@#Y*4}A2cRSvd_z)mqyzmZl=WT4!Yl0>8r2)=E$K#hxXsN zapPvQ*=+CGvuF3defui6ZvA`x{r7JUgit7DgrBjF=MYSKtnW?weT~HGgq&@tcPaAKriV?Ah1n=H~vgyu2KJOfUda@Fhbu5W%=DBScNIvSE1A z1?hPRrL2%r&}hu$7Zw)2lg(zcCr_R{f9lk!Th>~H5J)MJ(&9KqD20?7syRL+#ZcVN ze3R%IhnrrE3?wq}aD3lL&qJO*{fneZ{q78VwsJAVB5PR~=) z_pS8(Sb82(#mLzS{>g|TZ;_5O@6kH2lkCNqD0ERJhcwD#j4?DCjmI6wk@b4LTCdlu z0He_;x^m@Dw=ZA*{boL|RiTiojKIl6ga;(6Y|^BK-e%~%N{8~10&iZ_9M&0(&S0gq z?A<&0^DuN$t%cn#R4E~RA6YJIw^Gq=F^`jtagJ8GJQ2}H)8XQM@Q^jSN6ReT4tVcc z%8c~Db&$SqlQ7gyk_a;f7bs;!5E!RWK$UW+Vv4sf$Mvr&?yydq&oB~S$Br5LBMg5; z`vd&XRT$irh*ru@S0Mw13<6}fgenxQ%H@nxDp|Lf$1ORy#RPXY%k}S-cz0rjdz4ud zzh?AF$(2Bn0+00`rE)39uGeA?^jv~iVYG+A8NZMQp;AO1Mn|Xk^K*(1ifgnOu)+`M ziRZ_=DL!Fu639{D5sH*r0ogb6RNt0NuSC>h$a)ULs>jmPW&U+A&)UQ~eOBqP!97Ak z!9$$rqYr+J;ALDS0XfP%#sozI6as&XEgD0U5Jd}3hbI_`-;(@K2EA2<7^@EIK~Wfs l3>F{5T{NHtA2;Uh_z!e6Me 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 N002ovPDHLkV1j+@o=5-y literal 0 HcmV?d00001 diff --git a/plugins/Eq/handle3inactive.png b/plugins/Eq/handle3inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..4c0ebbd470eb70e81dd9478ccc80f0ada1600a7d GIT binary patch literal 920 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 b+O2;8AAocB!M>ng00000NkvXXu0mjftqqx4 literal 0 HcmV?d00001 diff --git a/plugins/Eq/handle5inactive.png b/plugins/Eq/handle5inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..a242ac176b4db3b5fc0f64d49c33d7b22a00d70b GIT binary patch literal 918 zcmV;H18Mw;P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00RC=L_t(Y$HkSsPg7wO#($+B zK>2KLF_Kus4yF+llMW4`F==2jCTwmbZis(?gF2gZfQ=1-kgzy0nrIA*Lt|r8F^Y-W zhy_GiES3WO;<`MS++dVE^?3UmYgzz7fm+O%OEC<3d%GvE!d3GDp|+zE655#S~;05l4)rn?hx>0SoXz+)f* z?Aohvo&fg&*MU30Wo=#r@@m0%y_dD-1$u!#pagtTn|=Xr2BHG)RZw0fZwYu; z1e^m(iA3UtX`1&<(|n-&-PzgMD_Y-Bd{z1V!owwSzfOfmC2uQXAE*Wb0ss2?`c@{B z`D*oWWo2bk>kgnvfUUww0ecp>SI4cck_x~fP<6Rn7=~fY&CNY6l}eRLrE)YqJ^enL z%^nK)Q1KnwAY|#nWgBRldT8~w3YgJo)bMyb&attvnAhuV1Q;J5{}GGDX42_&QE_GE z)r12!wOJck=eY)$0Fg+<50FeI-vt7J_~PQ?bDz)GJ~=sgO?jp*r*0=~iRcnAuZ1-r zt5RzxRc9E6JD1Dd%VaXyU@-VdIi0{cphr2kfVXz$MFo1LN;lw`n3xDIEiH`<4-fkR z!r^cyK%r15iJV*UUga0O(jjz6h|eu<%O2 zO^WZ3URITRETWoNM6ENbLDiDUWWJ@PWoKYupeGaxT__fdrKzc@C-Hdvqu3fUIiJKe zCo`)!Yzhqm_kbZCuWd;`Zyiew&tYS10e9*B1@I8~1k|0ji66*(`V{ODh|>n>5!*J! zbld#?GcW_ZwtUBKTs5h(Boi{k#!{c9z)k_5Q7ak+JP$0}2YS+SE3(ZsnUKY*MQqyz s*se{>z)LY+whZgP{E7bQKlD_upLJRi89{(q$p8QV07*qoM6N<$f;_s0I{*Lx literal 0 HcmV?d00001 diff --git a/plugins/Eq/handle6.png b/plugins/Eq/handle6.png new file mode 100644 index 0000000000000000000000000000000000000000..eadaff0ff16cf2498e23e2f35642896a48f00108 GIT binary patch literal 1506 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 N002ovPDHLkV1h>;#|r=e literal 0 HcmV?d00001 diff --git a/plugins/Eq/handle7inactive.png b/plugins/Eq/handle7inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..a7fe5d609644d67623c6887909c1aef51182a787 GIT binary patch literal 833 zcmV-H1HSx;P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00OB=L_t(Y$HkSuPg7A8$3M{5 z0+kj7iXlyq$bx}Jr#k4S44QOxBdp@c-i5!wKfuA|g~Wug5e7p@U{MCdIDnfFYm}B} z=`UV?x_obQ^Dr6{iEnxBz2|(+_ndprd2oeK&u{iZzyL4?M77oidiA>sQn_a8c=(fx7&{Ktevp zz!zoNg@=Hfz%wbX0jEF?_%5|oDfR`f3DOHhfKec>G8KW2W2v44?g94aLiR%nFk||n*UB`e z8k*WRlydi3TwI)-pPx^!uC8wH?ChLrzajgo{A0%6hC9}MZU(^s*=+VO+FE8&| z%N@(7CC(*y(`pbW*kGAV=En5&^yJpo*1qR?jX)zhR%11P1uw}Us;&&%0Tvb(ZUd~Z zuYU@F!?KUczZ8U5H7iW}59%#LILUmoI1TZ2s zVW20OOpc$QpO-3?O3MOAWtWg&U7S2t@oSoH?}7VrFpvUp5s$}T=92R(7Q?yUu zSHQM?puv$_*VsJP5HhN+No`!fxPtn?o)mAJf%RX$ME~>~dZo`#k=*EOkiuC600000 LNkvXXu0mjf3wdz1 literal 0 HcmV?d00001 diff --git a/plugins/Eq/handle8.png b/plugins/Eq/handle8.png new file mode 100644 index 0000000000000000000000000000000000000000..2b7344e8ba2d0ca0b9178e516e32e9158599f33e GIT binary patch literal 1429 zcmV;G1#0?202y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00jL>L_t(Y$F-F~XxnBOhTmWM zWks@N$2Myhr)+JYG~mMM+Ti%mLoS_jD73Vp1lqu$(Ay3z?Aqff^p-LKw4kk0z0N4iL0AK_p+RLK*zybgbKo&sUfT31UIZ{P+WF70n3@k1~ zwzJ4K^2o0iP>@qdB>=PmY($9K1SCB0<~{HrfG^r;56)wLxQz063oV(&SjY!>NF+ic z5=Atig3M$g;Uw53CaXmh*EDEN0BZnt`VSy`Mxg^3*~a!~kMQVp4YgcLZuz!ub4PIk zk9r}A5fVjF6eBS~4OLO^=#pk?bgVV@b_O#`8Du^I_zQqVK%)LwWB}PV+Jg`A@bqiE z&Y7CYw)Jh_8nCz%I)Tsp2&~&INfJ?2RqSLsAy4q2wpGgon*na&R$YhQ0pJ1X^x-N1 zZ65Q(b<}f)YOrRa={KdOXW3T37z;V)yFZIkN?g|sJ>3g~bP(YvP)9vi-YkEb!juI- zi4b{0uRmkJP|7Hew@Ax3;)dT8o1ST#Jef>Nj~_q&rqO78x3#tP{qpkiw>NLz9IxQLL>Egu1#Metp zOCO#;e_mA-MZS0M-nC1YE)BV^8@AhRZnjLnt+u(9v<51u9PO>|E}T|T9bsUhBRPQs zCt!?)p67+9PMtbYuh-w5KY#w`D_5@kdiCnnpF~k47cN}*((}B~b=}Z$oWK@r&Qumu zX?3Kh3$nZC>sTM=;GsvokOkcthhd0?g@wgJp^&?O|NfcP)m8KQ_3K}Go)FMe6ix)3m9Y20NJ25eF#`k@1c6Roc+qZAO>VtJ%r<$Wt-PAh;6gB~v0C?Y9QUFFu zD2+bBlZhR5hi#>{x(am;S7;xcPN$^|%SeMC2j$C~mw%hW)H?tl0POU~;sR(-VzRM@ zwYN2=mIDREgh*oXnC~b~;QM|g2m-<|gd|Bs(=@8fI!(K2DY=!5jcty-Euy#vzyjdx zH7*8VLxU#IU}gybYOPw1`czbOMYI*0`-&ey>iVcmWI+iOQ8P5E@95Gwe zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00SIJL_t(Y$HkRTNRx3G$3NRU zEoW+N8Ja|Dl7lTYA)2&Pbg&L3f)Ps4F+u{p1YNv!^W?=tV5gMu5Gr&~qL2j|EGwE&l{86XDS z1D*mKW)xNdd>?QQxCR{4;z?jtDOlHYM&H~(E#L>XfcHw%5AYHoByg>aRu%F`fj1QX zCXkh15l|_gcfg{e{0_H(!@yN3P6MBT55Om>O-XS^;Itr4pcwE1_G-QC@s&1UoC$o7ukXBV7>~yn z!r}0m9(N3%yvcML@SM>gF1x`-M@KJ~mX^A^y1H(AJf2%aLqiXIK40C~*w|U45nV=O z<$eZF%D}CzECL)}uh+A+wUrtf8ChIkU*8@a9DD&#RaNB?xJdSH`6mn0lG3cGQv2`K zyL>Dbdld`@1JP*o((>|hqNSzfD8Tge^b3J^%f3R&$JOX zkMdgy98fBD348~5WNv8T$jxeOzS9u0Rh3F@xq#(bGy^=7;z#zt`Y(T?zxogTr^h$z W_aHIbN=I-20000 literal 0 HcmV?d00001 diff --git a/plugins/Eq/handlehover.png b/plugins/Eq/handlehover.png new file mode 100644 index 0000000000000000000000000000000000000000..ff8021d87ff8b1e1088f20a6dd79cd75c2e9b13d GIT binary patch literal 967 zcmV;&133JNP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00S>cL_t(Y$F-GBYaB-qhM%hG z+1c6ETDENKut6bmAfQ|V0iWzcAeUeaHu(|0=a(dB{fOXPLXHX8r$DX-LoA4354Jb{ z*pJzr>8bLeXQh1DRv>7g>F(;c-l}e<-V)yP)y|H=SfB(9(9P^nDNK68pYQUQw;9*Y zWr5uYl|Yb0svX_|^E6_B(&1?#OwS}=JNqP3g?@nDAPfSO*(s`Oon?fl5mwRDZOTG8 zdMEkX`52hNK!t-IjC%>R1{yy_=He9HdQv-&YFHXDDumzvMc!q+fDbd_tAVhU1)8?u zb$d$OIOMVkkaHo6Xh35`5g)j|Wgk9iO#^L91^@4N!I8vxny5nt+ehZB|(IH4q z?lmhwG*YTC49aJpDhIDyzW$BGHx0G3BT&JuZQ=SMG(S7fzJnsmae>-ug7+xAdu6X# z(<2)6BqAAz3Lo5tkG>FYeF;BSwX>rF;|M{xcN1jfOn!iiC2RpBhbzFI!=A0#Gt%hn zBTu-CW%84eaPMZ~V;q1|pjP(p!t$Zw))ENh4rSO7GDfL?+) z1CbVU2ORSpkrW6(y5GkNm5ZncotOSVg}4f`>Hz^X)#qSLjPLg!L-Y~ zaxmlQJ`8Rcq7aEJ1?CD-JM%t_c@OeuEpv(fv+qDs`9yh|b{y@R=~a11~F> z12ci=z_Gxw791;SboQAf+{-HY`OG(vf9d`T+Wv>`{|3b;*LpPn1Oxy8002ovPDHLkV1hPevhV-^ literal 0 HcmV?d00001 From 97644f6513b82b9c4093a16caded8932db7c5309 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Sat, 20 Feb 2016 12:02:44 -0500 Subject: [PATCH 40/90] Fix corrupt samples Closes #2594 --- data/samples/drums/snare04.ogg | Bin 9465 -> 9088 bytes data/samples/drums/snare05.ogg | Bin 9470 -> 9484 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/data/samples/drums/snare04.ogg b/data/samples/drums/snare04.ogg index d4a116e8569da0fdeb121d914188bca39d6a721a..9a521d5aad48eb706866e0d80093a64170afe5ff 100644 GIT binary patch literal 9088 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 WUpQ;?-Ze3SL2uu`G6fa|i2njkzqmU9 diff --git a/data/samples/drums/snare05.ogg b/data/samples/drums/snare05.ogg index 0af08e5d2f21bc0d1ffe87ec0d0c4ad01b28b70a..5a34215c02bc90406d93c22060ccfc10857db507 100644 GIT binary patch literal 9484 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�nCe6EK`znq`t{THde!HC#-?at3RATL-5eR7=R7t%*=FumTN|V-#c7nK zYx&s_p3DMK11y2z7=I=#1G_m@Yu&(J%=M( z2Y`GDJ=2`x^y}qG&iikk%@n#c+`j28$BRBAhEOPiZ6+eOefn{iq)i=PEh+lloU5=5 zBK=ssv{JpjefoiQbNHp3?K4_KOgjzFj#l^Qjy+#uHxyC*ewhjZF!X>JOA93u;dbnR z-^;phl9|NK8OPO7JMAfLduQxNt#nC@7<)S&HOAz{={l9i!`mAVIm2XAte`mgl?yaG z3WIR3q$4(Z9=ip9GEzSKT(*$^3XJ=0Ft>5kugP(nPaYAk3##v!&Q|W&=CV<`ZYEM6 z=Z$SXe|JR4MGOqT;=ryZOl+QaD=IKV_x3FOs6-`6;&*{KEFDCAe{opOe)a^su0{L8 zFxst(;BCt)k_hf02)tA3kSl6fc}`5b=N~- z(gG}QRWQ`AThMRSgv4Hk!wruLHmMvfu$jKh|05#e(V+;j9q;cshYba@gyp|r_? z1A2<_$cGchn5eBbrc9;`-hTPo!f;;r%qyi==7R&L`S!LW-aRL67c5UihcZeTbRMC` z>&9(=yUvStoOKeI@@G%FadS6X<}a$<|!wD)1>c zja?Kp7fo6$KIN{gV#dshpRPjfpKais_EonMsUejl~fHg8p#kt}=3^xetxZaQ9{ z>*gr)8g6aB`|?XKY*C&A*U7MYSy&Nij~jDk_WHs-5%M8CJIxz*iN44Q zo_zIU#|(qeUnCsHXZ6Mv~GvpwP9(#AilmqVl*A$jRv zB!7!x(5f*wF=ciprS}x7PoD*@GmiUK@Z;@N*vI#MH>H2?E427x5UZaxe$0gDqAbdR zD%wEP8sO0YkAZU$mj(I7@p!Q3p?g>M+%$h?4gZeBz0P=UHD&7d;L`A4A3YWrzimxD zh!t->s&rN6(c5VT8OkhO6r^&Z!;_JZpBsmQK7BE_|9v~$!1Sbv)Qw5uMg>0xgX8C) z*Co9AtQoj!^Rqg&*>fh(hEBo0MYt}gF@K|dmNe5Nd#X@nY+Z7oGJG6;N}6*(=zL*& z#P6Enk7i7-T+7S`qodh5GKE8jQ(FwPv-O6yNN+^wv1*qF+iu&1{JhaT?lFe3h4)(W z=}&Rq3CS^iwzM1W@Z~e-z{d}}y~chKZ}>sOd($hsE_toxPxl7bKJ~;#-P% Date: Sun, 21 Feb 2016 17:19:55 +1300 Subject: [PATCH 41/90] Build: Make mingw build scripts paths independent of wdir --- cmake/build_mingw32.sh | 4 ++-- cmake/build_mingw64.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/build_mingw32.sh b/cmake/build_mingw32.sh index 455da6fc53e..8d36c94b593 100755 --- a/cmake/build_mingw32.sh +++ b/cmake/build_mingw32.sh @@ -16,5 +16,5 @@ if [ "$1" = "-qt5" ] ; then CMAKE_OPTS="-DWANT_QT5=ON -DCMAKE_PREFIX_PATH=$MINGW $CMAKE_OPTS" fi -cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/modules/Win32Toolchain.cmake -DCMAKE_MODULE_PATH=`pwd`/../cmake/modules/ $CMAKE_OPTS - +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cmake $DIR/.. -DCMAKE_TOOLCHAIN_FILE=$DIR/../cmake/modules/Win32Toolchain.cmake -DCMAKE_MODULE_PATH=$DIR/../cmake/modules/ $CMAKE_OPTS diff --git a/cmake/build_mingw64.sh b/cmake/build_mingw64.sh index d5f393d24eb..211b629c08b 100755 --- a/cmake/build_mingw64.sh +++ b/cmake/build_mingw64.sh @@ -14,5 +14,5 @@ if [ "$1" = "-qt5" ] ; then CMAKE_OPTS="-DWANT_QT5=ON -DCMAKE_PREFIX_PATH=$MINGW $CMAKE_OPTS" fi -cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/modules/Win64Toolchain.cmake -DCMAKE_MODULE_PATH=`pwd`/../cmake/modules/ $CMAKE_OPTS - +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cmake $DIR/.. -DCMAKE_TOOLCHAIN_FILE=$DIR/../cmake/modules/Win64Toolchain.cmake -DCMAKE_MODULE_PATH=$DIR/../cmake/modules/ $CMAKE_OPTS From 34ae0748845a198a82dc9ca47d31a4039ba2a6b3 Mon Sep 17 00:00:00 2001 From: Ben Bryan Date: Sun, 21 Feb 2016 00:10:20 -0600 Subject: [PATCH 42/90] Fix EQ labels back to resonance. --- plugins/Eq/EqControlsDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/Eq/EqControlsDialog.cpp b/plugins/Eq/EqControlsDialog.cpp index efda0ad0b2a..f2d8529f343 100644 --- a/plugins/Eq/EqControlsDialog.cpp +++ b/plugins/Eq/EqControlsDialog.cpp @@ -103,7 +103,7 @@ EqControlsDialog::EqControlsDialog( EqControls *controls ) : mainLayout->setAlignment( m_resKnob, Qt::AlignHCenter ); m_resKnob->setVolumeKnob(false); m_resKnob->setModel( m_parameterWidget->getBandModels( i )->res ); - if(i > 0 && i < 7) { m_resKnob->setHintText( tr( "Bandwidth: " ) , tr( " Octave" ) ); } + if(i > 1 && i < 6) { m_resKnob->setHintText( tr( "Bandwidth: " ) , tr( " Octave" ) ); } else { m_resKnob->setHintText( tr( "Resonance : " ) , "" ); } m_freqKnob = new Knob( knobBright_26, this ); From 020cb528b6cea3bfd895e0a51fba34009b3095e9 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Fri, 19 Feb 2016 16:21:41 -0500 Subject: [PATCH 43/90] Add additional build deps --- .travis/osx..install.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.travis/osx..install.sh b/.travis/osx..install.sh index af530b2258b..4c39880a3aa 100644 --- a/.travis/osx..install.sh +++ b/.travis/osx..install.sh @@ -1 +1,9 @@ -brew install qt libsndfile fftw libvorbis libogg jack sdl libsamplerate stk fluid-synth portaudio fltk +brew reinstall cmake pkgconfig qt fftw libogg libvorbis libsndfile libsamplerate jack sdl stk fluid-synth portaudio node +sudo npm install -g appdmg + +# Workaround per Homebrew bug #44806 +brew reinstall fltk +if [ $? -ne 0 ]; then + echo "Warning: fltk installation failed, trying workaround..." + brew reinstall --devel https://raw.githubusercontent.com/dpo/homebrew/ec46018128dde5bf466b013a6c7086d0880930a3/Library/Formula/fltk.rb +fi From 1e9dfcbf2b97fdfed487f79aba595d70b9c28df9 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Mon, 22 Feb 2016 13:54:39 -0500 Subject: [PATCH 44/90] Remove 64-bit channel limitation in readme Closes #2600 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 708190b1a2b..ad6b91b1972 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Features * Song-Editor for composing songs * A Beat+Bassline-Editor for creating beats and basslines * An easy-to-use Piano-Roll for editing patterns and melodies -* An FX mixer with 64 FX channels and arbitrary number of effects allow unlimited mixing possibilities +* An FX mixer with unlimited FX channels and arbitrary number of effects * Many powerful instrument and effect-plugins out of the box * Full user-defined track-based automation and computer-controlled automation sources * Compatible with many standards such as SoundFont2, VST(i), LADSPA, GUS Patches, and full MIDI support From 13125c62481a8d46db93a6443b76159f33510357 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Tue, 23 Feb 2016 10:11:38 +1300 Subject: [PATCH 45/90] Change cross compile scripts' shebang to bash --- cmake/build_mingw32.sh | 2 +- cmake/build_mingw64.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/build_mingw32.sh b/cmake/build_mingw32.sh index 8d36c94b593..8c47a0441f8 100755 --- a/cmake/build_mingw32.sh +++ b/cmake/build_mingw32.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # Accomodate both linux windows mingw locations MINGW=/mingw32 diff --git a/cmake/build_mingw64.sh b/cmake/build_mingw64.sh index 211b629c08b..9d0b1495bef 100755 --- a/cmake/build_mingw64.sh +++ b/cmake/build_mingw64.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # Accomodate both linux windows mingw locations MINGW=/mingw64 From d88902e95bc88ae77e6c75aee40ac945a0c5f324 Mon Sep 17 00:00:00 2001 From: tresf Date: Tue, 23 Feb 2016 01:08:08 -0500 Subject: [PATCH 46/90] Fix rawwaves directory on Windows Per #2577 --- plugins/stk/mallets/mallets.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/stk/mallets/mallets.cpp b/plugins/stk/mallets/mallets.cpp index 44b43830a64..d99c36820c7 100644 --- a/plugins/stk/mallets/mallets.cpp +++ b/plugins/stk/mallets/mallets.cpp @@ -532,7 +532,7 @@ malletsSynth::malletsSynth( const StkFloat _pitch, try { Stk::setSampleRate( _sample_rate ); - Stk::setRawwavePath( ConfigManager::inst()->stkDir() + Stk::setRawwavePath( QDir( ConfigManager::inst()->stkDir() ).absolutePath() .toLatin1().constData() ); m_voice = new ModalBar(); @@ -579,7 +579,7 @@ malletsSynth::malletsSynth( const StkFloat _pitch, try { Stk::setSampleRate( _sample_rate ); - Stk::setRawwavePath( ConfigManager::inst()->stkDir() + Stk::setRawwavePath( QDir( ConfigManager::inst()->stkDir() ).absolutePath() .toLatin1().constData() ); m_voice = new TubeBell(); @@ -624,7 +624,7 @@ malletsSynth::malletsSynth( const StkFloat _pitch, try { Stk::setSampleRate( _sample_rate ); - Stk::setRawwavePath( ConfigManager::inst()->stkDir() + Stk::setRawwavePath( QDir( ConfigManager::inst()->stkDir() ).absolutePath() .toLatin1().constData() ); m_voice = new BandedWG(); From eec7f634a866a145149c37e0bbf3ae960fbd298b Mon Sep 17 00:00:00 2001 From: Fastigium Date: Tue, 23 Feb 2016 10:36:35 +0100 Subject: [PATCH 47/90] Update two NotePlayHandle methods to ignore child NotePlayHandles The methods NotePlayHandle::index and NotePlayHandle::nphsOfInstrumentTrack had not yet been brought up-to-date with the new system of attaching child NotePlayHandles directly to the mixer. This caused strange glitches when arpeggio was used in sort mode. --- include/NotePlayHandle.h | 8 +++++--- src/core/NotePlayHandle.cpp | 8 ++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/NotePlayHandle.h b/include/NotePlayHandle.h index bedc095f54d..130799b0709 100644 --- a/include/NotePlayHandle.h +++ b/include/NotePlayHandle.h @@ -206,11 +206,13 @@ class EXPORT NotePlayHandle : public PlayHandle, public Note void mute(); /*! Returns index of NotePlayHandle in vector of note-play-handles - belonging to this instrument track - used by arpeggiator */ + belonging to this instrument track - used by arpeggiator. + Ignores child note-play-handles, returns -1 when called on one */ int index() const; - /*! returns list of note-play-handles belonging to given instrument track, - if allPlayHandles = true, also released note-play-handles are returned */ + /*! Returns list of note-play-handles belonging to given instrument track. + If allPlayHandles = true, also released note-play-handles and children + are returned */ static ConstNotePlayHandleList nphsOfInstrumentTrack( const InstrumentTrack* Track, bool allPlayHandles = false ); /*! Returns whether given NotePlayHandle instance is equal to *this */ diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index 368cecb9a58..d0fadece33c 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -449,17 +449,17 @@ int NotePlayHandle::index() const for( PlayHandleList::ConstIterator it = playHandles.begin(); it != playHandles.end(); ++it ) { const NotePlayHandle * nph = dynamic_cast( *it ); - if( nph == NULL || nph->m_instrumentTrack != m_instrumentTrack || nph->isReleased() ) + if( nph == NULL || nph->m_instrumentTrack != m_instrumentTrack || nph->isReleased() || nph->hasParent() ) { continue; } if( nph == this ) { - break; + return idx; } ++idx; } - return idx; + return -1; } @@ -473,7 +473,7 @@ ConstNotePlayHandleList NotePlayHandle::nphsOfInstrumentTrack( const InstrumentT for( PlayHandleList::ConstIterator it = playHandles.begin(); it != playHandles.end(); ++it ) { const NotePlayHandle * nph = dynamic_cast( *it ); - if( nph != NULL && nph->m_instrumentTrack == _it && ( nph->isReleased() == false || _all_ph == true ) ) + if( nph != NULL && nph->m_instrumentTrack == _it && ( ( nph->isReleased() == false && nph->hasParent() == false ) || _all_ph == true ) ) { cnphv.push_back( nph ); } From b645f43cfd08d17d01175603c154fc0cf5f7efaf Mon Sep 17 00:00:00 2001 From: Fastigium Date: Wed, 24 Feb 2016 16:37:53 +0100 Subject: [PATCH 48/90] Destroy the FxMixer before the Mixer when shutting down Fixes #2584. --- src/core/Engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Engine.cpp b/src/core/Engine.cpp index f1aebef97c5..3e345368ed8 100644 --- a/src/core/Engine.cpp +++ b/src/core/Engine.cpp @@ -94,8 +94,8 @@ void LmmsCore::destroy() deleteHelper( &s_bbTrackContainer ); deleteHelper( &s_dummyTC ); - deleteHelper( &s_mixer ); deleteHelper( &s_fxMixer ); + deleteHelper( &s_mixer ); deleteHelper( &s_ladspaManager ); From 389a1da30854e6d93e1be1a2599cab2f7a0c02cd Mon Sep 17 00:00:00 2001 From: tresf Date: Wed, 24 Feb 2016 15:07:26 -0500 Subject: [PATCH 49/90] Add Mac/Qt5 build directives for Travis Also explicitly defines bash as shell interpreter for all Travis related scripts --- .travis.yml | 2 ++ .travis/linux..before_install.sh | 5 +++-- .travis/linux..install.sh | 2 ++ .travis/linux..script.sh | 2 ++ .travis/linux.win32.before_install.sh | 2 ++ .travis/linux.win32.install.sh | 10 ++++++---- .travis/linux.win32.script.sh | 2 ++ .travis/linux.win64.before_install.sh | 4 +++- .travis/linux.win64.install.sh | 12 +++++++----- .travis/linux.win64.script.sh | 2 ++ .travis/osx..before_install.sh | 2 ++ .travis/osx..install.sh | 13 ++++++++++++- .travis/osx..script.sh | 9 ++++++++- 13 files changed, 53 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index a9530841608..5d4fb6c699b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,8 @@ matrix: - env: TARGET_OS=win64 - env: QT5=True - os: osx + - os: osx + env: QT5=True before_install: - sh ${TRAVIS_BUILD_DIR}/.travis/${TRAVIS_OS_NAME}.${TARGET_OS}.before_install.sh install: diff --git a/.travis/linux..before_install.sh b/.travis/linux..before_install.sh index 151db4d78c9..8a64d814c35 100644 --- a/.travis/linux..before_install.sh +++ b/.travis/linux..before_install.sh @@ -1,7 +1,8 @@ +#!/usr/bin/env bash + sudo add-apt-repository ppa:kalakris/cmake -y; sudo add-apt-repository ppa:andrewrk/libgroove -y; -if [ $QT5 ] - then +if [ $QT5 ]; then sudo add-apt-repository ppa:ubuntu-sdk-team/ppa -y fi sudo apt-get update -qq diff --git a/.travis/linux..install.sh b/.travis/linux..install.sh index 4be588ae832..96214d43dac 100644 --- a/.travis/linux..install.sh +++ b/.travis/linux..install.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + PACKAGES="cmake libsndfile-dev fftw3-dev libvorbis-dev libogg-dev libasound2-dev libjack-dev libsdl-dev libsamplerate0-dev libstk0-dev libfluidsynth-dev portaudio19-dev wine-dev g++-multilib libfltk1.3-dev diff --git a/.travis/linux..script.sh b/.travis/linux..script.sh index 3403b74f289..f4ab59f6f81 100644 --- a/.travis/linux..script.sh +++ b/.travis/linux..script.sh @@ -1 +1,3 @@ +#!/usr/bin/env bash + cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DUSE_WERROR=ON -DWANT_QT5=$QT5 .. diff --git a/.travis/linux.win32.before_install.sh b/.travis/linux.win32.before_install.sh index 73c14aedd2f..5ee747fa168 100644 --- a/.travis/linux.win32.before_install.sh +++ b/.travis/linux.win32.before_install.sh @@ -1,2 +1,4 @@ +#!/usr/bin/env bash + sudo add-apt-repository ppa:tobydox/mingw-x-precise -y sudo apt-get update -qq diff --git a/.travis/linux.win32.install.sh b/.travis/linux.win32.install.sh index d8398fad5a3..702eac4de9d 100644 --- a/.travis/linux.win32.install.sh +++ b/.travis/linux.win32.install.sh @@ -1,7 +1,9 @@ +#!/usr/bin/env bash + sudo apt-get install -y nsis cloog-isl libmpc2 mingw32 -sudo apt-get install -y mingw32-x-qt mingw32-x-sdl mingw32-x-libvorbis \ - mingw32-x-fluidsynth mingw32-x-stk mingw32-x-glib2 mingw32-x-portaudio \ - mingw32-x-libsndfile mingw32-x-fftw mingw32-x-flac mingw32-x-fltk \ - mingw32-x-libsamplerate mingw32-x-pkgconfig mingw32-x-binutils \ +sudo apt-get install -y mingw32-x-qt mingw32-x-sdl mingw32-x-libvorbis \ + mingw32-x-fluidsynth mingw32-x-stk mingw32-x-glib2 mingw32-x-portaudio \ + mingw32-x-libsndfile mingw32-x-fftw mingw32-x-flac mingw32-x-fltk \ + mingw32-x-libsamplerate mingw32-x-pkgconfig mingw32-x-binutils \ mingw32-x-gcc mingw32-x-runtime mingw32-x-libgig mingw32-x-libsoundio diff --git a/.travis/linux.win32.script.sh b/.travis/linux.win32.script.sh index 2101024a28d..ea2a6b7f7f1 100644 --- a/.travis/linux.win32.script.sh +++ b/.travis/linux.win32.script.sh @@ -1,2 +1,4 @@ +#!/usr/bin/env bash + export CMAKE_OPTS="-DUSE_WERROR=ON" ../cmake/build_mingw32.sh || ../cmake/build_mingw32.sh diff --git a/.travis/linux.win64.before_install.sh b/.travis/linux.win64.before_install.sh index a598ff1ca9c..8a473edb227 100644 --- a/.travis/linux.win64.before_install.sh +++ b/.travis/linux.win64.before_install.sh @@ -1 +1,3 @@ -sh .travis/linux.win32.before_install.sh +#!/usr/bin/env bash + +. .travis/linux.win32.before_install.sh diff --git a/.travis/linux.win64.install.sh b/.travis/linux.win64.install.sh index 1e3074ac13e..340311530df 100644 --- a/.travis/linux.win64.install.sh +++ b/.travis/linux.win64.install.sh @@ -1,7 +1,9 @@ -sh .travis/linux.win32.install.sh +#!/usr/bin/env bash -sudo apt-get install -y mingw64-x-qt mingw64-x-sdl mingw64-x-libvorbis \ - mingw64-x-fluidsynth mingw64-x-stk mingw64-x-glib2 mingw64-x-portaudio \ - mingw64-x-libsndfile mingw64-x-fftw mingw64-x-flac mingw64-x-fltk \ - mingw64-x-libsamplerate mingw64-x-pkgconfig mingw64-x-binutils mingw64-x-gcc\ +. .travis/linux.win32.install.sh + +sudo apt-get install -y mingw64-x-qt mingw64-x-sdl mingw64-x-libvorbis \ + mingw64-x-fluidsynth mingw64-x-stk mingw64-x-glib2 mingw64-x-portaudio \ + mingw64-x-libsndfile mingw64-x-fftw mingw64-x-flac mingw64-x-fltk \ + mingw64-x-libsamplerate mingw64-x-pkgconfig mingw64-x-binutils mingw64-x-gcc \ mingw64-x-runtime mingw64-x-libgig mingw64-x-libsoundio diff --git a/.travis/linux.win64.script.sh b/.travis/linux.win64.script.sh index 5bb99d6e5fa..ad9fc9e99c3 100644 --- a/.travis/linux.win64.script.sh +++ b/.travis/linux.win64.script.sh @@ -1,2 +1,4 @@ +#!/usr/bin/env bash + export CMAKE_OPTS="-DUSE_WERROR=ON" ../cmake/build_mingw64.sh || ../cmake/build_mingw64.sh diff --git a/.travis/osx..before_install.sh b/.travis/osx..before_install.sh index 3387d7dcfa0..75b692e9790 100644 --- a/.travis/osx..before_install.sh +++ b/.travis/osx..before_install.sh @@ -1 +1,3 @@ +#!/usr/bin/env bash + brew update diff --git a/.travis/osx..install.sh b/.travis/osx..install.sh index 4c39880a3aa..1e8fe0e1b5c 100644 --- a/.travis/osx..install.sh +++ b/.travis/osx..install.sh @@ -1,4 +1,15 @@ -brew reinstall cmake pkgconfig qt fftw libogg libvorbis libsndfile libsamplerate jack sdl stk fluid-synth portaudio node +#!/usr/bin/env bash + +PACKAGES="cmake pkgconfig fftw libogg libvorbis libsndfile libsamplerate jack sdl stk fluid-synth portaudio node" + +if [ $QT5 ]; then + PACKAGES="$PACKAGES qt5" +else + PACKAGES="$PACKAGES qt" +fi + +brew reinstall $PACKAGES + sudo npm install -g appdmg # Workaround per Homebrew bug #44806 diff --git a/.travis/osx..script.sh b/.travis/osx..script.sh index d594e58f6d4..981fb5b86f8 100644 --- a/.travis/osx..script.sh +++ b/.travis/osx..script.sh @@ -1 +1,8 @@ -cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo .. -DUSE_WERROR=OFF +#!/usr/bin/env bash + +if [ $QT5 ]; then + # Workaround; No FindQt5.cmake module exists + export CMAKE_PREFIX_PATH="$(brew --prefix qt5)" +fi + +cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWANT_QT5=$QT5 -DUSE_WERROR=OFF .. From 1598343b865b937d82d385ef449df471cadda99d Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Thu, 25 Feb 2016 00:38:25 +0200 Subject: [PATCH 50/90] Remove a completely useless warning --- src/core/EffectChain.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/core/EffectChain.cpp b/src/core/EffectChain.cpp index d3af38573c1..f06cc04aa90 100644 --- a/src/core/EffectChain.cpp +++ b/src/core/EffectChain.cpp @@ -223,20 +223,6 @@ bool EffectChain::processAudioBuffer( sampleFrame * _buf, const fpp_t _frames, b MixHelpers::sanitize( _buf, _frames ); } } - -#ifdef LMMS_DEBUG - for( int f = 0; f < _frames; ++f ) - { - if( fabs( _buf[f][0] ) > 5 || fabs( _buf[f][1] ) > 5 ) - { - it = m_effects.end()-1; - printf( "numerical overflow after processing " - "plugin \"%s\"\n", ( *it )-> - descriptor()->name); - break; - } - } -#endif } return moreEffects; From 67334a84c270e38a8d5a209970db073445e40bad Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Wed, 24 Feb 2016 19:17:34 -0500 Subject: [PATCH 51/90] Add Win/Qt5 build directives for Travis --- .travis.yml | 10 ++++++---- .travis/linux..install.sh | 3 +-- .travis/linux.win32.install.sh | 19 +++++++++++++------ .travis/linux.win64.install.sh | 23 +++++++++++++++++------ CMakeLists.txt | 2 +- cmake/build_mingw32.sh | 8 ++++++-- cmake/build_mingw64.sh | 8 ++++++-- plugins/vst_base/Win64/CMakeLists.txt | 10 ++++++++-- src/CMakeLists.txt | 18 +++++++++++++++++- 9 files changed, 75 insertions(+), 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5d4fb6c699b..9ae7ddff3d1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,18 +4,20 @@ matrix: include: - env: TARGET_OS=win32 - env: TARGET_OS=win64 + - os: osx - env: QT5=True - - os: osx + - env: QT5=True TARGET_OS=win32 + - env: QT5=True TARGET_OS=win64 - os: osx env: QT5=True before_install: - - sh ${TRAVIS_BUILD_DIR}/.travis/${TRAVIS_OS_NAME}.${TARGET_OS}.before_install.sh + - . ${TRAVIS_BUILD_DIR}/.travis/${TRAVIS_OS_NAME}.${TARGET_OS}.before_install.sh install: - - sh ${TRAVIS_BUILD_DIR}/.travis/${TRAVIS_OS_NAME}.${TARGET_OS}.install.sh + - . ${TRAVIS_BUILD_DIR}/.travis/${TRAVIS_OS_NAME}.${TARGET_OS}.install.sh before_script: - mkdir build && cd build script: - - sh ${TRAVIS_BUILD_DIR}/.travis/${TRAVIS_OS_NAME}.${TARGET_OS}.script.sh + - . ${TRAVIS_BUILD_DIR}/.travis/${TRAVIS_OS_NAME}.${TARGET_OS}.script.sh - make -j4 - if [[ $TARGET_OS != win* ]]; then make tests && ./tests/tests; fi; before_deploy: make package diff --git a/.travis/linux..install.sh b/.travis/linux..install.sh index 96214d43dac..dc27c5c17ca 100644 --- a/.travis/linux..install.sh +++ b/.travis/linux..install.sh @@ -5,8 +5,7 @@ PACKAGES="cmake libsndfile-dev fftw3-dev libvorbis-dev libogg-dev libfluidsynth-dev portaudio19-dev wine-dev g++-multilib libfltk1.3-dev libgig-dev libsoundio-dev" -if [ $QT5 ] -then +if [ $QT5 ]; then PACKAGES="$PACKAGES qtbase5-dev qttools5-dev-tools qttools5-dev" else PACKAGES="$PACKAGES libqt4-dev" diff --git a/.travis/linux.win32.install.sh b/.travis/linux.win32.install.sh index 702eac4de9d..5d61807d9f2 100644 --- a/.travis/linux.win32.install.sh +++ b/.travis/linux.win32.install.sh @@ -1,9 +1,16 @@ #!/usr/bin/env bash -sudo apt-get install -y nsis cloog-isl libmpc2 mingw32 +PACKAGES="nsis cloog-isl libmpc2 mingw32 + mingw32-x-sdl mingw32-x-libvorbis mingw32-x-fluidsynth mingw32-x-stk + mingw32-x-glib2 mingw32-x-portaudio mingw32-x-libsndfile mingw32-x-fftw + mingw32-x-flac mingw32-x-fltk mingw32-x-libsamplerate + mingw32-x-pkgconfig mingw32-x-binutils mingw32-x-gcc mingw32-x-runtime + mingw32-x-libgig mingw32-x-libsoundio" -sudo apt-get install -y mingw32-x-qt mingw32-x-sdl mingw32-x-libvorbis \ - mingw32-x-fluidsynth mingw32-x-stk mingw32-x-glib2 mingw32-x-portaudio \ - mingw32-x-libsndfile mingw32-x-fftw mingw32-x-flac mingw32-x-fltk \ - mingw32-x-libsamplerate mingw32-x-pkgconfig mingw32-x-binutils \ - mingw32-x-gcc mingw32-x-runtime mingw32-x-libgig mingw32-x-libsoundio +if [ $QT5 ]; then + PACKAGES="$PACKAGES mingw32-x-qt5base" +else + PACKAGES="$PACKAGES mingw32-x-qt" +fi + +sudo apt-get install -y $PACKAGES diff --git a/.travis/linux.win64.install.sh b/.travis/linux.win64.install.sh index 340311530df..26754ae6492 100644 --- a/.travis/linux.win64.install.sh +++ b/.travis/linux.win64.install.sh @@ -1,9 +1,20 @@ #!/usr/bin/env bash -. .travis/linux.win32.install.sh +# First, install 32-bit deps -sudo apt-get install -y mingw64-x-qt mingw64-x-sdl mingw64-x-libvorbis \ - mingw64-x-fluidsynth mingw64-x-stk mingw64-x-glib2 mingw64-x-portaudio \ - mingw64-x-libsndfile mingw64-x-fftw mingw64-x-flac mingw64-x-fltk \ - mingw64-x-libsamplerate mingw64-x-pkgconfig mingw64-x-binutils mingw64-x-gcc \ - mingw64-x-runtime mingw64-x-libgig mingw64-x-libsoundio +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +. $DIR/linux.win32.install.sh + +PACKAGES="mingw64-x-sdl mingw64-x-libvorbis mingw64-x-fluidsynth mingw64-x-stk + mingw64-x-glib2 mingw64-x-portaudio mingw64-x-libsndfile + mingw64-x-fftw mingw64-x-flac mingw64-x-fltk mingw64-x-libsamplerate + mingw64-x-pkgconfig mingw64-x-binutils mingw64-x-gcc mingw64-x-runtime + mingw64-x-libgig mingw64-x-libsoundio" + +if [ $QT5 ]; then + PACKAGES="$PACKAGES mingw64-x-qt5base" +else + PACKAGES="$PACKAGES mingw64-x-qt" +fi + +sudo apt-get install -y $PACKAGES diff --git a/CMakeLists.txt b/CMakeLists.txt index 1fe5abc83ad..aa24f2eace0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,7 +132,7 @@ IF(WANT_QT5) FIND_PACKAGE(Qt5Core REQUIRED) FIND_PACKAGE(Qt5Gui REQUIRED) - FIND_PACKAGE(Qt5LinguistTools REQUIRED) + FIND_PACKAGE(Qt5LinguistTools) FIND_PACKAGE(Qt5Widgets REQUIRED) FIND_PACKAGE(Qt5Xml REQUIRED) diff --git a/cmake/build_mingw32.sh b/cmake/build_mingw32.sh index 8c47a0441f8..f485daf9a6e 100755 --- a/cmake/build_mingw32.sh +++ b/cmake/build_mingw32.sh @@ -12,8 +12,12 @@ export PATH=$PATH:$MINGW/bin export CFLAGS="-march=pentium3 -mtune=generic -mpreferred-stack-boundary=5 -mfpmath=sse" export CXXFLAGS="$CFLAGS" -if [ "$1" = "-qt5" ] ; then - CMAKE_OPTS="-DWANT_QT5=ON -DCMAKE_PREFIX_PATH=$MINGW $CMAKE_OPTS" +if [ "$1" = "-qt5" ]; then + QT5=True +fi + +if [ $QT5 ]; then + CMAKE_OPTS="-DWANT_QT5=$QT5 -DCMAKE_PREFIX_PATH=$MINGW $CMAKE_OPTS" fi DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" diff --git a/cmake/build_mingw64.sh b/cmake/build_mingw64.sh index 9d0b1495bef..ceb850455ec 100755 --- a/cmake/build_mingw64.sh +++ b/cmake/build_mingw64.sh @@ -10,8 +10,12 @@ fi export PATH=$PATH:$MINGW/bin -if [ "$1" = "-qt5" ] ; then - CMAKE_OPTS="-DWANT_QT5=ON -DCMAKE_PREFIX_PATH=$MINGW $CMAKE_OPTS" +if [ "$1" = "-qt5" ]; then + QT5=True +fi + +if [ $QT5 ]; then + CMAKE_OPTS="-DWANT_QT5=$QT5 -DCMAKE_PREFIX_PATH=$MINGW $CMAKE_OPTS" fi DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" diff --git a/plugins/vst_base/Win64/CMakeLists.txt b/plugins/vst_base/Win64/CMakeLists.txt index a815e9c5f54..6a670829c6e 100644 --- a/plugins/vst_base/Win64/CMakeLists.txt +++ b/plugins/vst_base/Win64/CMakeLists.txt @@ -2,12 +2,18 @@ INCLUDE_DIRECTORIES("${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}/include") SET(CMAKE_CXX_COMPILER "${CMAKE_CXX_COMPILER32}") ADD_EXECUTABLE(RemoteVstPlugin32 "${CMAKE_CURRENT_SOURCE_DIR}/../RemoteVstPlugin.cpp") -TARGET_LINK_LIBRARIES(RemoteVstPlugin32 -lQtCore4 -lpthread -lgdi32 -lws2_32) + +IF(QT5) + SET(QTCORE "Qt5Core") +ELSE() + SET(QTCORE "QtCore4") +ENDIF() +TARGET_LINK_LIBRARIES(RemoteVstPlugin32 -l${QTCORE} -lpthread -lgdi32 -lws2_32) ADD_CUSTOM_COMMAND(TARGET RemoteVstPlugin32 POST_BUILD COMMAND "${STRIP}" "$") SET_TARGET_PROPERTIES(RemoteVstPlugin32 PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -O0") INSTALL(TARGETS RemoteVstPlugin32 RUNTIME DESTINATION "${PLUGIN_DIR}/32") -INSTALL(FILES "${MINGW_PREFIX32}/bin/QtCore4.dll" "${MINGW_PREFIX32}/bin/zlib1.dll" "${MINGW_PREFIX32}/${CMAKE_SYSTEM_PROCESSOR32}-w64-mingw32/bin/libwinpthread-1.dll" +INSTALL(FILES "${MINGW_PREFIX32}/bin/${QTCORE}.dll" "${MINGW_PREFIX32}/bin/zlib1.dll" "${MINGW_PREFIX32}/${CMAKE_SYSTEM_PROCESSOR32}-w64-mingw32/bin/libwinpthread-1.dll" DESTINATION "${PLUGIN_DIR}/32") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fb7038c740d..ba49245d1af 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -178,11 +178,27 @@ IF(LMMS_BUILD_WIN32) ENDIF() INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") - INSTALL(FILES + + IF(QT5) + INSTALL(FILES + "${MINGW_PREFIX}/bin/Qt5Core.dll" + "${MINGW_PREFIX}/bin/Qt5Gui.dll" + "${MINGW_PREFIX}/bin/Qt5Widgets.dll" + "${MINGW_PREFIX}/bin/Qt5Xml.dll" + DESTINATION .) + INSTALL(FILES + "${MINGW_PREFIX}/lib/qt5/plugins/platforms/qwindows.dll" + DESTINATION ./platforms) + ELSE() + INSTALL(FILES "${MINGW_PREFIX}/bin/QtCore4.dll" "${MINGW_PREFIX}/bin/QtGui4.dll" "${MINGW_PREFIX}/bin/QtSvg4.dll" "${MINGW_PREFIX}/bin/QtXml4.dll" + DESTINATION .) + ENDIF() + + INSTALL(FILES "${MINGW_PREFIX}/bin/libsamplerate-0.dll" "${MINGW_PREFIX}/bin/libsndfile-1.dll" "${MINGW_PREFIX}/bin/libvorbis-0.dll" From 59276a03075055581dad0b8bf70bbb6ced0182c0 Mon Sep 17 00:00:00 2001 From: Colin Wallace Date: Wed, 24 Feb 2016 18:25:49 -0800 Subject: [PATCH 52/90] Only use libc++ on APPLE; remove LMMS_BUILD_CLANG define, as it's no longer needed --- cmake/modules/DetectMachine.cmake | 4 ---- plugins/flp_import/CMakeLists.txt | 2 +- src/CMakeLists.txt | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/cmake/modules/DetectMachine.cmake b/cmake/modules/DetectMachine.cmake index f981df051e5..c0d6cba341b 100644 --- a/cmake/modules/DetectMachine.cmake +++ b/cmake/modules/DetectMachine.cmake @@ -8,10 +8,6 @@ ELSE() SET(LMMS_BUILD_LINUX 1) ENDIF(WIN32) -IF(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") - SET(LMMS_BUILD_CLANG 1) -ENDIF() - # See build_mingwXX.sh for LMMS_BUILD_MSYS MESSAGE("PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}") diff --git a/plugins/flp_import/CMakeLists.txt b/plugins/flp_import/CMakeLists.txt index bdc38e8162e..833bbd665fc 100644 --- a/plugins/flp_import/CMakeLists.txt +++ b/plugins/flp_import/CMakeLists.txt @@ -5,7 +5,7 @@ INCLUDE_DIRECTORIES(unrtf) # Enable C++11 ADD_DEFINITIONS(-std=c++0x) -IF(LMMS_BUILD_CLANG) +IF(LMMS_BUILD_APPLE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") ENDIF() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fb7038c740d..b6a8fc37f57 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,7 +10,7 @@ SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) # Enable C++11 ADD_DEFINITIONS(-std=c++0x) -IF(LMMS_BUILD_CLANG) +IF(LMMS_BUILD_APPLE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") ENDIF() From 4ddaa872fb28c777ca69e48888e00bb69dfdb9d3 Mon Sep 17 00:00:00 2001 From: Bastian Kummer Date: Tue, 1 Mar 2016 13:54:20 +0100 Subject: [PATCH 53/90] Fixup Zynaddsubfx-GUI on FreeBSD shmFifo destructor detaches shared-memory pointer before the included semaphores are destroyed which results in a Segfault (at least on FreeBSD) --- include/RemotePlugin.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index 42caa36aa66..5d067768ff5 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -221,9 +221,6 @@ class shmFifo ~shmFifo() { -#ifndef USE_QT_SHMEM - shmdt( m_data ); -#endif // master? if( m_master ) { @@ -235,6 +232,9 @@ class shmFifo sem_destroy( m_messageSem ); #endif } +#ifndef USE_QT_SHMEM + shmdt( m_data ); +#endif } inline bool isInvalid() const From cfb2c7201fc4f3adc0d0b30077a6e0100de5b9e0 Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Sat, 23 Jan 2016 06:11:49 +0100 Subject: [PATCH 54/90] Auto save timer setting --- include/MainWindow.h | 27 +++++++++-- include/SetupDialog.h | 10 +++- src/core/main.cpp | 4 +- src/gui/MainWindow.cpp | 18 +++++-- src/gui/SetupDialog.cpp | 104 +++++++++++++++++++++++++++++++++++----- 5 files changed, 141 insertions(+), 22 deletions(-) diff --git a/include/MainWindow.h b/include/MainWindow.h index 31089f9edaf..8a93739ff5a 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -30,6 +30,7 @@ #include #include +#include "ConfigManager.h" #include "SubWindow.h" class QAction; @@ -81,11 +82,31 @@ class MainWindow : public QMainWindow /// bool mayChangeProject(bool stopPlayback); - void autoSaveTimerStart() + // Auto save timer intervals. The slider in SetupDialog.cpp wants + // minutes and the rest milliseconds. + static const int DEFAULT_SAVE_INTERVAL_MINUTES = 2; + static const int DEFAULT_AUTO_SAVE_INTERVAL = DEFAULT_SAVE_INTERVAL_MINUTES * 60 * 1000; + + static const int m_autoSaveShortTime = 10 * 1000; // 10s short loop + + void autoSaveTimerReset( int msec = ConfigManager::inst()-> + value( "ui", "saveinterval" ).toInt() + * 60 * 1000 ) + { + if( msec < m_autoSaveShortTime ) // No 'saveinterval' in .lmmsrc.xml + { + msec = DEFAULT_AUTO_SAVE_INTERVAL; + } + m_autoSaveTimer.start( msec ); + } + + int getAutoSaveTimerInterval() { - m_autoSaveTimer.start( 1000 * 60 ); // 1 minute + return m_autoSaveTimer.interval(); } + void runAutoSave(); + enum SessionState { Normal, @@ -155,7 +176,6 @@ public slots: void redo(); void autoSave(); - void runAutoSave(); protected: virtual void closeEvent( QCloseEvent * _ce ); @@ -204,6 +224,7 @@ public slots: QBasicTimer m_updateTimer; QTimer m_autoSaveTimer; + int m_autoSaveInterval; friend class GuiApplication; diff --git a/include/SetupDialog.h b/include/SetupDialog.h index 8b5923724d4..3c27d3a67fa 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -44,7 +44,6 @@ class QSlider; class TabBar; - class SetupDialog : public QDialog { Q_OBJECT @@ -84,6 +83,11 @@ private slots: void setDefaultSoundfont( const QString & _sf ); void setBackgroundArtwork( const QString & _ba ); + // performance settings widget + void setAutoSaveInterval( int time ); + void resetAutoSaveInterval(); + void displaySaveIntervalHelp(); + // audio settings widget void audioInterfaceChanged( const QString & _driver ); void displayAudioHelp(); @@ -175,6 +179,10 @@ private slots: bool m_smoothScroll; bool m_enableAutoSave; + int m_saveInterval; + QSlider * m_saveIntervalSlider; + QLabel * m_saveIntervalLbl; + bool m_oneInstrumentTrackWindow; bool m_compactTrackButtons; bool m_syncVSTPlugins; diff --git a/src/core/main.cpp b/src/core/main.cpp index d8b1536c76c..3faa805847d 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -799,8 +799,8 @@ int main( int argc, char * * argv ) if( autoSaveEnabled && gui->mainWindow()->getSession() != MainWindow::SessionState::Limited ) { - gui->mainWindow()->runAutoSave(); - gui->mainWindow()->autoSaveTimerStart(); + gui->mainWindow()->autoSaveTimerReset(); + gui->mainWindow()->autoSave(); } } diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 41cf2112a20..3a95a2df6cc 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -203,10 +203,16 @@ MainWindow::MainWindow() : { // connect auto save connect(&m_autoSaveTimer, SIGNAL(timeout()), this, SLOT(autoSave())); + m_autoSaveInterval = ConfigManager::inst()->value( + "ui", "saveinterval" ).toInt() < 1 ? + DEFAULT_AUTO_SAVE_INTERVAL : + ConfigManager::inst()->value( + "ui", "saveinterval" ).toInt(); + // The auto save function mustn't run until there is a project // to save or it will run over recover.mmp if you hesitate at the // recover messagebox for a minute. It is now started in main. - // See autoSaveTimerStart() in MainWindow.h + // See autoSaveTimerReset() in MainWindow.h } connect( Engine::getSong(), SIGNAL( playbackStateChanged() ), @@ -1507,14 +1513,19 @@ void MainWindow::browseHelp() void MainWindow::autoSave() { if( !( Engine::getSong()->isPlaying() || - Engine::getSong()->isExporting() ) ) + Engine::getSong()->isExporting() || + QApplication::mouseButtons() ) ) { Engine::getSong()->saveProjectFile(ConfigManager::inst()->recoveryFile()); + autoSaveTimerReset(); // Reset timer } else { // try again in 10 seconds - QTimer::singleShot( 10*1000, this, SLOT( autoSave() ) ); + if( getAutoSaveTimerInterval() != m_autoSaveShortTime ) + { + autoSaveTimerReset( m_autoSaveShortTime ); + } } } @@ -1527,5 +1538,6 @@ void MainWindow::runAutoSave() getSession() != Limited ) { autoSave(); + autoSaveTimerReset(); // Reset timer } } diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index 4c64fac1173..ce1fb89c476 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -38,6 +38,7 @@ #include "TabWidget.h" #include "gui_templates.h" #include "Mixer.h" +#include "MainWindow.h" #include "ProjectJournal.h" #include "ConfigManager.h" #include "embed.h" @@ -121,7 +122,10 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : #endif m_backgroundArtwork( QDir::toNativeSeparators( ConfigManager::inst()->backgroundArtwork() ) ), m_smoothScroll( ConfigManager::inst()->value( "ui", "smoothscroll" ).toInt() ), - m_enableAutoSave( ConfigManager::inst()->value( "ui", "enableautosave" ).toInt() ), + m_enableAutoSave( ConfigManager::inst()->value( "ui", "enableautosave" ).toInt() ), + m_saveInterval( ConfigManager::inst()->value( "ui", "saveinterval" ).toInt() < 1 ? + MainWindow::DEFAULT_SAVE_INTERVAL_MINUTES : + ConfigManager::inst()->value( "ui", "saveinterval" ).toInt() ), m_oneInstrumentTrackWindow( ConfigManager::inst()->value( "ui", "oneinstrumenttrackwindow" ).toInt() ), m_compactTrackButtons( ConfigManager::inst()->value( "ui", @@ -654,16 +658,61 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : QWidget * performance = new QWidget( ws ); - performance->setFixedSize( 360, 240 ); + performance->setFixedSize( 360, 200 ); QVBoxLayout * perf_layout = new QVBoxLayout( performance ); perf_layout->setSpacing( 0 ); perf_layout->setMargin( 0 ); labelWidget( performance, tr( "Performance settings" ) ); + + TabWidget * auto_save_tw = new TabWidget( + tr( "Auto save" ).toUpper(), performance ); + auto_save_tw->setFixedHeight( 100 ); + + m_saveIntervalSlider = new QSlider( Qt::Horizontal, auto_save_tw ); + m_saveIntervalSlider->setRange( 1, 20 ); + m_saveIntervalSlider->setTickPosition( QSlider::TicksBelow ); + m_saveIntervalSlider->setPageStep( 1 ); + m_saveIntervalSlider->setTickInterval( 1 ); + m_saveIntervalSlider->setGeometry( 10, 16, 340, 18 ); + m_saveIntervalSlider->setValue( m_saveInterval ); + + connect( m_saveIntervalSlider, SIGNAL( valueChanged( int ) ), this, + SLOT( setAutoSaveInterval( int ) ) ); + + m_saveIntervalLbl = new QLabel( auto_save_tw ); + m_saveIntervalLbl->setGeometry( 10, 40, 200, 24 ); + setAutoSaveInterval( m_saveIntervalSlider->value() ); + + LedCheckBox * autoSave = new LedCheckBox( + tr( "Enable auto save feature" ), auto_save_tw ); + autoSave->move( 10, 70 ); + autoSave->setChecked( m_enableAutoSave ); + connect( autoSave, SIGNAL( toggled( bool ) ), + this, SLOT( toggleAutoSave( bool ) ) ); + if( ! m_enableAutoSave ){ m_saveIntervalSlider->setEnabled( false ); } + + QPushButton * saveIntervalResetBtn = new QPushButton( + embed::getIconPixmap( "reload" ), "", auto_save_tw ); + saveIntervalResetBtn->setGeometry( 290, 50, 28, 28 ); + connect( saveIntervalResetBtn, SIGNAL( clicked() ), this, + SLOT( resetAutoSaveInterval() ) ); + ToolTip::add( bufsize_reset_btn, tr( "Reset to default-value" ) ); + + QPushButton * saventervalBtn = new QPushButton( + embed::getIconPixmap( "help" ), "", auto_save_tw ); + saventervalBtn->setGeometry( 320, 50, 28, 28 ); + connect( saventervalBtn, SIGNAL( clicked() ), this, + SLOT( displaySaveIntervalHelp() ) ); + + perf_layout->addWidget( auto_save_tw ); + perf_layout->addSpacing( 10 ); + + TabWidget * ui_fx_tw = new TabWidget( tr( "UI effects vs. " "performance" ).toUpper(), performance ); - ui_fx_tw->setFixedHeight( 80 ); + ui_fx_tw->setFixedHeight( 70 ); LedCheckBox * smoothScroll = new LedCheckBox( tr( "Smooth scroll in Song Editor" ), ui_fx_tw ); @@ -672,19 +721,10 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) : connect( smoothScroll, SIGNAL( toggled( bool ) ), this, SLOT( toggleSmoothScroll( bool ) ) ); - - LedCheckBox * autoSave = new LedCheckBox( - tr( "Enable auto save feature" ), ui_fx_tw ); - autoSave->move( 10, 40 ); - autoSave->setChecked( m_enableAutoSave ); - connect( autoSave, SIGNAL( toggled( bool ) ), - this, SLOT( toggleAutoSave( bool ) ) ); - - LedCheckBox * animAFP = new LedCheckBox( tr( "Show playback cursor in AudioFileProcessor" ), ui_fx_tw ); - animAFP->move( 10, 60 ); + animAFP->move( 10, 40 ); animAFP->setChecked( m_animateAFP ); connect( animAFP, SIGNAL( toggled( bool ) ), this, SLOT( toggleAnimateAFP( bool ) ) ); @@ -986,6 +1026,8 @@ void SetupDialog::accept() QString::number( m_smoothScroll ) ); ConfigManager::inst()->setValue( "ui", "enableautosave", QString::number( m_enableAutoSave ) ); + ConfigManager::inst()->setValue( "ui", "saveinterval", + QString::number( m_saveInterval ) ); ConfigManager::inst()->setValue( "ui", "oneinstrumenttrackwindow", QString::number( m_oneInstrumentTrackWindow ) ); ConfigManager::inst()->setValue( "ui", "compacttrackbuttons", @@ -1169,6 +1211,7 @@ void SetupDialog::toggleSmoothScroll( bool _enabled ) void SetupDialog::toggleAutoSave( bool _enabled ) { m_enableAutoSave = _enabled; + m_saveIntervalSlider->setEnabled( _enabled ); } @@ -1471,6 +1514,41 @@ void SetupDialog::setBackgroundArtwork( const QString & _ba ) +void SetupDialog::setAutoSaveInterval( int value ) +{ + m_saveInterval = value; + m_saveIntervalSlider->setValue( m_saveInterval ); + QString minutes = m_saveInterval > 1 ? tr( "minutes" ) : tr( "minute" ); + m_saveIntervalLbl->setText( tr( "Auto save interval: %1 %2" ).arg( + QString::number( m_saveInterval ), minutes ) ); +} + + + + +void SetupDialog::resetAutoSaveInterval() +{ + if( m_enableAutoSave ) + { + setAutoSaveInterval( MainWindow::DEFAULT_SAVE_INTERVAL_MINUTES ); + } + +} + + + + +void SetupDialog::displaySaveIntervalHelp() +{ + QWhatsThis::showText( QCursor::pos(), + tr( "Set the time between automatic backup to %1.\n" + "Remember to also save your project manually." ).arg( + ConfigManager::inst()->recoveryFile() ) ); +} + + + + void SetupDialog::audioInterfaceChanged( const QString & _iface ) { for( AswMap::iterator it = m_audioIfaceSetupWidgets.begin(); From 60038b5f550253f1695e5a8e9bfb7061176b8afe Mon Sep 17 00:00:00 2001 From: Fastigium Date: Wed, 2 Mar 2016 09:47:24 +0100 Subject: [PATCH 55/90] Synchronize access to Mixer::m_playHandlesToRemove Put every access to m_playHandlesToRemove between lockPlayHandleRemoval() and unlockPlayHandleRemoval(). Fixes #2610 where a SIGSEGV would occur due to concurrent access. --- src/core/Mixer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 012144a2cd5..25acd1c659c 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -467,6 +467,7 @@ void Mixer::clear() { // TODO: m_midiClient->noteOffAll(); lock(); + lockPlayHandleRemoval(); for( PlayHandleList::Iterator it = m_playHandles.begin(); it != m_playHandles.end(); ++it ) { // we must not delete instrument-play-handles as they exist @@ -476,6 +477,7 @@ void Mixer::clear() m_playHandlesToRemove.push_back( *it ); } } + unlockPlayHandleRemoval(); unlock(); } @@ -635,12 +637,12 @@ bool Mixer::addPlayHandle( PlayHandle* handle ) void Mixer::removePlayHandle( PlayHandle * _ph ) { + lockPlayHandleRemoval(); // check thread affinity as we must not delete play-handles // which were created in a thread different than mixer thread if( _ph->affinityMatters() && _ph->affinity() == QThread::currentThread() ) { - lockPlayHandleRemoval(); _ph->audioPort()->removePlayHandle( _ph ); bool removedFromList = false; // Check m_newPlayHandles first because doing it the other way around @@ -674,12 +676,12 @@ void Mixer::removePlayHandle( PlayHandle * _ph ) } else delete _ph; } - unlockPlayHandleRemoval(); } else { m_playHandlesToRemove.push_back( _ph ); } + unlockPlayHandleRemoval(); } From e13ac405443b280dc7c8a7ed334f36c07e158c0e Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Wed, 2 Mar 2016 11:49:04 -0500 Subject: [PATCH 56/90] valgrind: init m_scrollArea in vestige instrument Closes #2041 --- plugins/vestige/vestige.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index a4836ff9364..9db5ea352b5 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -78,6 +78,7 @@ vestigeInstrument::vestigeInstrument( InstrumentTrack * _instrument_track ) : m_plugin( NULL ), m_pluginMutex(), m_subWindow( NULL ), + m_scrollArea( NULL ), vstKnobs( NULL ), knobFModel( NULL ), p_subWindow( NULL ) From f136ba3097d45b8651e45b494f8af5a6d606cd59 Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Tue, 16 Feb 2016 01:01:43 +0100 Subject: [PATCH 57/90] Refactor the drawing of TCO's; Get rid of hardcoded colors in TCOs; Make TCO gradient configurable; Even out the color scheme Thanks to @Fastigium for helping with the BB Pattern redraw problem --- data/themes/default/style.css | 30 +++-- include/AutomationPatternView.h | 15 +-- include/BBTrack.h | 9 +- include/Pattern.h | 14 +-- include/SampleTrack.h | 6 +- include/Track.h | 37 +++++- src/core/SampleBuffer.cpp | 4 +- src/core/Track.cpp | 76 +++++++++--- src/gui/AutomationPatternView.cpp | 187 ++++++++++++++++-------------- src/tracks/BBTrack.cpp | 119 ++++++++++++------- src/tracks/Pattern.cpp | 185 ++++++++++++++--------------- src/tracks/SampleTrack.cpp | 116 ++++++++++-------- 12 files changed, 461 insertions(+), 337 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index adc1547c19f..6780f7a1ead 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -115,7 +115,7 @@ PianoRoll { qproperty-noteColor: rgb( 119, 199, 216 ); qproperty-noteBorderRadiusX: 5; qproperty-noteBorderRadiusY: 2; - qproperty-selectedNoteColor: rgb( 0, 64, 192 ); + qproperty-selectedNoteColor: rgb( 0, 125, 255 ); qproperty-barColor: #4afd85; qproperty-markedSemitoneColor: rgba( 40, 40, 40, 200 ); /* Text on the white piano keys */ @@ -537,31 +537,37 @@ TrackContainerView QLabel /* Patterns */ +/* common pattern colors */ +TrackContentObjectView { + qproperty-mutedColor: rgb( 128, 128, 128 ); + qproperty-mutedBackgroundColor: rgb( 80, 80, 80 ); + qproperty-selectedColor: rgb( 0, 125, 255 ); + qproperty-textColor: rgb( 255, 255, 255 ); + qproperty-textShadowColor: rgb( 0, 0, 0 ); + qproperty-gradient: true; +} + /* instrument pattern */ PatternView { - color: rgb( 119, 199, 216 ); - qproperty-fgColor: rgb( 187, 227, 236 ); - qproperty-textColor: rgb( 255, 255, 255 ); + background-color: rgb( 119, 199, 216 ); + color: rgb( 187, 227, 236 ); } /* sample track pattern */ SampleTCOView { - color: rgb( 74, 253, 133 ); - qproperty-fgColor: rgb( 187, 227, 236 ); - qproperty-textColor: rgb( 255, 60, 60 ); + background-color: rgb( 74, 253, 133 ); + color: rgb( 187, 227, 236 ); } /* automation pattern */ AutomationPatternView { - color: #99afff; - qproperty-fgColor: rgb( 204, 215, 255 ); - qproperty-textColor: rgb( 255, 255, 255 ); + background-color: #99afff; + color: rgb( 204, 215, 255 ); } /* bb-pattern */ BBTCOView { - color: rgb( 128, 182, 175 ); /* default colour for bb-tracks, used when the colour hasn't been defined by the user */ - qproperty-textColor: rgb( 255, 255, 255 ); + background-color: rgb( 128, 182, 175 ); /* default colour for bb-tracks */ } /* Plugins */ diff --git a/include/AutomationPatternView.h b/include/AutomationPatternView.h index 714eaed5350..dfa94461daf 100644 --- a/include/AutomationPatternView.h +++ b/include/AutomationPatternView.h @@ -25,6 +25,8 @@ #ifndef AUTOMATION_PATTERN_VIEW_H #define AUTOMATION_PATTERN_VIEW_H +#include + #include "Track.h" class AutomationPattern; @@ -34,9 +36,6 @@ class AutomationPatternView : public TrackContentObjectView { Q_OBJECT -// theming qproperties - Q_PROPERTY( QColor fgColor READ fgColor WRITE setFgColor ) - Q_PROPERTY( QColor textColor READ textColor WRITE setTextColor ) public: AutomationPatternView( AutomationPattern * _pat, TrackView * _parent ); @@ -59,12 +58,7 @@ protected slots: protected: virtual void constructContextMenu( QMenu * ); virtual void mouseDoubleClickEvent(QMouseEvent * me ); - virtual void paintEvent( QPaintEvent * _pe ); - virtual void resizeEvent( QResizeEvent * _re ) - { - m_needsUpdate = true; - TrackContentObjectView::resizeEvent( _re ); - } + virtual void paintEvent( QPaintEvent * pe ); virtual void dragEnterEvent( QDragEnterEvent * _dee ); virtual void dropEvent( QDropEvent * _de ); @@ -72,7 +66,8 @@ protected slots: private: AutomationPattern * m_pat; QPixmap m_paintPixmap; - bool m_needsUpdate; + + QStaticText m_staticTextName; static QPixmap * s_pat_rec; diff --git a/include/BBTrack.h b/include/BBTrack.h index b822c8e2be6..b4d0a2cd90e 100644 --- a/include/BBTrack.h +++ b/include/BBTrack.h @@ -29,6 +29,7 @@ #include #include +#include #include "Track.h" @@ -107,14 +108,16 @@ protected slots: protected: - void paintEvent( QPaintEvent * ); - void mouseDoubleClickEvent( QMouseEvent * _me ); + virtual void paintEvent( QPaintEvent * pe ); + virtual void mouseDoubleClickEvent( QMouseEvent * _me ); virtual void constructContextMenu( QMenu * ); private: BBTCO * m_bbTCO; - + QPixmap m_paintPixmap; + + QStaticText m_staticTextName; } ; diff --git a/include/Pattern.h b/include/Pattern.h index ce6702fbb3c..505aff63e80 100644 --- a/include/Pattern.h +++ b/include/Pattern.h @@ -31,6 +31,7 @@ #include #include #include +#include #include "Note.h" @@ -159,9 +160,6 @@ class PatternView : public TrackContentObjectView { Q_OBJECT -// theming qproperties - Q_PROPERTY( QColor fgColor READ fgColor WRITE setFgColor ) - Q_PROPERTY( QColor textColor READ textColor WRITE setTextColor ) public: PatternView( Pattern* pattern, TrackView* parent ); virtual ~PatternView(); @@ -182,12 +180,7 @@ protected slots: virtual void constructContextMenu( QMenu * ); virtual void mousePressEvent( QMouseEvent * _me ); virtual void mouseDoubleClickEvent( QMouseEvent * _me ); - virtual void paintEvent( QPaintEvent * _pe ); - virtual void resizeEvent( QResizeEvent * _re ) - { - m_needsUpdate = true; - TrackContentObjectView::resizeEvent( _re ); - } + virtual void paintEvent( QPaintEvent * pe ); virtual void wheelEvent( QWheelEvent * _we ); @@ -199,7 +192,8 @@ protected slots: Pattern* m_pat; QPixmap m_paintPixmap; - bool m_needsUpdate; + + QStaticText m_staticTextName; } ; diff --git a/include/SampleTrack.h b/include/SampleTrack.h index c8b17b1481e..51fd43a1cd9 100644 --- a/include/SampleTrack.h +++ b/include/SampleTrack.h @@ -88,10 +88,6 @@ public slots: class SampleTCOView : public TrackContentObjectView { Q_OBJECT - -// theming qproperties - Q_PROPERTY( QColor fgColor READ fgColor WRITE setFgColor ) - Q_PROPERTY( QColor textColor READ textColor WRITE setTextColor ) public: SampleTCOView( SampleTCO * _tco, TrackView * _tv ); @@ -102,6 +98,7 @@ public slots: void updateSample(); + protected: virtual void contextMenuEvent( QContextMenuEvent * _cme ); virtual void mousePressEvent( QMouseEvent * _me ); @@ -113,6 +110,7 @@ public slots: private: SampleTCO * m_tco; + QPixmap m_paintPixmap; } ; diff --git a/include/Track.h b/include/Track.h index 4afc670764e..3b8c634a848 100644 --- a/include/Track.h +++ b/include/Track.h @@ -191,8 +191,12 @@ class TrackContentObjectView : public selectableObject, public ModelView Q_OBJECT // theming qproperties - Q_PROPERTY( QColor fgColor READ fgColor WRITE setFgColor ) + Q_PROPERTY( QColor mutedColor READ mutedColor WRITE setMutedColor ) + Q_PROPERTY( QColor mutedBackgroundColor READ mutedBackgroundColor WRITE setMutedBackgroundColor ) + Q_PROPERTY( QColor selectedColor READ selectedColor WRITE setSelectedColor ) Q_PROPERTY( QColor textColor READ textColor WRITE setTextColor ) + Q_PROPERTY( QColor textShadowColor READ textShadowColor WRITE setTextShadowColor ) + Q_PROPERTY( bool gradient READ gradient WRITE setGradient ) public: TrackContentObjectView( TrackContentObject * tco, TrackView * tv ); @@ -204,16 +208,29 @@ class TrackContentObjectView : public selectableObject, public ModelView { return m_tco; } -// qproperty access func - QColor fgColor() const; + // qproperty access func + QColor mutedColor() const; + QColor mutedBackgroundColor() const; + QColor selectedColor() const; QColor textColor() const; - void setFgColor( const QColor & c ); + QColor textShadowColor() const; + bool gradient() const; + void setMutedColor( const QColor & c ); + void setMutedBackgroundColor( const QColor & c ); + void setSelectedColor( const QColor & c ); void setTextColor( const QColor & c ); + void setTextShadowColor( const QColor & c ); + void setGradient( const bool & b ); + // access needsUpdate member variable + bool needsUpdate(); + void setNeedsUpdate( bool b ); + public slots: virtual bool close(); void cut(); void remove(); + virtual void update(); protected: virtual void constructContextMenu( QMenu * ) @@ -227,6 +244,11 @@ public slots: virtual void mousePressEvent( QMouseEvent * me ); virtual void mouseMoveEvent( QMouseEvent * me ); virtual void mouseReleaseEvent( QMouseEvent * me ); + virtual void resizeEvent( QResizeEvent * re ) + { + m_needsUpdate = true; + selectableObject::resizeEvent( re ); + } float pixelsPerTact(); @@ -267,9 +289,14 @@ protected slots: MidiTime m_oldTime;// used for undo/redo while mouse-button is pressed // qproperty fields - QColor m_fgColor; + QColor m_mutedColor; + QColor m_mutedBackgroundColor; + QColor m_selectedColor; QColor m_textColor; + QColor m_textShadowColor; + bool m_gradient; + bool m_needsUpdate; inline void setInitialMousePos( QPoint pos ) { m_initialMousePos = pos; diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index e44b246e548..7040babcba0 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -903,9 +903,7 @@ void SampleBuffer::visualize( QPainter & _p, const QRect & _dr, const bool focus_on_range = _to_frame <= m_frames && 0 <= _from_frame && _from_frame < _to_frame; -// _p.setClipRect( _clip ); -// _p.setPen( QColor( 0x22, 0xFF, 0x44 ) ); - //_p.setPen( QColor( 64, 224, 160 ) ); + //_p.setClipRect( _clip ); const int w = _dr.width(); const int h = _dr.height(); diff --git a/src/core/Track.cpp b/src/core/Track.cpp index 05d3750a5ff..56db1923ad6 100644 --- a/src/core/Track.cpp +++ b/src/core/Track.cpp @@ -251,8 +251,13 @@ TrackContentObjectView::TrackContentObjectView( TrackContentObject * tco, m_initialMousePos( QPoint( 0, 0 ) ), m_initialMouseGlobalPos( QPoint( 0, 0 ) ), m_hint( NULL ), - m_fgColor( 0, 0, 0 ), - m_textColor( 0, 0, 0 ) + m_mutedColor( 0, 0, 0 ), + m_mutedBackgroundColor( 0, 0, 0 ), + m_selectedColor( 0, 0, 0 ), + m_textColor( 0, 0, 0 ), + m_textShadowColor( 0, 0, 0 ), + m_gradient( true ), + m_needsUpdate( true ) { if( s_textFloat == NULL ) { @@ -264,10 +269,10 @@ TrackContentObjectView::TrackContentObjectView( TrackContentObject * tco, setAttribute( Qt::WA_DeleteOnClose, true ); setFocusPolicy( Qt::StrongFocus ); setCursor( QCursor( embed::getIconPixmap( "hand" ), 3, 3 ) ); - move( 0, 1 ); + move( 0, 0 ); show(); - setFixedHeight( tv->getTrackContentWidget()->height() - 2 ); + setFixedHeight( tv->getTrackContentWidget()->height() - 1); setAcceptDrops( true ); setMouseTracking( true ); @@ -300,6 +305,19 @@ TrackContentObjectView::~TrackContentObjectView() } +/*! \brief Update a TrackContentObjectView + * + * TCO's get drawn only when needed, + * and when a TCO is updated, + * it needs to be redrawn. + * + */ +void TrackContentObjectView::update() +{ + m_needsUpdate = true; + selectableObject::update(); +} + /*! \brief Does this trackContentObjectView have a fixed TCO? @@ -319,21 +337,48 @@ bool TrackContentObjectView::fixedTCOs() // qproperty access functions, to be inherited & used by TCOviews //! \brief CSS theming qproperty access method -QColor TrackContentObjectView::fgColor() const -{ return m_fgColor; } +QColor TrackContentObjectView::mutedColor() const +{ return m_mutedColor; } + +QColor TrackContentObjectView::mutedBackgroundColor() const +{ return m_mutedBackgroundColor; } + +QColor TrackContentObjectView::selectedColor() const +{ return m_selectedColor; } -//! \brief CSS theming qproperty access method QColor TrackContentObjectView::textColor() const { return m_textColor; } -//! \brief CSS theming qproperty access method -void TrackContentObjectView::setFgColor( const QColor & c ) -{ m_fgColor = QColor( c ); } +QColor TrackContentObjectView::textShadowColor() const +{ return m_textShadowColor; } + +bool TrackContentObjectView::gradient() const +{ return m_gradient; } //! \brief CSS theming qproperty access method +void TrackContentObjectView::setMutedColor( const QColor & c ) +{ m_mutedColor = QColor( c ); } + +void TrackContentObjectView::setMutedBackgroundColor( const QColor & c ) +{ m_mutedBackgroundColor = QColor( c ); } + +void TrackContentObjectView::setSelectedColor( const QColor & c ) +{ m_selectedColor = QColor( c ); } + void TrackContentObjectView::setTextColor( const QColor & c ) { m_textColor = QColor( c ); } +void TrackContentObjectView::setTextShadowColor( const QColor & c ) +{ m_textShadowColor = QColor( c ); } + +void TrackContentObjectView::setGradient( const bool & b ) +{ m_gradient = b; } + +// access needsUpdate member variable +bool TrackContentObjectView::needsUpdate() +{ return m_needsUpdate; } +void TrackContentObjectView::setNeedsUpdate( bool b ) +{ m_needsUpdate = b; } /*! \brief Close a trackContentObjectView * @@ -1047,11 +1092,8 @@ void TrackContentWidget::updateBackground() pmp.fillRect( w, 0, w , h, lighterColor() ); // draw lines - pmp.setPen( QPen( gridColor(), 1 ) ); - // horizontal line - pmp.drawLine( 0, h-1, w*2, h-1 ); - // vertical lines + pmp.setPen( QPen( gridColor(), 1 ) ); for( float x = 0; x < w * 2; x += ppt ) { pmp.drawLine( QLineF( x, 0.0, x, h ) ); @@ -1062,6 +1104,10 @@ void TrackContentWidget::updateBackground() { pmp.drawLine( QLineF( x, 0.0, x, h ) ); } + + // horizontal line + pmp.setPen( QPen( gridColor(), 1 ) ); + pmp.drawLine( 0, h-1, w*2, h-1 ); pmp.end(); @@ -1122,7 +1168,7 @@ void TrackContentWidget::update() for( tcoViewVector::iterator it = m_tcoViews.begin(); it != m_tcoViews.end(); ++it ) { - ( *it )->setFixedHeight( height() - 2 ); + ( *it )->setFixedHeight( height() - 1 ); ( *it )->update(); } QWidget::update(); diff --git a/src/gui/AutomationPatternView.cpp b/src/gui/AutomationPatternView.cpp index e92b5eb71af..0872260b764 100644 --- a/src/gui/AutomationPatternView.cpp +++ b/src/gui/AutomationPatternView.cpp @@ -21,12 +21,12 @@ * Boston, MA 02110-1301 USA. * */ +#include "AutomationPatternView.h" #include #include #include -#include "AutomationPatternView.h" #include "AutomationEditor.h" #include "AutomationPattern.h" #include "embed.h" @@ -45,8 +45,7 @@ AutomationPatternView::AutomationPatternView( AutomationPattern * _pattern, TrackView * _parent ) : TrackContentObjectView( _pattern, _parent ), m_pat( _pattern ), - m_paintPixmap(), - m_needsUpdate( true ) + m_paintPixmap() { connect( m_pat, SIGNAL( dataChanged() ), this, SLOT( update() ) ); @@ -54,7 +53,6 @@ AutomationPatternView::AutomationPatternView( AutomationPattern * _pattern, this, SLOT( update() ) ); setAttribute( Qt::WA_OpaquePaintEvent, true ); - setFixedHeight( parentWidget()->height() - 2 ); ToolTip::add( this, tr( "double-click to open this pattern in " "automation editor" ) ); @@ -85,7 +83,6 @@ void AutomationPatternView::openInAutomationEditor() void AutomationPatternView::update() { - m_needsUpdate = true; if( fixedTCOs() ) { m_pat->changeLength( m_pat->length() ); @@ -245,82 +242,66 @@ void AutomationPatternView::mouseDoubleClickEvent( QMouseEvent * me ) void AutomationPatternView::paintEvent( QPaintEvent * ) { - if( m_needsUpdate == false ) + QPainter painter( this ); + + if( !needsUpdate() ) { - QPainter p( this ); - p.drawPixmap( 0, 0, m_paintPixmap ); + painter.drawPixmap( 0, 0, m_paintPixmap ); return; } - QPainter _p( this ); - const QColor styleColor = _p.pen().brush().color(); - - m_needsUpdate = false; + setNeedsUpdate( false ); - if( m_paintPixmap.isNull() == true || m_paintPixmap.size() != size() ) - { - m_paintPixmap = QPixmap( size() ); - } + m_paintPixmap = m_paintPixmap.isNull() == true || m_paintPixmap.size() != size() + ? QPixmap( size() ) : m_paintPixmap; QPainter p( &m_paintPixmap ); QLinearGradient lingrad( 0, 0, 0, height() ); QColor c; - - if( !( m_pat->getTrack()->isMuted() || m_pat->isMuted() ) ) - c = styleColor; - else - c = QColor( 80, 80, 80 ); - - if( isSelected() == true ) - { - c.setRgb( qMax( c.red() - 128, 0 ), qMax( c.green() - 128, 0 ), 255 ); - } + bool muted = m_pat->getTrack()->isMuted() || m_pat->isMuted(); + bool current = gui->automationEditor()->currentPattern() == m_pat; + + // state: selected, muted, normal + c = isSelected() ? selectedColor() : ( muted ? mutedBackgroundColor() + : painter.background().color() ); lingrad.setColorAt( 1, c.darker( 300 ) ); lingrad.setColorAt( 0, c ); - - p.setBrush( lingrad ); - if( gui->automationEditor()->currentPattern() == m_pat ) - p.setPen( c.lighter( 160 ) ); + + if( gradient() ) + { + p.fillRect( rect(), lingrad ); + } else - p.setPen( c.lighter( 130 ) ); - p.drawRect( 1, 1, width()-3, height()-3 ); - - + { + p.fillRect( rect(), c ); + } + const float ppt = fixedTCOs() ? ( parentWidget()->width() - 2 * TCO_BORDER_WIDTH ) / (float) m_pat->length().getTact() : pixelsPerTact(); const int x_base = TCO_BORDER_WIDTH; - p.setPen( c.darker( 300 ) ); - - for( tact_t t = 1; t < m_pat->length().getTact(); ++t ) - { - const int tx = x_base + static_cast( ppt * t ) - 1; - if( tx < ( width() - TCO_BORDER_WIDTH*2 ) ) - { - p.drawLine( tx, TCO_BORDER_WIDTH, tx, 5 ); - p.drawLine( tx, height() - ( 4 + 2 * TCO_BORDER_WIDTH ), - tx, height() - 2 * TCO_BORDER_WIDTH ); - } - } - + const float min = m_pat->firstObject()->minValue(); const float max = m_pat->firstObject()->maxValue(); const float y_scale = max - min; - const float h = ( height() - 2*TCO_BORDER_WIDTH ) / y_scale; + const float h = ( height() - 2 * TCO_BORDER_WIDTH ) / y_scale; p.translate( 0.0f, max * height() / y_scale - TCO_BORDER_WIDTH ); p.scale( 1.0f, -h ); QLinearGradient lin2grad( 0, min, 0, max ); + QColor col; + + col = !muted ? painter.pen().brush().color() : mutedColor(); - lin2grad.setColorAt( 1, fgColor().lighter( 150 ) ); - lin2grad.setColorAt( 0.5, fgColor() ); - lin2grad.setColorAt( 0, fgColor().darker( 150 ) ); + lin2grad.setColorAt( 1, col.lighter( 150 ) ); + lin2grad.setColorAt( 0.5, col ); + lin2grad.setColorAt( 0, col.darker( 150 ) ); for( AutomationPattern::timeMap::const_iterator it = m_pat->getTimeMap().begin(); @@ -332,67 +313,105 @@ void AutomationPatternView::paintEvent( QPaintEvent * ) MidiTime::ticksPerTact(); const float x2 = (float)( width() - TCO_BORDER_WIDTH ); if( x1 > ( width() - TCO_BORDER_WIDTH ) ) break; - - p.fillRect( QRectF( x1, 0.0f, x2-x1, it.value() ), - lin2grad ); + if( gradient() ) + { + p.fillRect( QRectF( x1, 0.0f, x2 - x1, it.value() ), lin2grad ); + } + else + { + p.fillRect( QRectF( x1, 0.0f, x2 - x1, it.value() ), col ); + } break; } float *values = m_pat->valuesAfter( it.key() ); - for( int i = it.key(); i < (it+1).key(); i++ ) + for( int i = it.key(); i < (it + 1).key(); i++ ) { float value = values[i - it.key()]; const float x1 = x_base + i * ppt / MidiTime::ticksPerTact(); - const float x2 = x_base + (i+1) * ppt / + const float x2 = x_base + (i + 1) * ppt / MidiTime::ticksPerTact(); if( x1 > ( width() - TCO_BORDER_WIDTH ) ) break; - p.fillRect( QRectF( x1, 0.0f, x2-x1, value ), - lin2grad ); + if( gradient() ) + { + p.fillRect( QRectF( x1, 0.0f, x2 - x1, value ), lin2grad ); + } + else + { + p.fillRect( QRectF( x1, 0.0f, x2 - x1, value ), col ); + } } delete [] values; } p.resetMatrix(); + + // bar lines + const int lineSize = 3; + p.setPen( c.darker( 300 ) ); + + for( tact_t t = 1; t < m_pat->length().getTact(); ++t ) + { + const int tx = x_base + static_cast( ppt * t ) - 2; + if( tx < ( width() - TCO_BORDER_WIDTH * 2 ) ) + { + p.drawLine( tx, TCO_BORDER_WIDTH, tx, TCO_BORDER_WIDTH + lineSize ); + p.drawLine( tx, rect().bottom() - ( lineSize + TCO_BORDER_WIDTH ), + tx, rect().bottom() - TCO_BORDER_WIDTH ); + } + } // recording icon for when recording automation if( m_pat->isRecording() ) { - p.drawPixmap( 4, 14, *s_pat_rec ); + p.drawPixmap( 1, rect().bottom() - s_pat_rec->height(), + *s_pat_rec ); } - - // outer edge - p.setBrush( QBrush() ); - if( gui->automationEditor()->currentPattern() == m_pat ) - p.setPen( c.lighter( 130 ) ); - else - p.setPen( c.darker( 300 ) ); - p.drawRect( 0, 0, width()-1, height()-1 ); - + // pattern name - p.setFont( pointSize<8>( p.font() ) ); - - QColor text_color = ( m_pat->isMuted() || m_pat->getTrack()->isMuted() ) - ? QColor( 30, 30, 30 ) - : textColor(); - - p.setPen( QColor( 0, 0, 0 ) ); - p.drawText( 4, p.fontMetrics().height()+1, m_pat->name() ); - p.setPen( text_color ); - p.drawText( 3, p.fontMetrics().height(), m_pat->name() ); - + p.setRenderHint( QPainter::TextAntialiasing ); + + if( m_staticTextName.text() != m_pat->name() ) + { + m_staticTextName.setText( m_pat->name() ); + } + + QFont font; + font.setHintingPreference( QFont::PreferFullHinting ); + font.setPointSize( 8 ); + p.setFont( font ); + + const int textTop = TCO_BORDER_WIDTH + 1; + const int textLeft = TCO_BORDER_WIDTH + 1; + + p.setPen( textShadowColor() ); + p.drawStaticText( textLeft + 1, textTop + 1, m_staticTextName ); + p.setPen( textColor() ); + p.drawStaticText( textLeft, textTop, m_staticTextName ); + + // inner border + p.setPen( c.lighter( current ? 160 : 130 ) ); + p.drawRect( 1, 1, rect().right() - TCO_BORDER_WIDTH, + rect().bottom() - TCO_BORDER_WIDTH ); + + // outer border + p.setPen( current? c.lighter( 130 ) : c.darker( 300 ) ); + p.drawRect( 0, 0, rect().right(), rect().bottom() ); + + // draw the 'muted' pixmap only if the pattern was manualy muted if( m_pat->isMuted() ) { - p.drawPixmap( 3, p.fontMetrics().height() + 1, - embed::getIconPixmap( "muted", 16, 16 ) ); + const int spacing = TCO_BORDER_WIDTH; + const int size = 14; + p.drawPixmap( spacing, height() - ( size + spacing ), + embed::getIconPixmap( "muted", size, size ) ); } - p.end(); - _p.drawPixmap( 0, 0, m_paintPixmap ); - + painter.drawPixmap( 0, 0, m_paintPixmap ); } diff --git a/src/tracks/BBTrack.cpp b/src/tracks/BBTrack.cpp index 45210b05f4e..00b8f37b828 100644 --- a/src/tracks/BBTrack.cpp +++ b/src/tracks/BBTrack.cpp @@ -21,6 +21,7 @@ * Boston, MA 02110-1301 USA. * */ +#include "BBTrack.h" #include #include @@ -28,7 +29,6 @@ #include #include "BBEditor.h" -#include "BBTrack.h" #include "BBTrackContainer.h" #include "embed.h" #include "Engine.h" @@ -159,16 +159,14 @@ TrackContentObjectView * BBTCO::createView( TrackView * _tv ) - - - - - - BBTCOView::BBTCOView( TrackContentObject * _tco, TrackView * _tv ) : TrackContentObjectView( _tco, _tv ), - m_bbTCO( dynamic_cast( _tco ) ) + m_bbTCO( dynamic_cast( _tco ) ), + m_paintPixmap() { + connect( _tco->getTrack(), SIGNAL( dataChanged() ), this, SLOT( update() ) ); + + setStyle( QApplication::style() ); } @@ -215,64 +213,103 @@ void BBTCOView::mouseDoubleClickEvent( QMouseEvent * ) void BBTCOView::paintEvent( QPaintEvent * ) { - QPainter p( this ); + QPainter painter( this ); - QColor col; - if( m_bbTCO->getTrack()->isMuted() || m_bbTCO->isMuted() ) + if( !needsUpdate() ) { - col = QColor( 160, 160, 160 ); + painter.drawPixmap( 0, 0, m_paintPixmap ); + return; } - else if ( m_bbTCO->m_useStyleColor ) + + setNeedsUpdate( false ); + + m_paintPixmap = m_paintPixmap.isNull() == true || m_paintPixmap.size() != size() + ? QPixmap( size() ) : m_paintPixmap; + + QPainter p( &m_paintPixmap ); + + QLinearGradient lingrad( 0, 0, 0, height() ); + QColor c; + bool muted = m_bbTCO->getTrack()->isMuted() || m_bbTCO->isMuted(); + + // state: selected, muted, default, user selected + c = isSelected() ? selectedColor() : ( muted ? mutedBackgroundColor() + : ( m_bbTCO->m_useStyleColor ? painter.background().color() + : m_bbTCO->colorObj() ) ); + + lingrad.setColorAt( 0, c.light( 130 ) ); + lingrad.setColorAt( 1, c.light( 70 ) ); + + if( gradient() ) { - col = p.pen().brush().color(); + p.fillRect( rect(), lingrad ); } else { - col = m_bbTCO->colorObj(); + p.fillRect( rect(), c ); } - - if( isSelected() == true ) - { - col.setRgb( qMax( col.red() - 128, 0 ), qMax( col.green() - 128, 0 ), 255 ); - } - - QLinearGradient lingrad( 0, 0, 0, height() ); - lingrad.setColorAt( 0, col.light( 130 ) ); - lingrad.setColorAt( 1, col.light( 70 ) ); - p.fillRect( rect(), lingrad ); + + // bar lines + const int lineSize = 3; tact_t t = Engine::getBBTrackContainer()->lengthOfBB( m_bbTCO->bbTrackIndex() ); if( m_bbTCO->length() > MidiTime::ticksPerTact() && t > 0 ) { for( int x = static_cast( t * pixelsPerTact() ); - x < width()-2; + x < width() - 2; x += static_cast( t * pixelsPerTact() ) ) { - p.setPen( col.light( 80 ) ); - p.drawLine( x, 1, x, 5 ); - p.setPen( col.light( 120 ) ); - p.drawLine( x, height() - 6, x, height() - 2 ); + p.setPen( c.light( 80 ) ); + p.drawLine( x, TCO_BORDER_WIDTH, x, TCO_BORDER_WIDTH + lineSize ); + p.setPen( c.light( 120 ) ); + p.drawLine( x, rect().bottom() - ( TCO_BORDER_WIDTH + lineSize ), + x, rect().bottom() - TCO_BORDER_WIDTH ); } } - p.setPen( col.lighter( 130 ) ); - p.drawRect( 1, 1, rect().right()-2, rect().bottom()-2 ); + // pattern name + p.setRenderHint( QPainter::TextAntialiasing ); - p.setPen( col.darker( 300 ) ); - p.drawRect( 0, 0, rect().right(), rect().bottom() ); + if( m_staticTextName.text() != m_bbTCO->name() ) + { + m_staticTextName.setText( m_bbTCO->name() ); + } - p.setFont( pointSize<8>( p.font() ) ); - - p.setPen( QColor( 0, 0, 0 ) ); - p.drawText( 4, p.fontMetrics().height()+1, m_bbTCO->name() ); + QFont font; + font.setHintingPreference( QFont::PreferFullHinting ); + font.setPointSize( 8 ); + p.setFont( font ); + + const int textTop = TCO_BORDER_WIDTH + 1; + const int textLeft = TCO_BORDER_WIDTH + 1; + + p.setPen( textShadowColor() ); + p.drawStaticText( textLeft + 1, textTop + 1, m_staticTextName ); p.setPen( textColor() ); - p.drawText( 3, p.fontMetrics().height(), m_bbTCO->name() ); + p.drawStaticText( textLeft, textTop, m_staticTextName ); + + // inner border + p.setPen( c.lighter( 130 ) ); + p.drawRect( 1, 1, rect().right() - TCO_BORDER_WIDTH, + rect().bottom() - TCO_BORDER_WIDTH ); + + // outer border + p.setPen( c.darker( 300 ) ); + p.drawRect( 0, 0, rect().right(), rect().bottom() ); + // draw the 'muted' pixmap only if the pattern was manualy muted if( m_bbTCO->isMuted() ) { - p.drawPixmap( 3, p.fontMetrics().height() + 1, - embed::getIconPixmap( "muted", 16, 16 ) ); + const int spacing = TCO_BORDER_WIDTH; + const int size = 14; + p.drawPixmap( spacing, height() - ( size + spacing ), + embed::getIconPixmap( "muted", size, size ) ); } + + p.end(); + + painter.drawPixmap( 0, 0, m_paintPixmap ); + } diff --git a/src/tracks/Pattern.cpp b/src/tracks/Pattern.cpp index c32d6a2cadb..532b7c418bd 100644 --- a/src/tracks/Pattern.cpp +++ b/src/tracks/Pattern.cpp @@ -22,6 +22,7 @@ * Boston, MA 02110-1301 USA. * */ +#include "Pattern.h" #include #include @@ -33,7 +34,6 @@ #include #include -#include "Pattern.h" #include "InstrumentTrack.h" #include "templates.h" #include "gui_templates.h" @@ -673,8 +673,7 @@ void Pattern::changeTimeSignature() PatternView::PatternView( Pattern* pattern, TrackView* parent ) : TrackContentObjectView( pattern, parent ), m_pat( pattern ), - m_paintPixmap(), - m_needsUpdate( true ) + m_paintPixmap() { connect( gui->pianoRoll(), SIGNAL( currentPatternChanged() ), this, SLOT( update() ) ); @@ -703,8 +702,6 @@ PatternView::PatternView( Pattern* pattern, TrackView* parent ) : "step_btn_off_light" ) ); } - setFixedHeight( parentWidget()->height() - 2 ); - ToolTip::add( this, tr( "use mouse wheel to set velocity of a step" ) ); setStyle( QApplication::style() ); @@ -725,7 +722,6 @@ PatternView::~PatternView() void PatternView::update() { - m_needsUpdate = true; m_pat->changeLength( m_pat->length() ); TrackContentObjectView::update(); } @@ -946,96 +942,53 @@ void PatternView::wheelEvent( QWheelEvent * _we ) void PatternView::paintEvent( QPaintEvent * ) { - if( m_needsUpdate == false ) + QPainter painter( this ); + + if( !needsUpdate() ) { - QPainter p( this ); - p.drawPixmap( 0, 0, m_paintPixmap ); + painter.drawPixmap( 0, 0, m_paintPixmap ); return; } - QPainter _p( this ); - const QColor styleColor = _p.pen().brush().color(); + setNeedsUpdate( false ); - m_pat->changeLength( m_pat->length() ); - - m_needsUpdate = false; - - if( m_paintPixmap.isNull() == true || m_paintPixmap.size() != size() ) - { - m_paintPixmap = QPixmap( size() ); - } + m_paintPixmap = m_paintPixmap.isNull() == true || m_paintPixmap.size() != size() + ? QPixmap( size() ) : m_paintPixmap; QPainter p( &m_paintPixmap ); QLinearGradient lingrad( 0, 0, 0, height() ); - QColor c; - if(( m_pat->m_patternType != Pattern::BeatPattern ) && - !( m_pat->getTrack()->isMuted() || m_pat->isMuted() )) + bool muted = m_pat->getTrack()->isMuted() || m_pat->isMuted(); + bool current = gui->pianoRoll()->currentPattern() == m_pat; + bool beatPattern = m_pat->m_patternType == Pattern::BeatPattern; + + // state: selected, muted, normal + c = isSelected() ? selectedColor() : ( ( !muted && !beatPattern ) + ? painter.background().color() : mutedBackgroundColor() ); + + // invert the gradient for the background in the B&B editor + lingrad.setColorAt( beatPattern ? 0 : 1, c.darker( 300 ) ); + lingrad.setColorAt( beatPattern ? 1 : 0, c ); + + if( gradient() ) { - c = styleColor; + p.fillRect( rect(), lingrad ); } else { - c = QColor( 80, 80, 80 ); + p.fillRect( rect(), c ); } - - if( isSelected() == true ) - { - c.setRgb( qMax( c.red() - 128, 0 ), qMax( c.green() - 128, 0 ), 255 ); - } - - if( m_pat->m_patternType != Pattern::BeatPattern ) - { - lingrad.setColorAt( 1, c.darker( 300 ) ); - lingrad.setColorAt( 0, c ); - } - else - { - lingrad.setColorAt( 0, c.darker( 300 ) ); - lingrad.setColorAt( 1, c ); - } - - p.setBrush( lingrad ); - if( gui->pianoRoll()->currentPattern() == m_pat && m_pat->m_patternType != Pattern::BeatPattern ) - p.setPen( c.lighter( 130 ) ); - else - p.setPen( c.darker( 300 ) ); - p.drawRect( QRect( 0, 0, width() - 1, height() - 1 ) ); - - p.setBrush( QBrush() ); - if( m_pat->m_patternType != Pattern::BeatPattern ) - { - if( gui->pianoRoll()->currentPattern() == m_pat ) - p.setPen( c.lighter( 160 ) ); - else - p.setPen( c.lighter( 130 ) ); - p.drawRect( QRect( 1, 1, width() - 3, height() - 3 ) ); - } - + const float ppt = fixedTCOs() ? ( parentWidget()->width() - 2 * TCO_BORDER_WIDTH ) / (float) m_pat->length().getTact() : ( width() - 2 * TCO_BORDER_WIDTH ) / (float) m_pat->length().getTact(); - const int x_base = TCO_BORDER_WIDTH; - p.setPen( c.darker( 300 ) ); - - for( tact_t t = 1; t < m_pat->length().getTact(); ++t ) - { - p.drawLine( x_base + static_cast( ppt * t ) - 1, - TCO_BORDER_WIDTH, x_base + static_cast( - ppt * t ) - 1, 5 ); - p.drawLine( x_base + static_cast( ppt * t ) - 1, - height() - ( 4 + 2 * TCO_BORDER_WIDTH ), - x_base + static_cast( ppt * t ) - 1, - height() - 2 * TCO_BORDER_WIDTH ); - } - -// melody pattern paint event - + + // melody pattern paint event if( m_pat->m_patternType == Pattern::MelodyPattern ) { if( m_pat->m_notes.size() > 0 ) @@ -1077,15 +1030,7 @@ void PatternView::paintEvent( QPaintEvent * ) const int max_ht = height() - 1 - TCO_BORDER_WIDTH; // set colour based on mute status - if( m_pat->getTrack()->isMuted() || - m_pat->isMuted() ) - { - p.setPen( QColor( 160, 160, 160 ) ); - } - else - { - p.setPen( fgColor() ); - } + p.setPen( muted ? mutedColor() : painter.pen().brush().color() ); // scan through all the notes and draw them on the pattern for( NoteVector::Iterator it = @@ -1122,12 +1067,10 @@ void PatternView::paintEvent( QPaintEvent * ) } } } - } - -// beat pattern paint event + } - else if( m_pat->m_patternType == Pattern::BeatPattern && - ( fixedTCOs() || ppt >= 96 + // beat pattern paint event + else if( beatPattern && ( fixedTCOs() || ppt >= 96 || m_pat->m_steps != MidiTime::stepsPerTact() ) ) { QPixmap stepon; @@ -1193,30 +1136,72 @@ void PatternView::paintEvent( QPaintEvent * ) } } // end for loop } + + // bar lines + const int lineSize = 3; + p.setPen( c.darker( 300 ) ); - p.setFont( pointSize<8>( p.font() ) ); + for( tact_t t = 1; t < m_pat->length().getTact(); ++t ) + { + p.drawLine( x_base + static_cast( ppt * t ) - 1, + TCO_BORDER_WIDTH, x_base + static_cast( + ppt * t ) - 1, TCO_BORDER_WIDTH + lineSize ); + p.drawLine( x_base + static_cast( ppt * t ) - 1, + rect().bottom() - ( lineSize + TCO_BORDER_WIDTH ), + x_base + static_cast( ppt * t ) - 1, + rect().bottom() - TCO_BORDER_WIDTH ); + } - QColor text_color = ( m_pat->isMuted() || m_pat->getTrack()->isMuted() ) - ? QColor( 30, 30, 30 ) - : textColor(); + // pattern name + p.setRenderHint( QPainter::TextAntialiasing ); + + bool isDefaultName = m_pat->name() == m_pat->instrumentTrack()->name(); + + if( !isDefaultName && m_staticTextName.text() != m_pat->name() ) + { + m_staticTextName.setText( m_pat->name() ); + } + + QFont font; + font.setHintingPreference( QFont::PreferFullHinting ); + font.setPointSize( 8 ); + p.setFont( font ); + + const int textTop = TCO_BORDER_WIDTH + 1; + const int textLeft = TCO_BORDER_WIDTH + 1; + + if( !isDefaultName ) + { + p.setPen( textShadowColor() ); + p.drawStaticText( textLeft + 1, textTop + 1, m_staticTextName ); + p.setPen( textColor() ); + p.drawStaticText( textLeft, textTop, m_staticTextName ); + } - if( m_pat->name() != m_pat->instrumentTrack()->name() ) + // inner border + if( !beatPattern ) { - p.setPen( QColor( 0, 0, 0 ) ); - p.drawText( 4, p.fontMetrics().height()+1, m_pat->name() ); - p.setPen( text_color ); - p.drawText( 3, p.fontMetrics().height(), m_pat->name() ); + p.setPen( c.lighter( current ? 160 : 130 ) ); + p.drawRect( 1, 1, rect().right() - TCO_BORDER_WIDTH, + rect().bottom() - TCO_BORDER_WIDTH ); } + + // outer border + p.setPen( ( current && !beatPattern ) ? c.lighter( 130 ) : c.darker( 300 ) ); + p.drawRect( 0, 0, rect().right(), rect().bottom() ); + // draw the 'muted' pixmap only if the pattern was manualy muted if( m_pat->isMuted() ) { - p.drawPixmap( 3, p.fontMetrics().height() + 1, - embed::getIconPixmap( "muted", 16, 16 ) ); + const int spacing = TCO_BORDER_WIDTH; + const int size = 14; + p.drawPixmap( spacing, height() - ( size + spacing ), + embed::getIconPixmap( "muted", size, size ) ); } p.end(); - _p.drawPixmap( 0, 0, m_paintPixmap ); + painter.drawPixmap( 0, 0, m_paintPixmap ); } diff --git a/src/tracks/SampleTrack.cpp b/src/tracks/SampleTrack.cpp index 2f64fd7ef2d..5da7b6688b9 100644 --- a/src/tracks/SampleTrack.cpp +++ b/src/tracks/SampleTrack.cpp @@ -22,6 +22,7 @@ * Boston, MA 02110-1301 USA. * */ +#include "SampleTrack.h" #include #include @@ -33,7 +34,6 @@ #include #include "gui_templates.h" -#include "SampleTrack.h" #include "Song.h" #include "embed.h" #include "Engine.h" @@ -200,15 +200,10 @@ TrackContentObjectView * SampleTCO::createView( TrackView * _tv ) - - - - - - SampleTCOView::SampleTCOView( SampleTCO * _tco, TrackView * _tv ) : TrackContentObjectView( _tco, _tv ), - m_tco( _tco ) + m_tco( _tco ), + m_paintPixmap() { // update UI and tooltip updateSample(); @@ -273,9 +268,9 @@ void SampleTCOView::contextMenuEvent( QContextMenuEvent * _cme ) "Ctrl"), #endif m_tco, SLOT( toggleMute() ) ); - contextMenu.addAction( embed::getIconPixmap( "record" ), + /*contextMenu.addAction( embed::getIconPixmap( "record" ), tr( "Set/clear record" ), - m_tco, SLOT( toggleRecord() ) ); + m_tco, SLOT( toggleRecord() ) );*/ constructContextMenu( &contextMenu ); contextMenu.exec( QCursor::pos() ); @@ -351,77 +346,98 @@ void SampleTCOView::mouseDoubleClickEvent( QMouseEvent * ) -void SampleTCOView::paintEvent( QPaintEvent * _pe ) +void SampleTCOView::paintEvent( QPaintEvent * pe ) { - QPainter p( this ); - const QColor styleColor = p.pen().brush().color(); + QPainter painter( this ); - QColor c; - if( !( m_tco->getTrack()->isMuted() || m_tco->isMuted() ) ) + if( !needsUpdate() ) { - c = styleColor; - } - else - { - c = QColor( 80, 80, 80 ); - } - - if( isSelected() == true ) - { - c.setRgb( qMax( c.red() - 128, 0 ), qMax( c.green() - 128, 0 ), 255 ); + painter.drawPixmap( 0, 0, m_paintPixmap ); + return; } - QLinearGradient grad( 0, 0, 0, height() ); + setNeedsUpdate( false ); - grad.setColorAt( 1, c.darker( 300 ) ); - grad.setColorAt( 0, c ); + m_paintPixmap = m_paintPixmap.isNull() == true || m_paintPixmap.size() != size() + ? QPixmap( size() ) : m_paintPixmap; - p.setBrush( grad ); - p.setPen( c.lighter( 160 ) ); - p.drawRect( 1, 1, width()-3, height()-3 ); + QPainter p( &m_paintPixmap ); - p.setBrush( QBrush() ); - p.setPen( c.darker( 300 ) ); - p.drawRect( 0, 0, width()-1, height()-1 ); - - - if( m_tco->getTrack()->isMuted() || m_tco->isMuted() ) + QLinearGradient lingrad( 0, 0, 0, height() ); + QColor c; + bool muted = m_tco->getTrack()->isMuted() || m_tco->isMuted(); + + // state: selected, muted, normal + c = isSelected() ? selectedColor() : ( muted ? mutedBackgroundColor() + : painter.background().color() ); + + lingrad.setColorAt( 1, c.darker( 300 ) ); + lingrad.setColorAt( 0, c ); + + if( gradient() ) { - p.setPen( QColor( 128, 128, 128 ) ); + p.fillRect( rect(), lingrad ); } else { - p.setPen( fgColor() ); + p.fillRect( rect(), c ); } - QRect r = QRect( 1, 1, + + p.setPen( !muted ? painter.pen().brush().color() : mutedColor() ); + + const int spacing = TCO_BORDER_WIDTH + 1; + + QRect r = QRect( TCO_BORDER_WIDTH, spacing, qMax( static_cast( m_tco->sampleLength() * pixelsPerTact() / DefaultTicksPerTact ), 1 ), - height() - 4 ); - p.setClipRect( QRect( 1, 1, width() - 2, height() - 2 ) ); - m_tco->m_sampleBuffer->visualize( p, r, _pe->rect() ); + rect().bottom() - 2 * spacing ); + m_tco->m_sampleBuffer->visualize( p, r, pe->rect() ); + + // disable antialiasing for borders, since its not needed + p.setRenderHint( QPainter::Antialiasing, false ); + if( r.width() < width() - 1 ) { - p.drawLine( r.x() + r.width(), r.y() + r.height() / 2, - width() - 2, r.y() + r.height() / 2 ); + p.drawLine( r.x(), r.y() + r.height() / 2, + rect().right() - TCO_BORDER_WIDTH, r.y() + r.height() / 2 ); } - p.translate( 0, 0 ); + // inner border + p.setPen( c.lighter( 160 ) ); + p.drawRect( 1, 1, rect().right() - TCO_BORDER_WIDTH, + rect().bottom() - TCO_BORDER_WIDTH ); + + // outer border + p.setPen( c.darker( 300 ) ); + p.drawRect( 0, 0, rect().right(), rect().bottom() ); + + // draw the 'muted' pixmap only if the pattern was manualy muted if( m_tco->isMuted() ) { - p.drawPixmap( 3, 8, embed::getIconPixmap( "muted", 16, 16 ) ); + const int spacing = TCO_BORDER_WIDTH; + const int size = 14; + p.drawPixmap( spacing, height() - ( size + spacing ), + embed::getIconPixmap( "muted", size, size ) ); } - if( m_tco->isRecord() ) + + // recording sample tracks is not possible at the moment + + /* if( m_tco->isRecord() ) { p.setFont( pointSize<7>( p.font() ) ); - p.setPen( QColor( 0, 0, 0 ) ); + p.setPen( textShadowColor() ); p.drawText( 10, p.fontMetrics().height()+1, "Rec" ); p.setPen( textColor() ); p.drawText( 9, p.fontMetrics().height(), "Rec" ); p.setBrush( QBrush( textColor() ) ); p.drawEllipse( 4, 5, 4, 4 ); - } + }*/ + + p.end(); + + painter.drawPixmap( 0, 0, m_paintPixmap ); } From 12e7262e98ec711409e86c7b7b0842144aecd292 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Thu, 3 Mar 2016 17:36:38 +1300 Subject: [PATCH 58/90] Add missing Q_OBJECT macros --- include/DetuningHelper.h | 1 + include/DummyEffect.h | 1 + plugins/Flanger/FlangerControlsDialog.h | 1 + 3 files changed, 3 insertions(+) diff --git a/include/DetuningHelper.h b/include/DetuningHelper.h index f2cdde829ef..d0dbfe93c24 100644 --- a/include/DetuningHelper.h +++ b/include/DetuningHelper.h @@ -31,6 +31,7 @@ class DetuningHelper : public InlineAutomation { + Q_OBJECT MM_OPERATORS public: DetuningHelper() : diff --git a/include/DummyEffect.h b/include/DummyEffect.h index 155a98d335e..e969d8c3aa8 100644 --- a/include/DummyEffect.h +++ b/include/DummyEffect.h @@ -81,6 +81,7 @@ class DummyEffectControls : public EffectControls class DummyEffect : public Effect { + Q_OBJECT public: DummyEffect( Model * _parent, const QDomElement& originalPluginData ) : Effect( NULL, _parent, NULL ), diff --git a/plugins/Flanger/FlangerControlsDialog.h b/plugins/Flanger/FlangerControlsDialog.h index 1fef65a3e8a..6fe904ec52b 100644 --- a/plugins/Flanger/FlangerControlsDialog.h +++ b/plugins/Flanger/FlangerControlsDialog.h @@ -31,6 +31,7 @@ class FlangerControls; class FlangerControlsDialog : public EffectControlDialog { + Q_OBJECT public: FlangerControlsDialog( FlangerControls* controls ); virtual ~FlangerControlsDialog() From 85011cdcf72fbba721bb0c10f140bfabf7a35725 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Thu, 3 Mar 2016 17:37:41 +1300 Subject: [PATCH 59/90] Move CMake locale generation from src/ to data/locale/ --- data/locale/CMakeLists.txt | 40 ++++++++++++++++++++++++++++++++++++-- src/CMakeLists.txt | 35 --------------------------------- 2 files changed, 38 insertions(+), 37 deletions(-) diff --git a/data/locale/CMakeLists.txt b/data/locale/CMakeLists.txt index 4aa7d9e2af2..8454e9d8303 100644 --- a/data/locale/CMakeLists.txt +++ b/data/locale/CMakeLists.txt @@ -1,7 +1,43 @@ -FILE(GLOB QM_FILES *.qm) +if (QT5) + set (QT_LUPDATE_EXECUTABLE "${Qt5_LUPDATE_EXECUTABLE}") + set (QT_LRELEASE_EXECUTABLE "${Qt5_LRELEASE_EXECUTABLE}") +endif () + +# +# rules for building localizations +# +SET(ts_targets "") +SET(qm_targets "") +SET(QM_FILES "") + +FILE(GLOB lmms_LOCALES ${CMAKE_CURRENT_SOURCE_DIR}/*.ts) +FOREACH(_ts_file ${lmms_LOCALES}) + GET_FILENAME_COMPONENT(_ts_target "${_ts_file}" NAME) + STRING(REPLACE ".ts" ".qm" _qm_file "${_ts_file}") + STRING(REPLACE ".ts" ".qm" _qm_target "${_ts_target}") + ADD_CUSTOM_TARGET(${_ts_target} + COMMAND "${QT_LUPDATE_EXECUTABLE}" -locations none -no-obsolete -I ${CMAKE_SOURCE_DIR}/include/ ${LMMS_SRCS} ${LMMS_INCLUDES} ${LMMS_UIS} `find "\"${CMAKE_SOURCE_DIR}/plugins/\"" -type f -name '*.cpp' -or -name '*.h'` -ts "\"${_ts_file}\"" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + ADD_CUSTOM_TARGET(${_qm_target} + COMMAND "${QT_LRELEASE_EXECUTABLE}" "\"${_ts_file}\"" -qm "\"${_qm_file}\"" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + LIST(APPEND ts_targets "${_ts_target}") + LIST(APPEND qm_targets "${_qm_target}") + LIST(APPEND QM_FILES "${_qm_file}") +ENDFOREACH(_ts_file ${lmms_LOCALES}) + +ADD_CUSTOM_TARGET(update-locales) +FOREACH(_item ${ts_targets}) + ADD_DEPENDENCIES(update-locales "${_item}") +ENDFOREACH(_item ${ts_targets}) + +ADD_CUSTOM_TARGET(finalize-locales ALL) +FOREACH(_item ${qm_targets}) + ADD_DEPENDENCIES(finalize-locales "${_item}") +ENDFOREACH(_item ${qm_targets}) + IF(LMMS_BUILD_WIN32) FILE(GLOB QT_QM_FILES "${QT_TRANSLATIONS_DIR}/qt*[^h].qm") ENDIF(LMMS_BUILD_WIN32) INSTALL(FILES ${QM_FILES} ${QT_QM_FILES} DESTINATION "${LMMS_DATA_DIR}/locale") - diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0420a19dd8b..97d4c820270 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -132,41 +132,6 @@ IF(LMMS_BUILD_MSYS AND CMAKE_BUILD_TYPE STREQUAL "Debug") TARGET_LINK_LIBRARIES(lmms QtCore4 QtGui4 QtXml4) ENDIF() -if (QT5) - set (QT_LUPDATE_EXECUTABLE "${Qt5_LUPDATE_EXECUTABLE}") - set (QT_LRELEASE_EXECUTABLE "${Qt5_LRELEASE_EXECUTABLE}") -endif () - -# -# rules for building localizations -# -FILE(GLOB lmms_LOCALES ${CMAKE_SOURCE_DIR}/data/locale/*.ts) -SET(ts_targets "") -SET(qm_targets "") -FOREACH(_ts_file ${lmms_LOCALES}) - STRING(REPLACE "${CMAKE_SOURCE_DIR}/data/locale/" "" _ts_target "${_ts_file}") - STRING(REPLACE ".ts" ".qm" _qm_file "${_ts_file}") - STRING(REPLACE ".ts" ".qm" _qm_target "${_ts_target}") - ADD_CUSTOM_TARGET(${_ts_target} - COMMAND "${QT_LUPDATE_EXECUTABLE}" -locations none -no-obsolete -I ${CMAKE_SOURCE_DIR}/include/ ${LMMS_SRCS} ${LMMS_INCLUDES} ${LMMS_UIS} `find "\"${CMAKE_SOURCE_DIR}/plugins/\"" -type f -name '*.cpp' -or -name '*.h'` -ts "\"${_ts_file}\"" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) - ADD_CUSTOM_TARGET(${_qm_target} - COMMAND "${QT_LRELEASE_EXECUTABLE}" "\"${_ts_file}\"" -qm "\"${_qm_file}\"" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) - LIST(APPEND ts_targets "${_ts_target}") - LIST(APPEND qm_targets "${_qm_target}") -ENDFOREACH(_ts_file ${lmms_LOCALES}) - -ADD_CUSTOM_TARGET(update-locales) -FOREACH(_item ${ts_targets}) - ADD_DEPENDENCIES(update-locales "${_item}") -ENDFOREACH(_item ${ts_targets}) - -ADD_CUSTOM_TARGET(finalize-locales ALL) -FOREACH(_item ${qm_targets}) - ADD_DEPENDENCIES(finalize-locales "${_item}") -ENDFOREACH(_item ${qm_targets}) - # Install IF(LMMS_BUILD_WIN32) SET_TARGET_PROPERTIES(lmms PROPERTIES From 988b7886084a3c937a2fb1af8dd3ba6f4ef11123 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Thu, 3 Mar 2016 18:43:16 +1300 Subject: [PATCH 60/90] Try fixing linker errors on Win & Mac --- plugins/Flanger/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/Flanger/CMakeLists.txt b/plugins/Flanger/CMakeLists.txt index c3febd0942a..f2195e0bcd9 100644 --- a/plugins/Flanger/CMakeLists.txt +++ b/plugins/Flanger/CMakeLists.txt @@ -1,3 +1,3 @@ INCLUDE(BuildPlugin) -BUILD_PLUGIN(flanger FlangerEffect.cpp FlangerControls.cpp FlangerControlsDialog.cpp Noise.cpp QuadratureLfo.cpp MonoDelay.cpp MOCFILES FlangerControls.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") +BUILD_PLUGIN(flanger FlangerEffect.cpp FlangerControls.cpp FlangerControlsDialog.cpp Noise.cpp QuadratureLfo.cpp MonoDelay.cpp MOCFILES FlangerControls.h FlangerControlsDialog.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") From 3974faca50eb03bb2e6f4ba97c7d5cd88d9cbe6b Mon Sep 17 00:00:00 2001 From: liushuyu Date: Fri, 4 Mar 2016 17:26:29 +0800 Subject: [PATCH 61/90] Change link method of Vestige module Try to fix #2628 --- plugins/vestige/CMakeLists.txt | 6 +++++- plugins/vst_base/CMakeLists.txt | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/plugins/vestige/CMakeLists.txt b/plugins/vestige/CMakeLists.txt index edf85da321b..340e5038518 100644 --- a/plugins/vestige/CMakeLists.txt +++ b/plugins/vestige/CMakeLists.txt @@ -3,6 +3,10 @@ IF(LMMS_SUPPORT_VST) INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../vst_base") LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/../vst_base") LINK_LIBRARIES(vstbase) - BUILD_PLUGIN(vestige vestige.cpp vestige.h MOCFILES vestige.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") + IF(LMMS_BUILD_WIN32) + BUILD_PLUGIN(vestige vestige.cpp vestige.h MOCFILES vestige.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") + ELSE() + BUILD_PLUGIN(vestige vestige.cpp vestige.h MOCFILES vestige.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png" LINK SHARED) + ENDIF() ENDIF(LMMS_SUPPORT_VST) diff --git a/plugins/vst_base/CMakeLists.txt b/plugins/vst_base/CMakeLists.txt index 75a3f0f1860..18b944bc891 100644 --- a/plugins/vst_base/CMakeLists.txt +++ b/plugins/vst_base/CMakeLists.txt @@ -24,8 +24,11 @@ IF(LMMS_BUILD_WIN32) ENDIF(LMMS_BUILD_WIN64 AND NOT LMMS_BUILD_MSYS) ENDIF(LMMS_BUILD_WIN32) -BUILD_PLUGIN(vstbase vst_base.cpp VstPlugin.cpp VstPlugin.h communication.h MOCFILES VstPlugin.h) - +IF(LMMS_BUILD_WIN32) + BUILD_PLUGIN(vstbase vst_base.cpp VstPlugin.cpp VstPlugin.h communication.h MOCFILES VstPlugin.h) +ELSE() + BUILD_PLUGIN(vstbase vst_base.cpp VstPlugin.cpp VstPlugin.h communication.h MOCFILES VstPlugin.h LINK SHARED) +ENDIF() IF(LMMS_BUILD_LINUX AND NOT WANT_VST_NOWINE) From 5f48d1c596f6701cc1e4ad85d48a445f67f248da Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Fri, 4 Mar 2016 13:44:54 -0500 Subject: [PATCH 62/90] Fix menu bar colors for Qt5 Per #2611 --- data/themes/default/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 86db5a20453..88eb7c0426f 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -3,7 +3,7 @@ ********************/ /* most foreground text items */ -QLabel, QTreeWidget, QListWidget, QGroupBox { +QLabel, QTreeWidget, QListWidget, QGroupBox, QMenuBar { color: #e0e0e0; } From 1058ea4b3f1c292341ce554c9cd6144caede3cdb Mon Sep 17 00:00:00 2001 From: tresf Date: Fri, 4 Mar 2016 14:37:12 -0500 Subject: [PATCH 63/90] Hide splash screen before showing settings screen Per #2611 --- src/gui/GuiApplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/GuiApplication.cpp b/src/gui/GuiApplication.cpp index 6050f0cad6a..0a033996907 100644 --- a/src/gui/GuiApplication.cpp +++ b/src/gui/GuiApplication.cpp @@ -142,8 +142,8 @@ GuiApplication::GuiApplication() m_automationEditor = new AutomationEditorWindow; connect(m_automationEditor, SIGNAL(destroyed(QObject*)), this, SLOT(childDestroyed(QObject*))); - m_mainWindow->finalize(); splashScreen.finish(m_mainWindow); + m_mainWindow->finalize(); m_loadingProgressLabel = nullptr; } From d098a39c76321293af73f398ab89965e827b4d12 Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Fri, 4 Mar 2016 22:10:55 +0100 Subject: [PATCH 64/90] Fix dropdown menu icon margin --- data/themes/default/style.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 88eb7c0426f..81f2ac4d8cd 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -90,6 +90,10 @@ QMenu::item:disabled { padding: 4px 32px 4px 20px; } +QMenu::icon { + margin: 3px; +} + QMenu::indicator { width: 16; height: 16; From 9ff8091db3372b1e97a868323715986141b5b798 Mon Sep 17 00:00:00 2001 From: Fastigium Date: Sun, 6 Mar 2016 15:57:25 +0100 Subject: [PATCH 65/90] Fix regression that caused faulty FX channel index numbers Commit e919912 changed the behavior of the FX channel swapping code so that it no longer updated the m_channelIndex member of the swapped channels. This caused sends/receives of swapped FX channels to move about when a project was saved and loaded again. --- src/core/FxMixer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 2d5061abca9..55c9d27e8b3 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -383,6 +383,10 @@ void FxMixer::moveChannelLeft( int index ) // Swap positions in array qSwap(m_fxChannels[index], m_fxChannels[index - 1]); + + // Update m_channelIndex of both channels + m_fxChannels[index]->m_channelIndex = index; + m_fxChannels[index - 1]->m_channelIndex = index -1; } From f6317f126b44840ac35cc1a0fa665df3396d3b66 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 31 Jan 2016 13:18:36 +0100 Subject: [PATCH 66/90] Performance fixes Removes some repeated calls to Qt's font layouting by using QStaticText in FxLine and removing the overridden method ComboBox::sizeHint. Unifies Mixer::peakValueLeft and Mixer::peakValueRight into Mixer::getPeakValues so the array is only iterated once. --- include/ComboBox.h | 2 -- include/FxLine.h | 5 ++++- include/Mixer.h | 3 +-- src/core/FxMixer.cpp | 7 ++++-- src/core/Mixer.cpp | 30 ++++++++++++------------- src/gui/widgets/ComboBox.cpp | 18 --------------- src/gui/widgets/FxLine.cpp | 19 +++++++++++----- src/gui/widgets/VisualizationWidget.cpp | 14 +++++++----- 8 files changed, 46 insertions(+), 52 deletions(-) diff --git a/include/ComboBox.h b/include/ComboBox.h index 0c348e53b2f..3a592aa0e17 100644 --- a/include/ComboBox.h +++ b/include/ComboBox.h @@ -51,8 +51,6 @@ class EXPORT ComboBox : public QWidget, public IntModelView return castModel(); } - virtual QSize sizeHint() const; - public slots: void selectNext(); void selectPrevious(); diff --git a/include/FxLine.h b/include/FxLine.h index 6081912d431..c485eceb709 100644 --- a/include/FxLine.h +++ b/include/FxLine.h @@ -28,6 +28,7 @@ #include #include +#include #include "Knob.h" #include "LcdWidget.h" @@ -78,7 +79,7 @@ class FxLine : public QWidget static const int FxLineHeight; private: - static void drawFxLine( QPainter* p, const FxLine *fxLine, const QString& name, bool isActive, bool sendToThis, bool receiveFromThis ); + void drawFxLine( QPainter* p, const FxLine *fxLine, const QString& name, bool isActive, bool sendToThis, bool receiveFromThis ); FxMixerView * m_mv; LcdWidget* m_lcd; @@ -91,6 +92,8 @@ class FxLine : public QWidget static QPixmap * s_sendBgArrow; static QPixmap * s_receiveBgArrow; + QStaticText m_staticTextName; + private slots: void renameChannel(); void removeChannel(); diff --git a/include/Mixer.h b/include/Mixer.h index b8d2dec7c58..b57dc13d87f 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -314,8 +314,7 @@ class EXPORT Mixer : public QObject m_playHandleRemovalMutex.unlock(); } - static float peakValueLeft( sampleFrame * _ab, const f_cnt_t _frames ); - static float peakValueRight( sampleFrame * _ab, const f_cnt_t _frames ); + void getPeakValues( sampleFrame * _ab, const f_cnt_t _frames, float & peakLeft, float & peakRight ) const; bool criticalXRuns() const; diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 55c9d27e8b3..8777555569a 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -175,8 +175,11 @@ void FxChannel::doProcessing() m_stillRunning = m_fxChain.processAudioBuffer( m_buffer, fpp, m_hasInput ); - m_peakLeft = qMax( m_peakLeft, Engine::mixer()->peakValueLeft( m_buffer, fpp ) * v ); - m_peakRight = qMax( m_peakRight, Engine::mixer()->peakValueRight( m_buffer, fpp ) * v ); + float peakLeft = 0.; + float peakRight = 0.; + Engine::mixer()->getPeakValues( m_buffer, fpp, peakLeft, peakRight ); + m_peakLeft = qMax( m_peakLeft, peakLeft * v ); + m_peakRight = qMax( m_peakRight, peakRight * v ); } else { diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 25acd1c659c..6d3e0847476 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -484,27 +484,25 @@ void Mixer::clear() -float Mixer::peakValueLeft( sampleFrame * _ab, const f_cnt_t _frames ) +void Mixer::getPeakValues( sampleFrame * _ab, const f_cnt_t _frames, float & peakLeft, float & peakRight ) const { - float p = 0.0f; - for( f_cnt_t f = 0; f < _frames; ++f ) - { - p = qMax( p, qAbs( _ab[f][0] ) ); - } - return p; -} - - - + peakLeft = 0.0f; + peakRight = 0.0f; -float Mixer::peakValueRight( sampleFrame * _ab, const f_cnt_t _frames ) -{ - float p = 0.0f; for( f_cnt_t f = 0; f < _frames; ++f ) { - p = qMax( p, qAbs( _ab[f][1] ) ); + float const absLeft = qAbs( _ab[f][0] ); + float const absRight = qAbs( _ab[f][1] ); + if (absLeft > peakLeft) + { + peakLeft = absLeft; + } + + if (absRight > peakRight) + { + peakRight = absRight; + } } - return p; } diff --git a/src/gui/widgets/ComboBox.cpp b/src/gui/widgets/ComboBox.cpp index ab95a2b6640..c8670e49056 100644 --- a/src/gui/widgets/ComboBox.cpp +++ b/src/gui/widgets/ComboBox.cpp @@ -88,24 +88,6 @@ ComboBox::~ComboBox() -QSize ComboBox::sizeHint() const -{ - int maxTextWidth = 0; - for( int i = 0; model() && i < model()->size(); ++i ) - { - int w = fontMetrics().width( model()->itemText( i ) ); - if( w > maxTextWidth ) - { - maxTextWidth = w; - } - } - - return QSize( 32 + maxTextWidth, 22 ); -} - - - - void ComboBox::selectNext() { model()->setInitValue( model()->value() + 1 ); diff --git a/src/gui/widgets/FxLine.cpp b/src/gui/widgets/FxLine.cpp index 620f6d62621..11267534ab3 100644 --- a/src/gui/widgets/FxLine.cpp +++ b/src/gui/widgets/FxLine.cpp @@ -150,16 +150,25 @@ void FxLine::drawFxLine( QPainter* p, const FxLine *fxLine, const QString& name, } // draw the channel name + if( m_staticTextName.text() != name ) + { + m_staticTextName.setText( name ); + } p->rotate( -90 ); - p->setFont( pointSizeF( fxLine->font(), 7.5f ) ); + p->setFont( pointSizeF( fxLine->font(), 7.5f ) ); + + // Coordinates of the foreground text + int const textLeft = -145; + int const textTop = 9; + + // Draw text shadow p->setPen( sh_color ); - p->drawText( -146, 21, name ); + p->drawStaticText( textLeft - 1, textTop + 1, m_staticTextName ); + // Draw foreground text p->setPen( isActive ? bt_color : te_color ); - - p->drawText( -145, 20, name ); - + p->drawStaticText( textLeft, textTop, m_staticTextName ); } diff --git a/src/gui/widgets/VisualizationWidget.cpp b/src/gui/widgets/VisualizationWidget.cpp index 7fa3ac9c2f1..a99ec577dcf 100644 --- a/src/gui/widgets/VisualizationWidget.cpp +++ b/src/gui/widgets/VisualizationWidget.cpp @@ -122,7 +122,9 @@ void VisualizationWidget::paintEvent( QPaintEvent * ) if( m_active && !Engine::getSong()->isExporting() ) { - float master_output = Engine::mixer()->masterGain(); + Mixer const * mixer = Engine::mixer(); + + float master_output = mixer->masterGain(); int w = width()-4; const float half_h = -( height() - 6 ) / 3.0 * master_output - 1; int x_base = 2; @@ -131,11 +133,11 @@ void VisualizationWidget::paintEvent( QPaintEvent * ) // p.setClipRect( 2, 2, w, height()-4 ); - const fpp_t frames = - Engine::mixer()->framesPerPeriod(); - const float max_level = qMax( - Mixer::peakValueLeft( m_buffer, frames ), - Mixer::peakValueRight( m_buffer, frames ) ); + const fpp_t frames = mixer->framesPerPeriod(); + float peakLeft; + float peakRight; + mixer->getPeakValues( m_buffer, frames, peakLeft, peakRight ); + const float max_level = qMax( peakLeft, peakRight ); // and set color according to that... if( max_level * master_output < 0.9 ) From 1f39b607ba88256b1c77a1195a5ba2056ed14ef8 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 6 Mar 2016 19:04:51 +0100 Subject: [PATCH 67/90] Fixes #2624 ("Controls window of LFO controller is not destroyed upon closing a project") When it is destroyed the ControllerView now deletes the controller sub window in case it has one. --- src/gui/widgets/ControllerView.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/widgets/ControllerView.cpp b/src/gui/widgets/ControllerView.cpp index 641f27e7847..4e07907b7f1 100644 --- a/src/gui/widgets/ControllerView.cpp +++ b/src/gui/widgets/ControllerView.cpp @@ -104,6 +104,10 @@ ControllerView::ControllerView( Controller * _model, QWidget * _parent ) : ControllerView::~ControllerView() { + if (m_subWindow) + { + delete m_subWindow; + } } From 8768769450e245ef409fbe68cb6583c6253d90fc Mon Sep 17 00:00:00 2001 From: Lukas W Date: Mon, 7 Mar 2016 09:48:44 +1300 Subject: [PATCH 68/90] Fix channel indicator being on by default --- src/gui/widgets/FadeButton.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/widgets/FadeButton.cpp b/src/gui/widgets/FadeButton.cpp index 4fea14f97a4..5bd24918162 100644 --- a/src/gui/widgets/FadeButton.cpp +++ b/src/gui/widgets/FadeButton.cpp @@ -83,7 +83,7 @@ void FadeButton::customEvent( QEvent * ) void FadeButton::paintEvent( QPaintEvent * _pe ) { QColor col = m_normalColor; - if( m_stateTimer.elapsed() < FadeDuration ) + if( ! m_stateTimer.isNull() && m_stateTimer.elapsed() < FadeDuration ) { const float state = 1 - m_stateTimer.elapsed() / FadeDuration; const int r = (int)( m_normalColor.red() * From cbf3b92b6f53ff30aca019a75170debaa94b5409 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 6 Mar 2016 22:35:43 +0100 Subject: [PATCH 69/90] Removes an unused knob and enum (knob04.png aka knobGreen_17) Removes the knob image knob04.png. This knob corresponded to knobGreen_17 which was not used anywhere in the code. To be able to remove the enum value it was necessary to change the knob loading code in Knob::onKnobNumUpdated. However, the changed implementation is more explicit and therefore likely better to understand. --- data/themes/default/knob04.png | Bin 656 -> 0 bytes include/Knob.h | 2 +- src/gui/widgets/Knob.cpp | 30 +++++++++++++++++++++--------- 3 files changed, 22 insertions(+), 10 deletions(-) delete mode 100644 data/themes/default/knob04.png diff --git a/data/themes/default/knob04.png b/data/themes/default/knob04.png deleted file mode 100644 index 0e3af11c878b26aa02a2df4465d8bd7dc918e235..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 656 zcmV;B0&o3^P)7NPUF zm=A3Ybk$jp7RfW=fiMzvqvL1P7ru#?hnAx>m8^!rcfXJ%4B;TS9Ba%b;2R%N*;X=aD zY|Z&6gKBT+hpB5k9rn-iZgbdy4~1JDmRW@ zSQ%kkbGOOHZeugUsvQF~?^0^|Tw_DsXTeEqE`0YxmKzCZJs~f#FF1fE%;P?OON<6< z@F}*Sv1sgtsQdBZpt)BrZts`p$xa+ZdEwtew!rbziJx()a@w=kRsoccQOm3@(TASG qkjpTGhl!h6^2>Y}e|-AI8i40>GN!t%i{kwN0000width(), m_knobPixmap->height() ); } @@ -431,13 +450,6 @@ void Knob::drawKnob( QPainter * _p ) p.drawLine( ln ); break; } - case knobGreen_17: - { - p.setPen( QPen( QApplication::palette().color( QPalette::Active, - QPalette::BrightText), 2 ) ); - p.drawLine( calculateLine( mid, radius ) ); - break; - } case knobVintage_32: { p.setPen( QPen( QApplication::palette().color( QPalette::Active, From ac59d794fb41ee6c9dafc3c517db8c4c41d44211 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Sun, 6 Mar 2016 23:19:22 -0500 Subject: [PATCH 70/90] Disable libsoundio for win32 Closes #2576 --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index aa24f2eace0..9a11b3b5973 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,12 +83,14 @@ IF(LMMS_BUILD_WIN32) SET(WANT_ALSA OFF) SET(WANT_JACK OFF) SET(WANT_PULSEAUDIO OFF) + SET(WANT_SOUNDIO OFF) SET(WANT_SYSTEM_SR OFF) SET(WANT_WINMM ON) SET(LMMS_HAVE_WINMM TRUE) SET(STATUS_ALSA "") SET(STATUS_JACK "") SET(STATUS_PULSEAUDIO "") + SET(STATUS_SOUNDIO "") SET(STATUS_WINMM "OK") SET(STATUS_APPLEMIDI "") ELSE(LMMS_BUILD_WIN32) From 5e4f2190a9eb73064aa9cea93f7326d101039ea6 Mon Sep 17 00:00:00 2001 From: tresf Date: Mon, 7 Mar 2016 01:02:47 -0500 Subject: [PATCH 71/90] Fix locale generation for win32 builds Closes #2577 --- .travis/linux.win32.install.sh | 2 +- data/locale/CMakeLists.txt | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.travis/linux.win32.install.sh b/.travis/linux.win32.install.sh index 5d61807d9f2..fa910787a2a 100644 --- a/.travis/linux.win32.install.sh +++ b/.travis/linux.win32.install.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -PACKAGES="nsis cloog-isl libmpc2 mingw32 +PACKAGES="nsis cloog-isl libmpc2 qt4-linguist-tools mingw32 mingw32-x-sdl mingw32-x-libvorbis mingw32-x-fluidsynth mingw32-x-stk mingw32-x-glib2 mingw32-x-portaudio mingw32-x-libsndfile mingw32-x-fftw mingw32-x-flac mingw32-x-fltk mingw32-x-libsamplerate diff --git a/data/locale/CMakeLists.txt b/data/locale/CMakeLists.txt index 8454e9d8303..37fb24e3679 100644 --- a/data/locale/CMakeLists.txt +++ b/data/locale/CMakeLists.txt @@ -3,6 +3,17 @@ if (QT5) set (QT_LRELEASE_EXECUTABLE "${Qt5_LRELEASE_EXECUTABLE}") endif () +IF(QT_LUPDATE_EXECUTABLE STREQUAL "") + EXECUTE_PROCESS(COMMAND "lupdate" "--help" RESULT_VARIABLE LUPDATE_FALLBACK OUTPUT_QUIET) + IF(LUPDATE_FALLBACK EQUAL 0) + SET(QT_LUPDATE_EXECUTABLE lupdate) + SET(QT_LRELEASE_EXECUTABLE lrelease) + ELSE() + MESSAGE(FATAL_ERROR "Cannot generate locales") + ENDIF() +ENDIF() + + # # rules for building localizations # From a8f65ab0aff6266d006226db0fb17e5fa2d192d1 Mon Sep 17 00:00:00 2001 From: liushuyu Date: Tue, 8 Mar 2016 17:14:35 +0800 Subject: [PATCH 72/90] Update Chinese translations Progress: 1635 of 2627 strings (62.24%) --- data/locale/zh.ts | 4705 ++++++++++++++++++++++++++++++++------------- 1 file changed, 3358 insertions(+), 1347 deletions(-) diff --git a/data/locale/zh.ts b/data/locale/zh.ts index fd772feca7d..a5e37aa3e5b 100644 --- a/data/locale/zh.ts +++ b/data/locale/zh.ts @@ -1,12 +1,16 @@ - + AboutDialog About LMMS 关于LMMS + + LMMS + LMMS + Version %1 (%2/%3, Qt %4, %5) 版本 %1 (%2/%3, Qt %4, %5) @@ -19,10 +23,26 @@ LMMS - easy music production for everyone LMMS - 人人都是作曲家 + + Copyright © %1 + 版权所有 © %1 + + + <html><head/><body><p><a href="http://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">http://lmms.io</span></a></p></body></html> + <html><head/><body><p><a href="http://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">http://lmms.io</span></a></p></body></html> + Authors 作者 + + Involved + 参与者 + + + Contributors ordered by number of commits: + 贡献者名单(以提交次数排序): + Translation 翻译 @@ -33,13 +53,14 @@ If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! 当前语言是中文(中国) -您可以帮助我们改进翻译:https://github.com/LMMS/lmms/wiki/Creating-a-localization +翻译人员: +TonyChyi <tonychee1989 at gmail.com> +Min Zhang <zm1990s at gmail.com> +Jeff Bai <jeffbaichina at gmail.com> +Mingye Wang <arthur2e5@aosc.xyz> +Zixing Liu <liushuyu@aosc.xyz> -主要译者: -TonyChyi,邮箱:tonychee1989@gmail.com -Min Zhang ,邮箱:zm1990s@gmail.com -校对: -Jeff Bai,邮箱:jeffbaichina@gmail.com +若你有兴趣提高翻译质量,请联系维护团队 (https://github.com/AOSC-Dev/translations)、之前的译者或本项目维护者! License @@ -47,23 +68,11 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Copyright (c) 2004-2014, LMMS developers - Copyright (c) 2004-2014, LMMS 开发者 - - - <html><head/><body><p><a href="http://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">http://lmms.io</span></a></p></body></html> - <html><head/><body><p><a href="http://lmms.io"><span style=" text-decoration: underline; color:#0000ff;">http://lmms.io</span></a></p></body></html> - - - LMMS - LMMS - - - Involved - 参与者 + Copyright (c) 2004-2016, LMMS 开发者 - Contributors ordered by number of commits: - 贡献者名单(以提交次数排序): + <html><head/><body><p><a href="http://lmms.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">http://lmms.sourceforge.net</span></a></p></body></html> + <html><head/><body><p><a href="http://lmms.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">http://lmms.sourceforge.net</span></a></p></body></html> @@ -121,7 +130,7 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com - AudioAlsa::setupWidget + AudioAlsaSetupWidget DEVICE 设备 @@ -139,7 +148,7 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Click here, if you want to open another audio-file. A dialog will appear where you can select your file. Settings like looping-mode, start and end-points, amplify-value, and so on are not reset. So, it may not sound like the original sample. - 如果想打开另一个音频文件,请点击这里。接着会出现文件选择对话框。 诸如环回模式(looping-mode)、起始/结束点、放大值(amplify-value)之类的值不会被重置,因此音频听起来会和原采样有差异。 + 如果想打开另一个音频文件,请点击这里。接着会出现文件选择对话框。诸如环回模式(looping-mode),起始/结束点,放大值(amplify-value)之类的值不会被重置。因此听起来会和源采样有差异。 Reverse sample @@ -147,23 +156,27 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com If you enable this button, the whole sample is reversed. This is useful for cool effects, e.g. a reversed crash. - 如果点击此按钮,整个采样将会被反转。反转处理能用于制作很酷的效果,例如reversed crash。 + 如果点击此按钮,整个采样将会被反转。能用于制作很酷的效果,例如reversed crash. - Amplify: - 放大: + Disable loop + 禁用循环 - With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) - 此旋钮用于调整振幅放大比率。当设为100%时采样不会变化。除此之外,振幅不是放大就是减弱。 (原始的采样文件不会被更改) + This button disables looping. The sample plays only once from start to end. + 点击此按钮可以禁止循环播放。 - Startpoint: - 起始点: + Enable loop + 开启循环 - Endpoint: - 终止点: + This button enables forwards-looping. The sample loops between the end point and the loop point. + 点击此按钮后,Forwards-looping 会被打开,采样将在终止点(End Point)和循环点(Loop Point)之间播放。 + + + This button enables ping-pong-looping. The sample loops backwards and forwards between the end point and the loop point. + 点击此按钮后,Ping-pong-looping 会被打开,采样将在终止点(End Point)和循环点(Loop Point)之间来回播放。 Continue sample playback across notes @@ -174,29 +187,25 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com - Disable loop - 禁用循环 - - - This button disables looping. The sample plays only once from start to end. - 点击此按钮可以禁止循环播放。 - - - Enable loop - 开启循环 + Amplify: + 放大: - This button enables forwards-looping. The sample loops between the end point and the loop point. - 点击此按钮后,Forwards-looping 会被打开,采样将在终止点(End Point)和循环点(Loop Point)之间播放。 + With this knob you can set the amplify ratio. When you set a value of 100% your sample isn't changed. Otherwise it will be amplified up or down (your actual sample-file isn't touched!) + 此旋钮用于调整放大比率。当设为100% 时采样不会变化。除此之外,不是放大就是减弱(原始的采样文件不会被改变) - This button enables ping-pong-looping. The sample loops backwards and forwards between the end point and the loop point. - 点击此按钮后,Ping-pong-looping 会被打开,采样将在终止点(End Point)和循环点(Loop Point)之间来回播放。 + Startpoint: + 起始点: With this knob you can set the point where AudioFileProcessor should begin playing your sample. 调节此旋钮,以告诉 AudioFileProcessor 在哪里开始播放。 + + Endpoint: + 终点: + With this knob you can set the point where AudioFileProcessor should stop playing your sample. 调节此旋钮,以告诉 AudioFileProcessor 在哪里停止播放。 @@ -225,7 +234,7 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com LMMS was kicked by JACK for some reason. Therefore the JACK backend of LMMS has been restarted. You will have to make manual connections again. - LMMS由于某些原因与JACK断开连接。 这可能是因为LMMS的JACK后端重启导致的,你需要手动重新连接。 + LMMS由于某些原因与JACK断开连接,这可能是因为LMMS的JACK后端重启导致的,你需要手动重新连接。 JACK server down @@ -233,7 +242,7 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com The JACK server seems to have been shutdown and starting a new instance failed. Therefore LMMS is unable to proceed. You should save your project and restart JACK and LMMS. - JACK服务好像崩溃了,而且未能正常启动。 LMMS不能正常工作,你需要保存你的工作然后重启JACK和LMMS。 + JACK服务好像崩溃了而且未能正常启动,LMMS不能正常工作,你需要保存你的工作然后重启JACK和LMMS。 CLIENT-NAME @@ -284,23 +293,42 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com 设备 + + AudioSoundIo::setupWidget + + BACKEND + 后端 + + + DEVICE + 设备 + + AutomatableModel &Reset (%1%2) - 重置(%1%2)(&R) + 重置(%1%2)(&R) &Copy value (%1%2) - 复制值(%1%2)(&C) + 复制值(%1%2)(&C) &Paste value (%1%2) - 粘贴值(%1%2)(&P) + 粘贴值(%1%2)(&P) Edit song-global automation - 编辑歌曲全局自动控制选项 + 编辑歌曲全局自动控制 + + + Remove song-global automation + 删除歌曲全局自动控制 + + + Remove all linked controls + 删除所有已连接的控制器 Connected to %1 @@ -322,14 +350,6 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Connect to controller... 连接到控制器... - - Remove song-global automation - 删除歌曲全局自动控制 - - - Remove all linked controls - 移除所有已连接的控制器 - AutomationEditor @@ -345,6 +365,66 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com All selected values were copied to the clipboard. 所有选中的值已复制。 + + Automation Editor - %1 + 自动控制编辑器 - %1 + + + Draw mode (Shift+D) + 绘制模式 (Shift+D) + + + Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. + 点击这里启用绘制模式。在此模式下你可以增加或移动单个值。 大部分时间下默认使用此模式。你也可以按键盘上的 ‘Shift+D’激活此模式。 + + + Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. + 点击启用擦除模式。此模式下你可以擦除单个值。你可以按键盘上的 'Shift+E' 启用此模式。 + + + Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + 点击这里,选择的值将会被剪切到剪切板。你可以使用粘贴按钮将它们粘贴到任意地方,存为任意片段。 + + + Erase mode (Shift+E) + 擦除模式 (Shift+E) + + + Automation Editor - no pattern + 自动控制编辑器 - 没有片段 + + + Cut selected values (Ctrl+X) + 剪切选定值 (Ctrl+X) + + + Copy selected values (Ctrl+C) + 复制选定值 (Ctrl+C) + + + Click here if you want to play the current pattern. This is useful while editing it. The pattern is automatically looped when the end is reached. + 点击这里播放片段。编辑时很有用,片段会自动循环播放。 + + + Play/pause current pattern (Space) + 播放/暂停当前片段(空格) + + + Click here if you want to stop playing of the current pattern. + 点击这里停止播放片段。 + + + Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + 点击这里,选择的值将会被复制到剪切板。你可以使用粘贴按钮将它们粘贴到任意地方,存为任意片段。 + + + Stop playing of current pattern (Space) + 停止当前片段(空格) + + + Paste values from clipboard (Ctrl+V) + 从剪贴板粘贴值 (Ctrl+V) + AutomationEditorWindow @@ -364,6 +444,10 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Click here if you want to stop playing of the current pattern. 点击这里停止播放片段。 + + Edit actions + 编辑功能 + Draw mode (Shift+D) 绘制模式 (Shift+D) @@ -390,11 +474,15 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. - 点击这里启用绘制模式。在此模式下你可以增加或移动单个值。 大部分时间下默认使用此模式。你也可以按键盘上的 ‘Shift+D’激活此模式。 + 点击这里启用绘制模式。在此模式下你可以增加或移动单个值。 大部分时间下默认使用此模式。你也可以按键盘上的 ‘Shift+D’激活此模式。 Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. - 点击启用擦除模式。此模式下你可以擦除单个值。你可以按键盘上的 'Shift+E' 启用此模式。 + 点击启用擦除模式。此模式下你可以擦除单个值。你可以按键盘上的 'Shift+E' 启用此模式。 + + + Interpolation controls + 补间控制 Discrete progression @@ -428,13 +516,17 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. + + Tension: + + Cut selected values (%1+X) - 剪切选定值 (%1+X) + 剪切选定值 (%1+X) Copy selected values (%1+C) - 复制选定值 (%1+C) + 复制选定值 (%1+C) Paste values from clipboard (%1+V) @@ -442,27 +534,51 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - 点击这里,选择的值将会被剪切到剪切板。你可以使用粘贴按钮将它们粘贴到任意地方,存为任意片段。 + 点击这里,选择的值将会被剪切到剪切板。你可以使用粘贴按钮将它们粘贴到任意地方,存为任意片段。 Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - 点击这里,选择的值将会被复制到剪切板。你可以使用粘贴按钮将它们粘贴到任意地方,存为任意片段。 + 点击这里,选择的值将会被复制到剪切板。你可以使用粘贴按钮将它们粘贴到任意地方,存为任意片段。 Click here and the values from the clipboard will be pasted at the first visible measure. - 点击这里,选择的值将从剪贴板粘贴到第一个可见的小节。 + 点击这里,选择的值将从剪贴板粘贴到第一个可见的小节。 - Tension: + Timeline controls + 时间线控制 + + + Zoom controls + 缩放控制 + + + Quantization controls Automation Editor - no pattern - 自动控制编辑器 - 没有片段 + 自动控制编辑器 - 没有片段 Automation Editor - %1 - 自动控制编辑器 - %1 + 自动控制编辑器 - %1 + + + Model is already connected to this pattern. + 模型已连接到此片段。 + + + Cut selected values (Ctrl+X) + 剪切选定值 (Ctrl+X) + + + Copy selected values (Ctrl+C) + 复制选定值 (Ctrl+C) + + + Paste values from clipboard Ctrl+V) + 从剪切板粘贴数值 @@ -475,12 +591,16 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Model is already connected to this pattern. 模型已连接到此片段。 + + Drag a control while pressing <Ctrl> + 按住<Ctrl>拖动控制器 + AutomationPatternView double-click to open this pattern in automation editor - 双击以在自动编辑器中打开此片段 + 双击在自动编辑器中打开此片段 Open in Automation editor @@ -498,25 +618,29 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Change name 修改名称 - - %1 Connections - %1个连接 - - - Disconnect "%1" - 断开“%1”的连接 - Set/clear record 设置/清除录制 Flip Vertically (Visible) - + 垂直翻转 (可见) Flip Horizontally (Visible) - + 水平翻转 (可见) + + + %1 Connections + %1个连接 + + + Disconnect "%1" + 断开“%1”的连接 + + + Model is already connected to this pattern. + 模型已连接到此片段。 @@ -530,27 +654,35 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com BBEditor Beat+Bassline Editor - 节拍+Bassline编辑器 + 节拍+低音线编辑器 Play/pause current beat/bassline (Space) - 播放/暂停当前节拍/Bassline(空格) + 播放/暂停当前节拍/低音线(空格) Stop playback of current beat/bassline (Space) - 停止播放当前节拍/Bassline(空格) + 停止播放当前节拍/低音线(空格) Click here to play the current beat/bassline. The beat/bassline is automatically looped when its end is reached. - 点击这里停止播放当前节拍/Bassline。当结束时节拍/Bassline会自动循环播放。 + 点击这里停止播放当前节拍/低音线。当结束时节拍/低音线会自动循环播放。 Click here to stop playing of current beat/bassline. - 点击这里停止播发当前节拍/Bassline。 + 点击这里停止播发当前节拍/低音线。 + + + Beat selector + 节拍选择器 + + + Track and step actions + Add beat/bassline - 添加节拍/Bassline + 添加节拍/低音线 Add automation-track @@ -558,45 +690,49 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Remove steps - 移除音阶 + 移除音阶 Add steps - 添加音阶 + 添加音阶 + + + Clone Steps + BBTCOView Open in Beat+Bassline-Editor - 在节拍+Bassline编辑器中打开 + 在节拍+Bassline编辑器中打开 Reset name - 重置名称 + 重置名称 Change name - 修改名称 + 修改名称 Change color - 改变颜色 + 改变颜色 Reset color to default - 重置颜色 + 重置颜色 BBTrack Beat/Bassline %1 - 节拍/Bassline %1 + 节拍/Bassline %1 Clone of %1 - %1 的副本 + %1 的副本 @@ -645,19 +781,19 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com BitcrushControlDialog IN - + 输入 OUT - + 输出 GAIN - 增益 + 增益 Input Gain: - + 输入增益: NOIS @@ -665,19 +801,19 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Input Noise: - + 输入噪音: Output Gain: - + 输出增益: CLIP - + 压限 Output Clip: - + 输出压限: Rate @@ -693,11 +829,11 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Depth - + 位深 Depth Enabled - + 深度已启用 Enable bitdepth-crushing @@ -705,30 +841,30 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Sample rate: - + 采样率: STD - + STD Stereo difference: - + 双声道差异: Levels - + 级别 Levels: - + 级别: CaptionMenu &Help - 帮助(&H) + 帮助(&H) Help (not available) @@ -785,7 +921,7 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com MIDI-devices to receive MIDI-events from - 用来接收 MIDI 事件的 MIDI 设备 + 用来接收 MIDI 事件的MIDI 设备 USER CONTROLLER @@ -826,6 +962,10 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Confirm Delete 删除前确认 + + Confirm delete? There are existing connection(s) associated with this controller. There is no way to undo. + 确定要删除吗?此控制器仍处于被连接状态。此操作不可撤销。 + Confirm delete? There are existing connection(s) associted with this controller. There is no way to undo. 确定要删除吗?此控制器仍处于被连接状态。此操作不可撤销。 @@ -851,7 +991,11 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com &Remove this plugin - 删除这个插件(&R) + 删除这个插件(&R) + + + &Help + 帮助(&H) @@ -935,12 +1079,16 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Lfo Amount + + Output gain + 输出增益 + DelayControlsDialog Delay - + 延迟 Delay Time @@ -966,42 +1114,75 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Lfo Amt - - - DetuningHelper - Note detuning + Out Gain + + Gain + 增益 + DualFilterControlDialog - Filter 1 enabled - 已启用过滤器 1 + FREQ + 频率 - Filter 2 enabled - 已启用过滤器 2 + Cutoff frequency + 切除频率 - Click to enable/disable Filter 1 - 点击启用/禁用过滤器 1 + RESO + - Click to enable/disable Filter 2 - 点击启用/禁用过滤器 2 + Resonance + 共鸣 - - - DualFilterControls - Filter 1 enabled - 滤波器 1 已启用 + GAIN + 增益 - Filter 1 type - 滤波器 1 的类型 + Gain + 增益 + + + MIX + + + + Mix + 混合 + + + Filter 1 enabled + 已启用过滤器 1 + + + Filter 2 enabled + 已启用过滤器 2 + + + Click to enable/disable Filter 1 + 点击启用/禁用过滤器 1 + + + Click to enable/disable Filter 2 + 点击启用/禁用过滤器 2 + + + + DualFilterControls + + Filter 1 enabled + 过滤器1 已启用 + + + Filter 1 type + 过滤器 1 类型 Cutoff 1 frequency @@ -1021,11 +1202,11 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Filter 2 enabled - 滤波器 2 已启用 + 已启用过滤器 2 Filter 2 type - 滤波器 2 的类型 + 过滤器 1 类型 {2 ?} Cutoff 2 frequency @@ -1129,14 +1310,11 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com - DummyEffect + Editor - NOT FOUND - 未找到 + Transport controls + - - - Editor Play (Space) 播放(空格) @@ -1158,7 +1336,7 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Effect Effect enabled - 效果器已启用 + 启用效果器 Wet/Dry mix @@ -1177,7 +1355,7 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com EffectChain Effects enabled - 效果器已启用 + 启用效果器 @@ -1197,16 +1375,28 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Add effect 增加效果器 + + Name + 名称 + + + Description + 描述 + + + Author + + Plugin description - 插件说明 + 插件描述 EffectView Toggles the effect on or off. - 打开/关闭效果。 + 打开或关闭效果. On/Off @@ -1214,7 +1404,7 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com W/D - 干/湿 + W/D Wet Level: @@ -1250,7 +1440,7 @@ Jeff Bai,邮箱:jeffbaichina@gmail.com Controls - 控制器 + 控制 Effect plugins function as a chained series of effects where the signal will be processed from top to bottom. @@ -1270,15 +1460,19 @@ Right clicking will bring up a context menu where you can change the order in wh Move &up - 向上移 (&u) + 向上移(&U) Move &down - 向下移 (&d) + 向下移(&D) &Remove this plugin - 移除此插件 (&R) + 移除此插件(&R) + + + &Help + 帮助(&H) @@ -1289,7 +1483,7 @@ Right clicking will bring up a context menu where you can change the order in wh Attack - 起音 + 打进声 Hold @@ -1305,7 +1499,7 @@ Right clicking will bring up a context menu where you can change the order in wh Release - 释音 + 释放 Modulation @@ -1317,7 +1511,7 @@ Right clicking will bring up a context menu where you can change the order in wh LFO Attack - LFO 起音 + LFO 打进声(attack) LFO speed @@ -1348,7 +1542,7 @@ Right clicking will bring up a context menu where you can change the order in wh Predelay: - 预延迟 + 预延迟: Use this knob for setting predelay of the current envelope. The bigger this value the longer the time before start of actual envelope. @@ -1360,7 +1554,7 @@ Right clicking will bring up a context menu where you can change the order in wh Attack: - 起音: + 打进声: Use this knob for setting attack-time of the current envelope. The bigger this value the longer the envelope needs to increase to attack-level. Choose a small value for instruments like pianos and a big value for strings. @@ -1372,7 +1566,7 @@ Right clicking will bring up a context menu where you can change the order in wh Hold: - 持续: + 持续: Use this knob for setting hold-time of the current envelope. The bigger this value the longer the envelope holds attack-level before it begins to decrease to sustain-level. @@ -1396,7 +1590,7 @@ Right clicking will bring up a context menu where you can change the order in wh Sustain: - 持续: + 持续: Use this knob for setting sustain-level of the current envelope. The bigger this value the higher the level on which the envelope stays before going down to zero. @@ -1420,7 +1614,7 @@ Right clicking will bring up a context menu where you can change the order in wh Modulation amount: - 调制量 + 调制量: Use this knob for setting modulation amount of the current envelope. The bigger this value the more the according size (e.g. volume or cutoff-frequency) will be influenced by this envelope. @@ -1428,7 +1622,7 @@ Right clicking will bring up a context menu where you can change the order in wh LFO predelay: - LFO 预延迟 + LFO 预延迟: Use this knob for setting predelay-time of the current LFO. The bigger this value the the time until the LFO starts to oscillate. @@ -1478,6 +1672,10 @@ Right clicking will bring up a context menu where you can change the order in wh Click here for a user-defined wave. Afterwards, drag an according sample-file onto the LFO graph. + + Click here for random wave. + + FREQ x 100 @@ -1508,26 +1706,22 @@ Right clicking will bring up a context menu where you can change the order in wh Hint - 提示 + 提示 Drag a sample from somewhere and drop it in this window. - - Click here for random wave. - - EqControls Input gain - 输入增益 + 输入增益 Output gain - 输出增益 + 输出增益 Low shelf gain @@ -1681,6 +1875,16 @@ Right clicking will bring up a context menu where you can change the order in wh high pass type + + + Analyse IN + + + + + Analyse OUT + + EqControlsDialog @@ -1722,7 +1926,7 @@ Right clicking will bring up a context menu where you can change the order in wh Gain - 增益 + 增益 Out Gain @@ -1732,13 +1936,42 @@ Right clicking will bring up a context menu where you can change the order in wh Bandwidth: + + + Octave + + Resonance : Frequency: - 频率: + 频率: + + + lp grp + + + + hp grp + + + + + Frequency + + + + + + Resonance + + + + + Bandwidth + 12dB @@ -1752,19 +1985,23 @@ Right clicking will bring up a context menu where you can change the order in wh 48dB + + + EqHandle - lp grp + + Reso: - hp grp + + BW: - - - EqParameterWidget - Hz + + + Freq: @@ -1848,7 +2085,7 @@ Right clicking will bring up a context menu where you can change the order in wh Please note that not all of the parameters above apply for all file formats. - 请注意:上面的参数不一定适用于所有文件格式。 + 请注意上面的参数不一定适用于所有文件格式。 Quality settings @@ -1856,27 +2093,27 @@ Right clicking will bring up a context menu where you can change the order in wh Interpolation: - + 补间: Zero Order Hold - + 零阶保持 Sinc Fastest - + 最快 Sinc 补间 Sinc Medium (recommended) - + 中等 Sinc 补间 (推荐) Sinc Best (very slow!) - + 最佳 Sinc 补间 (很慢!) Oversampling (use with care!): - + 过采样 (请谨慎使用!): 1x (None) @@ -1895,87 +2132,103 @@ Right clicking will bring up a context menu where you can change the order in wh 8x - Start - 开始 + Export as loop (remove end silence) + 导出为回环loop(移除结尾的静音) - Cancel - 取消 + Export between loop markers + 只导出回环标记中间的部分 - Export as loop (remove end silence) - 导出为回环loop(移除结尾的静音) + Start + 开始 - Export between loop markers - + Cancel + 取消 Could not open file - 无法打开文件 + 无法打开文件 Could not open file %1 for writing. Please make sure you have write-permission to the file and the directory containing the file and try again! - 无法打开文件 %1 写入数据。 + 无法打开文件 %1 写入数据。 请确保你拥有对文件以及存储文件的目录的写权限,然后重试! Export project to %1 - 导出项目到 %1 + 导出项目到 %1 Error - 错误 + 错误 Error while determining file-encoder device. Please try to choose a different output format. - 寻找文件编码设备时出错。请使用另外一种输出格式。 + 寻找文件编码设备时出错。请使用另外一种输出格式。 Rendering: %1% - 渲染中:%1% + 渲染中:%1% Fader Please enter a new value between %1 and %2: - + 请输入一个介于%1和%2之间的数值: FileBrowser Browser - 浏览器 + 浏览器 FileBrowserTreeWidget Send to active instrument-track - 发送到活跃的乐器轨道 + 发送到活跃的乐器轨道 - Open in new instrument-track/Song-Editor - 在新乐器轨道/歌曲编辑器中打开 + Open in new instrument-track/Song Editor + 在新的乐器轨道/歌曲编辑器中打开 Open in new instrument-track/B+B Editor - 在新乐器轨道/B+B 编辑器中打开 + 在新乐器轨道/B+B 编辑器中打开 Loading sample - 加载采样中 + 加载采样中 Please wait, loading sample for preview... - 请稍候,加载采样中... + 请稍候,加载采样中... + + + Error + 错误 + + + does not appear to be a valid + 并不是一个有效的 + + + file + 文件 --- Factory files --- - ---软件自带文件--- + ---软件自带文件--- + + + Open in new instrument-track/Song-Editor + 在新乐器轨道/歌曲编辑器中打开 @@ -1990,7 +2243,7 @@ Please make sure you have write-permission to the file and the directory contain Seconds - + Regen @@ -1998,22 +2251,22 @@ Please make sure you have write-permission to the file and the directory contain Noise - 噪音 + 噪音 Invert - + 反转 FlangerControlsDialog Delay - + 延迟 Delay Time: - + 延迟时间: Lfo Hz @@ -2041,18 +2294,18 @@ Please make sure you have write-permission to the file and the directory contain Noise - 噪音 + 噪音 White Noise Amount: - + 白噪音数量: FxLine Channel send amount - + 通道发送的数量 The FX channel receives input from one or more instrument tracks. @@ -2066,23 +2319,23 @@ You can remove and move FX channels in the context menu, which is accessed by ri Move &left - + 向左移(&L) Move &right - + 向右移(&R) Rename &channel - + 重命名通道(&C) R&emove channel - + 删除通道(&E) Remove &unused channels - + 移除所有未用通道(&U) @@ -2098,37 +2351,37 @@ You can remove and move FX channels in the context menu, which is accessed by ri FxMixerView - - Rename FX channel - 重命名效果通道 - - - Enter the new name for this FX channel - 为此效果通道输入一个新的名称 - FX-Mixer 效果混合器 FX Fader %1 - FX 衰减器 %1 + FX 衰减器 %1 Mute - 静音 + 静音 Mute this FX channel - 静音此效果通道 + 静音此效果通道 Solo - 独奏 + 独奏 Solo FX channel - + 独奏效果通道 + + + Rename FX channel + 重命名效果通道 + + + Enter the new name for this FX channel + 为此效果通道输入一个新的名称 @@ -2142,50 +2395,50 @@ You can remove and move FX channels in the context menu, which is accessed by ri GigInstrument Bank - + Patch - + 音色 Gain - 增益 + 增益 GigInstrumentView Open other GIG file - + 打开另外的 GIG 文件 Click here to open another GIG file - + 点击这里打开另外一个 GIG 文件 Choose the patch - 选择路径 + 选择路径 Click here to change which patch of the GIG file to use - + 点击这里选择另一种 GIG 音色 Change which instrument of the GIG file is being played - + 更换正在使用的 GIG 文件中的乐器 Which GIG file is currently being used - + 哪一个 GIG 文件正在被使用 Which patch of the GIG file is currently being used - + GIG 文件的哪一个音色正在被使用 Gain - 增益 + 增益 Factor to multiply samples by @@ -2193,11 +2446,54 @@ You can remove and move FX channels in the context menu, which is accessed by ri Open GIG file - + 打开 GIG 文件 GIG Files (*.gig) - + GIG 文件 (*.gig) + + + + GuiApplication + + Working directory + 工作目录 + + + The LMMS working directory %1 does not exist. Create it now? You can change the directory later via Edit -> Settings. + LMMS工作目录%1不存在,现在新建一个吗?你可以稍后在 编辑 -> 设置 中更改此设置。 + + + Preparing UI + 正在准备界面 + + + Preparing song editor + 正在准备歌曲编辑器 + + + Preparing mixer + 正在准备混音器 + + + Preparing controller rack + 正在准备控制机架 + + + Preparing project notes + 正在准备工程注释 + + + Preparing beat/bassline editor + 正在准备节拍/低音线编辑器 + + + Preparing piano roll + 正在准备钢琴窗 + + + Preparing automation editor + 正在准备自动编辑器 @@ -2246,6 +2542,10 @@ You can remove and move FX channels in the context menu, which is accessed by ri Random 随机 + + Down and up + 下和上 + Free 自由 @@ -2258,16 +2558,12 @@ You can remove and move FX channels in the context menu, which is accessed by ri Sync 同步 - - Down and up - 下和上 - InstrumentFunctionArpeggioView ARPEGGIO - + 琶音 An arpeggio is a method playing (especially plucked) instruments, which makes the music much livelier. The strings of such instruments (e.g. harps) are plucked like chords. The only difference is that this is done in a sequential order, so the notes are not played at the same time. Typical arpeggios are major or minor triads, but there are a lot of other possible chords, you can select. @@ -2315,7 +2611,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri % - + % Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. @@ -2688,18 +2984,6 @@ You can remove and move FX channels in the context menu, which is accessed by ri Locrian Locrian - - Chords - Chords - - - Chord type - Chord type - - - Chord range - Chord range - Minor Minor @@ -2716,9 +3000,29 @@ You can remove and move FX channels in the context menu, which is accessed by ri 5 5 + + Chords + Chords + + + Chord type + Chord type + + + Chord range + Chord range + InstrumentFunctionNoteStackingView + + STACKING + 堆叠 + + + Chord: + 和弦: + RANGE 范围 @@ -2735,14 +3039,6 @@ You can remove and move FX channels in the context menu, which is accessed by ri Use this knob for setting the chord range in octaves. The selected chord will be played within specified number of octaves. - - STACKING - - - - Chord: - 和弦: - InstrumentMidiIOView @@ -2767,20 +3063,20 @@ You can remove and move FX channels in the context menu, which is accessed by ri 乐器 - MIDI devices to receive MIDI events from - + NOTE + 音符 - MIDI devices to send MIDI events to - + MIDI devices to receive MIDI events from + 用于接收 MIDI 事件的 MIDI 设备 - NOTE - 音符 + MIDI devices to send MIDI events to + 用于发送 MIDI 事件的 MIDI 设备 CUSTOM BASE VELOCITY - + 自定义基准力度 Specify the velocity normalization base for MIDI-based instruments at 100% note velocity @@ -2788,18 +3084,18 @@ You can remove and move FX channels in the context menu, which is accessed by ri BASE VELOCITY - + 基准力度 InstrumentMiscView MASTER PITCH - + 主音高 Enables the use of Master Pitch - + 启用主音高 @@ -2826,11 +3122,11 @@ You can remove and move FX channels in the context menu, which is accessed by ri Resonance - 共鸣 + 共鸣 Envelopes/LFOs - + 压限/低频振荡 Filter type @@ -2858,43 +3154,43 @@ You can remove and move FX channels in the context menu, which is accessed by ri Notch - 凹口滤波器 + 凹口滤波器 Allpass - 全通 + 全通 Moog - Moog + Moog 2x LowPass - 2 个低通串联 + 2 个低通串联 RC LowPass 12dB - RC 低通(12dB) + RC 低通(12dB) RC BandPass 12dB - RC 带通(12dB) + RC 带通(12dB) RC HighPass 12dB - RC 高通(12dB) + RC 高通(12dB) RC LowPass 24dB - RC 低通(24dB) + RC 低通(24dB) RC BandPass 24dB - RC 带通(24dB) + RC 带通(24dB) RC HighPass 24dB - RC 高通(24dB) + RC 高通(24dB) Vocal Formant Filter @@ -2933,7 +3229,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri InstrumentSoundShapingView TARGET - + 目标 These tabs contain envelopes. They're very important for modifying a sound, in that they are almost always necessary for substractive synthesis. For example if you have a volume envelope, you can set when the sound should have a specific volume. If you want to create some soft strings then your sound has to fade in and out very softly. This can be done by setting large attack and release times. It's the same for other envelope targets like panning, cutoff frequency for the used filter and so on. Just monkey around with it! You can really make cool sounds out of a saw-wave with just some envelopes...! @@ -2948,9 +3244,17 @@ You can remove and move FX channels in the context menu, which is accessed by ri - Hz + FREQ + 频率 + + + cutoff frequency: + + Hz + Hz + Use this knob for setting the cutoff frequency for the selected filter. The cutoff frequency specifies the frequency for cutting the signal by a filter. For example a lowpass-filter cuts all frequencies above the cutoff frequency. A highpass-filter cuts all frequencies below cutoff frequency, and so on... @@ -2961,31 +3265,35 @@ You can remove and move FX channels in the context menu, which is accessed by ri Resonance: - 共鸣: + 共鸣: Use this knob for setting Q/Resonance for the selected filter. Q/Resonance tells the filter how much it should amplify frequencies near Cutoff-frequency. - - FREQ - 频率 - - - cutoff frequency: - - Envelopes, LFOs and filters are not supported by the current instrument. - + 包络和低频振荡 (LFO) 不被当前乐器支持。 InstrumentTrack + + Default preset + 预置 + + + With this knob you can set the volume of the opened channel. + 使用此旋钮可以设置开放通道的音量。 + unnamed_track 未命名轨道 + + Base note + 基本音 + Volume 音量 @@ -2998,29 +3306,17 @@ You can remove and move FX channels in the context menu, which is accessed by ri Pitch 音高 - - FX channel - 效果通道 - - - Default preset - 预置 - - - With this knob you can set the volume of the opened channel. - 使用此旋钮可以设置开放通道的音量 - - - Base note - 基本音 - Pitch range 音域范围 + + FX channel + 效果通道 + Master Pitch - + 主音高 @@ -3061,12 +3357,20 @@ You can remove and move FX channels in the context menu, which is accessed by ri Output 输出 + + FX %1: %2 + 效果 %1: %2 + InstrumentTrackWindow GENERAL SETTINGS - 一般设置 + 常规设置 + + + Use these controls to view and edit the next/previous track in the song editor. + 使用这些控制选项来查看和编辑在歌曲编辑器中的上个/下个轨道。 Instrument volume @@ -3109,71 +3413,75 @@ You can remove and move FX channels in the context menu, which is accessed by ri - FX channel - 效果通道 + Pitch range (semitones) + 音域范围(半音) - ENV/LFO - + RANGE + 范围 - FUNC - + FX channel + 效果通道 FX 效果 - MIDI - MIDI + Save current instrument track settings in a preset file + 保存当前乐器轨道设置到预设文件 - Save preset - 保存预置 + Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. + 如果你想保存当前乐器轨道设置到预设文件, 请点击这里。稍后你可以在预设浏览器中双击以使用它。 - XML preset file (*.xpf) - XML 预设文件 (*.xpf) + SAVE + 保存 - PLUGIN - 插件 + ENV/LFO + 包络/低振 - Pitch range (semitones) - 音域范围(半音) + FUNC + 功能 - RANGE - 范围 + MIDI + MIDI - Save current instrument track settings in a preset file - + MISC + 杂项 - Click here, if you want to save current instrument track settings in a preset file. Later you can load this preset by double-clicking it in the preset-browser. - + Save preset + 保存预置 - MISC - 杂项 + XML preset file (*.xpf) + XML 预设文件 (*.xpf) + + + PLUGIN + 插件 Knob Set linear - + 设置为线性 Set logarithmic - + 设置为对数 Please enter a new value between -96.0 dBV and 6.0 dBV: - 请输入介于96.0 dBV 和 6.0 dBV之间的值: + 请输入介于96.0 dBV 和 6.0 dBV之间的值: Please enter a new value between %1 and %2: @@ -3219,6 +3527,10 @@ You can remove and move FX channels in the context menu, which is accessed by ri Unknown LADSPA plugin %1 requested. 已请求未知 LADSPA 插件 %1. + + Effect + 效果器 + LcdSpinBox @@ -3227,19 +3539,38 @@ You can remove and move FX channels in the context menu, which is accessed by ri 请输入一个介于%1和%2之间的数值: + + LeftRightNav + + Previous + 上个 + + + Next + 下个 + + + Previous (%1) + 上 (%1) + + + Next (%1) + 下 (%1) + + LfoController LFO Controller - + LFO 控制器 Base value - + 基准值 Oscillator speed - + 振动速度 Oscillator amount @@ -3251,7 +3582,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri Oscillator waveform - + 振动波形 Frequency Multiplier @@ -3266,7 +3597,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri LFO Controller - + LFO 控制器 BASE @@ -3298,7 +3629,7 @@ You can remove and move FX channels in the context menu, which is accessed by ri Modulation amount: - 调制量: + 调制量: Use this knob for setting modulation amount of the LFO. The bigger this value, the more the connected control (e.g. volume or cutoff-frequency) will be influenced by the LFO. @@ -3336,6 +3667,10 @@ You can remove and move FX channels in the context menu, which is accessed by ri Click here for a square-wave. + + Click here for a moog saw-wave. + + Click here for an exponential wave. @@ -3349,20 +3684,35 @@ You can remove and move FX channels in the context menu, which is accessed by ri Double click to pick a file. + + + LmmsCore - Click here for a moog saw-wave. - + Generating wavetables + 正在生成波形表 + + + Initializing data structures + 正在初始化数据结构 + + + Opening audio and midi devices + 正在启动音频和 MIDI 设备 + + + Launching mixer threads + 生在启动混音器线程 MainWindow - Working directory - 工作目录 + Configuration file + 配置文件 - The LMMS working directory %1 does not exist. Create it now? You can change the directory later via Edit -> Settings. - LMMS工作目录%1不存在,现在新建一个吗?你可以稍后在 编辑 -> 设置 中更改此设置。 + Error while parsing configuration file at line %1:%2: %3 + 解析配置文件发生错误(行%1:%2:%3) Could not save config-file @@ -3375,145 +3725,301 @@ Please make sure you have write-access to the file and try again. 请确保你可以写入这个文件并重试。 - &New - 新建(&N) + Project recovery + 工程恢复 - &Open... - 打开(&O)... + There is a recovery file present. It looks like the last session did not end properly or another instance of LMMS is already running. Do you want to recover the project of this session? + 发现了一个恢复文件。看上去上个会话没有正常结束或者其他的 LMMS 进程已经运行。你想要恢复这个项目吗? - &Save - 保存(&S)... + Recover + 恢复 - Save &As... - 另存为(&A)... + Recover the file. Please don't run multiple instances of LMMS when you do this. + 恢复文件。请不要在恢复文件时运行多个 LMMS 程序。 - Import... - 导入... + Ignore + 忽略 - E&xport... - 导出(&E)... + Launch LMMS as usual but with automatic backup disabled to prevent the present recover file from being overwritten. + 正常启动 LMMS 但是关闭自动备份来防止备份文件被覆盖。 - &Quit - 退出(&Q) + Discard + 丢弃 - &Edit - 编辑(&E) + Launch a default session and delete the restored files. This is not reversible. + 运行一个新的默认会话并且删除恢复文件。此操作无法撤销。 - Settings - 设置 + Quit + 退出 - &Tools - 工具(&T) + Shut down LMMS with no further action. + 什么也不做并关闭 LMMS。 - &Help - 帮助(&H) + Exit + 退出 - Help - 帮助 + Version %1 + 版本 %1 - What's this? - 这是什么? + Preparing plugin browser + 正在准备插件浏览器 - About - 关于 + Preparing file browsers + 正在准备文件浏览器 - Create new project - 新建工程 + My Projects + 我的工程 - Create new project from template - 从模版新建工程 + My Samples + 我的采样 - Open existing project - 打开已有工程 + My Presets + 我的预设 - Recently opened projects - 最近打开的工程 + My Home + 我的主目录 - Save current project - 保存当前工程 + Root directory + 根目录 - Export current project - 导出当前工程 + Volumes + 音量 - Song Editor - 显示/隐藏歌曲编辑器 + My Computer + 我的电脑 - By pressing this button, you can show or hide the Song-Editor. With the help of the Song-Editor you can edit song-playlist and specify when which track should be played. You can also insert and move samples (e.g. rap samples) directly into the playlist. - + Loading background artwork + 正在加载背景图案 - Beat+Bassline Editor - 显示/隐藏节拍+旋律编辑器 + &File + 文件(&F) - By pressing this button, you can show or hide the Beat+Bassline Editor. The Beat+Bassline Editor is needed for creating beats, and for opening, adding, and removing channels, and for cutting, copying and pasting beat and bassline-patterns, and for other things like that. - + &New + 新建(&N) - Piano Roll - 显示/隐藏钢琴窗 + New from template + 从模版新建工程 - Click here to show or hide the Piano-Roll. With the help of the Piano-Roll you can edit melodies in an easy way. - + &Open... + 打开(&O)... - Automation Editor - 显示/隐藏自动控制编辑器 + &Recently Opened Projects + 最近打开的工程(&R) - Click here to show or hide the Automation Editor. With the help of the Automation Editor you can edit dynamic values in an easy way. - + &Save + 保存(&S) - FX Mixer - 显示/隐藏混音器 + Save &As... + 另存为(&A)... - Click here to show or hide the FX Mixer. The FX Mixer is a very powerful tool for managing effects for your song. You can insert effects into different effect-channels. - + Save as New &Version + 保存为新版本(&V) - Project Notes - 显示/隐藏工程注释 + Save as default template + 保存为默认模板 - Click here to show or hide the project notes window. In this window you can put down your project notes. - 点击这里显示或隐藏工程注释窗。在此窗口中你可以写下工程的注释。 + Import... + 导入... - Controller Rack - 显示/隐藏控制器机架 + E&xport... + 导出(&E)... - Untitled + E&xport Tracks... + 导出音轨(&X)... + + + Export &MIDI... + 导出 MIDI (&M)... + + + &Quit + 退出(&Q) + + + &Edit + 编辑(&E) + + + Undo + 撤销 + + + Redo + 重做 + + + Settings + 设置 + + + &View + 视图 (&V) + + + &Tools + 工具(&T) + + + &Help + 帮助(&H) + + + Online Help + 在线帮助 + + + Help + 帮助 + + + What's This? + 这是什么? + + + About + 关于 + + + Create new project + 新建工程 + + + Create new project from template + 从模版新建工程 + + + Open existing project + 打开已有工程 + + + Recently opened projects + 最近打开的工程 + + + Save current project + 保存当前工程 + + + Export current project + 导出当前工程 + + + What's this? + 这是什么? + + + Toggle metronome + 开启/关闭节拍器 + + + Show/hide Song-Editor + 显示/隐藏歌曲编辑器 + + + By pressing this button, you can show or hide the Song-Editor. With the help of the Song-Editor you can edit song-playlist and specify when which track should be played. You can also insert and move samples (e.g. rap samples) directly into the playlist. + 点击这个按钮, 你可以显示/隐藏歌曲编辑器。在歌曲编辑器的帮助下, 你可以编辑歌曲播放列表并且设置哪个音轨在哪个时间播放。你还可以在播放列表中直接插入和移动采样(如 RAP 采样)。 + + + Show/hide Beat+Bassline Editor + 显示/隐藏节拍+旋律编辑器 + + + By pressing this button, you can show or hide the Beat+Bassline Editor. The Beat+Bassline Editor is needed for creating beats, and for opening, adding, and removing channels, and for cutting, copying and pasting beat and bassline-patterns, and for other things like that. + + + + Show/hide Piano-Roll + 显示/隐藏钢琴窗 + + + Click here to show or hide the Piano-Roll. With the help of the Piano-Roll you can edit melodies in an easy way. + 点击这里显示或隐藏钢琴窗。在钢琴窗的帮助下, 你可以很容易地编辑旋律。 + + + Show/hide Automation Editor + 显示/隐藏自动控制编辑器 + + + Click here to show or hide the Automation Editor. With the help of the Automation Editor you can edit dynamic values in an easy way. + 点击这里显示或隐藏自动控制编辑器。在自动控制编辑器的帮助下, 你可以很简单地控制动态数值。 + + + Show/hide FX Mixer + 显示/隐藏混音器 + + + Click here to show or hide the FX Mixer. The FX Mixer is a very powerful tool for managing effects for your song. You can insert effects into different effect-channels. + 点击这里显示或隐藏 FX 混音器。FX 混音器是管理你歌曲中不同音效的强大工具。你可以向不同的通道添加不同的效果。 + + + Show/hide project notes + 显示/隐藏工程注释 + + + Click here to show or hide the project notes window. In this window you can put down your project notes. + 点击这里显示或隐藏工程注释窗。在此窗口中你可以写下工程的注释。 + + + Show/hide controller rack + 显示/隐藏控制器机架 + + + Untitled 未标题 + + Recover session. Please save your work! + 恢复会话。请保存你的工作! + + + Automatic backup disabled. Remember to save your work! + 自动备份已禁用。记得保存你的作品哟! + LMMS %1 LMMS %1 + + Recovered project not saved + 恢复的工程没有保存 + + + This project was recovered from the previous session. It is currently unsaved and will be lost if you don't save it. Do you want to save it now? + 这个工程已从上一个会话中恢复。它现在没有被保存, 并且如果你不保存, 它将会丢失。你现在想保存它吗? + Project not saved 工程未保存 @@ -3522,6 +4028,34 @@ Please make sure you have write-access to the file and try again. The current project was modified since last saving. Do you want to save it now? 此工程自上次保存后有了修改,你想保存吗? + + Open Project + 打开工程 + + + LMMS (*.mmp *.mmpz) + LMMS (*.mmp *.mmpz) + + + Save Project + 保存工程 + + + LMMS Project + LMMS 工程 + + + LMMS Project Template + LMMS 工程模板 + + + Overwrite default template? + 覆盖默认的模板? + + + This will overwrite your current default template. + 这将会覆盖你的当前默认模板。 + Help not available 帮助不可用 @@ -3533,96 +4067,112 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. 请访问 http://lmms.sf.net/wiki 了解LMMS的相关文档。 - LMMS (*.mmp *.mmpz) - LMMS (*.mmp *.mmpz) + Song Editor + 显示/隐藏歌曲编辑器 - Version %1 - 版本 %1 + Beat+Bassline Editor + 显示/隐藏节拍+旋律编辑器 - Configuration file - 配置文件 + Piano Roll + 显示/隐藏钢琴窗 - Error while parsing configuration file at line %1:%2: %3 - 解析配置文件发生错误(行%1:%2:%3) + Automation Editor + 显示/隐藏自动控制编辑器 - Undo - 撤销 + FX Mixer + 显示/隐藏混音器 - Redo - 重做 + Project Notes + 显示/隐藏工程注释 - LMMS Project - LMMS 工程 + Controller Rack + 显示/隐藏控制器机架 - LMMS Project Template - LMMS 工程模板 + Volume as dBV + 以 dBV 显示音量 - Volumes - + Smooth scroll + 平滑滚动 - My Projects - + Enable note labels in piano roll + 在钢琴窗中显示音号 - My Samples - + Working directory + 工作目录 - My Presets - + The LMMS working directory %1 does not exist. Create it now? You can change the directory later via Edit -> Settings. + LMMS工作目录%1不存在,现在新建一个吗?你可以稍后在 编辑 -> 设置 中更改此设置。 - My Home - + Root Directory + 根目录 - My Computer - + E&xport tracks... + 导出音轨(&E)... - Root Directory - + Save project + 保存工程 - &File - + Open project + 打开工程 - &Recently Opened Projects - + Save as new &version + 保存为新版本(&V) - Save as New &Version - + Online help + 在线帮助 - E&xport Tracks... - + My home + 我的主目录 - Online Help - + My computer + 我的电脑 - What's This? - + Recently opened project + 最近打开的工程 - Open Project - + My presets + 我的预置 - Save Project - + &Project + 工程(&P) + + + My projects + 我的工程 + + + My samples + 我的采样 + + + LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + LMMS 工程 (*.mmpz *.mmp);;LMMS 工程模板 (*.mpt) + + + It looks like the last session did not end properly. Do you want to recover the project of this session? + 好像上次会话未能正常退出,你想要恢复上次会话未保存的工程吗? @@ -3637,7 +4187,7 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. TIME SIG - + 拍子记号 @@ -3651,25 +4201,11 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. - - MidiAlsaRaw::setupWidget - - DEVICE - 设备 - - - - MidiAlsaSeq - - DEVICE - 设备 - - MidiController MIDI Controller - + MIDI控制器 unnamed_midi_controller @@ -3680,22 +4216,19 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. MidiImport Setup incomplete - + 设置不完整 You do not have set up a default soundfont in the settings dialog (Edit->Settings). Therefore no sound will be played back after importing this MIDI file. You should download a General MIDI soundfont, specify it in settings dialog and try again. - + 你还没有在设置(在编辑->设置)中设置默认的 Soundfont。因此在导入此 MIDI 文件后将会没有声音。你需要下载一个通用 MIDI (GM) 的 Soundfont, 并且在设置对话框中选中后再试一次。 You did not compile LMMS with support for SoundFont2 player, which is used to add default sound to imported MIDI files. Therefore no sound will be played back after importing this MIDI file. - + 你在编译 LMMS 时没有加入 SoundFont2 播放器支持, 此播放器默认用于添加导入的 MIDI 文件。因此在 MIDI 文件导入后, 将没有声音。 - - - MidiOss::setupWidget - DEVICE - 设备 + Track + 轨道 @@ -3725,24 +4258,31 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. - Output MIDI program + Fixed output note - Receive MIDI-events + Output MIDI program - Send MIDI-events - + Base velocity + 基准力度 - Fixed output note - + Receive MIDI-events + 接受 MIDI 事件 - Base velocity - + Send MIDI-events + 发送 MIDI 事件 + + + + MidiSetupWidget + + DEVICE + 设备 @@ -4129,7 +4669,7 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. Sine wave - + 正弦波 Bandlimited Triangle wave @@ -4189,11 +4729,11 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. Triangle wave - + 三角波 Saw wave - 锯齿波 + 锯齿波 Ramp wave @@ -4201,7 +4741,7 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. Square wave - 方波 + 方波 Moog saw wave @@ -4213,7 +4753,7 @@ Please visit http://lmms.sf.net/wiki for documentation on LMMS. Random - 随机 + 随机 Random smooth @@ -4234,7 +4774,7 @@ Knobs and other widgets in the Operators view have their own what's this -t Matrix view - + 矩阵视图 The Matrix view contains the modulation matrix. Here you can define the modulation relationships between the various operators: Each audible operator (oscillators 1-3) has 3-4 properties that can be modulated by any of the modulators. Using more modulations consumes more CPU power. @@ -4244,6 +4784,110 @@ The view is divided to modulation targets, grouped by the target oscillator. Ava Each modulation target has 4 knobs, one for each modulator. By default the knobs are at 0, which means no modulation. Turning a knob to 1 causes that modulator to affect the modulation target as much as possible. Turning it to -1 does the same, but the modulation is inversed. + + Volume + 音量 + + + Panning + 声相 + + + Coarse detune + + + + semitones + 半音 + + + Finetune left + + + + cents + + + + Finetune right + + + + Stereo phase offset + + + + deg + + + + Pulse width + + + + Send sync on pulse rise + + + + Send sync on pulse fall + + + + Hard sync oscillator 2 + + + + Reverse sync oscillator 2 + + + + Sub-osc mix + + + + Hard sync oscillator 3 + + + + Reverse sync oscillator 3 + + + + Attack + 打进声 + + + Rate + + + + Phase + + + + Pre-delay + + + + Hold + 保持 + + + Decay + 衰减 + + + Sustain + 持续 + + + Release + 释放 + + + Slope + + Mix Osc2 with Osc3 @@ -4390,24 +5034,28 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator The slope knob controls the curve or shape of the envelope. A value of 0 creates straight rises and falls. Negative values create curves that start slowly, peak quickly and fall of slowly again. Positive values create curves that start and end quickly, and stay longer near the peaks. + + Modulation amount + + MultitapEchoControlDialog Length - 长度 + 长度 Step length: - 步进长度: + 步进长度: Dry - 干声 + 干声 Dry Gain: - 干声增益: + 干声增益: Stages @@ -4502,7 +5150,7 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Master volume - 主音量 + 主音量 Vibrato @@ -4510,23 +5158,146 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator - OscillatorObject + NesInstrumentView - Osc %1 volume + Volume + 音量 + + + Coarse detune - Osc %1 panning + Envelope length - Osc %1 coarse detuning + Enable channel 1 + + + + Enable envelope 1 + + + + Enable envelope 1 loop + + + + Enable sweep 1 + + + + Sweep amount + + + + Sweep rate + + + + 12.5% Duty cycle + + + + 25% Duty cycle + + + + 50% Duty cycle + + + + 75% Duty cycle + + + + Enable channel 2 + + + + Enable envelope 2 + + + + Enable envelope 2 loop + + + + Enable sweep 2 + + + + Enable channel 3 + + + + Noise Frequency + + + + Frequency sweep + + + + Enable channel 4 + + + + Enable envelope 4 + + + + Enable envelope 4 loop + + + + Quantize noise frequency when using note frequency + + + + Use note frequency for noise + + + + Noise mode + + + + Master Volume + + + + Vibrato + + + + + OscillatorObject + + Osc %1 waveform + Osc %1 波形 + + + Osc %1 harmonic + + Osc %1 volume + Osc %1 音量 + + + Osc %1 panning + Osc %1 声像 + Osc %1 fine detuning left + + Osc %1 coarse detuning + + Osc %1 fine detuning right @@ -4547,14 +5318,41 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator Modulation type %1 + + + PatchesDialog - Osc %1 waveform - + Qsynth: Channel Preset + Qsynth: 通道预设 - Osc %1 harmonic + Bank selector + 音色选择器 + + + Bank + + + + Program selector + + Patch + 音色 + + + Name + 名称 + + + OK + 确定 + + + Cancel + 取消 + PatmanView @@ -4606,10 +5404,8 @@ PM means phase modulation: Oscillator 3's phase is modulated by oscillator PatternView - double-click to open this pattern in piano-roll -use mouse wheel to set velocity of a step - 双击在钢琴窗中打开此片段 -使用鼠标滑轮设置此音阶的音量 + use mouse wheel to set velocity of a step + Open in piano-roll @@ -4635,20 +5431,32 @@ use mouse wheel to set velocity of a step Remove steps 移除音阶 + + double-click to open this pattern in piano-roll +use mouse wheel to set velocity of a step + 双击在钢琴窗中打开此片段 +使用鼠标滑轮设置此音阶的音量 + + + double-click to open this pattern in piano-roll +use mouse wheel to set volume of a step + 双击在钢琴窗中打开此片段 +使用鼠标滑轮设置此音阶的音量 + PeakController Peak Controller - + 峰值控制器 Peak Controller Bug - + 峰值控制器 Bug Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. - + 在老版本的 LMMS 中, 峰值控制器因为有 bug 而可能没有正确连接。请确保峰值控制器正常连接后再次保存次文件。我们对给你造成的不便深表歉意。 @@ -4659,49 +5467,49 @@ use mouse wheel to set velocity of a step LFO Controller - + LFO 控制器 PeakControllerEffectControlDialog BASE - + 基准 Base amount: + 基础值: + + + AMNT Modulation amount: - 调制量: + 调制量: - Attack: - 打进声: + MULT + - Release: - - - - AMNT + Amount Multiplicator: - MULT - + ATCK + 打击 - Amount Multiplicator: - + Attack: + 打击声: - ATCK + DCAY - DCAY + Release: @@ -4717,59 +5525,39 @@ use mouse wheel to set velocity of a step PeakControllerEffectControls Base value - + 基准值 Modulation amount - - - - Mute output - + 调制量 Attack - 打进声 + 打进声 Release - 释放 + 释放 - Abs Value - + Treshold + 阀值 - Amount Multiplicator + Mute output + 输出静音 + + + Abs Value - Treshold + Amount Multiplicator PianoRoll - - Piano-Roll - no pattern - 钢琴窗 - 没有片段 - - - Piano-Roll - %1 - 钢琴窗 - %1 - - - Please open a pattern by double-clicking on it! - 双击打开片段! - - - Last note - 上一个音符 - - - Note lock - - Note Velocity 音符音量 @@ -4780,6 +5568,10 @@ use mouse wheel to set velocity of a step Mark/unmark current semitone + 标记/取消标记当前半音 + + + Mark/unmark all corresponding octave semitones @@ -4794,6 +5586,18 @@ use mouse wheel to set velocity of a step Unmark all 取消标记所有 + + Select all notes on this key + 选中所有相同音调的音符 + + + Note lock + 音符锁定 + + + Last note + 上一个音符 + No scale @@ -4818,20 +5622,76 @@ use mouse wheel to set velocity of a step Panning: center 声相:居中 + + Please open a pattern by double-clicking on it! + 双击打开片段! + Please enter a new value between %1 and %2: 请输入一个介于 %1 和 %2 的值: + + Piano-Roll - no pattern + 钢琴窗 - 没有片段 + + + Piano-Roll - %1 + 钢琴窗 - %1 + + + Note Volume + 音符音量 + + + Volume: %1% + 音量:%1% + + + Cut selected notes (Ctrl+X) + 剪切选定音符 (Ctrl+X) + + + Draw mode (Shift+D) + 绘制模式 (Shift+D) + + + Erase mode (Shift+E) + 擦除模式 (Shift+E) + + + Play/pause current pattern (Space) + 播放/暂停当前片段(空格) + + + Select mode (Shift+S) + 选择模式 (Shift+S) + + + Paste notes from clipboard (Ctrl+V) + 从剪贴板粘贴音符 (Ctrl+V) + + + Record notes from MIDI-device/channel-piano + 从 MIDI 设备/通道钢琴(channel-piano) 录制音符 + + + Copy selected notes (Ctrl+C) + 复制选定音符 (Ctrl+C) + + + Stop playing of current pattern (Space) + 停止当前片段(空格) + PianoRollWindow Play/pause current pattern (Space) - 播放/暂停当前片段(空格) + 播放/暂停当前片段(空格) Record notes from MIDI-device/channel-piano - 从 MIDI 设备/通道钢琴(channel-piano) 录制音符 + 从 MIDI 设备/通道钢琴(channel-piano) 录制音符 Record notes from MIDI-device/channel-piano while playing song or BB track @@ -4839,7 +5699,7 @@ use mouse wheel to set velocity of a step Stop playing of current pattern (Space) - 停止当前片段(空格) + 停止当前片段(空格) Click here to play the current pattern. This is useful while editing it. The pattern is automatically looped when its end is reached. @@ -4857,17 +5717,21 @@ use mouse wheel to set velocity of a step Click here to stop playback of current pattern. + + Edit actions + + Draw mode (Shift+D) - 绘制模式 (Shift+D) + 绘制模式 (Shift+D) Erase mode (Shift+E) - 擦除模式 (Shift+E) + 擦除模式 (Shift+E) Select mode (Shift+S) - 选择模式 (Shift+S) + 选择模式 (Shift+S) Detune mode (Shift+T) @@ -4879,7 +5743,7 @@ use mouse wheel to set velocity of a step Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. - + 点击启用擦除模式。此模式下你可以擦除音符。你可以按键盘上的 'Shift+E' 启用此模式。 Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold %1 in draw mode to temporarily use select mode. @@ -4889,17 +5753,21 @@ use mouse wheel to set velocity of a step Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. + + Copy paste controls + + Cut selected notes (%1+X) - 剪切选定音符 (%1+X) + 剪切选定音符 (%1+X) Copy selected notes (%1+C) - 复制选定音符 (%1+C) + 复制选定音符 (%1+C) Paste notes from clipboard (%1+V) - 从剪贴板粘贴音符 (%1+V) + 从剪贴板粘贴音符 (%1+V) Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. @@ -4913,6 +5781,14 @@ use mouse wheel to set velocity of a step Click here and the notes from the clipboard will be pasted at the first visible measure. + + Timeline controls + + + + Zoom and note controls + + This controls the magnification of an axis. It can be helpful to choose magnification for a specific task. For ordinary editing, the magnification should be fitted to your smallest notes. @@ -4933,6 +5809,30 @@ use mouse wheel to set velocity of a step Let you select a chord which LMMS then can draw or highlight.You can find the most common chords in this drop-down menu. After you have selected a chord, click anywhere to place the chord, and right click on the virtual keyboard to open context menu and highlight the chord. To return to single note placement, you need to choose 'No chord' in this drop-down menu. + + Piano-Roll - %1 + 钢琴窗 - %1 + + + Piano-Roll - no pattern + 钢琴窗 - 没有片段 + + + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + 点击这里启用绘制模式。在此模式下你可以增加、改变尺寸或移动音符。大部分时间下默认使用此模式。你也可以按键盘上的 ‘Shift+D’激活此模式。在此模式中,按住 Ctrl 以便临时切换到选择模式。 + + + Cut selected notes (Ctrl+X) + 剪切选定音符 (Ctrl+X) + + + Copy selected notes (Ctrl+C) + 复制选定音符 (Ctrl+C) + + + Paste notes from clipboard (Ctrl+V) + 从剪贴板粘贴音符 (Ctrl+V) + PianoView @@ -4961,23 +5861,30 @@ Reason: "%2" Failed to load plugin "%1"! 载入插件“%1”失败! - - LMMS plugin %1 does not have a plugin descriptor named %2! - - PluginBrowser Instrument plugins - 乐器插件 + 乐器插件 Instrument browser - 乐器浏览器 + 乐器浏览器 Drag an instrument into either the Song-Editor, the Beat+Bassline Editor or into an existing instrument track. + 将乐器插件拖入歌曲编辑器, 节拍低音线编辑器, 或者现有的乐器轨道。 + + + + PluginFactory + + Plugin not found. + 未找到插件。 + + + LMMS plugin %1 does not have a plugin descriptor named %2! @@ -4985,218 +5892,178 @@ Reason: "%2" ProjectNotes Project notes - 工程注释 + 工程注释 Put down your project notes here. - 在这里写下你的工程注释。 + 在这里写下你的工程注释。 Edit Actions - 编辑功能 + 编辑功能 &Undo - 撤销(&U) + 撤销(&U) %1+Z - %1+Z + %1+Z &Redo - 重做(&R) + 重做(&R) %1+Y - %1+Y + %1+Y &Copy - 复制(&C) + 复制(&C) %1+C - %1+C + %1+C Cu&t - 剪切(&T) + 剪切(&T) %1+X - %1+X + %1+X &Paste - 粘贴(&P) + 粘贴(&P) %1+V - %1+V + %1+V Format Actions - 格式功能 + 格式功能 &Bold - 加粗(&B) + 加粗(&B) %1+B - %1+B + %1+B &Italic - 斜体(&I) + 斜体(&I) %1+I - %1+I + %1+I &Underline - 下划线(&U) + 下划线(&U) %1+U - %1+U + %1+U &Left - 左对齐(&L) + 左对齐(&L) %1+L - %1+L + %1+L C&enter - 居中(&E) + 居中(&E) %1+E - %1+E + %1+E &Right - 右对齐(&R) + 右对齐(&R) %1+R - %1+R + %1+R &Justify - 匀齐(&J) + 匀齐(&J) %1+J - %1+J + %1+J &Color... - 颜色(&C)... - - - - ProjectRenderer - - WAV-File (*.wav) - WAV-文件 (*.wav) - - - Compressed OGG-File (*.ogg) - 压缩的 OGG 文件(*.ogg) - - - - QObject - - C - Note name - C + 颜色(&C)... - Db - Note name - Db - - - C# - Note name - C# + Ctrl+Z + Ctrl+Z - D - Note name - D - - - Eb - Note name - Eb + Ctrl+Y + Ctrl+Y - D# - Note name - D# + Ctrl+C + Ctrl+C - E - Note name - E + Ctrl+X + Ctrl+X - Fb - Note name - Fb + Ctrl+V + Ctrl+V - Gb - Note name - Gb + Ctrl+B + Ctrl+B - F# - Note name - F# + Ctrl+I + Ctrl+I - G - Note name - G + Ctrl+U + Ctrl+U - Ab - Note name - Ab + Ctrl+L + Ctrl+L - G# - Note name - G# + Ctrl+E + Ctrl+E - A - Note name - A + Ctrl+R + Ctrl+R - Bb - Note name - Bb + Ctrl+J + Ctrl+J + + + ProjectRenderer - A# - Note name - A# + WAV-File (*.wav) + WAV-文件 (*.wav) - B - Note name - B + Compressed OGG-File (*.ogg) + 压缩的 OGG 文件(*.ogg) @@ -5215,7 +6082,7 @@ Reason: "%2" Requires Real Time: - 需要实时: + 要求实时: Yes @@ -5241,20 +6108,20 @@ Reason: "%2" Channels Out: 输出通道: - - File: - 文件: - File: %1 文件:%1 + + File: + 文件: + RenameDialog Rename... - 重命名... + 重命名... @@ -5263,6 +6130,10 @@ Reason: "%2" Open audio file 打开音频文件 + + All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + 所有音频文件 (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + Wave-Files (*.wav) Wave波形文件 (*.wav) @@ -5299,10 +6170,6 @@ Reason: "%2" RAW-Files (*.raw) RAW-文件 (*.raw) - - All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) - 所有音频文件 (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) - SampleTCOView @@ -5334,20 +6201,24 @@ Reason: "%2" Set/clear record 设置/清除录制 + + Mute/unmute (<Ctrl> + middle click) + 静音/取消静音 (<Ctrl> + 鼠标中键) + SampleTrack - - Sample track - 采样轨道 - Volume 音量 Panning - 声相 + 声相 + + + Sample track + 采样轨道 @@ -5366,291 +6237,350 @@ Reason: "%2" Panning - 声相 + 声相 Panning: - 声相: + 声相: PAN - PAN + PAN SetupDialog Setup LMMS - 设置LMMS + 设置LMMS General settings - 常规设置 + 常规设置 BUFFER SIZE - 缓冲区大小 + 缓冲区大小 Reset to default-value - 重置为默认值 + 重置为默认值 MISC - 杂项 + 杂项 Enable tooltips - 启用工具提示 + 启用工具提示 Show restart warning after changing settings - 在改变设置后显示重启警告 + 在改变设置后显示重启警告 Display volume as dBV - 音量显示为dBV + 音量显示为dBV Compress project files per default - 默认压缩项目文件 + 默认压缩项目文件 One instrument track window mode - + 单乐器轨道窗口模式 HQ-mode for output audio-device - + 对输出设备使用高质量输出 Compact track buttons - 紧凑化轨道图标 + 紧凑化轨道图标 Sync VST plugins to host playback - 同步 VST 插件和主机回放 + 同步 VST 插件和主机回放 Enable note labels in piano roll - 在钢琴窗中显示音号 + 在钢琴窗中显示音号 Enable waveform display by default - 默认启用波形图 + 默认启用波形图 Keep effects running even without input - + 在没有输入时也运行音频效果 Create backup file when saving a project - + 保存工程时建立备份 + + + Reopen last project on start + 启动时打开最近的项目 LANGUAGE - + 语言 Paths - 路径 + 路径 - LMMS working directory - LMMS工作目录 + Directories + 目录 - VST-plugin directory - VST插件目录 + LMMS working directory + LMMS工作目录 - Artwork directory - 插图目录 + Themes directory + 主题文件目录 Background artwork - 背景图片 + 背景图片 FL Studio installation directory - FL Studio安装目录 + FL Studio安装目录 - LADSPA plugin paths - LADSPA 插件路径 + VST-plugin directory + VST插件目录 + + + GIG directory + GIG 目录 + + + SF2 directory + SF2 目录 + + + LADSPA plugin directories + LADSPA 插件目录 STK rawwave directory - STK rawwave 目录 + STK rawwave 目录 Default Soundfont File - 默认 SoundFont 文件 + 默认 SoundFont 文件 Performance settings - 性能设置 + 性能设置 - UI effects vs. performance - 界面特效 vs 性能 + + Auto save + 自动保存 - Smooth scroll in Song Editor - 歌曲编辑器中启用平滑滚动 + Enable auto save feature + 启用自动保存功能 - Enable auto save feature - 启用自动保存功能 + UI effects vs. performance + 界面特效 vs 性能 + + + Smooth scroll in Song Editor + 歌曲编辑器中启用平滑滚动 Show playback cursor in AudioFileProcessor - 在 AudioFileProcessor 中显示回放光标 + 在 AudioFileProcessor 中显示回放光标 Audio settings - 音频设置 + 音频设置 AUDIO INTERFACE - 音频接口 + 音频接口 MIDI settings - MIDI设置 + MIDI设置 MIDI INTERFACE - MIDI接口 + MIDI接口 OK - 确定 + 确定 Cancel - 取消 + 取消 Restart LMMS - 重启LMMS + 重启LMMS Please note that most changes won't take effect until you restart LMMS! - 请注意很多设置需要重启LMMS才可生效! + 请注意很多设置需要重启LMMS才可生效! Frames: %1 Latency: %2 ms - 帧数: %1 + 帧数: %1 延迟: %2 毫秒 Here you can setup the internal buffer-size used by LMMS. Smaller values result in a lower latency but also may cause unusable sound or bad performance, especially on older computers or systems with a non-realtime kernel. - 在这里,你可以设置 LMMS 所用缓冲区的大小。缓冲区越小,延迟越小,但声音质量和性能可能会受影响。 + 在这里,你可以设置 LMMS 所用缓冲区的大小。缓冲区越小,延迟越小,但声音质量和性能可能会受影响。 Choose LMMS working directory - 选择 LMMS 工作目录 + 选择 LMMS 工作目录 + + + Choose your GIG directory + 选择 GIG 目录 + + + Choose your SF2 directory + 选择 SF2 目录 Choose your VST-plugin directory - 选择 VST 插件目录 + 选择 VST 插件目录 Choose artwork-theme directory - 选择插图目录 + 选择插图目录 Choose FL Studio installation directory - 选择 FL Studio 安装目录 + 选择 FL Studio 安装目录 Choose LADSPA plugin directory - 选择 LADSPA 插件目录 + 选择 LADSPA 插件目录 Choose STK rawwave directory - 选择 STK rawwave 目录 + 选择 STK rawwave 目录 Choose default SoundFont - 选择默认的 SoundFont + 选择默认的 SoundFont Choose background artwork - 选择背景图片 + 选择背景图片 + + + + minutes + 分钟 + + + + minute + 分钟 + + + + Auto save interval: %1 %2 + 自动保存间隔: %1 %2 + + + + Set the time between automatic backup to %1. +Remember to also save your project manually. + 设置自动备份到 %1 的保存时间间隔。 +不过, 请你还是记得时常手动保存你的项目哟。 Here you can select your preferred audio-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, JACK, OSS and more. Below you see a box which offers controls to setup the selected audio-interface. - + 在这里你可以选择你想要的音频接口。取决于你的系统和编译时的设置, 你可以选择 ALSA, JACK, OSS 等选项。在下面的方框中你可以设置音频接口的控制项目。 Here you can select your preferred MIDI-interface. Depending on the configuration of your system during compilation time you can choose between ALSA, OSS and more. Below you see a box which offers controls to setup the selected MIDI-interface. - + 在这里你可以选择你想要的 MIDI 接口。取决于你的系统和编译时的设置, 你可以选择 ALSA, OSS 等选项。在下面的方框中你可以设置 MIDI 接口的控制项目。 + + + Artwork directory + 插图目录 + + + LADSPA plugin paths + LADSPA 插件路径 Song Tempo - 节奏 + 节奏 Master volume - 主音量 + 主音量 Master pitch - 主音高 + 主音高 Project saved - 工程已保存 + 工程已保存 The project %1 is now saved. - 工程 %1 已保存。 + 工程 %1 已保存。 Project NOT saved. - 工程 **没有** 保存。 + 工程 **没有** 保存。 The project %1 was not saved! - 工程%1没有保存! + 工程%1没有保存! Import file - 导入文件 + 导入文件 MIDI sequences - MIDI 音序器 + MIDI 音序器 FL Studio projects - FL Studio 工程 + FL Studio 工程 Hydrogen projects - Hydrogen工程 + Hydrogen工程 All file types - 所有类型 + 所有类型 Empty project - 空工程 + 空工程 This project is empty so exporting makes no sense. Please put some items into Song Editor first! - 这个工程是空的所以就算导出也没有意义,请在歌曲编辑器中加入一点声音吧! + 这个工程是空的所以就算导出也没有意义,请在歌曲编辑器中加入一点声音吧! Select directory for writing exported tracks... - 选择写入导出音轨的目录... + 选择写入导出音轨的目录... untitled @@ -5658,7 +6588,11 @@ Latency: %2 ms Select file for project-export... - 为工程导出选择文件... + 为工程导出选择文件... + + + MIDI File (*.mid) + MIDI 文件 (*.mid) The following errors occured while loading: @@ -5671,16 +6605,20 @@ Latency: %2 ms Could not open file 无法打开文件 - - Could not write file - 无法写入文件 - Could not open file %1. You probably have no permissions to read this file. Please make sure to have at least read permissions to the file and try again. 无法打开 %1 。或许没有权限读此文件。 请确保您拥有对此文件的读权限,然后重试。 + + Could not write file + 无法写入文件 + + + Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. + 无法打开 %1 写入数据。或许没有权限修改此文件。请确保您拥有对此文件的写权限,然后重试。 + Error in file 文件错误 @@ -5689,6 +6627,14 @@ Latency: %2 ms The file %1 seems to contain errors and therefore can't be loaded. 文件 %1 似乎包含错误,无法被加载。 + + Project Version Mismatch + 版本号不匹配 + + + This %1 was created with LMMS version %2, but version %3 is installed + 这个 %1 是由版本为 %2 的 LMMS 创建的, 但是已安装的 LMMS 版本号为 %3 + Tempo 节奏 @@ -5734,8 +6680,52 @@ Latency: %2 ms 值: %1 半音程 - Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. - 无法打开 %1 写入数据。或许没有权限修改此文件。请确保您拥有对此文件的写权限,然后重试。 + Add beat/bassline + 添加节拍/低音线 + + + Record samples from Audio-device + 从音频设备录制样本 + + + Add automation-track + 添加自动化轨道 + + + Add sample-track + 添加采样轨道 + + + Song-Editor + 歌曲编辑器 + + + Record samples from Audio-device while playing song or BB track + 在播放歌曲或BB轨道时从音频设备录入样本 + + + Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. + 点击这里停止播放,歌曲位置标记会跳到歌曲的开头。 + + + Draw mode + 绘制模式 + + + Stop song (Space) + 停止歌曲(空格) + + + Play song (Space) + 播放歌曲(空格) + + + Edit mode (select and move) + 编辑模式(选定和移动) + + + Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. + 点击这里完整播放歌曲。将从绿色歌曲标记开始播放。在播放的同时可以对它进行移动。 @@ -5760,6 +6750,18 @@ Latency: %2 ms Stop song (Space) 停止歌曲(空格) + + Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. + 点击这里完整播放歌曲。将从绿色歌曲标记开始播放。在播放的同时可以对它进行移动。 + + + Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. + 点击这里停止播放,歌曲位置标记会跳到歌曲的开头。 + + + Track actions + 轨道动作 + Add beat/bassline 添加节拍/Bassline @@ -5772,6 +6774,10 @@ Latency: %2 ms Add automation-track 添加自动控制轨道 + + Edit actions + 编辑动作 + Draw mode 绘制模式 @@ -5781,12 +6787,12 @@ Latency: %2 ms 编辑模式(选定和移动) - Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. - 点击这里完整播放歌曲。将从绿色歌曲标记开始播放。在播放的同时可以对它进行移动。 + Timeline controls + 时间线控制 - Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. - 点击这里停止播放,歌曲位置标记会跳到歌曲的开头。 + Zoom controls + 缩放控制 @@ -5797,7 +6803,7 @@ Latency: %2 ms Linear Y axis - + 线性 Y 轴 @@ -5808,18 +6814,18 @@ Latency: %2 ms Linear Y axis - + 线性 Y 轴 Channel mode - + 通道模式 TabWidget Settings for %1 - + %1 的设定 @@ -5830,7 +6836,7 @@ Latency: %2 ms No Sync - + 无同步 Eight beats @@ -5908,141 +6914,167 @@ Latency: %2 ms TimeLineWidget Enable/disable auto-scrolling - 启用/禁用自动滚动 + 启用/禁用自动滚动 Enable/disable loop-points - 启用/禁用循环点 + 启用/禁用循环点 After stopping go back to begin - 停止后前往开头 + 停止后前往开头 After stopping go back to position at which playing was started - 停止后前往播放开始的地方 + 停止后前往播放开始的地方 After stopping keep position - 停止后保持位置不变 + 停止后保持位置不变 Hint - 提示 + 提示 Press <%1> to disable magnetic loop points. - 按住 <%1> 禁用磁性吸附。 + 按住 <%1> 禁用磁性吸附。 Hold <Shift> to move the begin loop point; Press <%1> to disable magnetic loop points. - 按住 <Shift> 移动起始循环点;按住 <%1> 禁用磁性吸附。 + 按住 <Shift> 移动起始循环点;按住 <%1> 禁用磁性吸附。 + + + Press <Ctrl> to disable magnetic loop points. + 按住 <Ctrl> 禁用磁性吸附。 + + + Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. + 按住 <Shift> 移动起始循环点;按住 <Ctrl> 禁用磁性吸附。 Track Mute - 静音 + 静音 Solo - 独奏 + 独奏 TrackContainer - Couldn't import file - + Importing FLP-file... + 正在导入 FLP-文件... - Couldn't find a filter for importing file %1. -You should convert this file into a format supported by LMMS using another software. - + Cancel + 取消 - Couldn't open file - + Please wait... + 请稍等... - Couldn't open file %1 for reading. -Please make sure you have read-permission to the file and the directory containing the file and try again! - + Importing MIDI-file... + 正在导入 MIDI-文件... - Loading project... - + Couldn't import file + 无法导入文件 - Cancel - 取消 + Couldn't find a filter for importing file %1. +You should convert this file into a format supported by LMMS using another software. + 无法找到导入文件 %1 的导入器 +你需要使用其他软件将此文件转换成 LMMS 支持的格式。 - Please wait... - + Couldn't open file + 无法打开文件 - Importing MIDI-file... - + Couldn't open file %1 for reading. +Please make sure you have read-permission to the file and the directory containing the file and try again! + 无法读取文件 %1 +请确认你有对该文件及其目录的读取权限后再试! - Importing FLP-file... - + Loading project... + 正在加载工程... TrackContentObject + + Mute + 静音 + Muted - 静音 + 静音 TrackContentObjectView Current position - 当前位置 + 当前位置 Hint - 提示 + 提示 Press <%1> and drag to make a copy. - 按住 <%1> 并拖动以创建副本。 + 按住 <%1> 并拖动以创建副本。 Current length - 当前长度 + 当前长度 Press <%1> for free resizing. - 按住 <%1> 自由调整大小。 + 按住 <%1> 自由调整大小。 %1:%2 (%3:%4 to %5:%6) - %1:%2 (%3:%4 到 %5:%6) + %1:%2 (%3:%4 到 %5:%6) Delete (middle mousebutton) - 删除 (鼠标中键) + 删除 (鼠标中键) Cut - 剪切 + 剪切 Copy - 复制 + 复制 Paste - 粘贴 + 粘贴 Mute/unmute (<%1> + middle click) - 静音/取消静音 (<%1> + 鼠标中键) + 静音/取消静音 (<%1> + 鼠标中键) + + + Press <Ctrl> and drag to make a copy. + 按住 <Ctrl> 并拖动以创建副本。 + + + Press <Ctrl> for free resizing. + 按住 <Ctrl> 自由调整大小。 + + + Mute/unmute (<Ctrl> + middle click) + 静音/取消静音 (<Ctrl> + 鼠标中键) @@ -6083,6 +7115,10 @@ Please make sure you have read-permission to the file and the directory containi FX %1: %2 + + Assign to new FX Channel + + Turn all recording on 打开所有录制 @@ -6091,6 +7127,10 @@ Please make sure you have read-permission to the file and the directory containi Turn all recording off 关闭所有录制 + + Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. + 按住 <Ctrl> 的同时拖动移动柄复制并移动此轨道。 + TripleOscillatorView @@ -6239,94 +7279,94 @@ Please make sure you have read-permission to the file and the directory containi VersionedSaveDialog Increment version number - + 递增版本号 Decrement version number - + 递减版本号 VestigeInstrumentView Open other VST-plugin - 打开其他的VST插件 + 打开其他的VST插件 Click here, if you want to open another VST-plugin. After clicking on this button, a file-open-dialog appears and you can select your file. - Show/hide GUI - 显示/隐藏界面 + Control VST-plugin from LMMS host + 从 LMMS 宿主控制 VST-插件 - Click here to show or hide the graphical user interface (GUI) of your VST-plugin. - 点此显示/隐藏VST插件的界面。 + Click here, if you want to control VST-plugin from host. + - Turn off all notes - 全部静音 + Open VST-plugin preset + 打开 VST-插件预设 - Open VST-plugin - 打开VST插件 + Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. + - DLL-files (*.dll) - + Previous (-) + 上一个 (-) - EXE-files (*.exe) + Click here, if you want to switch to another VST-plugin preset program. - No VST-plugin loaded - 未载入VST插件 + Save preset + 保存预置 - Control VST-plugin from LMMS host - + Click here, if you want to save current VST-plugin preset program. + 点击这里, 如果你想保存当前 VST-插件预设。 - Click here, if you want to control VST-plugin from host. - + Next (+) + 下一个 (+) - Open VST-plugin preset + Click here to select presets that are currently loaded in VST. - Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. - + Show/hide GUI + 显示/隐藏界面 - Previous (-) - + Click here to show or hide the graphical user interface (GUI) of your VST-plugin. + 点此显示/隐藏VST插件的界面。 - Click here, if you want to switch to another VST-plugin preset program. - + Turn off all notes + 全部静音 - Save preset - 保存预置 + Open VST-plugin + 打开VST插件 - Click here, if you want to save current VST-plugin preset program. - + DLL-files (*.dll) + DLL-文件 (*.dll) - Next (+) - + EXE-files (*.exe) + EXE-文件 (*.exe) - Click here to select presets that are currently loaded in VST. - + No VST-plugin loaded + 未载入VST插件 Preset - 预置 + 预置 by @@ -6334,29 +7374,29 @@ Please make sure you have read-permission to the file and the directory containi - VST plugin control - - VST插件控制 + - VST插件控制 VisualizationWidget click to enable/disable visualization of master-output - 点击启用/禁用视觉化主输出 + 点击启用/禁用视觉化主输出 Click to enable - 点击启用 + 点击启用 VstEffectControlDialog Show/hide - 显示/隐藏 + 显示/隐藏 Control VST-plugin from LMMS host - + 从 LMMS 宿主控制 VST-插件 Click here, if you want to control VST-plugin from host. @@ -6364,7 +7404,7 @@ Please make sure you have read-permission to the file and the directory containi Open VST-plugin preset - + 打开 VST-插件预设 Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. @@ -6372,7 +7412,7 @@ Please make sure you have read-permission to the file and the directory containi Previous (-) - + 上一个 (-) Click here, if you want to switch to another VST-plugin preset program. @@ -6380,7 +7420,7 @@ Please make sure you have read-permission to the file and the directory containi Next (+) - + 下一个 (+) Click here to select presets that are currently loaded in VST. @@ -6388,11 +7428,11 @@ Please make sure you have read-permission to the file and the directory containi Save preset - 保存预置 + 保存预置 Click here, if you want to save current VST-plugin preset program. - + 点击这里, 如果你想保存当前 VST-插件预设。 Effect by: @@ -6400,62 +7440,62 @@ Please make sure you have read-permission to the file and the directory containi &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> - + VstPlugin - Loading plugin - 载入插件 + The VST plugin %1 could not be loaded. + 无法载入VST插件 %1。 Open Preset - 打开预置 + 打开预置 Vst Plugin Preset (*.fxp *.fxb) - VST插件预置文件(*.fxp *.fxb) + VST插件预置文件(*.fxp *.fxb) : default - : 默认 + : 默认 " - + " ' - + ' Save Preset - 保存预置 + 保存预置 .fxp - + .fxp .FXP - + .FXP .FXB - + .FXB .fxb - + .fxb - Please wait while loading VST plugin... - 正在载入VST插件,请稍候…… + Loading plugin + 载入插件 - The VST plugin %1 could not be loaded. - 无法载入VST插件 %1。 + Please wait while loading VST plugin... + 正在载入VST插件,请稍候…… @@ -6579,6 +7619,54 @@ Please make sure you have read-permission to the file and the directory containi WatsynView + + Volume + 音量 + + + Panning + 声相 + + + Freq. multiplier + + + + Left detune + + + + cents + + + + Right detune + + + + A-B Mix + + + + Mix envelope amount + + + + Mix envelope attack + + + + Mix envelope hold + + + + Mix envelope decay + + + + Crosstalk + + Select oscillator A1 @@ -6657,7 +7745,7 @@ Please make sure you have read-permission to the file and the directory containi Normalize - 标准化 + 标准化 Click to normalize @@ -6665,7 +7753,7 @@ Please make sure you have read-permission to the file and the directory containi Invert - + 反转 Click to invert @@ -6673,7 +7761,7 @@ Please make sure you have read-permission to the file and the directory containi Smooth - 平滑 + 平滑 Click to smooth @@ -6681,7 +7769,7 @@ Please make sure you have read-permission to the file and the directory containi Sine wave - + 正弦波 Click for sine wave @@ -6689,7 +7777,7 @@ Please make sure you have read-permission to the file and the directory containi Triangle wave - + 三角波 Click for triangle wave @@ -6701,7 +7789,7 @@ Please make sure you have read-permission to the file and the directory containi Square wave - 方波 + 方波 Click for square wave @@ -6745,14 +7833,6 @@ Please make sure you have read-permission to the file and the directory containi ZynAddSubFxView - - Show GUI - 显示图形界面 - - - Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. - - Portamento: @@ -6767,7 +7847,7 @@ Please make sure you have read-permission to the file and the directory containi FREQ - 频率 + 频率 Filter Resonance: @@ -6813,56 +7893,64 @@ Please make sure you have read-permission to the file and the directory containi Forward MIDI Control Changes + + Show GUI + 显示图形界面 + + + Click here to show or hide the graphical user interface (GUI) of ZynAddSubFX. + + audioFileProcessor Amplify - + 增益 Start of sample - + 采样起始 End of sample - + 采样结尾 - Reverse sample - 反转采样 + Loopback point + 循环点 - Stutter - + Reverse sample + 反转采样 - Loopback point - + Loop mode + 循环模式 - Loop mode - 循环模式 + Stutter + Interpolation mode - + 补间方式 None - + Linear - + 线性插补 Sinc - + 辛格(Sinc)插补 Sample not found: %1 - + 采样未找到: %1 @@ -6879,72 +7967,72 @@ Please make sure you have read-permission to the file and the directory containi 采样长度 - Sine wave + Draw your own waveform here by dragging your mouse on this graph. - Triangle wave - + Sine wave + 正弦波 - Saw wave - 锯齿波 + Click for a sine-wave. + - Square wave - 方波 + Triangle wave + 三角波 - White noise wave - 白噪音 + Click here for a triangle-wave. + - User defined wave - 用户自定义波形 + Saw wave + 锯齿波 - Smooth - 平滑 + Click here for a saw-wave. + - Click here to smooth waveform. - 点击这里平滑波形。 + Square wave + 方波 - Interpolation + Click here for a square-wave. - Normalize - 标准化 + White noise wave + 白噪音 - Draw your own waveform here by dragging your mouse on this graph. + Click here for white-noise. - Click for a sine-wave. - + User defined wave + 用户自定义波形 - Click here for a triangle-wave. + Click here for a user-defined shape. - Click here for a saw-wave. - + Smooth + 平滑 - Click here for a square-wave. - + Click here to smooth waveform. + 点击这里平滑波形。 - Click here for white-noise. + Interpolation - Click here for a user-defined shape. - + Normalize + 标准化 @@ -7042,11 +8130,11 @@ Please make sure you have read-permission to the file and the directory containi dynProcControls Input gain - 输入增益 + 输入增益 Output gain - 输出增益 + 输出增益 Attack time @@ -7061,6 +8149,17 @@ Please make sure you have read-permission to the file and the directory containi + + fxLineLcdSpinBox + + Assign to: + 分配给: + + + New FX Channel + 新的效果通道 + + graphModel @@ -7078,21 +8177,21 @@ Please make sure you have read-permission to the file and the directory containi End frequency 结束频率 - - Gain - 增益 - Length 长度 Distortion Start - + 起始失真度 Distortion End - + 结束失真度 + + + Gain + 增益 Envelope Slope @@ -7129,14 +8228,14 @@ Please make sure you have read-permission to the file and the directory containi End frequency: 结束频率: - - Gain: - 增益: - Frequency Slope: 频率倾斜度: + + Gain: + 增益: + Envelope Length: 包络长度: @@ -7198,11 +8297,23 @@ Analysis Tools are plugins for which only input channels were identified. Don't Knows are plugins for which no input or output channels were identified. Double clicking any of the plugins will bring up information on the ports. - + 这个对话框显示 LMMS 找到的所有 LADSPA 插件信息。这些插件根据接口类型和名字被分为五个类别。 + +"可用效果" 是指可以被 LMMS 使用的插件。为了让 LMMS 可以开启效果, 首先, 这个插件需要是有效果的。也就是说, 这个插件需要有输入和输出通道。LMMS 会将音频接口名称中有 ‘in’ 的接口识别为输入接口, 将音频接口名称中有 ‘out’ 的接口识别为输出接口。并且, 效果插件需要有相同的输入输出通道, 还要能支持实时处理。 + +"不可用效果" 是指被识别为效果插件的插件, 但是输入输出通道数不同或者不支持实时音频处理。 + +"乐器" 是指只检测到有输出通道的插件。 + +"分析工具" 是指只检测到有输入通道的插件。 + +"未知" 是指没有检测到任何输出或输出通道的插件。 + +双击任意插件将会显示接口信息。 Type: - 类型 + 类型: @@ -7224,7 +8335,7 @@ Double clicking any of the plugins will bring up information on the ports. Name - + 名称 Rate @@ -7232,19 +8343,19 @@ Double clicking any of the plugins will bring up information on the ports. Direction - + 方向 Type - + 类型 Min < Default < Max - + 最小 < 默认 < 最大 Logarithmic - + 对数 SR Dependent @@ -7252,19 +8363,19 @@ Double clicking any of the plugins will bring up information on the ports. Audio - + 音频 Control - + 控制 Input - 输入 + 输入 Output - 输出 + 输出 Toggled @@ -7272,15 +8383,15 @@ Double clicking any of the plugins will bring up information on the ports. Integer - + 整型 Float - + 浮点 Yes - + @@ -7338,7 +8449,7 @@ Double clicking any of the plugins will bring up information on the ports. Resonance: - 共鸣: + 共鸣: Env Mod: @@ -7346,7 +8457,7 @@ Double clicking any of the plugins will bring up information on the ports. Decay: - 衰减: + 衰减: 303-es-que, 24dB/octave, 3 pole filter @@ -7362,7 +8473,7 @@ Double clicking any of the plugins will bring up information on the ports. Saw wave - 锯齿波 + 锯齿波 Click here for a saw-wave. @@ -7370,7 +8481,7 @@ Double clicking any of the plugins will bring up information on the ports. Triangle wave - + 三角波 Click here for a triangle-wave. @@ -7378,7 +8489,7 @@ Double clicking any of the plugins will bring up information on the ports. Square wave - 方波 + 方波 Click here for a square-wave. @@ -7402,7 +8513,7 @@ Double clicking any of the plugins will bring up information on the ports. Sine wave - + 正弦波 Click for a sine-wave. @@ -7410,7 +8521,7 @@ Double clicking any of the plugins will bring up information on the ports. White noise wave - 白噪音 + 白噪音 Click here for an exponential wave. @@ -7454,188 +8565,78 @@ Double clicking any of the plugins will bring up information on the ports. - lb303Synth + malletsInstrument - VCF Cutoff Frequency + Hardness - VCF Resonance + Position - VCF Envelope Mod + Vibrato Gain - VCF Envelope Decay + Vibrato Freq - Distortion - 失真 + Stick Mix + - Waveform - 波形 + Modulator + - Slide Decay + Crossfade - Slide + LFO Speed - Accent + LFO Depth - Dead + ADSR - 24dB/oct Filter + Pressure - - - lb303SynthView - Cutoff Freq: + Motion - CUT + Speed - Resonance: - 共鸣: + Bowed + - RES + Spread - Env Mod: + Marimba - ENV MOD + Vibraphone - Decay: - 衰减: - - - DEC - 衰减 - - - 303-es-que, 24dB/octave, 3 pole filter - - - - Slide Decay: - - - - SLIDE - - - - DIST: - - - - DIST - - - - WAVE: - - - - WAVE - - - - - malletsInstrument - - Hardness - - - - Position - - - - Vibrato Gain - - - - Vibrato Freq - - - - Stick Mix - - - - Modulator - - - - Crossfade - - - - LFO Speed - - - - LFO Depth - - - - ADSR - - - - Pressure - - - - Motion - - - - Speed - - - - Bowed - - - - Spread - - - - Marimba - - - - Vibraphone - - - - Agogo - + Agogo + Wood1 @@ -7681,14 +8682,6 @@ Double clicking any of the plugins will bring up information on the ports.Tibetan Bowl - - Missing files - - - - Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! - - malletsInstrumentView @@ -7704,6 +8697,14 @@ Double clicking any of the plugins will bring up information on the ports.Spread: + + Missing files + + + + Your Stk-installation seems to be incomplete. Please make sure the full Stk-package is installed! + + Hardness @@ -7825,19 +8826,19 @@ Double clicking any of the plugins will bring up information on the ports.manageVSTEffectView - VST parameter control - + - VST 参数控制 VST Sync - + VST 同步 Click here if you want to synchronize all parameters with VST plugin. - + 点击这里, 如果你想与 VST 插件同步所有参数。 Automated - + 自动 Click here if you want to display automated parameters only. @@ -7856,19 +8857,19 @@ Double clicking any of the plugins will bring up information on the ports.manageVestigeInstrumentView - VST plugin control - + - VST插件控制 VST Sync - + VST 同步 Click here if you want to synchronize all parameters with VST plugin. - + 点击这里, 如果你想与 VST 插件同步所有参数。 Automated - + 自动 Click here if you want to display automated parameters only. @@ -7887,7 +8888,7 @@ Double clicking any of the plugins will bring up information on the ports.opl2instrument Patch - + 音色 Op 1 Attack @@ -8002,6 +9003,25 @@ Double clicking any of the plugins will bring up information on the ports. + + opl2instrumentView + + Attack + 打进声 + + + Decay + 衰减 + + + Release + 释放 + + + Frequency multiplier + + + organicInstrument @@ -8019,45 +9039,45 @@ Double clicking any of the plugins will bring up information on the ports.Distortion: 失真: + + The distortion knob adds distortion to the output of the instrument. + + Volume: 音量: - Randomise + The volume knob controls the volume of the output of the instrument. It is cumulative with the instrument window's volume control. - Osc %1 waveform: - + Randomise + 随机 - Osc %1 volume: + The randomize button randomizes all knobs except the harmonics,main volume and distortion knobs. - Osc %1 panning: + Osc %1 waveform: - cents - 音分 cents - - - The distortion knob adds distortion to the output of the instrument. + Osc %1 volume: - The volume knob controls the volume of the output of the instrument. It is cumulative with the instrument window's volume control. + Osc %1 panning: - The randomize button randomizes all knobs except the harmonics,main volume and distortion knobs. + Osc %1 stereo detuning - Osc %1 stereo detuning - + cents + 音分 cents Osc %1 harmonic: @@ -8106,6 +9126,10 @@ Double clicking any of the plugins will bring up information on the ports.Channel 4 volume + + Shift Register width + + Right Output level 右声道输出电平 @@ -8154,10 +9178,6 @@ Double clicking any of the plugins will bring up information on the ports.Bass 低音 - - Shift Register width - - papuInstrumentView @@ -8169,6 +9189,10 @@ Double clicking any of the plugins will bring up information on the ports.Sweep Time + + The amount of increase or decrease in frequency + + Sweep RtShift amount: @@ -8177,6 +9201,10 @@ Double clicking any of the plugins will bring up information on the ports.Sweep RtShift amount + + The rate at which increase or decrease in frequency occurs + + Wave pattern duty: @@ -8185,10 +9213,18 @@ Double clicking any of the plugins will bring up information on the ports.Wave Pattern Duty + + The duty cycle is the ratio of the duration (time) that a signal is ON versus the total period of the signal. + + Square Channel 1 Volume: + + Square Channel 1 Volume + + Length of each step in sweep: @@ -8197,6 +9233,10 @@ Double clicking any of the plugins will bring up information on the ports.Length of each step in sweep + + The delay between step change + + Wave pattern duty @@ -8255,7 +9295,7 @@ Double clicking any of the plugins will bring up information on the ports. Bass - 低音 + 低音 Sweep Direction @@ -8306,143 +9346,133 @@ Double clicking any of the plugins will bring up information on the ports. - The amount of increase or decrease in frequency + Draw the wave here + + + patchesDialog - The rate at which increase or decrease in frequency occurs - + Qsynth: Channel Preset + Qsynth: 通道预设 - The duty cycle is the ratio of the duration (time) that a signal is ON versus the total period of the signal. - + Bank selector + 音色选择器 - Square Channel 1 Volume - + Bank + - The delay between step change + Program selector - Draw the wave here - + Patch + 音色 + + + Name + 名称 + + + OK + 确定 + + + Cancel + 取消 pluginBrowser - no description - 没有描述 + A native amplifier plugin + 原生增益插件 - Incomplete monophonic imitation tb303 - + Simple sampler with various settings for using samples (e.g. drums) in an instrument-track + 简单地在乐器栏使用采样(比如鼓音源), 同时也提供多种设置 - Plugin for freely manipulating stereo output + Boost your bass the fast and simple way - Plugin for controlling knobs with sound peaks - + Customizable wavetable synthesizer + 可自定制的波表合成器 - Plugin for enhancing stereo separation of a stereo input file + An oversampling bitcrusher - List installed LADSPA plugins - 列出已安装的 LADSPA 插件 + Carla Patchbay Instrument + Carla Patchbay 乐器 - Filter for importing FL Studio projects into LMMS - + Carla Rack Instrument + Carla Rack 乐器 - GUS-compatible patch instrument + A 4-band Crossover Equalizer - Additive Synthesizer for organ-like sounds - + A native delay plugin + 原生的衰减插件 - Tuneful things to bang on + A Dual filter plugin - VST-host for using VST(i)-plugins within LMMS - LMMS的VST(i)插件宿主 + plugin for processing dynamics in a flexible way + - Vibrating string modeler - - - - plugin for using arbitrary LADSPA-effects inside LMMS. - - - - Filter for importing MIDI-files into LMMS - - - - Emulation of the MOS6581 and MOS8580 SID. -This chip was used in the Commodore 64 computer. - - - - Player for SoundFont files - 在工程中使用SoundFont - - - Emulation of GameBoy (TM) APU - + A native eq plugin + 原生的 EQ 插件 - Customizable wavetable synthesizer - 可自定制的波表合成器 + A native flanger plugin + 一个原生的 镶边 (Flanger) 插件 - Embedded ZynAddSubFX - + Filter for importing FL Studio projects into LMMS + 将 FL Studio 工程导入 LMMS 的过滤器 - 2-operator FM Synth - + Player for GIG files + 播放 GIG 文件的播放器 Filter for importing Hydrogen files into LMMS - - - - LMMS port of sfxr - + 导入 Hydrogen 工程文件到 LMMS 的解析器 - plugin for processing dynamics in a flexible way - + Versatile drum synthesizer + 多功能鼓合成器 - plugin for waveshaping - + List installed LADSPA plugins + 列出已安装的 LADSPA 插件 - Versatile drum synthesizer - + plugin for using arbitrary LADSPA-effects inside LMMS. + 在 LMMS 中使用任意 LADSPA 效果的插件。 - 4-oscillator modulatable wavetable synth + Incomplete monophonic imitation tb303 - A native amplifier plugin + Filter for exporting MIDI-files from LMMS - plugin for using arbitrary VST effects inside LMMS. + Filter for importing MIDI-files into LMMS @@ -8450,111 +9480,102 @@ This chip was used in the Commodore 64 computer. - Three powerful oscillators you can modulate in several ways - - - - Boost your bass the fast and simple way + A multitap echo delay plugin A NES-like synthesizer - - - - Graphical spectrum analyzer plugin - + 类似于 NES 的合成器 - Simple sampler with various settings for using samples (e.g. drums) in an instrument-track + 2-operator FM Synth - Carla Rack Instrument + Additive Synthesizer for organ-like sounds - Carla Patchbay Instrument - + Emulation of GameBoy (TM) APU + GameBoy (TM) APU 模拟器 - Player for GIG files - + GUS-compatible patch instrument + GUS 兼容音色的乐器 - A multitap echo delay plugin + Plugin for controlling knobs with sound peaks - A native flanger plugin - + Player for SoundFont files + 在工程中使用SoundFont - A native delay plugin - + LMMS port of sfxr + sfxr 的 LMMS 移植版本 - An oversampling bitcrusher - + Emulation of the MOS6581 and MOS8580 SID. +This chip was used in the Commodore 64 computer. + 模拟 MOS6581 和 MOS8580 SID 的模拟器 +这些芯片曾在 Commodore 64 电脑上用过。 - A native eq plugin - + Graphical spectrum analyzer plugin + 图形频谱分析器插件 - A 4-band Crossover Equalizer + Plugin for enhancing stereo separation of a stereo input file - - - setupWidget - JACK (JACK Audio Connection Kit) + Plugin for freely manipulating stereo output - OSS Raw-MIDI (Open Sound System) + Tuneful things to bang on - SDL (Simple DirectMedia Layer) + Three powerful oscillators you can modulate in several ways - PulseAudio - + VST-host for using VST(i)-plugins within LMMS + LMMS的VST(i)插件宿主 - Dummy (no MIDI support) + Vibrating string modeler - ALSA Raw-MIDI (Advanced Linux Sound Architecture) + plugin for using arbitrary VST effects inside LMMS. - PortAudio + 4-oscillator modulatable wavetable synth - Dummy (no sound output) + plugin for waveshaping - ALSA (Advanced Linux Sound Architecture) - + Embedded ZynAddSubFX + 内置的 ZynAddSubFX - OSS (Open Sound System) - + no description + 没有描述 - WinMM MIDI - + Instrument browser + 乐器浏览器 - ALSA-Sequencer (Advanced Linux Sound Architecture) - + Instrument plugins + 乐器插件 @@ -8565,7 +9586,7 @@ This chip was used in the Commodore 64 computer. Patch - 音色 + 音色 Gain @@ -8597,7 +9618,7 @@ This chip was used in the Commodore 64 computer. Chorus Lines - + 合唱声部 Chorus Level @@ -8613,7 +9634,7 @@ This chip was used in the Commodore 64 computer. A soundfont %1 could not be loaded. - 无法载入Soundfont %1。 + 无法载入Soundfont %1。 @@ -8664,15 +9685,15 @@ This chip was used in the Commodore 64 computer. This button enables the chorus effect. This is useful for cool echo effects, but only works on files that support it. - 此按钮会启用合唱效果器。 + 此按钮会启用合唱效果器。 Chorus Lines: - + 合唱声部: Chorus Level: - + 合唱级别: Chorus Speed: @@ -8702,7 +9723,7 @@ This chip was used in the Commodore 64 computer. sidInstrument Cutoff - 切频谱 + 切除 Resonance @@ -8714,7 +9735,7 @@ This chip was used in the Commodore 64 computer. Voice 3 off - 声音 3 关 + 声音 3 关 Volume @@ -8722,7 +9743,7 @@ This chip was used in the Commodore 64 computer. Chip model - + 芯片型号 @@ -8757,15 +9778,15 @@ This chip was used in the Commodore 64 computer. MOS6581 SID - + MOS6581 SID MOS8580 SID - + MOS8580 SID Attack: - 打进声: + 打进声: Attack rate determines how rapidly the output of Voice %1 rises from zero to peak amplitude. @@ -8773,7 +9794,7 @@ This chip was used in the Commodore 64 computer. Decay: - 衰减: + 衰减: Decay rate determines how rapidly the output falls from the peak amplitude to the selected Sustain level. @@ -8781,7 +9802,7 @@ This chip was used in the Commodore 64 computer. Sustain: - 振幅持平: + 振幅持平: Output of Voice %1 will remain at the selected Sustain amplitude as long as the note is held. @@ -8789,7 +9810,7 @@ This chip was used in the Commodore 64 computer. Release: - 声音消失: + 声音消失: The output of of Voice %1 will fall from Sustain amplitude to zero amplitude at the selected Release rate. @@ -8825,11 +9846,11 @@ This chip was used in the Commodore 64 computer. Noise - 噪音 + 噪音 Sync - 同步 + 同步 Sync synchronizes the fundamental frequency of Oscillator %1 with the fundamental frequency of Oscillator %2 producing "Hard Sync" effects. @@ -8853,7 +9874,7 @@ This chip was used in the Commodore 64 computer. Test - + 测试 Test, when set, resets and locks Oscillator %1 at zero until Test is turned off. @@ -8868,14 +9889,14 @@ This chip was used in the Commodore 64 computer. Width: - + 宽度: stereoEnhancerControls Width - + 宽度 @@ -8926,6 +9947,16 @@ This chip was used in the Commodore 64 computer. Please wait while loading VST-plugin... 请等待VST插件加载完成... + + The VST-plugin %1 could not be loaded for some reason. +If it runs with other VST-software under Linux, please contact an LMMS-developer! + VST插件%1由于某些原因不能加载 +如果它在Linux下的其他VST宿主中运行正常,请联系LMMS开发者! + + + Failed loading VST-plugin + 加载VST插件失败 + vibed @@ -8955,7 +9986,7 @@ This chip was used in the Commodore 64 computer. Fuzziness %1 - + 模糊度 %1 Length %1 @@ -9030,7 +10061,7 @@ This chip was used in the Commodore 64 computer. Length: - + 长度: The Length knob sets the length of the selected string. Longer strings will both ring longer and sound brighter, however, they will also eat up more CPU cycles. @@ -9082,7 +10113,7 @@ The LED in the lower right corner of the waveform editor determines whether the Enable waveform - + 启用波形 Click here to enable/disable waveform. @@ -9098,28 +10129,52 @@ The LED in the lower right corner of the waveform editor determines whether the Sine wave - + 正弦波 + + + Use a sine-wave for current oscillator. + 为当前振荡器使用正弦波。 Triangle wave - + 三角波 + + + Use a triangle-wave for current oscillator. + 为当前振荡器使用三角波。 Saw wave 锯齿波 + + Use a saw-wave for current oscillator. + 为当前振荡器使用锯齿波。 + Square wave 方波 + + Use a square-wave for current oscillator. + 为当前振荡器使用方波。 + White noise wave 白噪音 + + Use white-noise for current oscillator. + 为当前振荡器使用白噪音。 + User defined wave 用户自定义波形 + + Use a user-defined waveform for current oscillator. + 为当前振荡器使用用户自定波形。 + Smooth 平滑 @@ -9137,28 +10192,8 @@ The LED in the lower right corner of the waveform editor determines whether the 点击这里标准化波形。 - Use a sine-wave for current oscillator. - - - - Use a triangle-wave for current oscillator. - - - - Use a saw-wave for current oscillator. - - - - Use a square-wave for current oscillator. - - - - Use white-noise for current oscillator. - - - - Use a user-defined waveform for current oscillator. - + &Help + 帮助(&H) @@ -9189,11 +10224,11 @@ The LED in the lower right corner of the waveform editor determines whether the Voice %1 wave shape - + 声音 %1 波形形状 Voice %1 sync - + 声音 %1 同步 Voice %1 ring modulate @@ -9205,30 +10240,30 @@ The LED in the lower right corner of the waveform editor determines whether the Voice %1 test - + 声音 %1 测试 waveShaperControlDialog INPUT - + 输入 Input gain: - + 输入增益: OUTPUT - + 输出 Output gain: - + 输出增益: Reset waveform - + 重置波形 Click here to reset the wavegraph back to default @@ -9236,11 +10271,11 @@ The LED in the lower right corner of the waveform editor determines whether the Smooth waveform - + 平滑波形 Click here to apply smoothing to wavegraph - + 点击这里来使波形图更为平滑 Increase graph amplitude by 1dB @@ -9260,11 +10295,11 @@ The LED in the lower right corner of the waveform editor determines whether the Clip input - + 输入压限 Clip input signal to 0dB - + 将输入信号限制到 0dB @@ -9278,4 +10313,980 @@ The LED in the lower right corner of the waveform editor determines whether the 输出增益 + + AudioAlsa::setupWidget + + DEVICE + 设备 + + + CHANNELS + 声道数 + + + + AudioJack::setupWidget + + CLIENT-NAME + 客户端名称 + + + CHANNELS + 声道数 + + + + DummyEffect + + NOT FOUND + 未找到 + + + + EqParameterWidget + + Hz + Hz + + + + FxMixerView::FxChannelView + + Mute + 静音 + + + Mute this FX channel + 静音此效果通道 + + + FX Fader %1 + FX 衰减器 %1 + + + Solo + 独奏 + + + Solo FX channel + 独奏效果通道 + + + + MidiAlsaRaw::setupWidget + + DEVICE + 设备 + + + + MidiAlsaSeq + + DEVICE + 设备 + + + + MidiAlsaSeq::setupWidget + + DEVICE + 设备 + + + + MidiOss::setupWidget + + DEVICE + 设备 + + + + QObject + + C + Note name + C + + + Db + Note name + Db + + + C# + Note name + C# + + + D + Note name + D + + + Eb + Note name + Eb + + + D# + Note name + D# + + + E + Note name + E + + + Fb + Note name + Fb + + + Gb + Note name + Gb + + + F# + Note name + F# + + + G + Note name + G + + + Ab + Note name + Ab + + + G# + Note name + G# + + + A + Note name + A + + + Bb + Note name + Bb + + + A# + Note name + A# + + + B + Note name + B + + + A + A + + + B + B + + + C + C + + + D + D + + + E + E + + + G + G + + + A# + A# + + + C# + C# + + + D# + D# + + + Ab + Ab + + + Bb + Bb + + + F# + F# + + + G# + G# + + + Db + Db + + + Eb + Eb + + + Fb + Fb + + + Gb + Gb + + + + bbEditor + + Add beat/bassline + 添加节拍/低音线 + + + Click here to stop playing of current beat/bassline. + 点击这里停止播发当前节拍/低音线。 + + + Add automation-track + 添加自动轨道 + + + Stop playback of current beat/bassline (Space) + 停止播放当前节拍/低音线(空格) + + + Remove steps + 移除音阶 + + + Beat+Bassline Editor + 节拍+低音线编辑器 + + + Add steps + 添加音阶 + + + Click here to play the current beat/bassline. The beat/bassline is automatically looped when its end is reached. + 点击这里停止播放当前节拍/低音线。当结束时节拍/低音线会自动循环播放。 + + + Play/pause current beat/bassline (Space) + 播放/暂停当前节拍/低音线(空格) + + + + bbTCOView + + Open in Beat+Bassline-Editor + 在节拍+低音线编辑器中打开 + + + Reset color to default + 重置颜色 + + + Change color + 改变颜色 + + + Reset name + 重置名称 + + + Change name + 修改名称 + + + + bbTrack + + Beat/Bassline %1 + 节拍/低音线 %1 + + + Clone of %1 + %1 的副本 + + + + exportProjectDialog + + Error + 错误 + + + Could not open file + 无法打开文件 + + + Could not open file %1 for writing. +Please make sure you have write-permission to the file and the directory containing the file and try again! + 无法打开文件 %1 写入数据。 +请确保你拥有对文件以及存储文件的目录的写权限,然后重试! + + + Error while determining file-encoder device. Please try to choose a different output format. + 寻找文件编码设备时出错。请使用另外一种输出格式。 + + + Rendering: %1% + 渲染中:%1% + + + Export project to %1 + 导出项目到 %1 + + + + fader + + Please enter a new value between %1 and %2: + 请输入一个介于 %1 和 %2 之间的值: + + + + knob + + &Help + 帮助(&H) + + + Please enter a new value between -96.0 dBV and 6.0 dBV: + 请输入介于96.0 dBV 和 6.0 dBV之间的值: + + + Please enter a new value between %1 and %2: + 请输入介于%1和%2之间的值: + + + + lb303Synth + + Distortion + 失真 + + + Waveform + 波形 + + + + lb303SynthView + + Resonance: + 共鸣: + + + Decay: + 衰减: + + + DEC + 衰减 + + + + projectNotes + + Cu&t + 剪切(&T) + + + &Bold + 加粗(&B) + + + &Copy + 复制(&C) + + + &Left + 左对齐(&L) + + + &Redo + 重做(&R) + + + &Undo + 撤销(&U) + + + Format Actions + 格式功能 + + + &Justify + 匀齐(&J) + + + Project notes + 工程注释 + + + &Paste + 粘贴(&P) + + + &Right + 右对齐(&R) + + + Edit Actions + 编辑功能 + + + Ctrl+B + Ctrl+B + + + Ctrl+C + Ctrl+C + + + Ctrl+E + Ctrl+E + + + Ctrl+I + Ctrl+I + + + Ctrl+J + Ctrl+J + + + Ctrl+L + Ctrl+L + + + Ctrl+R + Ctrl+R + + + Ctrl+U + Ctrl+U + + + Ctrl+V + Ctrl+V + + + Ctrl+X + Ctrl+X + + + Ctrl+Y + Ctrl+Y + + + Ctrl+Z + Ctrl+Z + + + Put down your project notes here. + 在这里写下你的工程注释。 + + + C&enter + 居中(&E) + + + &Color... + 颜色(&C)... + + + &Underline + 下划线(&U) + + + &Italic + 斜体(&I) + + + + renameDialog + + Rename... + 重命名... + + + + setupDialog + + OK + 确定 + + + MISC + 杂项 + + + General settings + 常规设置 + + + AUDIO INTERFACE + 音频接口 + + + Paths + 路径 + + + Performance settings + 性能设置 + + + Choose background artwork + 选择背景图片 + + + FL Studio installation directory + FL Studio安装目录 + + + Enable waveform display by default + 默认启用波形图 + + + Reset to default-value + 重置为默认值 + + + Choose LADSPA plugin directory + 选择LADSPA插件目录 + + + LMMS working directory + LMMS工作目录 + + + Choose default SoundFont + 选择默认SoundFont + + + Please note that most changes won't take effect until you restart LMMS! + 请注意很多设置需要重启LMMS才可生效! + + + Enable tooltips + 启用工具提示 + + + Show restart warning after changing settings + 在改变设置后显示重启警告 + + + Cancel + 取消 + + + Smooth scroll in Song Editor + 歌曲编辑器中启用平滑滚动 + + + Frames: %1 +Latency: %2 ms + 帧数: %1 +延迟: %2 毫秒 + + + MIDI INTERFACE + MIDI接口 + + + Background artwork + 背景图片 + + + Compact track buttons + 紧凑化轨道图标 + + + Choose FL Studio installation directory + 选择FL Studio安装目录 + + + Audio settings + 音频设置 + + + UI effects vs. performance + 界面特效 vs 性能 + + + LADSPA plugin paths + LADSPA插件目录 + + + Choose artwork-theme directory + 选择插图目录 + + + Show playback cursor in AudioFileProcessor + 在 AudioFileProcessor 中显示回放光标 + + + Enable auto save feature + 启用自动保存功能 + + + Compress project files per default + 默认压缩项目文件 + + + BUFFER SIZE + 缓冲大小 + + + Display volume as dBV + 音量显示为dBV + + + Choose STK rawwave directory + 选择 STK rawwave 文件夹 + + + Default Soundfont File + 默认SoundFont文件 + + + Sync VST plugins to host playback + 同步 VST 插件和主机回放 + + + Setup LMMS + 设置LMMS + + + Choose your VST-plugin directory + 选择VST插件目录 + + + Choose LMMS working directory + 选择LMMS工作目录 + + + Restart LMMS + 重启LMMS + + + STK rawwave directory + STK rawwave 目录 + + + VST-plugin directory + VST插件目录 + + + MIDI settings + MIDI设置 + + + Artwork directory + 插图目录 + + + Enable note labels in piano roll + 在钢琴窗中显示音号 + + + + setupWidget + + JACK (JACK Audio Connection Kit) + JACK (JACK 音频连接套件) + + + OSS Raw-MIDI (Open Sound System) + OSS 原始-MIDI (开放声音系统) + + + SDL (Simple DirectMedia Layer) + SDL (Simple DirectMedia Layer) + + + PulseAudio + PulseAudio + + + Dummy (no MIDI support) + Dummy (无 MIDI 支持) + + + ALSA Raw-MIDI (Advanced Linux Sound Architecture) + ALSA 原始-MIDI (高级 Linux 音频架构) + + + PortAudio + PortAudio + + + Dummy (no sound output) + Dummy (无声音输出) + + + ALSA (Advanced Linux Sound Architecture) + ALSA (高级Linux声音架构) + + + OSS (Open Sound System) + OSS (开放声音系统) + + + WinMM MIDI + WinMM MIDI + + + ALSA-Sequencer (Advanced Linux Sound Architecture) + ALSA-序列器 (高级 Linux 音频架构) + + + + song + + Tempo + 节奏 + + + Master pitch + 主音高 + + + Project saved + 工程已保存 + + + Master volume + 主音量 + + + This project is empty so exporting makes no sense. Please put some items into Song Editor first! + 这个工程是空的所以就算导出也没有意义,请在歌曲编辑器中加入一点声音吧! + + + MIDI sequences + MIDI音序器 + + + All file types + 所有类型 + + + untitled + 未标题 + + + Select file for project-export... + 为工程导出选择文件... + + + FL Studio projects + FL Studio工程 + + + Project NOT saved. + 工程没有保存。 + + + Import file + 导入文件 + + + The project %1 is now saved. + 工程%1已保存。 + + + Select directory for writing exported tracks... + 选择写入导出音轨的目录... + + + Empty project + 空工程 + + + The project %1 was not saved! + 工程%1未保存! + + + Hydrogen projects + Hydrogen工程 + + + + timeLine + + Hint + 提示 + + + After stopping go back to begin + 停止后前往开头 + + + Press <Ctrl> to disable magnetic loop points. + 按住 <Ctrl> 禁用磁性吸附。 + + + Enable/disable auto-scrolling + 启用/禁用自动滚动 + + + After stopping go back to position at which playing was started + 停止后前往播放开始的地方 + + + Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. + 按住 <Shift> 移动起始循环点;按住 <Ctrl> 禁用磁性吸附。 + + + After stopping keep position + 停止后保持位置不变 + + + Enable/disable loop-points + 启用/禁用循环点 + + + + track + + Solo + 独奏 + + + Muted + 静音 + + + + trackContentObject + + Muted + 静音 + + + + trackContentObjectView + + Cut + 剪切 + + + Copy + 复制 + + + Hint + 提示 + + + Paste + 粘贴 + + + Press <Ctrl> for free resizing. + 按住 <Ctrl> 自由调整大小。 + + + Delete (middle mousebutton) + 删除 (鼠标中键) + + + Press <Ctrl> and drag to make a copy. + 按住 <Ctrl> 并拖动以创建副本。 + + + %1:%2 (%3:%4 to %5:%6) + %1:%2 (%3:%4 到 %5:%6) + + + Current length + 当前长度 + + + Mute/unmute (<Ctrl> + middle click) + 静音/取消静音 (<Ctrl> + 鼠标中键) + + + Current position + 当前位置 + + + + trackOperationsWidget + + Mute + 静音 + + + Solo + 独奏 + + + Clone this track + 克隆此轨道 + + + Actions for this track + 对此轨道可进行的操作 + + + Turn all recording on + 打开所有录制 + + + Turn all recording off + 关闭所有录制 + + + Remove this track + 移除此轨道 + + + Clear this track + 清除此轨道 + + + Press <Ctrl> while clicking on move-grip to begin a new drag'n'drop-action. + 按住 <Ctrl> 的同时拖动移动柄复制并移动此轨道。 + + + Mute this track + 静音此轨道 + + + + visualizationWidget + + click to enable/disable visualization of master-output + 点击启用/禁用视觉化主输出 + + + Click to enable + 点击启用 + + From c3abe3a69dca0ae0b0cc674bf82752f5e2ced6fc Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Tue, 8 Mar 2016 13:10:57 -0500 Subject: [PATCH 73/90] Add gig player to win32 builds Gig player was missing a dll during the package process. This fixes it. --- src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 97d4c820270..954a4695266 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -175,6 +175,7 @@ IF(LMMS_BUILD_WIN32) "${MINGW_PREFIX}/bin/libfluidsynth.dll" "${MINGW_PREFIX}/bin/libfftw3f-3.dll" "${MINGW_PREFIX}/bin/libFLAC-8.dll" + "${MINGW_PREFIX}/bin/libgig-6.dll" "${MINGW_PREFIX}/bin/libportaudio-2.dll" "${MINGW_PREFIX}/lib/libsoundio.dll" "${MINGW_PREFIX}/bin/libpng16-16.dll" From ef2cb5328276eb63db7b53a1fe23b2bafa887c7b Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Tue, 8 Mar 2016 13:12:00 -0500 Subject: [PATCH 74/90] White-space formatting --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 954a4695266..4d1a4a60d5c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -175,7 +175,7 @@ IF(LMMS_BUILD_WIN32) "${MINGW_PREFIX}/bin/libfluidsynth.dll" "${MINGW_PREFIX}/bin/libfftw3f-3.dll" "${MINGW_PREFIX}/bin/libFLAC-8.dll" - "${MINGW_PREFIX}/bin/libgig-6.dll" + "${MINGW_PREFIX}/bin/libgig-6.dll" "${MINGW_PREFIX}/bin/libportaudio-2.dll" "${MINGW_PREFIX}/lib/libsoundio.dll" "${MINGW_PREFIX}/bin/libpng16-16.dll" From 9ab18f5ae8fcbdcb93dfcb27336655682f1a6399 Mon Sep 17 00:00:00 2001 From: Mingcong Bai Date: Tue, 8 Mar 2016 16:41:45 -0700 Subject: [PATCH 75/90] data/locale: zh_CN.ts not zh.ts --- data/locale/{zh.ts => zh_CN.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename data/locale/{zh.ts => zh_CN.ts} (100%) diff --git a/data/locale/zh.ts b/data/locale/zh_CN.ts similarity index 100% rename from data/locale/zh.ts rename to data/locale/zh_CN.ts From 3f6f266a4622fe879c2ae250db2d4f9b1c5c7d7a Mon Sep 17 00:00:00 2001 From: Cyrille Bollu Date: Wed, 9 Mar 2016 11:53:54 +0100 Subject: [PATCH 76/90] Rewrote ProjectVersionTest.cpp to use QVERIFY and indeed fail when it's supposed to fail, and added 2 tests in this test suite. --- tests/src/core/ProjectVersionTest.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/src/core/ProjectVersionTest.cpp b/tests/src/core/ProjectVersionTest.cpp index 7e6d981ea1b..f0198ff5e89 100644 --- a/tests/src/core/ProjectVersionTest.cpp +++ b/tests/src/core/ProjectVersionTest.cpp @@ -30,14 +30,16 @@ class ProjectVersionTest : QTestSuite { Q_OBJECT private slots: - void test() - { - Q_ASSERT(ProjectVersion("1.1.0", CompareType::Minor) > "1.0.3"); - Q_ASSERT(ProjectVersion("1.1.0", CompareType::Major) < "2.1.0"); - Q_ASSERT(ProjectVersion("1.1.0", CompareType::Release) > "0.2.1"); - Q_ASSERT(ProjectVersion("1.1.4", CompareType::Release) < "1.1.10"); - Q_ASSERT(ProjectVersion("1.1.0", CompareType::Minor) == "1.1.5"); - } -} instance; + void ProjectVersionComparaisonTests() + { + QVERIFY(ProjectVersion("1.1.0", CompareType::Minor) > "1.0.3"); + QVERIFY(ProjectVersion("1.1.0", CompareType::Major) < "2.1.0"); + QVERIFY(ProjectVersion("1.1.0", CompareType::Release) > "0.2.1"); + QVERIFY(ProjectVersion("1.1.4", CompareType::Release) < "1.1.10"); + QVERIFY(ProjectVersion("1.1.0", CompareType::Minor) == "1.1.5"); + QVERIFY( ! ( ProjectVersion("3.1.0", CompareType::Minor) < "2.2.5" ) ); + QVERIFY( ! ( ProjectVersion("2.5.0", CompareType::Release) < "2.2.5" ) ); + } +} ProjectVersionTests; #include "ProjectVersionTest.moc" From fcec8ddd0283152935bcd87d8f1b5862d07f1a62 Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Wed, 9 Mar 2016 16:59:19 +0100 Subject: [PATCH 77/90] Fix BBtrack updating; Fix the Pattern tooltip --- src/gui/AutomationPatternView.cpp | 2 ++ src/tracks/Pattern.cpp | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/gui/AutomationPatternView.cpp b/src/gui/AutomationPatternView.cpp index 0872260b764..71fd0d6a422 100644 --- a/src/gui/AutomationPatternView.cpp +++ b/src/gui/AutomationPatternView.cpp @@ -60,6 +60,8 @@ AutomationPatternView::AutomationPatternView( AutomationPattern * _pattern, if( s_pat_rec == NULL ) { s_pat_rec = new QPixmap( embed::getIconPixmap( "pat_rec" ) ); } + + update(); } diff --git a/src/tracks/Pattern.cpp b/src/tracks/Pattern.cpp index 532b7c418bd..1257a76d91c 100644 --- a/src/tracks/Pattern.cpp +++ b/src/tracks/Pattern.cpp @@ -701,9 +701,9 @@ PatternView::PatternView( Pattern* pattern, TrackView* parent ) : s_stepBtnOffLight = new QPixmap( embed::getIconPixmap( "step_btn_off_light" ) ); } + + update(); - ToolTip::add( this, - tr( "use mouse wheel to set velocity of a step" ) ); setStyle( QApplication::style() ); } @@ -722,7 +722,22 @@ PatternView::~PatternView() void PatternView::update() { - m_pat->changeLength( m_pat->length() ); + if( fixedTCOs() ) + { + m_pat->changeLength( m_pat->length() ); + } + + if ( m_pat->m_patternType == Pattern::BeatPattern ) + { + ToolTip::add( this, + tr( "use mouse wheel to set velocity of a step" ) ); + } + else + { + ToolTip::add( this, + tr( "double-click to open in Piano Roll" ) ); + } + TrackContentObjectView::update(); } From 6a10cb184d3469f94f562a7708c8baf4788e02dd Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Thu, 10 Mar 2016 16:06:59 +0100 Subject: [PATCH 78/90] Fix regression caused by fcec8dd --- src/tracks/Pattern.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/tracks/Pattern.cpp b/src/tracks/Pattern.cpp index 1257a76d91c..3bb324860a7 100644 --- a/src/tracks/Pattern.cpp +++ b/src/tracks/Pattern.cpp @@ -722,10 +722,7 @@ PatternView::~PatternView() void PatternView::update() { - if( fixedTCOs() ) - { - m_pat->changeLength( m_pat->length() ); - } + m_pat->changeLength( m_pat->length() ); if ( m_pat->m_patternType == Pattern::BeatPattern ) { From 311b28cf71f1ba41cce4bd1a49cf54fe92cb125c Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Fri, 11 Mar 2016 10:30:43 +0100 Subject: [PATCH 79/90] File browser, factory files off by one --- src/gui/FileBrowser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp index 0a88224cf78..828800ba4af 100644 --- a/src/gui/FileBrowser.cpp +++ b/src/gui/FileBrowser.cpp @@ -766,7 +766,7 @@ void Directory::update( void ) "--- Factory files ---" ) ); sep->setIcon( 0, embed::getIconPixmap( "factory_files" ) ); - insertChild( m_dirCount + top_index - 1, sep ); + insertChild( m_dirCount + top_index, sep ); } } } From bfa83da572bc9c677ca05f1e87adf68652b5b18f Mon Sep 17 00:00:00 2001 From: Fastigium Date: Sun, 13 Mar 2016 15:05:40 +0100 Subject: [PATCH 80/90] Make lb302 include math.h so we can switch it to C++11 M_PI is no longer defined by default in C++11, but lb302.cpp needs it. Therefore, before switching to C++11, we add an include. --- plugins/lb302/lb302.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 85320d21d01..399c01f547b 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -28,6 +28,10 @@ * */ +// Need to include this first to ensure we get M_PI in MinGW with C++11 +#define _USE_MATH_DEFINES +#include + #include "lb302.h" #include "AutomatableButton.h" #include "Engine.h" From ac67f2adb8fd0bd9c500d9cfc345fac29f5dce54 Mon Sep 17 00:00:00 2001 From: Fastigium Date: Fri, 11 Mar 2016 16:32:56 +0100 Subject: [PATCH 81/90] Compile several plugins with -std=c++0x to support range-based for loops --- plugins/GigPlayer/CMakeLists.txt | 3 +++ plugins/MidiExport/CMakeLists.txt | 3 +++ plugins/VstEffect/CMakeLists.txt | 4 ++++ plugins/lb302/CMakeLists.txt | 3 +++ plugins/opl2/CMakeLists.txt | 3 +++ plugins/sf2_player/CMakeLists.txt | 3 +++ plugins/vestige/CMakeLists.txt | 3 +++ plugins/zynaddsubfx/CMakeLists.txt | 3 +++ 8 files changed, 25 insertions(+) diff --git a/plugins/GigPlayer/CMakeLists.txt b/plugins/GigPlayer/CMakeLists.txt index 24db813bdee..4e49988eb55 100644 --- a/plugins/GigPlayer/CMakeLists.txt +++ b/plugins/GigPlayer/CMakeLists.txt @@ -12,6 +12,9 @@ if(LMMS_HAVE_GIG) add_definitions(${GCC_GIG_COMPILE_FLAGS}) endif(LMMS_BUILD_WIN32) + # Enable C++11 + ADD_DEFINITIONS(-std=c++0x) + LINK_DIRECTORIES(${GIG_LIBRARY_DIRS} ${SAMPLERATE_LIBRARY_DIRS}) LINK_LIBRARIES(${GIG_LIBRARIES} ${SAMPLERATE_LIBRARIES}) BUILD_PLUGIN(gigplayer GigPlayer.cpp GigPlayer.h PatchesDialog.cpp PatchesDialog.h PatchesDialog.ui MOCFILES GigPlayer.h PatchesDialog.h UICFILES PatchesDialog.ui EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") diff --git a/plugins/MidiExport/CMakeLists.txt b/plugins/MidiExport/CMakeLists.txt index 1d19f081e6a..d5b08016921 100644 --- a/plugins/MidiExport/CMakeLists.txt +++ b/plugins/MidiExport/CMakeLists.txt @@ -1,4 +1,7 @@ INCLUDE(BuildPlugin) +# Enable C++11 +ADD_DEFINITIONS(-std=c++0x) + BUILD_PLUGIN(midiexport MidiExport.cpp MidiExport.h MidiFile.hpp MOCFILES MidiExport.h) diff --git a/plugins/VstEffect/CMakeLists.txt b/plugins/VstEffect/CMakeLists.txt index 9b262397a5d..b842e194c36 100644 --- a/plugins/VstEffect/CMakeLists.txt +++ b/plugins/VstEffect/CMakeLists.txt @@ -3,6 +3,10 @@ INCLUDE(BuildPlugin) INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../vst_base") LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/../vst_base") LINK_LIBRARIES(vstbase) + +# Enable C++11 +ADD_DEFINITIONS(-std=c++0x) + BUILD_PLUGIN(vsteffect VstEffect.cpp VstEffectControls.cpp VstEffectControlDialog.cpp VstSubPluginFeatures.cpp VstEffect.h VstEffectControls.h VstEffectControlDialog.h VstSubPluginFeatures.h MOCFILES VstEffectControlDialog.h VstEffectControls.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") SET_TARGET_PROPERTIES(vsteffect PROPERTIES COMPILE_FLAGS "-Wno-attributes") diff --git a/plugins/lb302/CMakeLists.txt b/plugins/lb302/CMakeLists.txt index c9389eb189a..ba2edbd4baa 100644 --- a/plugins/lb302/CMakeLists.txt +++ b/plugins/lb302/CMakeLists.txt @@ -1,3 +1,6 @@ INCLUDE(BuildPlugin) +# Enable C++11 +ADD_DEFINITIONS(-std=c++0x) + BUILD_PLUGIN(lb302 lb302.cpp lb302.h MOCFILES lb302.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") diff --git a/plugins/opl2/CMakeLists.txt b/plugins/opl2/CMakeLists.txt index c12530af8ec..785c3676ed4 100644 --- a/plugins/opl2/CMakeLists.txt +++ b/plugins/opl2/CMakeLists.txt @@ -1,3 +1,6 @@ INCLUDE(BuildPlugin) +# Enable C++11 +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + BUILD_PLUGIN(OPL2 opl2instrument.cpp opl2instrument.h opl.h fmopl.c fmopl.h temuopl.cpp temuopl.h MOCFILES opl2instrument.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") diff --git a/plugins/sf2_player/CMakeLists.txt b/plugins/sf2_player/CMakeLists.txt index d087f437d4e..51b8e29ee7f 100644 --- a/plugins/sf2_player/CMakeLists.txt +++ b/plugins/sf2_player/CMakeLists.txt @@ -1,4 +1,7 @@ if(LMMS_HAVE_FLUIDSYNTH) + # Enable C++11 + ADD_DEFINITIONS(-std=c++0x) + INCLUDE(BuildPlugin) INCLUDE_DIRECTORIES(${FLUIDSYNTH_INCLUDE_DIRS} ${SAMPLERATE_INCLUDE_DIRS}) LINK_DIRECTORIES(${FLUIDSYNTH_LIBRARY_DIRS} ${SAMPLERATE_LIBRARY_DIRS}) diff --git a/plugins/vestige/CMakeLists.txt b/plugins/vestige/CMakeLists.txt index 340e5038518..ccc12984d88 100644 --- a/plugins/vestige/CMakeLists.txt +++ b/plugins/vestige/CMakeLists.txt @@ -1,4 +1,7 @@ IF(LMMS_SUPPORT_VST) + # Enable C++11 + ADD_DEFINITIONS(-std=c++0x) + INCLUDE(BuildPlugin) INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../vst_base") LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/../vst_base") diff --git a/plugins/zynaddsubfx/CMakeLists.txt b/plugins/zynaddsubfx/CMakeLists.txt index 28a2a35d4f2..fa96b9f3240 100644 --- a/plugins/zynaddsubfx/CMakeLists.txt +++ b/plugins/zynaddsubfx/CMakeLists.txt @@ -19,6 +19,9 @@ ENDIF(LMMS_HOST_X86 OR LMMS_HOST_X86_64) # build ZynAddSubFX with full optimizations SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wno-write-strings -Wno-deprecated-declarations -fpermissive") +# Enable C++11, but only for ZynAddSubFx.cpp +set_property(SOURCE ZynAddSubFx.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -std=c++0x ") + # link system-libraries when on win32 IF(LMMS_BUILD_WIN32) ADD_DEFINITIONS(-DPTW32_STATIC_LIB) From 3c7bfbac643ade723b2edb3b8206da50468a39f6 Mon Sep 17 00:00:00 2001 From: Fastigium Date: Fri, 11 Mar 2016 16:35:48 +0100 Subject: [PATCH 82/90] Replace every use of the foreach macro with a C++11 range-based for loop This prevents a race condition with Qt5. A foreach loop makes a copy of its Qt container, increasing the reference count to the container's internal data. Qt5 often asserts isDetached(), which requires the reference count to be <= 1. This assertion fails when the foreach loop increases the reference count at exactly the wrong moment. Using a range-based for loop prevents an unnecessary copy from being made and ensures this race condition isn't triggered. --- include/InstrumentPlayHandle.h | 8 ++++---- plugins/MidiExport/MidiExport.cpp | 4 ++-- plugins/zynaddsubfx/ZynAddSubFx.cpp | 2 +- src/core/AutomatableModel.cpp | 2 +- src/core/ComboBoxModel.cpp | 2 +- src/core/FxMixer.cpp | 14 +++++++------- src/core/NotePlayHandle.cpp | 13 +------------ src/core/audio/AudioPort.cpp | 2 +- src/core/fft_helpers.cpp | 2 +- src/gui/EffectSelectDialog.cpp | 2 +- src/gui/FxMixerView.cpp | 2 +- src/gui/MainWindow.cpp | 4 ++-- src/gui/editors/BBEditor.cpp | 2 +- src/gui/widgets/AutomatableButton.cpp | 4 ++-- src/tracks/BBTrack.cpp | 12 ------------ src/tracks/InstrumentTrack.cpp | 2 +- 16 files changed, 27 insertions(+), 50 deletions(-) diff --git a/include/InstrumentPlayHandle.h b/include/InstrumentPlayHandle.h index ffbfbce735a..74ceebbf219 100644 --- a/include/InstrumentPlayHandle.h +++ b/include/InstrumentPlayHandle.h @@ -56,13 +56,13 @@ class EXPORT InstrumentPlayHandle : public PlayHandle do { nphsLeft = false; - foreach( const NotePlayHandle * cnph, nphv ) + for( const NotePlayHandle * constNotePlayHandle : nphv ) { - NotePlayHandle * nph = const_cast( cnph ); - if( nph->state() != ThreadableJob::Done && ! nph->isFinished() ) + NotePlayHandle * notePlayHandle = const_cast( constNotePlayHandle ); + if( notePlayHandle->state() != ThreadableJob::Done && ! notePlayHandle->isFinished() ) { nphsLeft = true; - nph->process(); + notePlayHandle->process(); } } } diff --git a/plugins/MidiExport/MidiExport.cpp b/plugins/MidiExport/MidiExport.cpp index 03ef3a49683..4cb0b356b88 100644 --- a/plugins/MidiExport/MidiExport.cpp +++ b/plugins/MidiExport/MidiExport.cpp @@ -83,7 +83,7 @@ bool MidiExport::tryExport( const TrackContainer::TrackList &tracks, int tempo, uint8_t buffer[BUFFER_SIZE]; uint32_t size; - foreach( Track* track, tracks ) if( track->type() == Track::InstrumentTrack ) nTracks++; + for( const Track* track : tracks ) if( track->type() == Track::InstrumentTrack ) nTracks++; // midi header MidiFile::MIDIHeader header(nTracks); @@ -91,7 +91,7 @@ bool MidiExport::tryExport( const TrackContainer::TrackList &tracks, int tempo, midiout.writeRawData((char *)buffer, size); // midi tracks - foreach( Track* track, tracks ) + for( Track* track : tracks ) { DataFile dataFile( DataFile::SongProject ); MidiFile::MIDITrack mtrack; diff --git a/plugins/zynaddsubfx/ZynAddSubFx.cpp b/plugins/zynaddsubfx/ZynAddSubFx.cpp index ad1e8ff90be..14080f3bec3 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/ZynAddSubFx.cpp @@ -262,7 +262,7 @@ void ZynAddSubFxInstrument::loadSettings( const QDomElement & _this ) m_pluginMutex.unlock(); m_modifiedControllers.clear(); - foreach( const QString & c, _this.attribute( "modifiedcontrollers" ).split( ',' ) ) + for( const QString & c : _this.attribute( "modifiedcontrollers" ).split( ',' ) ) { if( !c.isEmpty() ) { diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index bf56285e5ca..20b7b7d094a 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -450,7 +450,7 @@ void AutomatableModel::unlinkModels( AutomatableModel* model1, AutomatableModel* void AutomatableModel::unlinkAllModels() { - foreach( AutomatableModel* model, m_linkedModels ) + for( AutomatableModel* model : m_linkedModels ) { unlinkModels( this, model ); } diff --git a/src/core/ComboBoxModel.cpp b/src/core/ComboBoxModel.cpp index e5df419a8e1..a669cb3d7ca 100644 --- a/src/core/ComboBoxModel.cpp +++ b/src/core/ComboBoxModel.cpp @@ -39,7 +39,7 @@ void ComboBoxModel::addItem( const QString& item, PixmapLoader* loader ) void ComboBoxModel::clear() { setRange( 0, 0 ); - foreach( const Item& i, m_items ) + for( const Item& i : m_items ) { delete i.second; } diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 8777555569a..be4378bd8bf 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -87,7 +87,7 @@ FxChannel::~FxChannel() inline void FxChannel::processed() { - foreach( FxRoute * receiverRoute, m_sends ) + for( const FxRoute * receiverRoute : m_sends ) { if( receiverRoute->receiver()->m_muted == false ) { @@ -121,7 +121,7 @@ void FxChannel::doProcessing() if( m_muted == false ) { - foreach( FxRoute * senderRoute, m_receives ) + for( FxRoute * senderRoute : m_receives ) { FxChannel * sender = senderRoute->sender(); FloatModel * sendModel = senderRoute->amount(); @@ -293,7 +293,7 @@ void FxMixer::deleteChannel( int index ) tracks += Engine::getSong()->tracks(); tracks += Engine::getBBTrackContainer()->tracks(); - foreach( Track* t, tracks ) + for( Track* t : tracks ) { if( t->type() == Track::InstrumentTrack ) { @@ -335,11 +335,11 @@ void FxMixer::deleteChannel( int index ) m_fxChannels[i]->m_channelIndex = i; // now check all routes and update names of the send models - foreach( FxRoute * r, m_fxChannels[i]->m_sends ) + for( FxRoute * r : m_fxChannels[i]->m_sends ) { r->updateName(); } - foreach( FxRoute * r, m_fxChannels[i]->m_receives ) + for( FxRoute * r : m_fxChannels[i]->m_receives ) { r->updateName(); } @@ -528,7 +528,7 @@ FloatModel * FxMixer::channelSendModel( fx_ch_t fromChannel, fx_ch_t toChannel ) const FxChannel * from = m_fxChannels[fromChannel]; const FxChannel * to = m_fxChannels[toChannel]; - foreach( FxRoute * route, from->m_sends ) + for( FxRoute * route : from->m_sends ) { if( route->receiver() == to ) { @@ -578,7 +578,7 @@ void FxMixer::masterMix( sampleFrame * _buf ) // also instantly add all muted channels as they don't need to care about their senders, and can just increment the deps of // their recipients right away. MixerWorkerThread::resetJobQueue( MixerWorkerThread::JobQueue::Dynamic ); - foreach( FxChannel * ch, m_fxChannels ) + for( FxChannel * ch : m_fxChannels ) { ch->m_muted = ch->m_muteModel.value(); if( ch->m_muted ) // instantly "process" muted channels diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index d0fadece33c..d027fef1a60 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -301,17 +301,6 @@ void NotePlayHandle::play( sampleFrame * _working_buffer ) } } - // play sub-notes (e.g. chords) - // handled by mixer now -/* foreach( NotePlayHandle * n, m_subNotes ) - { - n->play( _working_buffer ); - if( n->isFinished() ) - { - NotePlayHandleManager::release( n ); - } - }*/ - // update internal data m_totalFramesPlayed += framesThisPeriod; unlock(); @@ -369,7 +358,7 @@ void NotePlayHandle::noteOff( const f_cnt_t _s ) m_released = true; // first note-off all sub-notes - foreach( NotePlayHandle * n, m_subNotes ) + for( NotePlayHandle * n : m_subNotes ) { n->lock(); n->noteOff( _s ); diff --git a/src/core/audio/AudioPort.cpp b/src/core/audio/AudioPort.cpp index bbec65a3873..7d26bd367bc 100644 --- a/src/core/audio/AudioPort.cpp +++ b/src/core/audio/AudioPort.cpp @@ -116,7 +116,7 @@ void AudioPort::doProcessing() BufferManager::clear( m_portBuffer, fpp ); //qDebug( "Playhandles: %d", m_playHandles.size() ); - foreach( PlayHandle * ph, m_playHandles ) // now we mix all playhandle buffers into the audioport buffer + for( PlayHandle * ph : m_playHandles ) // now we mix all playhandle buffers into the audioport buffer { if( ph->buffer() ) { diff --git a/src/core/fft_helpers.cpp b/src/core/fft_helpers.cpp index 11f619c4a00..4924403c586 100644 --- a/src/core/fft_helpers.cpp +++ b/src/core/fft_helpers.cpp @@ -134,7 +134,7 @@ int compressbands(float *absspec_buffer, float *compressedband, int num_old, int ratio=(float)usefromold/(float)num_new; - // foreach new subband + // for each new subband for ( i=0; isetSpacing( 0 ); m_currentSelection.desc->subPluginFeatures-> fillDescriptionWidget( subWidget, &m_currentSelection ); - foreach( QWidget * w, subWidget->findChildren() ) + for( QWidget * w : subWidget->findChildren() ) { if( w->parent() == subWidget ) { diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index 380fec099f7..5826ed9d4d5 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -420,7 +420,7 @@ void FxMixerView::deleteUnusedChannels() { // check if an instrument references to the current channel bool empty=true; - foreach( Track* t, tracks ) + for( Track* t : tracks ) { if( t->type() == Track::InstrumentTrack ) { diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 3a95a2df6cc..f6f2ef6637f 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -145,7 +145,7 @@ MainWindow::MainWindow() : #if ! defined(LMMS_BUILD_APPLE) QFileInfoList drives = QDir::drives(); - foreach( const QFileInfo & drive, drives ) + for( const QFileInfo & drive : drives ) { root_paths += drive.absolutePath(); } @@ -602,7 +602,7 @@ void MainWindow::finalize() gui->songEditor()->parentWidget()->show(); // reset window title every time we change the state of a subwindow to show the correct title - foreach( QMdiSubWindow * subWindow, workspace()->subWindowList() ) + for( const QMdiSubWindow * subWindow : workspace()->subWindowList() ) { connect( subWindow, SIGNAL( windowStateChanged(Qt::WindowStates,Qt::WindowStates) ), this, SLOT( resetWindowTitle() ) ); } diff --git a/src/gui/editors/BBEditor.cpp b/src/gui/editors/BBEditor.cpp index 097b2c2a5a1..569759562f4 100644 --- a/src/gui/editors/BBEditor.cpp +++ b/src/gui/editors/BBEditor.cpp @@ -220,7 +220,7 @@ void BBTrackContainerView::addAutomationTrack() void BBTrackContainerView::removeBBView(int bb) { - foreach( TrackView* view, trackViews() ) + for( TrackView* view : trackViews() ) { view->getTrackContentWidget()->removeTCOView( bb ); } diff --git a/src/gui/widgets/AutomatableButton.cpp b/src/gui/widgets/AutomatableButton.cpp index 1e482d7f7d3..4e31d644704 100644 --- a/src/gui/widgets/AutomatableButton.cpp +++ b/src/gui/widgets/AutomatableButton.cpp @@ -236,7 +236,7 @@ void automatableButtonGroup::activateButton( AutomatableButton * _btn ) m_buttons.indexOf( _btn ) != -1 ) { model()->setValue( m_buttons.indexOf( _btn ) ); - foreach( AutomatableButton * btn, m_buttons ) + for( AutomatableButton * btn : m_buttons ) { btn->update(); } @@ -261,7 +261,7 @@ void automatableButtonGroup::updateButtons() { model()->setRange( 0, m_buttons.size() - 1 ); int i = 0; - foreach( AutomatableButton * btn, m_buttons ) + for( AutomatableButton * btn : m_buttons ) { btn->model()->setValue( i == model()->value() ); ++i; diff --git a/src/tracks/BBTrack.cpp b/src/tracks/BBTrack.cpp index cf9a9292f1d..b8ae5968ac6 100644 --- a/src/tracks/BBTrack.cpp +++ b/src/tracks/BBTrack.cpp @@ -664,17 +664,5 @@ void BBTrackView::clickedTrackLabel() { Engine::getBBTrackContainer()->setCurrentBB( m_bbTrack->index() ); gui->getBBEditor()->show(); -/* foreach( bbTrackView * tv, - trackContainerView()->findChildren() ) - { - tv->m_trackLabel->update(); - }*/ - } - - - - - - diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index e1f7f4b416e..d1eb5bc1e2a 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -949,7 +949,7 @@ InstrumentTrackView::~InstrumentTrackView() InstrumentTrackWindow * InstrumentTrackView::topLevelInstrumentTrackWindow() { InstrumentTrackWindow * w = NULL; - foreach( QMdiSubWindow * sw, + for( const QMdiSubWindow * sw : gui->mainWindow()->workspace()->subWindowList( QMdiArea::ActivationHistoryOrder ) ) { From 1c5d57dce99b6ddbab0f46600a6a2f69608fdca5 Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Sun, 13 Mar 2016 22:50:30 +0100 Subject: [PATCH 83/90] Elide channel names to prevent text overflow in FxLine --- src/gui/widgets/FxLine.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gui/widgets/FxLine.cpp b/src/gui/widgets/FxLine.cpp index 11267534ab3..249afdf0a91 100644 --- a/src/gui/widgets/FxLine.cpp +++ b/src/gui/widgets/FxLine.cpp @@ -152,7 +152,11 @@ void FxLine::drawFxLine( QPainter* p, const FxLine *fxLine, const QString& name, // draw the channel name if( m_staticTextName.text() != name ) { - m_staticTextName.setText( name ); + // elide the name of the fxLine when its too long + const int maxTextHeight = 78; + QFontMetrics metrics( fxLine->font() ); + QString elidedName = metrics.elidedText( name, Qt::ElideRight, maxTextHeight ); + m_staticTextName.setText( elidedName ); } p->rotate( -90 ); From f3ea8350a6ba38f74e8d9043cd0f2c8d6661f631 Mon Sep 17 00:00:00 2001 From: Fastigium Date: Tue, 15 Mar 2016 10:47:08 +0100 Subject: [PATCH 84/90] Add C++11 compile flag to the carla plugin as well Fixes the carla plugin not compiling anymore after switching to C++11 range-based for loops. --- plugins/carlabase/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/carlabase/CMakeLists.txt b/plugins/carlabase/CMakeLists.txt index 8fdde2ec51f..90bc08a36db 100644 --- a/plugins/carlabase/CMakeLists.txt +++ b/plugins/carlabase/CMakeLists.txt @@ -1,4 +1,7 @@ if(LMMS_HAVE_CARLA) + # Enable C++11 + ADD_DEFINITIONS(-std=c++0x) + INCLUDE(BuildPlugin) INCLUDE_DIRECTORIES(${CARLA_INCLUDE_DIRS}) LINK_DIRECTORIES(${CARLA_LIBRARY_DIRS}) From b34c3827500e7eaeb237ef6d8c8117a4c405a5cf Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Tue, 15 Mar 2016 11:06:19 +0100 Subject: [PATCH 85/90] Kicker 'version' 0 on first save --- plugins/kicker/kicker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index 38149519f42..bc27340399f 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -71,7 +71,7 @@ kickerInstrument::kickerInstrument( InstrumentTrack * _instrument_track ) : m_slopeModel( 0.06f, 0.001f, 1.0f, 0.001f, this, tr( "Frequency Slope" ) ), m_startNoteModel( true, this, tr( "Start from note" ) ), m_endNoteModel( false, this, tr( "End to note" ) ), - m_versionModel( 0, 0, KICKER_PRESET_VERSION, this, "" ) + m_versionModel( KICKER_PRESET_VERSION, 0, KICKER_PRESET_VERSION, this, "" ) { } @@ -137,7 +137,7 @@ void kickerInstrument::loadSettings( const QDomElement & _this ) // Try to maintain backwards compatibility if( !_this.hasAttribute( "version" ) ) { - + m_startNoteModel.setValue( false ); m_decayModel.setValue( m_decayModel.value() * 1.33f ); m_envModel.setValue( 1.0f ); m_slopeModel.setValue( 1.0f ); From c6863060bf9f39c429bdd89067bf3cead3743fc3 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Tue, 15 Mar 2016 18:41:03 +0100 Subject: [PATCH 86/90] Enables style sheets for knob line colors for all knob types The fix works as follows: until now the method Knob::drawKnob has used hard coded palette colors to draw the knob lines for the different knob types. These palette colors are now assigned to the line color property in Knob::initUi. The method Knob::drawKnob in turn now uses the line color property for almost all knob types. This means that all knobs lines will be painted in the same color as before unless that property is overridden by the stylesheet. Also removes an unnecessary typedef from QWidget to trackSettingsWidget in Track.h. --- include/Track.h | 5 ++--- src/gui/widgets/Knob.cpp | 32 ++++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/Track.h b/include/Track.h index 3b8c634a848..b9098922878 100644 --- a/include/Track.h +++ b/include/Track.h @@ -54,7 +54,6 @@ class TrackContainerView; class TrackContentWidget; class TrackView; -typedef QWidget trackSettingsWidget; const int DEFAULT_SETTINGS_WIDGET_WIDTH = 224; const int TRACK_OP_WIDTH = 78; @@ -640,7 +639,7 @@ class TrackView : public QWidget, public ModelView, public JournallingObject return &m_trackOperationsWidget; } - inline trackSettingsWidget * getTrackSettingsWidget() + inline QWidget * getTrackSettingsWidget() { return &m_trackSettingsWidget; } @@ -703,7 +702,7 @@ public slots: TrackContainerView * m_trackContainerView; TrackOperationsWidget m_trackOperationsWidget; - trackSettingsWidget m_trackSettingsWidget; + QWidget m_trackSettingsWidget; TrackContentWidget m_trackContentWidget; Actions m_action; diff --git a/src/gui/widgets/Knob.cpp b/src/gui/widgets/Knob.cpp index 6c2a9c74d04..6eb05587f66 100644 --- a/src/gui/widgets/Knob.cpp +++ b/src/gui/widgets/Knob.cpp @@ -101,6 +101,28 @@ void Knob::initUi( const QString & _name ) setInnerRadius( 1.0f ); setOuterRadius( 10.0f ); setFocusPolicy( Qt::ClickFocus ); + + // This is a workaround to enable style sheets for knobs which are not styled knobs. + // + // It works as follows: the palette colors that are assigned as the line color previously + // had been hard coded in the drawKnob method for the different knob types. Now the + // drawKnob method uses the line color to draw the lines. By assigning the palette colors + // as the line colors here the knob lines will be drawn in this color unless the stylesheet + // overrides that color. + switch (knobNum()) + { + case knobSmall_17: + case knobBright_26: + case knobDark_28: + setlineColor(QApplication::palette().color( QPalette::Active, QPalette::WindowText )); + break; + case knobVintage_32: + setlineColor(QApplication::palette().color( QPalette::Active, QPalette::Shadow )); + break; + default: + break; + } + doConnections(); } @@ -428,20 +450,19 @@ void Knob::drawKnob( QPainter * _p ) { case knobSmall_17: { - p.setPen( QPen( QApplication::palette().color( QPalette::Active, - QPalette::WindowText ), 2 ) ); + p.setPen( QPen( lineColor(), 2 ) ); p.drawLine( calculateLine( mid, radius-2 ) ); break; } case knobBright_26: { - p.setPen( QPen( QApplication::palette().color( QPalette::Active, QPalette::WindowText ), 2 ) ); + p.setPen( QPen( lineColor(), 2 ) ); p.drawLine( calculateLine( mid, radius-5 ) ); break; } case knobDark_28: { - p.setPen( QPen( QApplication::palette().color( QPalette::Active, QPalette::WindowText ), 2 ) ); + p.setPen( QPen( lineColor(), 2 ) ); const float rb = qMax( ( radius - 10 ) / 3.0, 0.0 ); const float re = qMax( ( radius - 4 ), 0.0 ); @@ -452,8 +473,7 @@ void Knob::drawKnob( QPainter * _p ) } case knobVintage_32: { - p.setPen( QPen( QApplication::palette().color( QPalette::Active, - QPalette::Shadow), 2 ) ); + p.setPen( QPen( lineColor(), 2 ) ); p.drawLine( calculateLine( mid, radius-2, 2 ) ); break; } From 908175d5f1112d39e8c3c5158c2e10b5e3d6465a Mon Sep 17 00:00:00 2001 From: Fastigium Date: Wed, 16 Mar 2016 09:27:57 +0100 Subject: [PATCH 87/90] Get rid of another copy constructor call to prevent Qt5 crashes Cf. the commit message of 3c7bfba --- include/FxMixer.h | 5 ----- src/tracks/InstrumentTrack.cpp | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/include/FxMixer.h b/include/FxMixer.h index ac5c725301d..0c2ac02a5b5 100644 --- a/include/FxMixer.h +++ b/include/FxMixer.h @@ -194,11 +194,6 @@ class EXPORT FxMixer : public Model, public JournallingObject return m_fxChannels.size(); } - inline QVector fxChannels() const - { - return m_fxChannels; - } - FxRouteVector m_fxRoutes; private: diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index d1eb5bc1e2a..2a1790e92e9 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -1191,9 +1191,9 @@ QMenu * InstrumentTrackView::createFxMenu(QString title, QString newFxLabel) fxMenu->addAction( newFxLabel, this, SLOT( createFxLine() ) ); fxMenu->addSeparator(); - for (int i = 0; i < Engine::fxMixer()->fxChannels().size(); ++i) + for (int i = 0; i < Engine::fxMixer()->numChannels(); ++i) { - FxChannel * currentChannel = Engine::fxMixer()->fxChannels()[i]; + FxChannel * currentChannel = Engine::fxMixer()->effectChannel( i ); if ( currentChannel != fxChannel ) { From acb5ff8d0441f809713b70422868105301a9e9db Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Fri, 18 Mar 2016 10:11:56 +0200 Subject: [PATCH 88/90] Clear buffer of dummy instruments. Should fix #2682 --- include/DummyInstrument.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/DummyInstrument.h b/include/DummyInstrument.h index c3ba12f8320..c369924b754 100644 --- a/include/DummyInstrument.h +++ b/include/DummyInstrument.h @@ -28,6 +28,9 @@ #include "Instrument.h" #include "InstrumentView.h" +#include "Engine.h" + +#include class DummyInstrument : public Instrument @@ -42,8 +45,10 @@ class DummyInstrument : public Instrument { } - virtual void playNote( NotePlayHandle *, sampleFrame * ) + virtual void playNote( NotePlayHandle *, sampleFrame * buffer ) { + memset( buffer, 0, sizeof( sampleFrame ) * + Engine::mixer()->framesPerPeriod() ); } virtual void saveSettings( QDomDocument &, QDomElement & ) From e8ac40c2fbcb87a3c056cf524549d573419bda6b Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Fri, 18 Mar 2016 04:48:21 +0100 Subject: [PATCH 89/90] Crash at clearing path in settings manager --- src/core/ConfigManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ConfigManager.cpp b/src/core/ConfigManager.cpp index 89128aa826f..b81bad20045 100644 --- a/src/core/ConfigManager.cpp +++ b/src/core/ConfigManager.cpp @@ -38,7 +38,7 @@ static inline QString ensureTrailingSlash( const QString & s ) { - if(s.at(s.length()-1) != '/') + if( ! s.isEmpty() && !s.endsWith('/') && !s.endsWith('\\') ) { return s + '/'; } From 23cd3002a6cff7a5352ab69c3b46a435f8d4d38e Mon Sep 17 00:00:00 2001 From: Umcaruje Date: Fri, 18 Mar 2016 23:51:03 +0100 Subject: [PATCH 90/90] Grey out muted patterns in the BB editor --- src/tracks/Pattern.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/tracks/Pattern.cpp b/src/tracks/Pattern.cpp index 3bb324860a7..acae5927040 100644 --- a/src/tracks/Pattern.cpp +++ b/src/tracks/Pattern.cpp @@ -1147,6 +1147,14 @@ void PatternView::paintEvent( QPaintEvent * ) p.drawPixmap( x, y, stepoff ); } } // end for loop + + // draw a transparent rectangle over muted patterns + if ( muted ) + { + p.setBrush( mutedBackgroundColor() ); + p.setOpacity( 0.3 ); + p.drawRect( 0, 0, width(), height() ); + } } // bar lines