Compare commits
159 Commits
Author | SHA1 | Date |
---|---|---|
Elnur Ismailzada | 44e7ed9209 | |
Eism | 6b9052b2b9 | |
Eism | 542a3034ae | |
Eism | 548562132f | |
pereverzev_v | e9869aa88d | |
pereverzev_v | 9dcd13144a | |
Michele Spagnolo | 24b8e34858 | |
DmitryArefiev | 2ada4e779d | |
pereverzev+v | 1d3a5a8771 | |
pereverzev+v | 4da8e5ed18 | |
Aaron Sattely | 25266e98a5 | |
pereverzev+v | 2e2085eb5d | |
pereverzev+v | bab78a6f81 | |
pereverzev+v | 12ec72a7fe | |
Elnur Ismailzada | dbbf2ad8e7 | |
Michele Spagnolo | dc67d6429f | |
RomanPudashkin | c9b9717951 | |
RomanPudashkin | 65f14814b9 | |
Elnur Ismailzada | 5654eb1da0 | |
Eism | 701184d894 | |
pereverzev_v | f23002aedf | |
RomanPudashkin | 92b3462113 | |
DmitryArefiev | 8e17b96de8 | |
DmitryArefiev | 95179da691 | |
pereverzev_v | 1c5e4eb077 | |
pereverzev_v | 3820cd5411 | |
RomanPudashkin | cb5a7a8475 | |
Roman Pudashkin | a43001b591 | |
DmitryArefiev | 02e6f1fdcf | |
DmitryArefiev | 2df795a9d7 | |
RomanPudashkin | ebf26c28e7 | |
RomanPudashkin | 7cd27b0805 | |
Elnur Ismailzada | cd7f437b6e | |
Eism | cc1853ea39 | |
Eism | 32570c870e | |
pereverzev+v | 19abc468ad | |
Elnur Ismailzada | 40c5b42bbd | |
RomanPudashkin | d791118d7b | |
Eism | 57e5f382e0 | |
Eism | 5a8d6ea733 | |
pereverzev_v | d050fb0a2d | |
pereverzev+v | 85598a7881 | |
pereverzev+v | 9de702260e | |
pereverzev+v | 7f989ff0ce | |
pereverzev+v | 28ff70f8fb | |
Casper Jeukendrup | 2fa6ad8bcd | |
Casper Jeukendrup | 95a9ac3ff1 | |
RomanPudashkin | 890dfd80ec | |
RomanPudashkin | 98a738855c | |
Elnur Ismailzada | 9f5e9f34d0 | |
RomanPudashkin | 34b69c9a2f | |
Michele Spagnolo | 973a9a47ec | |
pereverzev_v | b5a1133c6e | |
RomanPudashkin | a1bbe6487a | |
pereverzev_v | a988b5c549 | |
pereverzev_v | d7782c2413 | |
RomanPudashkin | d63f0cc1b3 | |
RomanPudashkin | f9d4900da0 | |
Michele Spagnolo | 551fc83c6b | |
Michele Spagnolo | 0fbf0281ab | |
Michele Spagnolo | e8cea477ab | |
Elnur Ismailzada | 78350f8d80 | |
Roman Pudashkin | 40dee9a240 | |
Roman Pudashkin | b83262b669 | |
Roman Pudashkin | c938c281c9 | |
Roman Pudashkin | 02fa60e839 | |
Roman Pudashkin | 262ccb2028 | |
Roman Pudashkin | cea5f9b6c6 | |
Casper Jeukendrup | bcc69e95f8 | |
Casper Jeukendrup | d2635ec790 | |
Roman Pudashkin | df5498313a | |
RomanPudashkin | 2ec580f288 | |
DmitryArefiev | fe562d71b8 | |
pereverzev_v | 805f1c1087 | |
Casper Jeukendrup | acc57e2d5b | |
jeetee | cbba750a10 | |
Marc Sabatella | a1874b3a29 | |
Marc Sabatella | 3b71ff3b16 | |
Elnur Ismailzada | 239f96a643 | |
Eism | 3d9d3d4d41 | |
RomanPudashkin | 4e334b10dd | |
RomanPudashkin | 88a494cfb4 | |
Michele Spagnolo | 7836c0f5d0 | |
Aaron Sattely | eee1c1cd84 | |
Roman Pudashkin | 707e5852c7 | |
Roman Pudashkin | 02945cbf12 | |
Hemant Antony | 1a023ff2d5 | |
Casper Jeukendrup | 1209e0b0ec | |
Casper Jeukendrup | 67cfccc028 | |
Casper Jeukendrup | 458dca54fb | |
pereverzev_v | 04c04001d7 | |
RomanPudashkin | 1431b58233 | |
RomanPudashkin | f57122f224 | |
Elnur Ismailzada | 9cfe34a1d5 | |
Eism | 9f8c23b254 | |
pereverzev_v | fe8a2de4c8 | |
RomanPudashkin | c4977d4381 | |
RomanPudashkin | a4b5fed825 | |
Casper Jeukendrup | 6014da2192 | |
Casper Jeukendrup | f745355e94 | |
pereverzev_v | 7abe56a213 | |
pereverzev_v | 9e37717e15 | |
RomanPudashkin | 6e5c4dc8e3 | |
RomanPudashkin | e74b6f308f | |
pereverzev_v | dadc7d92cf | |
RomanPudashkin | 06b8692dec | |
RomanPudashkin | fdbd087461 | |
Peter Jonas | 365446e370 | |
Grzegorz Pruchniakowski | 1ddc154484 | |
RomanPudashkin | b43a6ec5a0 | |
pereverzev_v | e17bc32e88 | |
Roman Pudashkin | 5f171c5f6d | |
Roman Pudashkin | 54976734b4 | |
Roman Pudashkin | ff1999223a | |
Roman Pudashkin | 149ea72df8 | |
Casper Jeukendrup | 427f872221 | |
Roman Pudashkin | f3168db80b | |
Roman Pudashkin | 84b26667a3 | |
Michele Spagnolo | 6596497e7d | |
Eism | b942cc8ed0 | |
Igor Korsukov | a0de6dc41b | |
Michele Spagnolo | 5e8eb895c2 | |
Michele Spagnolo | c241032b8b | |
RomanPudashkin | 2409b8a330 | |
Peter Jonas | 818bd2a763 | |
Peter Jonas | 64e5086467 | |
pereverzev_v | 3eb411716f | |
pereverzev_v | 0ed7932801 | |
RomanPudashkin | a4675ee803 | |
Roman Pudashkin | 33498f043c | |
Roman Pudashkin | 69e21a5ee6 | |
Roman Pudashkin | f5a95dd0e1 | |
pereverzev_v | 0fe713fe5a | |
pereverzev_v | cd0626cce6 | |
pereverzev_v | 14d66858ea | |
pereverzev_v | 4ec9de79bc | |
pereverzev_v | 82240d807b | |
pereverzev_v | cb75da2b3b | |
pereverzev_v | 580307d973 | |
pereverzev_v | 5ec90f8827 | |
pereverzev_v | 74fb76bae0 | |
pereverzev_v | b65574ea33 | |
pereverzev_v | aba024eda0 | |
RomanPudashkin | f0aa06f3ad | |
Roman Pudashkin | 4474b20d99 | |
RomanPudashkin | d21ebb58fb | |
RomanPudashkin | 2c14fae122 | |
Casper Jeukendrup | d4c4e6f6dc | |
Casper Jeukendrup | 02354e514a | |
Casper Jeukendrup | ff380a0958 | |
Casper Jeukendrup | 737f3d3b4b | |
RomanPudashkin | 1279972e0b | |
RomanPudashkin | 172169ea80 | |
Roman Pudashkin | 40c7901b41 | |
Roman Pudashkin | 0ca2295793 | |
Roman Pudashkin | c76f4e72ab | |
RomanPudashkin | 1e44ca6969 | |
Roman Pudashkin | d2afb72dab | |
Aaron Sattely | f217faaf1d |
|
@ -4,6 +4,7 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- 4.0_rc
|
||||
|
||||
jobs:
|
||||
codestyle:
|
||||
|
|
|
@ -4,9 +4,11 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- 4.0_rc
|
||||
|
||||
schedule:
|
||||
- cron: '0 4 */1 */1 *' # At 04:00 on every day-of-month
|
||||
schedule:
|
||||
- cron: '0 3 */1 */1 *' # At 03:00 on every day-of-month for master
|
||||
- cron: '0 5 */1 */1 *' # At 05:00 on every day-of-month for 4.0_rc
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build_mode:
|
||||
|
@ -30,8 +32,14 @@ jobs:
|
|||
uses: styfle/cancel-workflow-action@0.9.1
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
- name: Clone repository
|
||||
- name: Clone repository (default)
|
||||
uses: actions/checkout@v2
|
||||
if: ${{ github.event_name != 'schedule' || github.event.schedule == '0 3 */1 */1 *' }}
|
||||
- name: Clone repository (4.0_rc)
|
||||
uses: actions/checkout@v2
|
||||
if: ${{ github.event_name == 'schedule' && github.event.schedule == '0 5 */1 */1 *' }}
|
||||
with:
|
||||
ref: 4.0_rc
|
||||
- name: Ccache cache files
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
|
@ -101,8 +109,10 @@ jobs:
|
|||
DO_PUBLISH='false'
|
||||
fi
|
||||
|
||||
if [ "${{ github.event_name }}" == "pull_request" ]; then PR_INFO="_${{ github.event.pull_request.number }}_${pull_request_title}"; fi
|
||||
UPLOAD_ARTIFACT_NAME="$(tr '":<>|*?/\\' '_' <<<"MU4_${BUILD_NUMBER}_Lin${PR_INFO}")"
|
||||
ADD_INFO="_${GITHUB_REF#refs/heads/}"
|
||||
if [ "${{ github.event_name }}" == "schedule" && "${{ github.event.schedule }}" == "0 5 */1 */1 *" }} ]; then ADD_INFO="_4.0_rc"; fi
|
||||
if [ "${{ github.event_name }}" == "pull_request" ]; then ADD_INFO="_${{ github.event.pull_request.number }}_${pull_request_title}"; fi
|
||||
UPLOAD_ARTIFACT_NAME="$(tr '":<>|*?/\\' '_' <<<"MU4_${BUILD_NUMBER}_Lin${ADD_INFO}")"
|
||||
|
||||
echo "github.repository: ${{ github.repository }}"
|
||||
echo "BUILD_MODE=$BUILD_MODE" >> $GITHUB_ENV
|
||||
|
|
|
@ -4,9 +4,11 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- 4.0_rc
|
||||
|
||||
schedule:
|
||||
- cron: '0 4 */1 */1 *' # At 04:00 on every day-of-month
|
||||
schedule:
|
||||
- cron: '0 3 */1 */1 *' # At 03:00 on every day-of-month for master
|
||||
- cron: '0 5 */1 */1 *' # At 05:00 on every day-of-month for 4.0_rc
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build_mode:
|
||||
|
@ -33,8 +35,14 @@ jobs:
|
|||
uses: styfle/cancel-workflow-action@0.9.1
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
- name: Clone repository
|
||||
- name: Clone repository (default)
|
||||
uses: actions/checkout@v2
|
||||
if: ${{ github.event_name != 'schedule' || github.event.schedule == '0 3 */1 */1 *' }}
|
||||
- name: Clone repository (4.0_rc)
|
||||
uses: actions/checkout@v2
|
||||
if: ${{ github.event_name == 'schedule' && github.event.schedule == '0 5 */1 */1 *' }}
|
||||
with:
|
||||
ref: 4.0_rc
|
||||
- name: Ccache cache files
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
|
@ -118,8 +126,10 @@ jobs:
|
|||
DO_PUBLISH='false'
|
||||
fi
|
||||
|
||||
if [ "${{ github.event_name }}" == "pull_request" ]; then PR_INFO="_${{ github.event.pull_request.number }}_${pull_request_title}"; fi
|
||||
UPLOAD_ARTIFACT_NAME="$(tr '":<>|*?/\\' '_' <<<"MU4_${BUILD_NUMBER}_Mac${PR_INFO}")"
|
||||
ADD_INFO="_${GITHUB_REF#refs/heads/}"
|
||||
if [ "${{ github.event_name }}" == "schedule" && "${{ github.event.schedule }}" == "0 5 */1 */1 *" }} ]; then ADD_INFO="_4.0_rc"; fi
|
||||
if [ "${{ github.event_name }}" == "pull_request" ]; then ADD_INFO="_${{ github.event.pull_request.number }}_${pull_request_title}"; fi
|
||||
UPLOAD_ARTIFACT_NAME="$(tr '":<>|*?/\\' '_' <<<"MU4_${BUILD_NUMBER}_Mac${ADD_INFO}")"
|
||||
|
||||
echo "github.repository: ${{ github.repository }}"
|
||||
echo "BUILD_MODE=$BUILD_MODE" >> $GITHUB_ENV
|
||||
|
|
|
@ -4,6 +4,7 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- 4.0_rc
|
||||
|
||||
jobs:
|
||||
run_tests:
|
||||
|
|
|
@ -4,6 +4,7 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- 4.0_rc
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
|
|
|
@ -4,8 +4,11 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
schedule:
|
||||
- cron: '0 4 */1 */1 *' # At 04:00 on every day-of-month
|
||||
- 4.0_rc
|
||||
|
||||
schedule:
|
||||
- cron: '0 3 */1 */1 *' # At 03:00 on every day-of-month for master
|
||||
- cron: '0 5 */1 */1 *' # At 05:00 on every day-of-month for 4.0_rc
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build_mode:
|
||||
|
@ -29,10 +32,17 @@ jobs:
|
|||
uses: styfle/cancel-workflow-action@0.9.1
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
- name: Clone repository
|
||||
- name: Clone repository (default)
|
||||
uses: actions/checkout@v2
|
||||
if: ${{ github.event_name != 'schedule' || github.event.schedule == '0 3 */1 */1 *' }}
|
||||
with:
|
||||
fetch-depth: 3
|
||||
- name: Clone repository (4.0_rc)
|
||||
uses: actions/checkout@v2
|
||||
if: ${{ github.event_name == 'schedule' && github.event.schedule == '0 5 */1 */1 *' }}
|
||||
with:
|
||||
fetch-depth: 3
|
||||
ref: 4.0_rc
|
||||
- name: Fetch submodules
|
||||
run: |
|
||||
git submodule update --init --recursive
|
||||
|
@ -97,8 +107,10 @@ jobs:
|
|||
DO_PUBLISH='false'
|
||||
fi
|
||||
|
||||
if [ "${{ github.event_name }}" == "pull_request" ]; then PR_INFO="_${{ github.event.pull_request.number }}_${pull_request_title}"; fi
|
||||
UPLOAD_ARTIFACT_NAME="$(tr '":<>|*?/\\' '_' <<<"MU4_${BUILD_NUMBER}_Win${PR_INFO}")"
|
||||
ADD_INFO="_${GITHUB_REF#refs/heads/}"
|
||||
if [ "${{ github.event_name }}" == "schedule" && "${{ github.event.schedule }}" == "0 5 */1 */1 *" }} ]; then ADD_INFO="_4.0_rc"; fi
|
||||
if [ "${{ github.event_name }}" == "pull_request" ]; then ADD_INFO="_${{ github.event.pull_request.number }}_${pull_request_title}"; fi
|
||||
UPLOAD_ARTIFACT_NAME="$(tr '":<>|*?/\\' '_' <<<"MU4_${BUILD_NUMBER}_Win${ADD_INFO}")"
|
||||
|
||||
echo "github.repository: ${{ github.repository }}"
|
||||
echo "BUILD_MODE=$BUILD_MODE" >> $GITHUB_ENV
|
||||
|
|
|
@ -4,6 +4,7 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- 4.0_rc
|
||||
|
||||
jobs:
|
||||
run_tests:
|
||||
|
|
|
@ -1153,7 +1153,7 @@
|
|||
</Instrument>
|
||||
<Instrument id="g-soprano-ocarina">
|
||||
<family>ocarinas</family>
|
||||
<trackName>G Soprano Ocarina</trackName>
|
||||
<trackName>Soprano Ocarina</trackName>
|
||||
<longName>G Soprano Ocarina</longName>
|
||||
<shortName>G S. Oc.</shortName>
|
||||
<traitName type="tuning">G</traitName>
|
||||
|
@ -1171,7 +1171,7 @@
|
|||
</Instrument>
|
||||
<Instrument id="f-soprano-ocarina">
|
||||
<family>ocarinas</family>
|
||||
<trackName>F Soprano Ocarina</trackName>
|
||||
<trackName>Soprano Ocarina</trackName>
|
||||
<longName>F Soprano Ocarina</longName>
|
||||
<shortName>F S. Oc.</shortName>
|
||||
<traitName type="tuning">F</traitName>
|
||||
|
@ -7532,6 +7532,33 @@
|
|||
<program value="0"/> <!--Standard Kit-->
|
||||
</Channel>
|
||||
</Instrument>
|
||||
<Instrument id="bell-tree">
|
||||
<family>unpitched-metal-percussion</family>
|
||||
<trackName>Bell Tree</trackName>
|
||||
<longName>Bell Tree</longName>
|
||||
<shortName>Be. Tr.</shortName>
|
||||
<description>Inverted metal bowls nested on a vertical rod in order of pitch. The pitches are indefinite.</description>
|
||||
<musicXMLid>metal.bells.bell-tree</musicXMLid>
|
||||
<clef>PERC</clef>
|
||||
<stafftype staffTypePreset="perc1Line">percussion</stafftype>
|
||||
<barlineSpan>1</barlineSpan>
|
||||
<drumset>1</drumset>
|
||||
<singleNoteDynamics>0</singleNoteDynamics>
|
||||
<Drum pitch="84"> <!--Belltree-->
|
||||
<head>normal</head>
|
||||
<line>0</line>
|
||||
<voice>0</voice>
|
||||
<name>Glissando Down</name>
|
||||
<stem>1</stem>
|
||||
<shortcut>A</shortcut>
|
||||
</Drum>
|
||||
<Channel>
|
||||
<!--MIDI: Bank 128, Prog 0; MS General: Standard-->
|
||||
<controller ctrl="0" value="1"/> <!--Bank MSB-->
|
||||
<program value="0"/> <!--Standard Kit-->
|
||||
</Channel>
|
||||
<genre>world</genre>
|
||||
</Instrument>
|
||||
<Instrument id="bells">
|
||||
<family>unpitched-metal-percussion</family>
|
||||
<trackName>Bells</trackName>
|
||||
|
@ -7817,6 +7844,33 @@
|
|||
<program value="0"/> <!--Standard Kit-->
|
||||
</Channel>
|
||||
</Instrument>
|
||||
<Instrument id="mark-tree">
|
||||
<family>unpitched-metal-percussion</family>
|
||||
<trackName>Mark Tree</trackName>
|
||||
<longName>Mark Tree</longName>
|
||||
<shortName>Mk. Tr.</shortName>
|
||||
<description>Chimes hung from a horizontal bar in order of pitch. The pitches are indefinite.</description>
|
||||
<musicXMLid>metal.bells.mark-tree</musicXMLid>
|
||||
<clef>PERC</clef>
|
||||
<stafftype staffTypePreset="perc1Line">percussion</stafftype>
|
||||
<barlineSpan>1</barlineSpan>
|
||||
<drumset>1</drumset>
|
||||
<singleNoteDynamics>0</singleNoteDynamics>
|
||||
<Drum pitch="84"> <!--Belltree-->
|
||||
<head>normal</head>
|
||||
<line>0</line>
|
||||
<voice>0</voice>
|
||||
<name>Glissando Down</name>
|
||||
<stem>1</stem>
|
||||
<shortcut>A</shortcut>
|
||||
</Drum>
|
||||
<Channel>
|
||||
<!--MIDI: Bank 128, Prog 0; MS General: Standard-->
|
||||
<controller ctrl="0" value="1"/> <!--Bank MSB-->
|
||||
<program value="0"/> <!--Standard Kit-->
|
||||
</Channel>
|
||||
<genre>world</genre>
|
||||
</Instrument>
|
||||
<Instrument id="metal-castanets">
|
||||
<family>unpitched-metal-percussion</family>
|
||||
<trackName>Metal Castanets</trackName>
|
||||
|
|
|
@ -596,26 +596,26 @@ QT_TRANSLATE_NOOP3("engraving/instruments", "Contrabass Recorder", "contrabass-r
|
|||
//: shortName for Contrabass Recorder; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Cb. Rec.", "contrabass-recorder shortName"),
|
||||
|
||||
//: description for G Soprano Ocarina; tuning: G; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
//: description for Soprano Ocarina; tuning: G; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Soprano ocarina pitched in G.", "g-soprano-ocarina description"),
|
||||
//: trackName for G Soprano Ocarina; tuning: G; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "G Soprano Ocarina", "g-soprano-ocarina trackName"),
|
||||
//: longName for G Soprano Ocarina; tuning: G; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
//: trackName for Soprano Ocarina; tuning: G; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Soprano Ocarina", "g-soprano-ocarina trackName"),
|
||||
//: longName for Soprano Ocarina; tuning: G; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "G Soprano Ocarina", "g-soprano-ocarina longName"),
|
||||
//: shortName for G Soprano Ocarina; tuning: G; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
//: shortName for Soprano Ocarina; tuning: G; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "G S. Oc.", "g-soprano-ocarina shortName"),
|
||||
//: traitName for G Soprano Ocarina; tuning: G; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
//: traitName for Soprano Ocarina; tuning: G; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "G", "g-soprano-ocarina traitName"),
|
||||
|
||||
//: description for F Soprano Ocarina; tuning: F; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
//: description for Soprano Ocarina; tuning: F; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Soprano ocarina pitched in F.", "f-soprano-ocarina description"),
|
||||
//: trackName for F Soprano Ocarina; tuning: F; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "F Soprano Ocarina", "f-soprano-ocarina trackName"),
|
||||
//: longName for F Soprano Ocarina; tuning: F; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
//: trackName for Soprano Ocarina; tuning: F; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Soprano Ocarina", "f-soprano-ocarina trackName"),
|
||||
//: longName for Soprano Ocarina; tuning: F; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "F Soprano Ocarina", "f-soprano-ocarina longName"),
|
||||
//: shortName for F Soprano Ocarina; tuning: F; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
//: shortName for Soprano Ocarina; tuning: F; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "F S. Oc.", "f-soprano-ocarina shortName"),
|
||||
//: traitName for F Soprano Ocarina; tuning: F; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
//: traitName for Soprano Ocarina; tuning: F; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "F", "f-soprano-ocarina traitName"),
|
||||
|
||||
//: description for Ocarina; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
|
@ -3951,6 +3951,15 @@ QT_TRANSLATE_NOOP3("engraving/instruments", "Bell Plate", "bell-plate longName")
|
|||
//: shortName for Bell Plate; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Be. Pla.", "bell-plate shortName"),
|
||||
|
||||
//: description for Bell Tree; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Inverted metal bowls nested on a vertical rod in order of pitch. The pitches are indefinite.", "bell-tree description"),
|
||||
//: trackName for Bell Tree; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Bell Tree", "bell-tree trackName"),
|
||||
//: longName for Bell Tree; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Bell Tree", "bell-tree longName"),
|
||||
//: shortName for Bell Tree; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Be. Tr.", "bell-tree shortName"),
|
||||
|
||||
//: description for Bells; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Bells.", "bells description"),
|
||||
//: trackName for Bells; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
|
@ -4041,6 +4050,15 @@ QT_TRANSLATE_NOOP3("engraving/instruments", "Iron Pipes", "iron-pipes longName")
|
|||
//: shortName for Iron Pipes; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Ir. Pi.", "iron-pipes shortName"),
|
||||
|
||||
//: description for Mark Tree; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Chimes hung from a horizontal bar in order of pitch. The pitches are indefinite.", "mark-tree description"),
|
||||
//: trackName for Mark Tree; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Mark Tree", "mark-tree trackName"),
|
||||
//: longName for Mark Tree; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Mark Tree", "mark-tree longName"),
|
||||
//: shortName for Mark Tree; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Mk. Tr.", "mark-tree shortName"),
|
||||
|
||||
//: description for Metal Castanets; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
QT_TRANSLATE_NOOP3("engraving/instruments", "Metal castanets.", "metal-castanets description"),
|
||||
//: trackName for Metal Castanets; Please see https://github.com/musescore/MuseScore/wiki/Translating-instrument-names
|
||||
|
|
|
@ -383,6 +383,26 @@
|
|||
<render>striangle</render>
|
||||
</token>
|
||||
|
||||
<token class="modifier">
|
||||
<name>add</name>
|
||||
<render>add</render>
|
||||
</token>
|
||||
|
||||
<token class="modifier">
|
||||
<name>sus</name>
|
||||
<render>sus</render>
|
||||
</token>
|
||||
|
||||
<token class="modifier">
|
||||
<name>no</name>
|
||||
<render>no</render>
|
||||
</token>
|
||||
|
||||
<token class="modifier">
|
||||
<name>omit</name>
|
||||
<render>omit</render>
|
||||
</token>
|
||||
|
||||
<renderRoot>:n :a m:0.5:0</renderRoot>
|
||||
<renderFunction>:a m:0.5:0 :n</renderFunction>
|
||||
<renderBase>m:-0.2:1 / m:0.2:1 :n :a m:0:-2</renderBase>
|
||||
|
|
|
@ -69,7 +69,9 @@ int AppShell::run(int argc, char** argv)
|
|||
qputenv("QML_DISABLE_DISK_CACHE", "true");
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
qputenv("QT_QPA_PLATFORMTHEME", "gtk3");
|
||||
if (qEnvironmentVariable("QT_QPA_PLATFORM") != "offscreen") {
|
||||
qputenv("QT_QPA_PLATFORMTHEME", "gtk3");
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* appName;
|
||||
|
@ -150,9 +152,10 @@ int AppShell::run(int argc, char** argv)
|
|||
m->onPreInit(runMode);
|
||||
}
|
||||
|
||||
SplashScreen splashScreen;
|
||||
SplashScreen* splashScreen = nullptr;
|
||||
if (runMode == framework::IApplication::RunMode::Editor) {
|
||||
splashScreen.show();
|
||||
splashScreen = new SplashScreen();
|
||||
splashScreen->show();
|
||||
}
|
||||
|
||||
// ====================================================
|
||||
|
@ -257,7 +260,10 @@ int AppShell::run(int argc, char** argv)
|
|||
|
||||
engine->load(url);
|
||||
|
||||
splashScreen.close();
|
||||
if (splashScreen) {
|
||||
splashScreen->close();
|
||||
delete splashScreen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,8 @@ void CommandLineController::parse(const QStringList& args)
|
|||
// m_parser.addOption(QCommandLineOption("piano-position", "Show Piano top or bottom. Default bottom", "bottom"));
|
||||
m_parser.addOption(QCommandLineOption("resolution", "Resolution [2160p, 1440p, 1080p, 720p, 480p, 360p]", "1080p"));
|
||||
m_parser.addOption(QCommandLineOption("fps", "Frame per second [60, 30, 24]", "24"));
|
||||
m_parser.addOption(QCommandLineOption("ls", "Pause before playback in seconds (3.0)", "3.0"));
|
||||
m_parser.addOption(QCommandLineOption("ts", "Pause before end of video in seconds (3.0)", "3.0"));
|
||||
|
||||
m_parser.addOption(QCommandLineOption("gp-linked", "create tabulature linked staves for guitar pro"));
|
||||
m_parser.addOption(QCommandLineOption("gp-experimental", "experimental features for guitar pro import"));
|
||||
|
@ -316,6 +318,14 @@ void CommandLineController::apply()
|
|||
if (m_parser.isSet("fps")) {
|
||||
videoExportConfiguration()->setFps(intValue("fps"));
|
||||
}
|
||||
|
||||
if (m_parser.isSet("ls")) {
|
||||
videoExportConfiguration()->setLeadingSec(doubleValue("ls"));
|
||||
}
|
||||
|
||||
if (m_parser.isSet("ts")) {
|
||||
videoExportConfiguration()->setTrailingSec(doubleValue("ts"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -324,7 +334,7 @@ void CommandLineController::apply()
|
|||
}
|
||||
|
||||
if (m_parser.isSet("f")) {
|
||||
m_converterTask.params[CommandLineController::ParamKey::ForceMode] = m_parser.value("f");
|
||||
m_converterTask.params[CommandLineController::ParamKey::ForceMode] = true;
|
||||
}
|
||||
|
||||
if (m_parser.isSet("S")) {
|
||||
|
|
|
@ -167,7 +167,11 @@ void ApplicationActionController::quit(bool isAllInstances, const io::path_t& in
|
|||
}
|
||||
|
||||
if (multiInstancesProvider()->instances().size() == 1 && !installerPath.empty()) {
|
||||
#if defined(Q_OS_LINUX)
|
||||
interactive()->revealInFileBrowser(installerPath);
|
||||
#else
|
||||
interactive()->openUrl(QUrl::fromLocalFile(installerPath.toQString()));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (multiInstancesProvider()->instances().size() > 1) {
|
||||
|
|
|
@ -42,7 +42,7 @@ static const Settings::Key HAS_COMPLETED_FIRST_LAUNCH_SETUP(module_name, "applic
|
|||
static const Settings::Key STARTUP_MODE_TYPE(module_name, "application/startup/modeStart");
|
||||
static const Settings::Key STARTUP_SCORE_PATH(module_name, "application/startup/startScore");
|
||||
|
||||
static const std::string MUSESCORE_ONLINE_HANDBOOK_URL_PATH("/redirect/help");
|
||||
static const std::string MUSESCORE_ONLINE_HANDBOOK_URL_PATH("/handbook/4");
|
||||
static const std::string MUSESCORE_ASK_FOR_HELP_URL_PATH("/redirect/post/question");
|
||||
static const std::string MUSESCORE_BUG_REPORT_URL_PATH("/redirect/post/bug-report?locale=");
|
||||
static const std::string MUSESCORE_FORUM_URL_PATH("/forum");
|
||||
|
@ -116,7 +116,7 @@ std::string AppShellConfiguration::handbookUrl() const
|
|||
QString::fromStdString(utm)
|
||||
};
|
||||
|
||||
return MUSESCORE_ONLINE_HANDBOOK_URL_PATH + "?" + params.join("&").toStdString();
|
||||
return museScoreUrl() + MUSESCORE_ONLINE_HANDBOOK_URL_PATH + "?" + params.join("&").toStdString();
|
||||
}
|
||||
|
||||
std::string AppShellConfiguration::askForHelpUrl() const
|
||||
|
@ -127,7 +127,7 @@ std::string AppShellConfiguration::askForHelpUrl() const
|
|||
"locale=" + QString::fromStdString(languageCode)
|
||||
};
|
||||
|
||||
return MUSESCORE_ASK_FOR_HELP_URL_PATH + "?" + params.join("&").toStdString();
|
||||
return museScoreUrl() + MUSESCORE_ASK_FOR_HELP_URL_PATH + "?" + params.join("&").toStdString();
|
||||
}
|
||||
|
||||
std::string AppShellConfiguration::bugReportUrl() const
|
||||
|
@ -142,7 +142,7 @@ std::string AppShellConfiguration::bugReportUrl() const
|
|||
QString::fromStdString(_sha)
|
||||
};
|
||||
|
||||
return MUSESCORE_BUG_REPORT_URL_PATH + "?" + params.join("&").toStdString();
|
||||
return museScoreUrl() + MUSESCORE_BUG_REPORT_URL_PATH + "?" + params.join("&").toStdString();
|
||||
}
|
||||
|
||||
std::string AppShellConfiguration::leaveFeedbackUrl() const
|
||||
|
@ -163,12 +163,12 @@ std::string AppShellConfiguration::museScoreUrl() const
|
|||
|
||||
std::string AppShellConfiguration::museScoreForumUrl() const
|
||||
{
|
||||
return globalConfiguration()->museScoreUrl() + MUSESCORE_FORUM_URL_PATH;
|
||||
return museScoreUrl() + MUSESCORE_FORUM_URL_PATH;
|
||||
}
|
||||
|
||||
std::string AppShellConfiguration::museScoreContributionUrl() const
|
||||
{
|
||||
return globalConfiguration()->museScoreUrl() + MUSESCORE_CONTRIBUTE_URL_PATH;
|
||||
return museScoreUrl() + MUSESCORE_CONTRIBUTE_URL_PATH;
|
||||
}
|
||||
|
||||
std::string AppShellConfiguration::musicXMLLicenseUrl() const
|
||||
|
|
|
@ -50,7 +50,7 @@ StyledDialogView {
|
|||
|
||||
property string value: ""
|
||||
width: 150
|
||||
onCurrentTextEdited: input.value = newTextValue
|
||||
onTextChanged: input.value = newTextValue
|
||||
}
|
||||
|
||||
StyledTextLabel {
|
||||
|
|
|
@ -57,7 +57,7 @@ Rectangle {
|
|||
FlatButton {
|
||||
anchors.left: parent.left
|
||||
|
||||
width: 160
|
||||
minWidth: 160
|
||||
|
||||
navigation.panel: root.navigation
|
||||
navigation.order: 2
|
||||
|
@ -76,7 +76,6 @@ Rectangle {
|
|||
navigation.panel: root.navigation
|
||||
navigation.order: 3
|
||||
|
||||
width: 132
|
||||
text: qsTrc("global", "Cancel")
|
||||
|
||||
onClicked: {
|
||||
|
@ -92,7 +91,6 @@ Rectangle {
|
|||
navigation.panel: root.navigation
|
||||
navigation.order: 1
|
||||
|
||||
width: 132
|
||||
accentButton: true
|
||||
|
||||
text: qsTrc("global", "OK")
|
||||
|
|
|
@ -51,12 +51,14 @@ BaseSection {
|
|||
width: parent.width
|
||||
|
||||
delegate: Row {
|
||||
width: parent.width
|
||||
spacing: root.columnSpacing
|
||||
|
||||
RoundedRadioButton {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
width: root.columnWidth
|
||||
width: filePicker.visible ? Math.max(implicitWidth, root.columnWidth)
|
||||
: parent.width
|
||||
|
||||
checked: modelData.checked
|
||||
text: modelData.title
|
||||
|
@ -72,6 +74,8 @@ BaseSection {
|
|||
}
|
||||
|
||||
FilePicker {
|
||||
id: filePicker
|
||||
|
||||
pathFieldWidth: root.columnWidth
|
||||
spacing: root.columnSpacing
|
||||
|
||||
|
@ -102,6 +106,8 @@ BaseSection {
|
|||
height: contentHeight
|
||||
|
||||
delegate: CheckBox {
|
||||
width: parent.width
|
||||
|
||||
text: modelData.title
|
||||
checked: modelData.visible
|
||||
|
||||
|
|
|
@ -91,6 +91,8 @@ QList<unsigned int> CommonAudioApiConfigurationModel::bufferSizeList() const
|
|||
result << bufferSize;
|
||||
}
|
||||
|
||||
std::sort(result.begin(), result.end());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
virtual void signIn() = 0;
|
||||
virtual void signOut() = 0;
|
||||
|
||||
virtual Ret requireAuthorization(const std::string& text = {}) = 0;
|
||||
virtual Ret ensureAuthorization(const std::string& text = {}) = 0;
|
||||
|
||||
virtual ValCh<bool> userAuthorized() const = 0;
|
||||
virtual ValCh<AccountInfo> accountInfo() const = 0;
|
||||
|
|
|
@ -158,5 +158,5 @@ mu::io::path_t CloudConfiguration::tokensFilePath() const
|
|||
|
||||
QString CloudConfiguration::apiRootUrl() const
|
||||
{
|
||||
return "https://api.musescore.com/editor/v1";
|
||||
return "https://desktop.musescore.com/editor/v1";
|
||||
}
|
||||
|
|
|
@ -416,8 +416,12 @@ void CloudService::signOut()
|
|||
clearTokens();
|
||||
}
|
||||
|
||||
mu::Ret CloudService::requireAuthorization(const std::string& text)
|
||||
mu::Ret CloudService::ensureAuthorization(const std::string& text)
|
||||
{
|
||||
if (m_userAuthorized.val) {
|
||||
return make_ok();
|
||||
}
|
||||
|
||||
UriQuery query("musescore://cloud/requireauthorization");
|
||||
query.addParam("text", Val(text));
|
||||
return interactive()->open(query).ret;
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
void signIn() override;
|
||||
void signOut() override;
|
||||
|
||||
Ret requireAuthorization(const std::string& text = {}) override;
|
||||
Ret ensureAuthorization(const std::string& text = {}) override;
|
||||
|
||||
ValCh<bool> userAuthorized() const override;
|
||||
ValCh<AccountInfo> accountInfo() const override;
|
||||
|
|
|
@ -109,7 +109,7 @@ FocusScope {
|
|||
|
||||
FlatButton {
|
||||
id: accountInfoButton
|
||||
width: prv.buttonWidth
|
||||
minWidth: prv.buttonWidth
|
||||
text: qsTrc("cloud", "Account info")
|
||||
|
||||
accentButton: true
|
||||
|
@ -131,7 +131,7 @@ FocusScope {
|
|||
}
|
||||
|
||||
FlatButton {
|
||||
width: prv.buttonWidth
|
||||
minWidth: prv.buttonWidth
|
||||
text: qsTrc("cloud", "Sign out")
|
||||
|
||||
navigation.name: "SignOut"
|
||||
|
|
|
@ -108,7 +108,7 @@ FocusScope {
|
|||
FlatButton {
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
|
||||
width: privateProperties.buttonWidth
|
||||
minWidth: privateProperties.buttonWidth
|
||||
text: qsTrc("cloud", "Learn more")
|
||||
|
||||
navigation.name: "LearnMore"
|
||||
|
@ -126,7 +126,7 @@ FocusScope {
|
|||
spacing: 22
|
||||
|
||||
FlatButton {
|
||||
width: privateProperties.buttonWidth
|
||||
minWidth: privateProperties.buttonWidth
|
||||
text: qsTrc("cloud", "Sign in")
|
||||
|
||||
navigation.name: "SignIn"
|
||||
|
@ -140,7 +140,7 @@ FocusScope {
|
|||
|
||||
FlatButton {
|
||||
id: createNewAccount
|
||||
width: privateProperties.buttonWidth
|
||||
minWidth: privateProperties.buttonWidth
|
||||
text: qsTrc("cloud", "Create new account")
|
||||
|
||||
accentButton: true
|
||||
|
|
|
@ -56,7 +56,7 @@ void UiContextResolver::init()
|
|||
notifyAboutContextChanged();
|
||||
});
|
||||
|
||||
notation->interaction()->textEditingEnded().onNotify(this, [this]() {
|
||||
notation->interaction()->textEditingEnded().onReceive(this, [this](engraving::TextBase*) {
|
||||
notifyAboutContextChanged();
|
||||
});
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ Rectangle {
|
|||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.margins: 16
|
||||
clearTextButtonVisible: true
|
||||
onCurrentTextEdited: function(newTextValue) {
|
||||
onTextChanged: function(newTextValue) {
|
||||
profModel.find(newTextValue)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "libmscore/segment.h"
|
||||
#include "libmscore/chord.h"
|
||||
#include "libmscore/note.h"
|
||||
#include "libmscore/bracketItem.h"
|
||||
|
||||
#ifndef ENGRAVING_NO_ACCESSIBILITY
|
||||
#include "accessibility/accessibleitem.h"
|
||||
|
@ -44,6 +45,7 @@ DummyElement::DummyElement(EngravingObject* parent)
|
|||
|
||||
DummyElement::~DummyElement()
|
||||
{
|
||||
delete m_bracketItem;
|
||||
delete m_note;
|
||||
delete m_chord;
|
||||
delete m_segment;
|
||||
|
@ -83,6 +85,9 @@ void DummyElement::init()
|
|||
|
||||
m_note = Factory::createNote(m_chord);
|
||||
m_note->setParent(m_chord);
|
||||
|
||||
m_bracketItem = Factory::createBracketItem(m_system);
|
||||
m_bracketItem->setParent(m_system);
|
||||
}
|
||||
|
||||
RootItem* DummyElement::rootItem()
|
||||
|
@ -120,6 +125,11 @@ Note* DummyElement::note()
|
|||
return m_note;
|
||||
}
|
||||
|
||||
BracketItem* DummyElement::bracketItem()
|
||||
{
|
||||
return m_bracketItem;
|
||||
}
|
||||
|
||||
EngravingItem* DummyElement::clone() const
|
||||
{
|
||||
return nullptr;
|
||||
|
|
|
@ -48,6 +48,7 @@ public:
|
|||
Segment* segment();
|
||||
Chord* chord();
|
||||
Note* note();
|
||||
BracketItem* bracketItem();
|
||||
|
||||
EngravingItem* clone() const override;
|
||||
|
||||
|
@ -66,6 +67,7 @@ private:
|
|||
Segment* m_segment = nullptr;
|
||||
Chord* m_chord = nullptr;
|
||||
Note* m_note = nullptr;
|
||||
BracketItem* m_bracketItem = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,8 @@ public:
|
|||
virtual io::path_t partStyleFilePath() const = 0;
|
||||
virtual void setPartStyleFilePath(const io::path_t& path) = 0;
|
||||
|
||||
virtual SizeF defaultPageSize() const = 0;
|
||||
|
||||
virtual String iconsFontFamily() const = 0;
|
||||
|
||||
virtual draw::Color defaultColor() const = 0;
|
||||
|
|
|
@ -560,7 +560,7 @@ bool SymbolFont::isValid(SymId id) const
|
|||
|
||||
bool SymbolFont::useFallbackFont(SymId id) const
|
||||
{
|
||||
return MScore::useFallbackFont && !sym(id).isValid() && this != SymbolFonts::fallbackFont();
|
||||
return MScore::useFallbackFont && !sym(id).isValid() && this != SymbolFonts::fallbackFont(false);
|
||||
}
|
||||
|
||||
// =============================================
|
||||
|
|
|
@ -52,17 +52,7 @@ SymbolFont* SymbolFonts::fontByName(const String& name)
|
|||
}
|
||||
|
||||
if (!font) {
|
||||
LOGE() << "ScoreFont not found in list: " << name;
|
||||
LOGE() << "ScoreFonts in list:";
|
||||
|
||||
for (const SymbolFont& f : s_symbolFonts) {
|
||||
LOGE() << " " << f.name();
|
||||
}
|
||||
|
||||
font = fallbackFont();
|
||||
|
||||
LOGE() << "Using fallback font " << font->name() << " instead.";
|
||||
return font;
|
||||
return fallbackFont();
|
||||
}
|
||||
|
||||
if (!font->m_loaded) {
|
||||
|
@ -92,11 +82,11 @@ void SymbolFonts::setFallbackFont(const String& name)
|
|||
}
|
||||
}
|
||||
|
||||
SymbolFont* SymbolFonts::fallbackFont()
|
||||
SymbolFont* SymbolFonts::fallbackFont(bool load)
|
||||
{
|
||||
SymbolFont* font = &s_symbolFonts[s_fallback.index];
|
||||
|
||||
if (!font->m_loaded) {
|
||||
if (load && !font->m_loaded) {
|
||||
font->load();
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
static SymbolFont* fontByName(const String& name);
|
||||
|
||||
static void setFallbackFont(const String& name);
|
||||
static SymbolFont* fallbackFont();
|
||||
static SymbolFont* fallbackFont(bool load = true);
|
||||
static const char* fallbackTextFont();
|
||||
|
||||
private:
|
||||
|
|
|
@ -21,6 +21,13 @@
|
|||
*/
|
||||
#include "engravingconfiguration.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#ifndef NO_QT_SUPPORT
|
||||
#include <QLocale>
|
||||
#include <QPageSize>
|
||||
#endif
|
||||
|
||||
#include "global/settings.h"
|
||||
#include "draw/types/color.h"
|
||||
#include "libmscore/mscore.h"
|
||||
|
@ -98,6 +105,44 @@ void EngravingConfiguration::setPartStyleFilePath(const io::path_t& path)
|
|||
settings()->setSharedValue(PART_STYLE_FILE_PATH, Val(path.toStdString()));
|
||||
}
|
||||
|
||||
static bool defaultPageSizeIsLetter()
|
||||
{
|
||||
// try PAPERSIZE environment variable
|
||||
const char* papersize = getenv("PAPERSIZE");
|
||||
if (papersize) {
|
||||
return strcmp(papersize, "letter") == 0;
|
||||
}
|
||||
#ifndef NO_QT_SUPPORT
|
||||
// try locale
|
||||
switch (QLocale::system().country()) {
|
||||
case QLocale::UnitedStates:
|
||||
case QLocale::Canada:
|
||||
case QLocale::Mexico:
|
||||
case QLocale::Chile:
|
||||
case QLocale::Colombia:
|
||||
case QLocale::CostaRica:
|
||||
case QLocale::Panama:
|
||||
case QLocale::Guatemala:
|
||||
case QLocale::DominicanRepublic:
|
||||
case QLocale::Philippines:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
SizeF EngravingConfiguration::defaultPageSize() const
|
||||
{
|
||||
// Needs to be determined only once, therefore static
|
||||
static SizeF size = SizeF::fromQSizeF(
|
||||
QPageSize::size(defaultPageSizeIsLetter() ? QPageSize::Letter : QPageSize::A4, QPageSize::Inch));
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
mu::String EngravingConfiguration::iconsFontFamily() const
|
||||
{
|
||||
return String::fromStdString(uiConfiguration()->iconsFontFamily());
|
||||
|
|
|
@ -53,6 +53,8 @@ public:
|
|||
io::path_t partStyleFilePath() const override;
|
||||
void setPartStyleFilePath(const io::path_t& path) override;
|
||||
|
||||
SizeF defaultPageSize() const override;
|
||||
|
||||
String iconsFontFamily() const override;
|
||||
|
||||
draw::Color defaultColor() const override;
|
||||
|
|
|
@ -111,8 +111,8 @@ void LayoutBeams::restoreBeams(Measure* m)
|
|||
for (EngravingItem* e : s->elist()) {
|
||||
if (e && e->isChordRest()) {
|
||||
ChordRest* cr = toChordRest(e);
|
||||
if (isTopBeam(cr)) {
|
||||
Beam* b = cr->beam();
|
||||
Beam* b = cr->beam();
|
||||
if (b && !b->elements().empty() && b->elements().front() == cr) {
|
||||
b->layout();
|
||||
b->addSkyline(m->system()->staff(b->staffIdx())->skyline());
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ void LayoutMeasure::createMMRest(const LayoutOptions& options, Score* score, Mea
|
|||
for (size_t staffIdx = 0; staffIdx < score->nstaves(); ++staffIdx) {
|
||||
track_idx_t track = staffIdx * VOICES;
|
||||
if (s->element(track) == 0) {
|
||||
MMRest* mmr = new MMRest(s);
|
||||
MMRest* mmr = Factory::createMMRest(s);
|
||||
mmr->setDurationType(DurationType::V_MEASURE);
|
||||
mmr->setTicks(mmrMeasure->ticks());
|
||||
mmr->setTrack(track);
|
||||
|
|
|
@ -1397,6 +1397,9 @@ void LayoutSystem::processLines(System* system, std::vector<Spanner*> lines, boo
|
|||
for (SpannerSegment* ss : segments) {
|
||||
if (ss->addToSkyline()) {
|
||||
staff_idx_t stfIdx = ss->systemFlag() ? ss->staffIdxOrNextVisible() : ss->staffIdx();
|
||||
if (stfIdx == mu::nidx) {
|
||||
continue;
|
||||
}
|
||||
system->staff(stfIdx)->skyline().add(ss->shape().translated(ss->pos()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1189,7 +1189,7 @@ void Beam::offsetBeamWithAnchorShortening(std::vector<ChordRest*> chordRests, in
|
|||
return;
|
||||
}
|
||||
// min stem lengths according to how many beams there are (starting with 1)
|
||||
static const int minStemLengths[] = { 11, 13, 15, 18, 21 };
|
||||
static const int minStemLengths[] = { 11, 13, 15, 18, 21, 24, 27, 30 };
|
||||
const int middleLine = getMiddleStaffLine(startChord, endChord, staffLines);
|
||||
int maxDictatorReduce = stemLengthDictator - minStemLengths[(isStartDictator ? startChord : endChord)->beams() - 1];
|
||||
maxDictatorReduce = std::min(abs(dictator - middleLine), maxDictatorReduce);
|
||||
|
|
|
@ -312,21 +312,29 @@ bool Box::readProperties(XmlReader& e)
|
|||
//! but when we add it to Box, the parent will be rewritten.
|
||||
add(f);
|
||||
} else if (tag == "HBox") {
|
||||
HBox* hb = new HBox(this->system());
|
||||
hb->read(e);
|
||||
//! TODO Looks like a bug.
|
||||
//! The HBox parent must be System
|
||||
//! there is a method: `System* system() const { return (System*)parent(); }`,
|
||||
//! but when we add it to Box, the parent will be rewritten.
|
||||
add(hb);
|
||||
// m_parent is used here (rather than system()) because explicit parent isn't set for this object
|
||||
// until it is fully read. m_parent is nonetheless valid and using it here matches MU3 behavior.
|
||||
// If we do not set the parent of this new box correctly, it will cause a crash on read()
|
||||
// because it needs access to the system it is being added to. (c.r. issue #14643)
|
||||
if (m_parent && m_parent->isSystem()) {
|
||||
HBox* hb = new HBox(toSystem(m_parent));
|
||||
hb->read(e);
|
||||
//! TODO Looks like a bug.
|
||||
//! The HBox parent must be System
|
||||
//! there is a method: `System* system() const { return (System*)parent(); }`,
|
||||
//! but when we add it to Box, the parent will be rewritten.
|
||||
add(hb);
|
||||
}
|
||||
} else if (tag == "VBox") {
|
||||
VBox* vb = new VBox(this->system());
|
||||
vb->read(e);
|
||||
//! TODO Looks like a bug.
|
||||
//! The VBox parent must be System
|
||||
//! there is a method: `System* system() const { return (System*)parent(); }`,
|
||||
//! but when we add it to Box, the parent will be rewritten.
|
||||
add(vb);
|
||||
if (m_parent && m_parent->isSystem()) {
|
||||
VBox* vb = new VBox(toSystem(m_parent));
|
||||
vb->read(e);
|
||||
//! TODO Looks like a bug.
|
||||
//! The VBox parent must be System
|
||||
//! there is a method: `System* system() const { return (System*)parent(); }`,
|
||||
//! but when we add it to Box, the parent will be rewritten.
|
||||
add(vb);
|
||||
}
|
||||
} else if (MeasureBase::readProperties(e)) {
|
||||
} else {
|
||||
return false;
|
||||
|
|
|
@ -553,7 +553,7 @@ void Bracket::undoChangeProperty(Pid id, const PropertyValue& v, PropertyFlags p
|
|||
|
||||
void Bracket::setSelected(bool f)
|
||||
{
|
||||
// _bi->setSelected(f);
|
||||
_bi->setSelected(f);
|
||||
EngravingItem::setSelected(f);
|
||||
}
|
||||
|
||||
|
|
|
@ -523,16 +523,19 @@ EngravingItem* ChordRest::drop(EditData& data)
|
|||
if (part()->instruments().find(tick().ticks()) != part()->instruments().end()) {
|
||||
LOGD() << "InstrumentChange already exists at tick = " << tick().ticks();
|
||||
delete e;
|
||||
return 0;
|
||||
return nullptr;
|
||||
} else {
|
||||
InstrumentChange* ic = toInstrumentChange(e);
|
||||
ic->setParent(segment());
|
||||
ic->setTrack(trackZeroVoice(track()));
|
||||
Instrument* instr = ic->instrument();
|
||||
Instrument* prevInstr = part()->instrument(tick());
|
||||
if (instr && instr->isDifferentInstrument(*prevInstr)) {
|
||||
ic->setupInstrument(instr);
|
||||
|
||||
const Instrument* instr = part()->instrument(tick());
|
||||
IF_ASSERT_FAILED(instr) {
|
||||
delete e;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ic->setInstrument(*instr);
|
||||
score()->undoAddElement(ic);
|
||||
return e;
|
||||
}
|
||||
|
|
|
@ -3210,7 +3210,7 @@ void Score::cmdExplode()
|
|||
// keep note "i" from top, which is backwards from nnotes - 1
|
||||
// reuse notes if there are more instruments than notes
|
||||
size_t stavesPerNote = std::max((lastStaff - srcStaff) / nnotes, static_cast<size_t>(1));
|
||||
size_t keepIndex = std::max(nnotes - 1 - (i / stavesPerNote), static_cast<size_t>(0));
|
||||
size_t keepIndex = static_cast<size_t>(std::max(static_cast<int>(nnotes) - 1 - static_cast<int>(i / stavesPerNote), 0));
|
||||
Note* keepNote = c->notes()[keepIndex];
|
||||
for (Note* n : notes) {
|
||||
if (n != keepNote) {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "durationelement.h"
|
||||
|
||||
#include "rw/xml.h"
|
||||
#include "realfn.h"
|
||||
|
||||
#include "property.h"
|
||||
#include "score.h"
|
||||
|
@ -96,6 +97,14 @@ Fraction DurationElement::globalTicks() const
|
|||
return f;
|
||||
}
|
||||
|
||||
float DurationElement::timeStretchFactor() const
|
||||
{
|
||||
int nominalDuration = _duration.ticks();
|
||||
int actualDuration = actualTicks().ticks();
|
||||
|
||||
return actualDuration / static_cast<float>(nominalDuration);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// actualTicks
|
||||
//---------------------------------------------------------
|
||||
|
|
|
@ -60,6 +60,7 @@ public:
|
|||
// Length expressed as a fraction of a whole note
|
||||
virtual Fraction ticks() const { return _duration; }
|
||||
Fraction globalTicks() const;
|
||||
float timeStretchFactor() const;
|
||||
void setTicks(const Fraction& f) { _duration = f; }
|
||||
|
||||
PropertyValue getProperty(Pid propertyId) const override;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "infrastructure/messagebox.h"
|
||||
|
||||
#include "accidental.h"
|
||||
#include "articulation.h"
|
||||
#include "barline.h"
|
||||
|
@ -243,7 +245,9 @@ Tuplet* Score::addTuplet(ChordRest* destinationChordRest, Fraction ratio, Tuplet
|
|||
|
||||
Fraction fr = f * Fraction(1, _ratio.denominator());
|
||||
if (!TDuration::isValid(fr)) {
|
||||
// todo: there needs to be some kind of user feedback for failure to add tuplet
|
||||
MessageBox::warning(mtrc("engraving", "Cannot create tuplet with ratio %1 for duration %2")
|
||||
.arg(_ratio.toString(), f.toString()).toStdString(),
|
||||
std::string(), { MessageBox::Ok });
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -4856,7 +4860,7 @@ static EngravingItem* findLinkedVoiceElement(EngravingItem* e, Staff* nstaff)
|
|||
Measure* measure = segment->measure();
|
||||
Measure* m = score->tick2measure(measure->tick());
|
||||
Segment* s = m->findSegment(segment->segmentType(), segment->tick());
|
||||
return s->element(dtrack);
|
||||
return s ? s->element(dtrack) : nullptr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
|
|
@ -2639,43 +2639,11 @@ bool EngravingItem::selected() const
|
|||
void EngravingItem::setSelected(bool f)
|
||||
{
|
||||
setFlag(ElementFlag::SELECTED, f);
|
||||
|
||||
#ifndef ENGRAVING_NO_ACCESSIBILITY
|
||||
if (f) {
|
||||
initAccessibleIfNeed();
|
||||
|
||||
if (m_accessible) {
|
||||
AccessibleRoot* currAccRoot = m_accessible->accessibleRoot();
|
||||
AccessibleRoot* accRoot = score()->rootItem()->accessible()->accessibleRoot();
|
||||
AccessibleRoot* dummyAccRoot = score()->dummy()->rootItem()->accessible()->accessibleRoot();
|
||||
|
||||
if (accRoot && currAccRoot == accRoot && accRoot->registered()) {
|
||||
accRoot->setFocusedElement(m_accessible);
|
||||
|
||||
if (AccessibleItemPtr focusedElement = dummyAccRoot->focusedElement().lock()) {
|
||||
accRoot->updateStaffInfo(m_accessible, focusedElement);
|
||||
}
|
||||
|
||||
dummyAccRoot->setFocusedElement(nullptr);
|
||||
}
|
||||
|
||||
if (dummyAccRoot && currAccRoot == dummyAccRoot && dummyAccRoot->registered()) {
|
||||
dummyAccRoot->setFocusedElement(m_accessible);
|
||||
|
||||
if (AccessibleItemPtr focusedElement = accRoot->focusedElement().lock()) {
|
||||
dummyAccRoot->updateStaffInfo(m_accessible, focusedElement);
|
||||
}
|
||||
|
||||
accRoot->setFocusedElement(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef ENGRAVING_NO_ACCESSIBILITY
|
||||
void EngravingItem::initAccessibleIfNeed()
|
||||
{
|
||||
#ifndef ENGRAVING_NO_ACCESSIBILITY
|
||||
if (!engravingConfiguration()->isAccessibleEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
@ -2685,12 +2653,10 @@ void EngravingItem::initAccessibleIfNeed()
|
|||
}
|
||||
|
||||
doInitAccessible();
|
||||
#endif
|
||||
}
|
||||
|
||||
void EngravingItem::doInitAccessible()
|
||||
{
|
||||
#ifndef ENGRAVING_NO_ACCESSIBILITY
|
||||
EngravingItemList parents;
|
||||
auto parent = parentItem(false /*not explicit*/);
|
||||
while (parent) {
|
||||
|
@ -2703,9 +2669,10 @@ void EngravingItem::doInitAccessible()
|
|||
}
|
||||
|
||||
setupAccessible();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // ENGRAVING_NO_ACCESSIBILITY
|
||||
|
||||
KerningType EngravingItem::computeKerningType(const EngravingItem* nextItem) const
|
||||
{
|
||||
if (_userSetKerning != KerningType::NOT_SET) {
|
||||
|
|
|
@ -532,7 +532,9 @@ public:
|
|||
|
||||
#ifndef ENGRAVING_NO_ACCESSIBILITY
|
||||
AccessibleItemPtr accessible() const;
|
||||
void initAccessibleIfNeed();
|
||||
#endif
|
||||
|
||||
virtual String accessibleInfo() const;
|
||||
virtual String screenReaderInfo() const { return accessibleInfo(); }
|
||||
// if the screen-reader needs a special string (see note for example)
|
||||
|
@ -563,10 +565,8 @@ public:
|
|||
std::vector<Spanner*>& endingSpanners() { return _endingSpanners; }
|
||||
|
||||
private:
|
||||
void initAccessibleIfNeed();
|
||||
void doInitAccessible();
|
||||
|
||||
#ifndef ENGRAVING_NO_ACCESSIBILITY
|
||||
void doInitAccessible();
|
||||
AccessibleItemPtr m_accessible;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -186,6 +186,20 @@ void EngravingObject::moveToDummy()
|
|||
void EngravingObject::setScore(Score* s)
|
||||
{
|
||||
doSetScore(s);
|
||||
|
||||
if (!m_parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_parent->score() == s) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_parent->isType(ElementType::DUMMY)) {
|
||||
moveToDummy();
|
||||
} else if (m_parent->isType(ElementType::SCORE)) {
|
||||
setParent(s);
|
||||
}
|
||||
}
|
||||
|
||||
void EngravingObject::addChild(EngravingObject* o)
|
||||
|
|
|
@ -853,6 +853,7 @@ bool Harmony::isEditAllowed(EditData& ed) const
|
|||
}
|
||||
|
||||
if (ed.key == Key_Return || ed.key == Key_Enter) {
|
||||
// This "edit" is actually handled in NotationInteraction::editElement
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -869,11 +870,6 @@ bool Harmony::edit(EditData& ed)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (ed.key == Key_Return || ed.key == Key_Enter) {
|
||||
endEdit(ed);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rv = TextBase::edit(ed);
|
||||
|
||||
// layout as text, without position reset
|
||||
|
|
|
@ -413,6 +413,10 @@ void Image::read(XmlReader& e)
|
|||
|
||||
bool Image::load(const io::path_t& ss)
|
||||
{
|
||||
if (ss.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
io::path_t path(ss);
|
||||
// if file path is relative, prepend score path
|
||||
FileInfo fi(path);
|
||||
|
|
|
@ -1779,6 +1779,16 @@ void Instrument::setTrait(const Trait& trait)
|
|||
_trait = trait;
|
||||
}
|
||||
|
||||
bool Instrument::isPrimary() const
|
||||
{
|
||||
return _isPrimary;
|
||||
}
|
||||
|
||||
void Instrument::setIsPrimary(bool isPrimary)
|
||||
{
|
||||
_isPrimary = isPrimary;
|
||||
}
|
||||
|
||||
void Instrument::updateInstrumentId()
|
||||
{
|
||||
if (_instrumentId.isEmpty()) {
|
||||
|
|
|
@ -335,6 +335,7 @@ class Instrument
|
|||
bool _singleNoteDynamics = false;
|
||||
|
||||
Trait _trait;
|
||||
bool _isPrimary = false;
|
||||
|
||||
public:
|
||||
Instrument(String id = String());
|
||||
|
@ -429,6 +430,9 @@ public:
|
|||
Trait trait() const;
|
||||
void setTrait(const Trait& trait);
|
||||
|
||||
bool isPrimary() const;
|
||||
void setIsPrimary(bool isPrimary);
|
||||
|
||||
void updateInstrumentId();
|
||||
|
||||
bool singleNoteDynamics() const { return _singleNoteDynamics; }
|
||||
|
|
|
@ -981,6 +981,15 @@ PointF SLine::linePos(Grip grip, System** sys) const
|
|||
x += cr->segment()->pos().x() + m->pos().x();
|
||||
} else {
|
||||
Segment* segment = (grip == Grip::START) ? startSegment() : endSegment();
|
||||
if (grip == Grip::END && segment && segment->rtick().ticks() == 0) {
|
||||
// The line should end on the left-most segment at this tick. If endSegment() is the first of
|
||||
// the measure, we need to look back for other segments (eg endBarLine) in the prev measure
|
||||
Segment* prevSegment = segment->prev1();
|
||||
while (prevSegment && prevSegment->tick() == segment->tick()) {
|
||||
segment = prevSegment;
|
||||
prevSegment = segment->prev1();
|
||||
}
|
||||
}
|
||||
if (segment) {
|
||||
m = segment->measure();
|
||||
if (m->mmRest()) {
|
||||
|
|
|
@ -193,6 +193,12 @@ void MasterScore::updateRepeatListTempo()
|
|||
_repeatList2->updateTempo();
|
||||
}
|
||||
|
||||
void MasterScore::updateRepeatList()
|
||||
{
|
||||
_repeatList->update(MScore::playRepeats);
|
||||
_repeatList2->update(false);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// repeatList
|
||||
//---------------------------------------------------------
|
||||
|
|
|
@ -161,6 +161,7 @@ public:
|
|||
void setExpandRepeats(bool expandRepeats);
|
||||
bool expandRepeats() const { return _expandRepeats; }
|
||||
void updateRepeatListTempo();
|
||||
void updateRepeatList();
|
||||
const RepeatList& repeatList() const override;
|
||||
const RepeatList& repeatList2() const override;
|
||||
|
||||
|
|
|
@ -681,8 +681,12 @@ int MeasureBase::index() const
|
|||
{
|
||||
int idx = 0;
|
||||
MeasureBase* m = score()->first();
|
||||
Measure* mmRestFirst = nullptr;
|
||||
if (isMeasure() && toMeasure(this)->isMMRest()) {
|
||||
mmRestFirst = toMeasure(this)->mmRestFirst();
|
||||
}
|
||||
while (m) {
|
||||
if (m == this) {
|
||||
if (m == this || m == mmRestFirst) {
|
||||
return idx;
|
||||
}
|
||||
m = m->next();
|
||||
|
|
|
@ -125,4 +125,38 @@ void MScore::registerUiTypes()
|
|||
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string MScore::errorToString(MsError err)
|
||||
{
|
||||
switch (err) {
|
||||
case MsError::MS_NO_ERROR: return "MS_NO_ERROR";
|
||||
case MsError::NO_NOTE_SELECTED: return "NO_NOTE_SELECTED";
|
||||
case MsError::NO_CHORD_REST_SELECTED: return "NO_CHORD_REST_SELECTED";
|
||||
case MsError::NO_LYRICS_SELECTED: return "NO_LYRICS_SELECTED";
|
||||
case MsError::NO_NOTE_REST_SELECTED: return "NO_NOTE_REST_SELECTED";
|
||||
case MsError::NO_FLIPPABLE_SELECTED: return "NO_FLIPPABLE_SELECTED";
|
||||
case MsError::NO_STAFF_SELECTED: return "NO_STAFF_SELECTED";
|
||||
case MsError::NO_NOTE_FIGUREDBASS_SELECTED: return "NO_NOTE_FIGUREDBASS_SELECTED";
|
||||
case MsError::CANNOT_INSERT_TUPLET: return "CANNOT_INSERT_TUPLET";
|
||||
case MsError::CANNOT_SPLIT_TUPLET: return "CANNOT_SPLIT_TUPLET";
|
||||
case MsError::CANNOT_SPLIT_MEASURE_FIRST_BEAT: return "CANNOT_SPLIT_MEASURE_FIRST_BEAT";
|
||||
case MsError::CANNOT_SPLIT_MEASURE_TUPLET: return "CANNOT_SPLIT_MEASURE_TUPLET";
|
||||
case MsError::INSUFFICIENT_MEASURES: return "INSUFFICIENT_MEASURES";
|
||||
case MsError::CANNOT_SPLIT_MEASURE_REPEAT: return "CANNOT_SPLIT_MEASURE_REPEAT";
|
||||
case MsError::CANNOT_SPLIT_MEASURE_TOO_SHORT: return "CANNOT_SPLIT_MEASURE_TOO_SHORT";
|
||||
case MsError::CANNOT_REMOVE_TIME_TUPLET: return "CANNOT_REMOVE_TIME_TUPLET";
|
||||
case MsError::CANNOT_REMOVE_TIME_MEASURE_REPEAT: return "CANNOT_REMOVE_TIME_MEASURE_REPEAT";
|
||||
case MsError::NO_DEST: return "NO_DEST";
|
||||
case MsError::DEST_TUPLET: return "DEST_TUPLET";
|
||||
case MsError::TUPLET_CROSSES_BAR: return "TUPLET_CROSSES_BAR";
|
||||
case MsError::DEST_LOCAL_TIME_SIGNATURE: return "DEST_LOCAL_TIME_SIGNATURE";
|
||||
case MsError::DEST_TREMOLO: return "DEST_TREMOLO";
|
||||
case MsError::NO_MIME: return "NO_MIME";
|
||||
case MsError::DEST_NO_CR: return "DEST_NO_CR";
|
||||
case MsError::CANNOT_CHANGE_LOCAL_TIMESIG: return "CANNOT_CHANGE_LOCAL_TIMESIG";
|
||||
case MsError::CORRUPTED_MEASURE: return "CORRUPTED_MEASURE";
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -280,6 +280,8 @@ public:
|
|||
static double horizontalPageGapOdd;
|
||||
|
||||
static void setError(MsError e) { _error = e; }
|
||||
|
||||
static std::string errorToString(MsError err);
|
||||
};
|
||||
} // namespace mu::engraving
|
||||
|
||||
|
|
|
@ -1708,7 +1708,7 @@ bool Note::readProperties(XmlReader& e)
|
|||
}
|
||||
} else if (tag == "offset") {
|
||||
EngravingItem::readProperties(e);
|
||||
} else if (tag == "ChordLine") {
|
||||
} else if (tag == "ChordLine" && chord()) {
|
||||
ChordLine* cl = Factory::createChordLine(chord());
|
||||
cl->setNote(this);
|
||||
cl->read(e);
|
||||
|
|
|
@ -332,13 +332,14 @@ Note* Score::addPitch(NoteVal& nval, bool addFlag, InputState* externalInputStat
|
|||
// mouse click in state NoteType::ENTRY
|
||||
//---------------------------------------------------------
|
||||
|
||||
void Score::putNote(const PointF& pos, bool replace, bool insert)
|
||||
Ret Score::putNote(const PointF& pos, bool replace, bool insert)
|
||||
{
|
||||
Position p;
|
||||
if (!getPosition(&p, pos, _is.voice())) {
|
||||
LOGD("cannot put note here, get position failed");
|
||||
return;
|
||||
return make_ret(Ret::Code::UnknownError);
|
||||
}
|
||||
|
||||
Score* score = p.segment->score();
|
||||
// it is not safe to call Score::repitchNote() if p is on a TAB staff
|
||||
bool isTablature = staff(p.staffIdx)->isTabStaff(p.segment->tick());
|
||||
|
@ -351,17 +352,19 @@ void Score::putNote(const PointF& pos, bool replace, bool insert)
|
|||
p.line -= stepOffset + 2 * stYOffset / lineDist;
|
||||
|
||||
if (score->inputState().usingNoteEntryMethod(NoteEntryMethod::REPITCH) && !isTablature) {
|
||||
score->repitchNote(p, replace);
|
||||
return score->repitchNote(p, replace);
|
||||
} else {
|
||||
if (insert || score->inputState().usingNoteEntryMethod(NoteEntryMethod::TIMEWISE)) {
|
||||
score->insertChord(p);
|
||||
return score->insertChord(p);
|
||||
} else {
|
||||
score->putNote(p, replace);
|
||||
return score->putNote(p, replace);
|
||||
}
|
||||
}
|
||||
|
||||
return make_ok();
|
||||
}
|
||||
|
||||
void Score::putNote(const Position& p, bool replace)
|
||||
Ret Score::putNote(const Position& p, bool replace)
|
||||
{
|
||||
Staff* st = staff(p.staffIdx);
|
||||
Segment* s = p.segment;
|
||||
|
@ -373,15 +376,15 @@ void Score::putNote(const Position& p, bool replace)
|
|||
const TracksMap& tracks = excerpt->tracksMapping();
|
||||
|
||||
if (!tracks.empty() && mu::key(tracks, _is.track(), mu::nidx) == mu::nidx) {
|
||||
return;
|
||||
return make_ret(Ret::Code::UnknownError);
|
||||
}
|
||||
}
|
||||
|
||||
DirectionV stemDirection = DirectionV::AUTO;
|
||||
bool error;
|
||||
bool error = false;
|
||||
NoteVal nval = noteValForPosition(p, _is.accidentalType(), error);
|
||||
if (error) {
|
||||
return;
|
||||
return make_ret(Ret::Code::UnknownError);
|
||||
}
|
||||
|
||||
// warn and delete MeasureRepeat if necessary
|
||||
|
@ -393,8 +396,9 @@ void Score::putNote(const Position& p, bool replace)
|
|||
" If you enter notes here, it will be deleted."
|
||||
" Do you want to continue?"));
|
||||
if (b == MessageBox::Cancel) {
|
||||
return;
|
||||
return make_ret(Ret::Code::Cancel);
|
||||
}
|
||||
|
||||
Score::deleteItem(m->measureRepeatElement(staffIdx));
|
||||
}
|
||||
|
||||
|
@ -454,7 +458,7 @@ void Score::putNote(const Position& p, bool replace)
|
|||
int tpc2 = note->tpc2default(nval.pitch);
|
||||
undoChangeFretting(note, nval.pitch, nval.string, nval.fret, tpc1, tpc2);
|
||||
setPlayNote(true);
|
||||
return;
|
||||
return make_ok();
|
||||
}
|
||||
}
|
||||
} else { // not TAB
|
||||
|
@ -465,7 +469,7 @@ void Score::putNote(const Position& p, bool replace)
|
|||
if (chord->notes().size() > 1) {
|
||||
undoRemoveElement(note);
|
||||
}
|
||||
return;
|
||||
return make_ok();
|
||||
}
|
||||
}
|
||||
addToChord = true; // if no special case, add note to chord
|
||||
|
@ -476,31 +480,45 @@ void Score::putNote(const Position& p, bool replace)
|
|||
NoteVal nval2 = noteValForPosition(p, AccidentalType::NONE, error);
|
||||
forceAccidental = (nval.pitch == nval2.pitch);
|
||||
}
|
||||
|
||||
Ret ret = make_ok();
|
||||
|
||||
if (addToChord && cr->isChord()) {
|
||||
// if adding, add!
|
||||
addNote(toChord(cr), nval, forceAccidental, _is.articulationIds());
|
||||
Note* note = addNote(toChord(cr), nval, forceAccidental, _is.articulationIds());
|
||||
if (!note) {
|
||||
ret = make_ret(Ret::Code::UnknownError);
|
||||
}
|
||||
|
||||
_is.setAccidentalType(AccidentalType::NONE);
|
||||
return;
|
||||
return ret;
|
||||
} else {
|
||||
// if not adding, replace current chord (or create a new one)
|
||||
|
||||
if (_is.rest()) {
|
||||
nval.pitch = -1;
|
||||
}
|
||||
setNoteRest(_is.segment(), _is.track(), nval, _is.duration().fraction(), stemDirection, forceAccidental, _is.articulationIds());
|
||||
|
||||
Segment* seg = setNoteRest(_is.segment(), _is.track(), nval,
|
||||
_is.duration().fraction(), stemDirection, forceAccidental, _is.articulationIds());
|
||||
if (!seg) {
|
||||
ret = make_ret(Ret::Code::UnknownError);
|
||||
}
|
||||
|
||||
_is.setAccidentalType(AccidentalType::NONE);
|
||||
}
|
||||
|
||||
if (cr && !st->isTabStaff(cr->tick())) {
|
||||
_is.moveToNextInputPos();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// repitchNote
|
||||
//---------------------------------------------------------
|
||||
|
||||
void Score::repitchNote(const Position& p, bool replace)
|
||||
Ret Score::repitchNote(const Position& p, bool replace)
|
||||
{
|
||||
Segment* s = p.segment;
|
||||
Fraction tick = s->tick();
|
||||
|
@ -516,7 +534,7 @@ void Score::repitchNote(const Position& p, bool replace)
|
|||
AccidentalVal acci
|
||||
= (at == AccidentalType::NONE ? s->measure()->findAccidental(s, p.staffIdx, p.line, error) : Accidental::subtype2value(at));
|
||||
if (error) {
|
||||
return;
|
||||
return make_ret(Ret::Code::UnknownError);
|
||||
}
|
||||
|
||||
int step = absStep(p.line, clef);
|
||||
|
@ -532,7 +550,7 @@ void Score::repitchNote(const Position& p, bool replace)
|
|||
}
|
||||
|
||||
if (!_is.segment()) {
|
||||
return;
|
||||
return make_ret(Ret::Code::UnknownError);
|
||||
}
|
||||
|
||||
Chord* chord;
|
||||
|
@ -540,7 +558,7 @@ void Score::repitchNote(const Position& p, bool replace)
|
|||
if (!cr) {
|
||||
cr = _is.segment()->nextChordRest(_is.track());
|
||||
if (!cr) {
|
||||
return;
|
||||
return make_ret(Ret::Code::UnknownError);
|
||||
}
|
||||
}
|
||||
if (cr->isRest()) { //skip rests
|
||||
|
@ -551,7 +569,7 @@ void Score::repitchNote(const Position& p, bool replace)
|
|||
if (next) {
|
||||
_is.moveInputPos(next->segment());
|
||||
}
|
||||
return;
|
||||
return make_ok();
|
||||
} else {
|
||||
chord = toChord(cr);
|
||||
}
|
||||
|
@ -641,13 +659,15 @@ void Score::repitchNote(const Position& p, bool replace)
|
|||
if (next) {
|
||||
_is.moveInputPos(next->segment());
|
||||
}
|
||||
|
||||
return make_ok();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// insertChord
|
||||
//---------------------------------------------------------
|
||||
|
||||
void Score::insertChord(const Position& pos)
|
||||
Ret Score::insertChord(const Position& pos)
|
||||
{
|
||||
// insert
|
||||
// TODO:
|
||||
|
@ -656,18 +676,20 @@ void Score::insertChord(const Position& pos)
|
|||
|
||||
EngravingItem* el = selection().element();
|
||||
if (!el || !(el->isNote() || el->isRest())) {
|
||||
return;
|
||||
return make_ret(Ret::Code::UnknownError);
|
||||
}
|
||||
Segment* seg = pos.segment;
|
||||
if (seg->splitsTuplet()) {
|
||||
MScore::setError(MsError::CANNOT_INSERT_TUPLET);
|
||||
return;
|
||||
return make_ret(Ret::Code::UnknownError);
|
||||
}
|
||||
if (_is.insertMode()) {
|
||||
globalInsertChord(pos);
|
||||
} else {
|
||||
localInsertChord(pos);
|
||||
}
|
||||
|
||||
return make_ok();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
|
|
@ -42,6 +42,7 @@ using namespace mu;
|
|||
using namespace mu::engraving;
|
||||
|
||||
namespace mu::engraving {
|
||||
const Fraction Part::MAIN_INSTRUMENT_TICK = Fraction(-1, 1);
|
||||
//---------------------------------------------------------
|
||||
// Part
|
||||
//---------------------------------------------------------
|
||||
|
@ -62,7 +63,7 @@ Part::Part(Score* s)
|
|||
|
||||
void Part::initFromInstrTemplate(const InstrumentTemplate* t)
|
||||
{
|
||||
_partName = t->trackName;
|
||||
_partName = !t->longNames.empty() ? t->longNames.front().name() : t->trackName;
|
||||
setInstrument(Instrument::fromTemplate(t));
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,8 @@ class Part final : public EngravingObject
|
|||
friend class compat::Read206;
|
||||
|
||||
public:
|
||||
static const Fraction MAIN_INSTRUMENT_TICK;
|
||||
|
||||
Part(Score* score = nullptr);
|
||||
void initFromInstrTemplate(const InstrumentTemplate*);
|
||||
|
||||
|
|
|
@ -834,10 +834,10 @@ void RepeatList::unwind()
|
|||
activeVolta = nullptr;
|
||||
// Start next rs on the following measure
|
||||
Measure const* const possibleNextMeasure = (*repeatListElementIt)->measure->nextMeasure();
|
||||
rs = new RepeatSegment(playbackCount);
|
||||
if (possibleNextMeasure == nullptr) {
|
||||
rs = nullptr; // end of score, but will still encounter section break, notify it
|
||||
// end of score, but will still encounter section break, notify it
|
||||
} else {
|
||||
rs = new RepeatSegment(playbackCount);
|
||||
rs->addMeasure(possibleNextMeasure);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,6 +93,11 @@
|
|||
#include "undo.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifndef ENGRAVING_NO_ACCESSIBILITY
|
||||
#include "accessibility/accessibleitem.h"
|
||||
#include "accessibility/accessibleroot.h"
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "log.h"
|
||||
|
@ -109,6 +114,30 @@ bool noMidi = false;
|
|||
bool midiInputTrace = false;
|
||||
bool midiOutputTrace = false;
|
||||
|
||||
static void markInstrumentsAsPrimary(std::vector<Part*>& parts)
|
||||
{
|
||||
TRACEFUNC;
|
||||
|
||||
std::unordered_map<String /*instrumentId*/, int /*count*/> instrumentCount;
|
||||
|
||||
for (Part* part : parts) {
|
||||
Instrument* instrument = part->instrument();
|
||||
if (!instrument) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto it = instrumentCount.find(instrument->id());
|
||||
if (it == instrumentCount.cend()) {
|
||||
it = instrumentCount.insert(instrumentCount.begin(), { instrument->id(), 0 });
|
||||
}
|
||||
|
||||
it->second++;
|
||||
|
||||
bool isPrimary = (it->second % 2 != 0);
|
||||
instrument->setIsPrimary(isPrimary);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// MeasureBaseList
|
||||
//---------------------------------------------------------
|
||||
|
@ -383,9 +412,6 @@ Score::~Score()
|
|||
m = nm;
|
||||
}
|
||||
|
||||
for (auto it = _spanner.cbegin(); it != _spanner.cend(); ++it) {
|
||||
delete it->second;
|
||||
}
|
||||
_spanner.clear();
|
||||
|
||||
DeleteAll(_parts);
|
||||
|
@ -457,6 +483,19 @@ bool Score::isPaletteScore() const
|
|||
return this == gpaletteScore;
|
||||
}
|
||||
|
||||
static void onBracketItemDestruction(const Score* score, const BracketItem* item)
|
||||
{
|
||||
BracketItem* dummy = score->dummy()->bracketItem();
|
||||
|
||||
for (const System* system : score->systems()) {
|
||||
for (Bracket* bracket : system->brackets()) {
|
||||
if (bracket && bracket->bracketItem() == item) {
|
||||
bracket->setBracketItem(dummy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Score::onElementDestruction
|
||||
// Ensure correct state of the score after destruction
|
||||
|
@ -472,6 +511,10 @@ void Score::onElementDestruction(EngravingItem* e)
|
|||
return;
|
||||
}
|
||||
|
||||
if (e->isBracketItem()) {
|
||||
onBracketItemDestruction(score, toBracketItem(e));
|
||||
}
|
||||
|
||||
score->selection().remove(e);
|
||||
score->cmdState().unsetElement(e);
|
||||
score->elementDestroyed().send(e);
|
||||
|
@ -2501,6 +2544,7 @@ void Score::insertPart(Part* part, staff_idx_t idx)
|
|||
bool inserted = false;
|
||||
staff_idx_t staff = 0;
|
||||
|
||||
part->setScore(this);
|
||||
assignIdIfNeed(*part);
|
||||
|
||||
for (auto i = _parts.begin(); i != _parts.end(); ++i) {
|
||||
|
@ -2516,6 +2560,7 @@ void Score::insertPart(Part* part, staff_idx_t idx)
|
|||
}
|
||||
masterScore()->rebuildMidiMapping();
|
||||
setInstrumentsChanged(true);
|
||||
markInstrumentsAsPrimary(_parts);
|
||||
}
|
||||
|
||||
void Score::appendPart(Part* part)
|
||||
|
@ -2524,8 +2569,10 @@ void Score::appendPart(Part* part)
|
|||
return;
|
||||
}
|
||||
|
||||
part->setScore(this);
|
||||
assignIdIfNeed(*part);
|
||||
_parts.push_back(part);
|
||||
markInstrumentsAsPrimary(_parts);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
@ -2546,6 +2593,7 @@ void Score::removePart(Part* part)
|
|||
}
|
||||
|
||||
_parts.erase(_parts.begin() + index);
|
||||
markInstrumentsAsPrimary(_parts);
|
||||
|
||||
if (_excerpt) {
|
||||
for (Part* excerptPart : _excerpt->parts()) {
|
||||
|
@ -2554,6 +2602,7 @@ void Score::removePart(Part* part)
|
|||
}
|
||||
|
||||
mu::remove(_excerpt->parts(), excerptPart);
|
||||
markInstrumentsAsPrimary(_excerpt->parts());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2992,6 +3041,7 @@ void Score::sortStaves(std::vector<staff_idx_t>& dst)
|
|||
}
|
||||
}
|
||||
setLayoutAll();
|
||||
markInstrumentsAsPrimary(_parts);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
@ -3324,6 +3374,58 @@ void Score::padToggle(Pad p, const EditData& ed)
|
|||
}
|
||||
}
|
||||
|
||||
static void onFocusedItemChanged(EngravingItem* item)
|
||||
{
|
||||
#ifndef ENGRAVING_NO_ACCESSIBILITY
|
||||
if (!item || !item->selected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (item->isSpannerSegment()) {
|
||||
item = toSpannerSegment(item)->spanner();
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item->initAccessibleIfNeed();
|
||||
|
||||
AccessibleItemPtr accessible = item->accessible();
|
||||
if (!accessible) {
|
||||
return;
|
||||
}
|
||||
|
||||
const Score* score = item->score();
|
||||
if (!score) {
|
||||
return;
|
||||
}
|
||||
|
||||
AccessibleRoot* currAccRoot = accessible->accessibleRoot();
|
||||
AccessibleRoot* accRoot = score->rootItem()->accessible()->accessibleRoot();
|
||||
AccessibleRoot* dummyAccRoot = score->dummy()->rootItem()->accessible()->accessibleRoot();
|
||||
|
||||
if (accRoot && currAccRoot == accRoot && accRoot->registered()) {
|
||||
accRoot->setFocusedElement(accessible);
|
||||
|
||||
if (AccessibleItemPtr focusedElement = dummyAccRoot->focusedElement().lock()) {
|
||||
accRoot->updateStaffInfo(accessible, focusedElement);
|
||||
}
|
||||
|
||||
dummyAccRoot->setFocusedElement(nullptr);
|
||||
}
|
||||
|
||||
if (dummyAccRoot && currAccRoot == dummyAccRoot && dummyAccRoot->registered()) {
|
||||
dummyAccRoot->setFocusedElement(accessible);
|
||||
|
||||
if (AccessibleItemPtr focusedElement = accRoot->focusedElement().lock()) {
|
||||
dummyAccRoot->updateStaffInfo(accessible, focusedElement);
|
||||
}
|
||||
|
||||
accRoot->setFocusedElement(nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// deselect
|
||||
//---------------------------------------------------------
|
||||
|
@ -3341,7 +3443,23 @@ void Score::deselect(EngravingItem* el)
|
|||
// staffIdx is valid, if element is of type MEASURE
|
||||
//---------------------------------------------------------
|
||||
|
||||
void Score::select(EngravingItem* e, SelectType type, staff_idx_t staffIdx)
|
||||
void Score::select(EngravingItem* item, SelectType type, staff_idx_t staffIdx)
|
||||
{
|
||||
select(std::vector<EngravingItem*> { item }, type, staffIdx);
|
||||
}
|
||||
|
||||
void Score::select(const std::vector<EngravingItem*>& items, SelectType type, staff_idx_t staffIdx)
|
||||
{
|
||||
for (EngravingItem* item : items) {
|
||||
doSelect(item, type, staffIdx);
|
||||
}
|
||||
|
||||
if (!_selection.elements().empty()) {
|
||||
onFocusedItemChanged(_selection.elements().back());
|
||||
}
|
||||
}
|
||||
|
||||
void Score::doSelect(EngravingItem* e, SelectType type, staff_idx_t staffIdx)
|
||||
{
|
||||
// Move the playhead to the selected element's preferred play position.
|
||||
if (e) {
|
||||
|
@ -3386,7 +3504,7 @@ void Score::selectSingle(EngravingItem* e, staff_idx_t staffIdx)
|
|||
setUpdateAll();
|
||||
} else {
|
||||
if (e->isMeasure()) {
|
||||
select(e, SelectType::RANGE, staffIdx);
|
||||
doSelect(e, SelectType::RANGE, staffIdx);
|
||||
return;
|
||||
}
|
||||
addRefresh(e->abbox());
|
||||
|
@ -3428,7 +3546,7 @@ void Score::selectAdd(EngravingItem* e)
|
|||
SelState selState = _selection.state();
|
||||
|
||||
if (_selection.isRange()) {
|
||||
select(e, SelectType::SINGLE, 0);
|
||||
doSelect(e, SelectType::SINGLE, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3542,7 +3660,7 @@ void Score::selectRange(EngravingItem* e, staff_idx_t staffIdx)
|
|||
_selection.setRange(ocr->segment(), endSeg, oe->staffIdx(), oe->staffIdx() + 1);
|
||||
_selection.extendRangeSelection(cr);
|
||||
} else {
|
||||
select(e, SelectType::SINGLE, 0);
|
||||
doSelect(e, SelectType::SINGLE, 0);
|
||||
return;
|
||||
}
|
||||
} else if (_selection.isRange()) {
|
||||
|
@ -3600,7 +3718,7 @@ void Score::selectRange(EngravingItem* e, staff_idx_t staffIdx)
|
|||
}
|
||||
}
|
||||
}
|
||||
select(e, SelectType::SINGLE, staffIdx);
|
||||
doSelect(e, SelectType::SINGLE, staffIdx);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3761,9 +3879,7 @@ void Score::selectSimilar(EngravingItem* e, bool sameStaff)
|
|||
score->scanElements(&pattern, collectMatch);
|
||||
|
||||
score->select(0, SelectType::SINGLE, 0);
|
||||
for (EngravingItem* ee : pattern.el) {
|
||||
score->select(ee, SelectType::ADD, 0);
|
||||
}
|
||||
score->select(pattern.el, SelectType::ADD, 0);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
@ -3796,9 +3912,7 @@ void Score::selectSimilarInRange(EngravingItem* e)
|
|||
score->scanElementsInRange(&pattern, collectMatch);
|
||||
|
||||
score->select(0, SelectType::SINGLE, 0);
|
||||
for (EngravingItem* ee : pattern.el) {
|
||||
score->select(ee, SelectType::ADD, 0);
|
||||
}
|
||||
score->select(pattern.el, SelectType::ADD, 0);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
@ -3925,14 +4039,18 @@ void Score::lassoSelect(const RectF& bbox)
|
|||
break;
|
||||
}
|
||||
|
||||
std::vector<EngravingItem*> el = page->items(frr);
|
||||
for (EngravingItem* e : el) {
|
||||
if (frr.contains(e->abbox())) {
|
||||
if (e->type() != ElementType::MEASURE && e->selectable()) {
|
||||
select(e, SelectType::ADD, 0);
|
||||
std::vector<EngravingItem*> items = page->items(frr);
|
||||
std::vector<EngravingItem*> itemsToSelect;
|
||||
|
||||
for (EngravingItem* item : items) {
|
||||
if (frr.contains(item->abbox())) {
|
||||
if (item->type() != ElementType::MEASURE && item->selectable()) {
|
||||
itemsToSelect.push_back(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
select(itemsToSelect, SelectType::ADD, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3940,7 +4058,7 @@ void Score::lassoSelect(const RectF& bbox)
|
|||
// lassoSelectEnd
|
||||
//---------------------------------------------------------
|
||||
|
||||
void Score::lassoSelectEnd(bool convertToRange)
|
||||
void Score::lassoSelectEnd()
|
||||
{
|
||||
int noteRestCount = 0;
|
||||
Segment* startSegment = 0;
|
||||
|
@ -3956,11 +4074,6 @@ void Score::lassoSelectEnd(bool convertToRange)
|
|||
}
|
||||
_selection.setState(SelState::LIST);
|
||||
|
||||
if (!convertToRange) {
|
||||
setUpdateAll();
|
||||
return;
|
||||
}
|
||||
|
||||
for (const EngravingItem* e : _selection.elements()) {
|
||||
if (e->type() != ElementType::NOTE && e->type() != ElementType::REST) {
|
||||
continue;
|
||||
|
@ -5198,9 +5311,8 @@ void Score::changeSelectedNotesVoice(voice_idx_t voice)
|
|||
if (!el.empty()) {
|
||||
selection().clear();
|
||||
}
|
||||
for (EngravingItem* e : el) {
|
||||
select(e, SelectType::ADD, mu::nidx);
|
||||
}
|
||||
|
||||
select(el, SelectType::ADD, mu::nidx);
|
||||
setLayoutAll();
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "async/channel.h"
|
||||
#include "io/iodevice.h"
|
||||
#include "types/ret.h"
|
||||
|
||||
#include "modularity/ioc.h"
|
||||
#include "draw/iimageprovider.h"
|
||||
|
@ -459,13 +460,14 @@ private:
|
|||
std::list<Fraction> splitGapToMeasureBoundaries(ChordRest*, Fraction);
|
||||
void pasteChordRest(ChordRest* cr, const Fraction& tick, const Interval&);
|
||||
|
||||
void doSelect(EngravingItem* e, SelectType type, staff_idx_t staffIdx);
|
||||
void selectSingle(EngravingItem* e, staff_idx_t staffIdx);
|
||||
void selectAdd(EngravingItem* e);
|
||||
void selectRange(EngravingItem* e, staff_idx_t staffIdx);
|
||||
|
||||
void cmdToggleVisible();
|
||||
|
||||
void putNote(const Position&, bool replace);
|
||||
Ret putNote(const Position&, bool replace);
|
||||
|
||||
void resetTempo();
|
||||
void resetTempoRange(const Fraction& tick1, const Fraction& tick2);
|
||||
|
@ -732,14 +734,14 @@ public:
|
|||
void cmdDeleteSelection();
|
||||
void cmdFullMeasureRest();
|
||||
|
||||
void putNote(const mu::PointF&, bool replace, bool insert);
|
||||
void insertChord(const Position&);
|
||||
Ret putNote(const mu::PointF&, bool replace, bool insert);
|
||||
Ret insertChord(const Position&);
|
||||
void localInsertChord(const Position&);
|
||||
void globalInsertChord(const Position&);
|
||||
|
||||
void cloneVoice(track_idx_t strack, track_idx_t dtrack, Segment* sf, const Fraction& lTick, bool link = true, bool spanner = true);
|
||||
|
||||
void repitchNote(const Position& pos, bool replace);
|
||||
Ret repitchNote(const Position& pos, bool replace);
|
||||
void regroupNotesAndRests(const Fraction& startTick, const Fraction& endTick, track_idx_t track);
|
||||
bool checkTimeDelete(Segment*, Segment*);
|
||||
void timeDelete(Measure*, Segment*, const Fraction&);
|
||||
|
@ -808,7 +810,8 @@ public:
|
|||
std::set<ChordRest*> getSelectedChordRests() const;
|
||||
void getSelectedChordRest2(ChordRest** cr1, ChordRest** cr2) const;
|
||||
|
||||
void select(EngravingItem* obj, SelectType = SelectType::SINGLE, staff_idx_t staff = 0);
|
||||
void select(EngravingItem* item, SelectType = SelectType::SINGLE, staff_idx_t staff = 0);
|
||||
void select(const std::vector<EngravingItem*>& items, SelectType = SelectType::SINGLE, staff_idx_t staff = 0);
|
||||
void selectSimilar(EngravingItem* e, bool sameStaff);
|
||||
void selectSimilarInRange(EngravingItem* e);
|
||||
static void collectMatch(void* data, EngravingItem* e);
|
||||
|
@ -967,7 +970,7 @@ public:
|
|||
void setBracketsAndBarlines();
|
||||
|
||||
void lassoSelect(const mu::RectF&);
|
||||
void lassoSelectEnd(bool);
|
||||
void lassoSelectEnd();
|
||||
|
||||
Page* searchPage(const mu::PointF&) const;
|
||||
std::vector<System*> searchSystem(const mu::PointF& p, const System* preferredSystem = nullptr, double spacingFactor = 0.5,
|
||||
|
@ -1160,7 +1163,9 @@ public:
|
|||
void setNoteHeadWidth(double n) { _noteHeadWidth = n; }
|
||||
|
||||
std::list<staff_idx_t> uniqueStaves() const;
|
||||
|
||||
void transpositionChanged(Part* part, Interval oldTransposition, Fraction tickStart = { 0, 1 }, Fraction tickEnd = { -1, 1 });
|
||||
void transpositionChanged(Part* part, const Fraction& instrumentTick, Interval oldTransposition);
|
||||
|
||||
void moveUp(ChordRest*);
|
||||
void moveDown(ChordRest*);
|
||||
|
|
|
@ -552,8 +552,8 @@ void Selection::updateSelectedElements()
|
|||
// the first segment for them.
|
||||
return;
|
||||
}
|
||||
if (s2 && s2 == s2->measure()->first()) {
|
||||
s2 = s2->prev1(); // we want the last segment of the previous measure
|
||||
if (s2 && s2 == s2->measure()->first() && !(s2->measure()->prevMeasure() && s2->measure()->prevMeasure()->mmRest1())) {
|
||||
s2 = s2->prev1(); // we want the last segment of the previous measure (unless it's part of a MMrest)
|
||||
}
|
||||
setRange(s1, s2, staffStart, staffEnd);
|
||||
_plannedTick1 = Fraction(-1, 1);
|
||||
|
|
|
@ -44,7 +44,7 @@ class Chord;
|
|||
//---------------------------------------------------------
|
||||
|
||||
struct ElementPattern {
|
||||
std::list<EngravingItem*> el;
|
||||
std::vector<EngravingItem*> el;
|
||||
int type = 0;
|
||||
int subtype = 0;
|
||||
staff_idx_t staffStart = 0;
|
||||
|
|
|
@ -1053,24 +1053,25 @@ void Slur::slurPos(SlurPos* sp)
|
|||
};
|
||||
SlurAnchor sa1 = SlurAnchor::NONE;
|
||||
SlurAnchor sa2 = SlurAnchor::NONE;
|
||||
|
||||
if (sc && sc->hook() && sc->up() == _up) {
|
||||
sa1 = SlurAnchor::STEM;
|
||||
}
|
||||
if (scr->up() == ecr->up() && scr->up() == _up) {
|
||||
if (stem1 && !stemSideStartForBeam()) {
|
||||
if (staffHasStems) {
|
||||
if (sc && sc->hook() && sc->up() == _up) {
|
||||
sa1 = SlurAnchor::STEM;
|
||||
}
|
||||
if (stem2 && !stemSideEndForBeam()) {
|
||||
sa2 = SlurAnchor::STEM;
|
||||
}
|
||||
} else if (ecr->segment()->system() != scr->segment()->system()) {
|
||||
// in the case of continued slurs, we anchor to stem when necessary
|
||||
if (scr->up() == _up && stem1 && !scr->beam()) {
|
||||
sa1 = SlurAnchor::STEM;
|
||||
}
|
||||
if (ecr->up() == _up && stem2 && !ecr->beam()) {
|
||||
sa2 = SlurAnchor::STEM;
|
||||
if (scr->up() == ecr->up() && scr->up() == _up) {
|
||||
if (stem1 && !stemSideStartForBeam()) {
|
||||
sa1 = SlurAnchor::STEM;
|
||||
}
|
||||
if (stem2 && !stemSideEndForBeam()) {
|
||||
sa2 = SlurAnchor::STEM;
|
||||
}
|
||||
} else if (ecr->segment()->system() != scr->segment()->system()) {
|
||||
// in the case of continued slurs, we anchor to stem when necessary
|
||||
if (scr->up() == _up && stem1 && !scr->beam()) {
|
||||
sa1 = SlurAnchor::STEM;
|
||||
}
|
||||
if (ecr->up() == _up && stem2 && !ecr->beam()) {
|
||||
sa2 = SlurAnchor::STEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2094,7 +2095,8 @@ bool Slur::isOverBeams()
|
|||
ChordRest* cr = toChordRest(seg->elist().at(track));
|
||||
bool hasBeam = cr->beam() && cr->up() == up();
|
||||
bool hasTrem = false;
|
||||
if (Chord* c = toChord(cr)) {
|
||||
if (cr->isChord()) {
|
||||
Chord* c = toChord(cr);
|
||||
hasTrem = c->tremolo() && c->tremolo()->twoNotes() && c->up() == up();
|
||||
}
|
||||
if (!(hasBeam || hasTrem)) {
|
||||
|
|
|
@ -399,21 +399,6 @@ Spanner::Spanner(const Spanner& s)
|
|||
}
|
||||
}
|
||||
|
||||
Spanner::~Spanner()
|
||||
{
|
||||
for (SpannerSegment* s : segments) {
|
||||
if (s->parent() == this) {
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
|
||||
for (SpannerSegment* s : unusedSegments) {
|
||||
if (s->parent() == this) {
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// mag
|
||||
//---------------------------------------------------------
|
||||
|
@ -1016,24 +1001,7 @@ Segment* Spanner::startSegment() const
|
|||
|
||||
Segment* Spanner::endSegment() const
|
||||
{
|
||||
Segment* endSeg = score()->tick2leftSegment(tick2());
|
||||
if (!systemFlag()) {
|
||||
return endSeg;
|
||||
}
|
||||
if (endSeg->rtick().ticks() == 0) {
|
||||
// If this is the first segment of the measure, it may not be the left-most segment at this tick.
|
||||
// There could be segments at the end of the previous measure. We nees those for correct layout of system lines.
|
||||
Measure* prevMeas = endSeg->measure()->prevMeasure();
|
||||
if (prevMeas) {
|
||||
for (Segment& s : prevMeas->segments()) {
|
||||
if (s.tick() == tick2()) {
|
||||
endSeg = &s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return endSeg;
|
||||
return score()->tick2leftSegment(tick2());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
@ -1668,6 +1636,10 @@ void SpannerSegment::autoplaceSpannerSegment()
|
|||
sl.add(sh.translated(pos()));
|
||||
double yd = 0.0;
|
||||
staff_idx_t stfIdx = systemFlag() ? staffIdxOrNextVisible() : staffIdx();
|
||||
if (stfIdx == mu::nidx) {
|
||||
_skipDraw = true;
|
||||
return;
|
||||
}
|
||||
if (above) {
|
||||
double d = system()->topDistance(stfIdx, sl);
|
||||
if (d > -md) {
|
||||
|
|
|
@ -186,9 +186,6 @@ protected:
|
|||
const std::vector<SpannerSegment*> spannerSegments() const { return segments; }
|
||||
|
||||
public:
|
||||
|
||||
~Spanner();
|
||||
|
||||
// Score Tree functions
|
||||
virtual EngravingObject* scanParent() const override;
|
||||
virtual EngravingObjectList scanChildren() const override;
|
||||
|
|
|
@ -80,15 +80,6 @@ Staff::Staff(const Staff& staff)
|
|||
_part = staff._part;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// ~Staff
|
||||
//---------------------------------------------------------
|
||||
|
||||
Staff::~Staff()
|
||||
{
|
||||
DeleteAll(brackets());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// clone
|
||||
//---------------------------------------------------------
|
||||
|
|
|
@ -128,9 +128,7 @@ private:
|
|||
void updateVisibilityVoices(Staff* masterStaff, const TracksMap& tracks);
|
||||
|
||||
public:
|
||||
|
||||
Staff* clone() const override;
|
||||
~Staff();
|
||||
|
||||
void init(const InstrumentTemplate*, const StaffType* staffType, int);
|
||||
void initFromStaffType(const StaffType* staffType);
|
||||
|
|
|
@ -914,7 +914,6 @@ void System::layout2(const LayoutContext& ctx)
|
|||
}
|
||||
|
||||
if (visibleStaves.empty()) {
|
||||
LOGD() << "====no visible staves, staves: " << _staves.size() << ", score staves: " << score()->nstaves();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1710,7 +1709,6 @@ staff_idx_t System::firstVisibleSysStaff() const
|
|||
return i;
|
||||
}
|
||||
}
|
||||
LOGD("no sys staff");
|
||||
return mu::nidx;
|
||||
}
|
||||
|
||||
|
@ -1726,7 +1724,6 @@ staff_idx_t System::lastVisibleSysStaff() const
|
|||
return static_cast<staff_idx_t>(i);
|
||||
}
|
||||
}
|
||||
LOGD("no sys staff");
|
||||
return mu::nidx;
|
||||
}
|
||||
|
||||
|
|
|
@ -2293,10 +2293,12 @@ void TextBase::writeProperties(XmlWriter& xml, bool writeText, bool /*writeStyle
|
|||
}
|
||||
}
|
||||
for (const auto& spp : *textStyle(textStyleType())) {
|
||||
if (!isStyled(spp.pid) && spp.pid != Pid::FONT_FACE && spp.pid != Pid::FONT_SIZE && spp.pid != Pid::FONT_STYLE
|
||||
&& spp.pid != Pid::TEXT_SCRIPT_ALIGN) {
|
||||
writeProperty(xml, spp.pid);
|
||||
if (isStyled(spp.pid)
|
||||
|| (spp.pid == Pid::FONT_SIZE && getProperty(spp.pid).toDouble() == TextBase::UNDEFINED_FONT_SIZE)
|
||||
|| (spp.pid == Pid::FONT_FACE && getProperty(spp.pid).value<String>() == TextBase::UNDEFINED_FONT_FAMILY)) {
|
||||
continue;
|
||||
}
|
||||
writeProperty(xml, spp.pid);
|
||||
}
|
||||
if (writeText) {
|
||||
xml.writeXml(u"text", xmlText());
|
||||
|
@ -2332,7 +2334,9 @@ bool TextBase::readProperties(XmlReader& e)
|
|||
}
|
||||
}
|
||||
if (tag == "text") {
|
||||
setXmlText(e.readXml());
|
||||
String str = e.readXml();
|
||||
setXmlText(str);
|
||||
checkCustomFormatting(str);
|
||||
} else if (tag == "bold") {
|
||||
bool val = e.readInt();
|
||||
if (val) {
|
||||
|
@ -2501,6 +2505,19 @@ void TextBase::setXmlText(const String& s)
|
|||
layoutInvalid = true;
|
||||
}
|
||||
|
||||
void TextBase::checkCustomFormatting(const String& s)
|
||||
{
|
||||
if (s.contains(u"<font face")) {
|
||||
setPropertyFlags(Pid::FONT_FACE, PropertyFlags::UNSTYLED);
|
||||
}
|
||||
if (s.contains(u"<font size")) {
|
||||
setPropertyFlags(Pid::FONT_SIZE, PropertyFlags::UNSTYLED);
|
||||
}
|
||||
if (s.contains(u"<b>") || s.contains(u"<i>") || s.contains(u"<u>") || s.contains(u"<s>")) {
|
||||
setPropertyFlags(Pid::FONT_STYLE, PropertyFlags::UNSTYLED);
|
||||
}
|
||||
}
|
||||
|
||||
void TextBase::resetFormatting()
|
||||
{
|
||||
// reset any formatting properties that can be changed per-character (doesn't change existing text)
|
||||
|
|
|
@ -365,6 +365,7 @@ public:
|
|||
void setPlainText(const String& t) { setXmlText(plainToXmlText(t)); }
|
||||
virtual void setXmlText(const String&);
|
||||
void setXmlText(const char* str) { setXmlText(String::fromUtf8(str)); }
|
||||
void checkCustomFormatting(const String&);
|
||||
String xmlText() const;
|
||||
String plainText() const;
|
||||
void resetFormatting();
|
||||
|
@ -505,12 +506,16 @@ public:
|
|||
inline bool isTextNavigationKey(int key, KeyboardModifiers modifiers)
|
||||
{
|
||||
if (modifiers & TextEditingControlModifier) {
|
||||
static const std::set<int> standardTextOperationsKeys {
|
||||
Key_Space, // Ctrl + Space inserts the space symbol
|
||||
Key_A // select all
|
||||
static const std::set<int> controlNavigationKeys {
|
||||
Key_Left,
|
||||
Key_Right,
|
||||
Key_Up,
|
||||
Key_Down,
|
||||
Key_Home,
|
||||
Key_End
|
||||
};
|
||||
|
||||
return standardTextOperationsKeys.find(key) == standardTextOperationsKeys.end();
|
||||
return controlNavigationKeys.find(key) != controlNavigationKeys.end();
|
||||
}
|
||||
|
||||
static const std::set<int> navigationKeys {
|
||||
|
|
|
@ -860,4 +860,17 @@ void Score::transpositionChanged(Part* part, Interval oldV, Fraction tickStart,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Score::transpositionChanged(Part* part, const Fraction& instrumentTick, Interval oldTransposition)
|
||||
{
|
||||
Fraction tickStart = instrumentTick;
|
||||
Fraction tickEnd = { -1, 1 };
|
||||
|
||||
auto mainInstrumentEndIt = part->instruments().upper_bound(tickStart.ticks());
|
||||
if (mainInstrumentEndIt != part->instruments().cend()) {
|
||||
tickEnd = Fraction::fromTicks(mainInstrumentEndIt->first);
|
||||
}
|
||||
|
||||
transpositionChanged(part, oldTransposition, tickStart, tickEnd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ class Tremolo final : public EngravingItem
|
|||
DirectionV _direction;
|
||||
mu::draw::PainterPath path;
|
||||
|
||||
int _lines; // derived from _subtype
|
||||
int _lines = 0; // derived from _subtype
|
||||
TremoloStyle _style { TremoloStyle::DEFAULT };
|
||||
|
||||
friend class Factory;
|
||||
|
|
|
@ -80,3 +80,13 @@ int SpannerFilter::spannerActualDurationTicks(const Spanner* spanner, const int
|
|||
|
||||
return nominalDurationTicks;
|
||||
}
|
||||
|
||||
bool SpannerFilter::isMultiStaffSpanner(const Spanner* spanner)
|
||||
{
|
||||
static const ElementTypeSet MULTI_STAFF_SPANNERS = {
|
||||
ElementType::PEDAL,
|
||||
ElementType::PEDAL_SEGMENT
|
||||
};
|
||||
|
||||
return MULTI_STAFF_SPANNERS.find(spanner->type()) != MULTI_STAFF_SPANNERS.cend();
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ public:
|
|||
//!HACK Unfortunately, the behavior of different types of "spanners" is not consistent in terms of
|
||||
//! calculation of their durations. This hack would not be actual once we'll get rid of "anchors" system
|
||||
static int spannerActualDurationTicks(const Spanner* spanner, const int nominalDurationTicks);
|
||||
static bool isMultiStaffSpanner(const Spanner* spanner);
|
||||
|
||||
protected:
|
||||
friend class FilterBase<SpannerFilter>;
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
using namespace mu::engraving;
|
||||
using namespace mu::mpe;
|
||||
|
||||
const PlaybackSetupData& KeyboardsSetupDataResolver::doResolve(const Instrument* instrument)
|
||||
PlaybackSetupData KeyboardsSetupDataResolver::doResolve(const Instrument* instrument)
|
||||
{
|
||||
static std::unordered_map<std::string, mpe::PlaybackSetupData> SETUP_DATA_MAP = {
|
||||
static const std::unordered_map<std::string, mpe::PlaybackSetupData> SETUP_DATA_MAP = {
|
||||
{ "celesta", { SoundId::Celesta, SoundCategory::Keyboards, {}, {} } },
|
||||
{ "clavichord", { SoundId::Clavichord, SoundCategory::Keyboards, { SoundSubCategory::Baroque }, {} } },
|
||||
{ "clavinet", { SoundId::Clavichord, SoundCategory::Keyboards, { SoundSubCategory::Electric }, {} } },
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace mu::engraving {
|
|||
class KeyboardsSetupDataResolver : public SetupDataResolverBase<KeyboardsSetupDataResolver>
|
||||
{
|
||||
public:
|
||||
static const mpe::PlaybackSetupData& doResolve(const Instrument* instrument);
|
||||
static mpe::PlaybackSetupData doResolve(const Instrument* instrument);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
using namespace mu::engraving;
|
||||
using namespace mu::mpe;
|
||||
|
||||
const PlaybackSetupData& PercussionsSetupDataResolver::doResolve(const Instrument* instrument)
|
||||
PlaybackSetupData PercussionsSetupDataResolver::doResolve(const Instrument* instrument)
|
||||
{
|
||||
static std::unordered_map<std::string, mpe::PlaybackSetupData> SETUP_DATA_MAP = {
|
||||
static const std::unordered_map<std::string, mpe::PlaybackSetupData> SETUP_DATA_MAP = {
|
||||
{ "timpani", { SoundId::Timpani, SoundCategory::Percussions, {}, {} } },
|
||||
{ "roto-toms", { SoundId::RotoToms, SoundCategory::Percussions, {}, {} } },
|
||||
{ "tubaphone", { SoundId::Tubaphone, SoundCategory::Percussions, { SoundSubCategory::Metal }, {} } },
|
||||
|
@ -117,6 +117,7 @@ const PlaybackSetupData& PercussionsSetupDataResolver::doResolve(const Instrumen
|
|||
{ "anvil", { SoundId::Anvil, SoundCategory::Percussions, { SoundSubCategory::Metal }, {} } },
|
||||
{ "bell-plate", { SoundId::Bell, SoundCategory::Percussions, { SoundSubCategory::Plate,
|
||||
SoundSubCategory::Metal }, {} } },
|
||||
{ "bell-tree", { SoundId::BellTree, SoundCategory::Percussions, { SoundSubCategory::Metal }, {} } },
|
||||
{ "bells", { SoundId::Bell, SoundCategory::Percussions, { SoundSubCategory::Metal }, {} } },
|
||||
{ "bowl-gongs", { SoundId::Gong, SoundCategory::Percussions, { SoundSubCategory::Metal,
|
||||
SoundSubCategory::Bowl }, {} } },
|
||||
|
@ -133,6 +134,7 @@ const PlaybackSetupData& PercussionsSetupDataResolver::doResolve(const Instrumen
|
|||
{ "hi-hat", { SoundId::HiHat, SoundCategory::Percussions, { SoundSubCategory::Metal }, {} } },
|
||||
{ "iron-pipes", { SoundId::Pipe, SoundCategory::Percussions, { SoundSubCategory::Metal,
|
||||
SoundSubCategory::Iron }, {} } },
|
||||
{ "mark-tree", { SoundId::MarkTree, SoundCategory::Percussions, { SoundSubCategory::Metal }, {} } },
|
||||
{ "metal-castanets", { SoundId::Castanet, SoundCategory::Percussions, { SoundSubCategory::Metal }, {} } },
|
||||
{ "metal-wind-chimes", { SoundId::Chimes, SoundCategory::Percussions, { SoundSubCategory::Metal,
|
||||
SoundSubCategory::Wind }, {} } },
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace mu::engraving {
|
|||
class PercussionsSetupDataResolver : public SetupDataResolverBase<PercussionsSetupDataResolver>
|
||||
{
|
||||
public:
|
||||
static const mpe::PlaybackSetupData& doResolve(const Instrument* instrument);
|
||||
static mpe::PlaybackSetupData doResolve(const Instrument* instrument);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -25,153 +25,227 @@
|
|||
using namespace mu::engraving;
|
||||
using namespace mu::mpe;
|
||||
|
||||
const PlaybackSetupData& StringsSetupDataResolver::doResolve(const Instrument* instrument)
|
||||
PlaybackSetupData StringsSetupDataResolver::doResolve(const Instrument* instrument)
|
||||
{
|
||||
static std::unordered_map<std::string, mpe::PlaybackSetupData> SETUP_DATA_MAP = {
|
||||
{ "harp", { SoundId::Harp, SoundCategory::Strings, {}, {} } },
|
||||
static const std::unordered_map<std::string, mpe::PlaybackSetupData> SETUP_DATA_MAP = {
|
||||
{ "harp", { SoundId::Harp, SoundCategory::Strings, { mpe::SoundSubCategory::Plucked }, {} } },
|
||||
{ "cavaquinho", { SoundId::Cavaquinho, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Steel }, {} } },
|
||||
SoundSubCategory::Steel,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "cavaquinho-tablature", { SoundId::Cavaquinho, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Steel }, {} } },
|
||||
SoundSubCategory::Steel,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "soprano-guitar", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Nylon,
|
||||
SoundSubCategory::Soprano }, {} } },
|
||||
SoundSubCategory::Soprano,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "alto-guitar", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Nylon,
|
||||
SoundSubCategory::Alto }, {} } },
|
||||
SoundSubCategory::Alto,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "baritone-guitar", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Nylon,
|
||||
SoundSubCategory::Baritone }, {} } },
|
||||
SoundSubCategory::Baritone,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "contra-guitar", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Nylon,
|
||||
SoundSubCategory::Contra }, {} } },
|
||||
SoundSubCategory::Contra,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
|
||||
{ "electric-guitar", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Electric }, {} } },
|
||||
{ "electric-guitar-treble-clef", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Electric }, {} } },
|
||||
{ "electric-guitar-treble-clef", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Electric }, {} } },
|
||||
{ "electric-guitar", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "electric-guitar-treble-clef", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "electric-guitar-tablature", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
|
||||
{ "guitar-steel", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Steel }, {} } },
|
||||
SoundSubCategory::Steel,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "guitar-steel-treble-clef", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Steel }, {} } },
|
||||
SoundSubCategory::Steel,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "guitar-steel-tablature", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Steel }, {} } },
|
||||
SoundSubCategory::Steel,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "pedal-steel-guitar", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Pedal,
|
||||
SoundSubCategory::Steel }, {} } },
|
||||
SoundSubCategory::Steel,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
|
||||
{ "guitar-nylon", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Nylon }, {} } },
|
||||
SoundSubCategory::Nylon,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "guitar-nylon-treble-clef", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Nylon }, {} } },
|
||||
SoundSubCategory::Nylon,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "guitar-nylon-tablature", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Nylon }, {} } },
|
||||
SoundSubCategory::Nylon,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "7-string-guitar", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Nylon }, {} } },
|
||||
SoundSubCategory::Nylon,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "7-string-guitar-tablature", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Nylon }, {} } },
|
||||
SoundSubCategory::Nylon,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "11-string-alto-guitar", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Nylon,
|
||||
SoundSubCategory::Alto }, {} } },
|
||||
SoundSubCategory::Alto,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "12-string-guitar", { SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Steel,
|
||||
SoundSubCategory::TwelveString }, {} } },
|
||||
SoundSubCategory::TwelveString,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
|
||||
{ "5-string-electric-bass-high-c", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Tenor }, {} } },
|
||||
SoundSubCategory::Tenor,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "5-string-electric-bass-tab-high-c", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Tenor }, {} } },
|
||||
{ "5-string-electric-bass-tab", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric }, {} } },
|
||||
{ "5-string-electric-bass", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric }, {} } },
|
||||
{ "6-string-electric-bass", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric }, {} } },
|
||||
{ "6-string-electric-bass-tab", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric }, {} } },
|
||||
{ "bass-guitar", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric }, {} } },
|
||||
{ "bass-guitar-tablature", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric }, {} } },
|
||||
{ "electric-bass-4-str-tab", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric }, {} } },
|
||||
{ "electric-bass", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric }, {} } },
|
||||
SoundSubCategory::Tenor,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "5-string-electric-bass-tab", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "5-string-electric-bass", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "6-string-electric-bass", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "6-string-electric-bass-tab", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "bass-guitar", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "bass-guitar-tablature", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "electric-bass-4-str-tab", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "electric-bass", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "fretless-electric-bass", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Fretless }, {} } },
|
||||
{ "acoustic-bass", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Acoustic }, {} } },
|
||||
SoundSubCategory::Fretless,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "acoustic-bass", { SoundId::BassGuitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
|
||||
{ "banjo", { SoundId::Banjo, SoundCategory::Strings, {}, {} } },
|
||||
{ "tenor-banjo", { SoundId::Banjo, SoundCategory::Strings, { SoundSubCategory::Tenor }, {} } },
|
||||
{ "banjo-tablature", { SoundId::Banjo, SoundCategory::Strings, {}, {} } },
|
||||
{ "banjo", { SoundId::Banjo, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
{ "tenor-banjo", { SoundId::Banjo, SoundCategory::Strings, { SoundSubCategory::Tenor,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "banjo-tablature", { SoundId::Banjo, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
{ "irish-tenor-banjo", { SoundId::Banjo, SoundCategory::Strings, { SoundSubCategory::Irish,
|
||||
SoundSubCategory::Tenor }, {} } },
|
||||
SoundSubCategory::Tenor,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "irish-tenor-banjo-tablature", { SoundId::Banjo, SoundCategory::Strings, { SoundSubCategory::Irish,
|
||||
SoundSubCategory::Tenor }, {} } },
|
||||
SoundSubCategory::Tenor,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
|
||||
{ "ukulele", { SoundId::Ukulele, SoundCategory::Strings, {}, {} } },
|
||||
{ "ukulele-4-str-tab", { SoundId::Ukulele, SoundCategory::Strings, {}, {} } },
|
||||
{ "ukulele-low-g", { SoundId::Ukulele, SoundCategory::Strings, { SoundSubCategory::Tenor }, {} } },
|
||||
{ "tenor-ukulele", { SoundId::Ukulele, SoundCategory::Strings, { SoundSubCategory::Tenor }, {} } },
|
||||
{ "baritone-ukulele", { SoundId::Ukulele, SoundCategory::Strings, { SoundSubCategory::Baritone }, {} } },
|
||||
{ "ukulele", { SoundId::Ukulele, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
{ "ukulele-4-str-tab", { SoundId::Ukulele, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
{ "ukulele-low-g", { SoundId::Ukulele, SoundCategory::Strings, { SoundSubCategory::Tenor,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "tenor-ukulele", { SoundId::Ukulele, SoundCategory::Strings, { SoundSubCategory::Tenor,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "baritone-ukulele", { SoundId::Ukulele, SoundCategory::Strings, { SoundSubCategory::Baritone,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
|
||||
{ "mandolin", { SoundId::Mandolin, SoundCategory::Strings, {}, {} } },
|
||||
{ "mandolin-tablature", { SoundId::Mandolin, SoundCategory::Strings, {}, {} } },
|
||||
{ "alto-mandola", { SoundId::Mandolin, SoundCategory::Strings, { SoundSubCategory::Alto }, {} } },
|
||||
{ "mandola", { SoundId::Mandolin, SoundCategory::Strings, {}, {} } },
|
||||
{ "tenor-mandola", { SoundId::Mandolin, SoundCategory::Strings, { SoundSubCategory::Tenor }, {} } },
|
||||
{ "octave-mandolin", { SoundId::Mandolin, SoundCategory::Strings, { SoundSubCategory::Octave }, {} } },
|
||||
{ "mandocello", { SoundId::Mandolin, SoundCategory::Strings, { SoundSubCategory::Octave }, {} } },
|
||||
{ "mandolin", { SoundId::Mandolin, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
{ "mandolin-tablature", { SoundId::Mandolin, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
{ "alto-mandola", { SoundId::Mandolin, SoundCategory::Strings, { SoundSubCategory::Alto,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "mandola", { SoundId::Mandolin, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
{ "tenor-mandola", { SoundId::Mandolin, SoundCategory::Strings, { SoundSubCategory::Tenor,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "octave-mandolin", { SoundId::Mandolin, SoundCategory::Strings, { SoundSubCategory::Octave,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "mandocello", { SoundId::Mandolin, SoundCategory::Strings, { SoundSubCategory::Octave,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
|
||||
{ "mtn-dulcimer-std", { SoundId::MtnDulcimer, SoundCategory::Strings, {}, {} } },
|
||||
{ "mtn-dulcimer-std-chrom-tab", { SoundId::MtnDulcimer, SoundCategory::Strings, {}, {} } },
|
||||
{ "mtn-dulcimer-baritone", { SoundId::MtnDulcimer, SoundCategory::Strings, { SoundSubCategory::Baritone }, {} } },
|
||||
{ "mtn-dulcimer-bartn-chrom-tab", { SoundId::MtnDulcimer, SoundCategory::Strings, { SoundSubCategory::Baritone }, {} } },
|
||||
{ "mtn-dulcimer-bass", { SoundId::MtnDulcimer, SoundCategory::Strings, { SoundSubCategory::Bass }, {} } },
|
||||
{ "mtn-dulcimer-bass-chrom-tab", { SoundId::MtnDulcimer, SoundCategory::Strings, { SoundSubCategory::Bass }, {} } },
|
||||
{ "mtn-dulcimer-std", { SoundId::MtnDulcimer, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
{ "mtn-dulcimer-std-chrom-tab", { SoundId::MtnDulcimer, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
{ "mtn-dulcimer-baritone", { SoundId::MtnDulcimer, SoundCategory::Strings, { SoundSubCategory::Baritone,
|
||||
SoundSubCategory::Plucked, }, {} } },
|
||||
{ "mtn-dulcimer-bartn-chrom-tab", { SoundId::MtnDulcimer, SoundCategory::Strings, { SoundSubCategory::Baritone,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "mtn-dulcimer-bass", { SoundId::MtnDulcimer, SoundCategory::Strings, { SoundSubCategory::Bass,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "mtn-dulcimer-bass-chrom-tab", { SoundId::MtnDulcimer, SoundCategory::Strings, { SoundSubCategory::Bass,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
|
||||
{ "lute", { SoundId::Lute, SoundCategory::Strings, {}, {} } },
|
||||
{ "lute-tablature", { SoundId::Lute, SoundCategory::Strings, {}, {} } },
|
||||
{ "ren.-tenor-lute-5-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Tenor }, {} } },
|
||||
{ "ren.-tenor-lute-6-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Tenor }, {} } },
|
||||
{ "ren.-tenor-lute-7-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Tenor }, {} } },
|
||||
{ "ren.-tenor-lute-8-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Tenor }, {} } },
|
||||
{ "ren.-tenor-lute-9-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Tenor }, {} } },
|
||||
{ "ren.-tenor-lute-10-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Tenor }, {} } },
|
||||
{ "baroque-lute-13-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Baroque }, {} } },
|
||||
{ "archlute-14-course", { SoundId::Lute, SoundCategory::Strings, {}, {} } },
|
||||
{ "bouzouki-3-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Greek }, {} } },
|
||||
{ "bouzouki-4-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Greek }, {} } },
|
||||
{ "lute", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
{ "lute-tablature", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
{ "ren.-tenor-lute-5-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Tenor,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "ren.-tenor-lute-6-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Tenor,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "ren.-tenor-lute-7-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Tenor,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "ren.-tenor-lute-8-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Tenor,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "ren.-tenor-lute-9-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Tenor,
|
||||
SoundSubCategory::Plucked, }, {} } },
|
||||
{ "ren.-tenor-lute-10-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Tenor,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "baroque-lute-13-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Baroque,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "archlute-14-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
{ "bouzouki-3-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Greek,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "bouzouki-4-course", { SoundId::Lute, SoundCategory::Strings, { SoundSubCategory::Greek,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
|
||||
{ "theorbo-14-course", { SoundId::Theorbo, SoundCategory::Strings, {}, {} } },
|
||||
{ "theorbo-14-course", { SoundId::Theorbo, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
|
||||
{ "balalaika", { SoundId::Balalaika, SoundCategory::Strings, { SoundSubCategory::Prima }, {} } },
|
||||
{ "balalaika-piccolo", { SoundId::Balalaika, SoundCategory::Strings, { SoundSubCategory::Piccolo }, {} } },
|
||||
{ "balalaika-prima", { SoundId::Balalaika, SoundCategory::Strings, { SoundSubCategory::Prima }, {} } },
|
||||
{ "balalaika", { SoundId::Balalaika, SoundCategory::Strings, { SoundSubCategory::Prima,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "balalaika-piccolo", { SoundId::Balalaika, SoundCategory::Strings, { SoundSubCategory::Piccolo,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "balalaika-prima", { SoundId::Balalaika, SoundCategory::Strings, { SoundSubCategory::Prima,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "balalaika-alto", { SoundId::Balalaika, SoundCategory::Strings, { SoundSubCategory::Prima,
|
||||
SoundSubCategory::Alto }, {} } },
|
||||
SoundSubCategory::Alto,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "balalaika-bass", { SoundId::Balalaika, SoundCategory::Strings, { SoundSubCategory::Prima,
|
||||
SoundSubCategory::Bass }, {} } },
|
||||
SoundSubCategory::Bass,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "balalaika-contrabass", { SoundId::Balalaika, SoundCategory::Strings, { SoundSubCategory::Prima,
|
||||
SoundSubCategory::Contra_Bass }, {} } },
|
||||
{ "balalaika-secunda", { SoundId::Balalaika, SoundCategory::Strings, { SoundSubCategory::Secunda }, {} } },
|
||||
SoundSubCategory::Contra_Bass,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "balalaika-secunda", { SoundId::Balalaika, SoundCategory::Strings, { SoundSubCategory::Secunda,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
|
||||
{ "koto", { SoundId::Koto, SoundCategory::Strings, { SoundSubCategory::Japanese }, {} } },
|
||||
{ "shamisen", { SoundId::Shamisen, SoundCategory::Strings, { SoundSubCategory::Japanese }, {} } },
|
||||
{ "sitar", { SoundId::Sitar, SoundCategory::Strings, { SoundSubCategory::Indian }, {} } },
|
||||
{ "oud", { SoundId::Oud, SoundCategory::Strings, { SoundSubCategory::African }, {} } },
|
||||
{ "prim", { SoundId::Prim, SoundCategory::Strings, {}, {} } },
|
||||
{ "brac", { SoundId::Brac, SoundCategory::Strings, {}, {} } },
|
||||
{ "bugarija", { SoundId::Bugarija, SoundCategory::Strings, {}, {} } },
|
||||
{ "berda", { SoundId::Berda, SoundCategory::Strings, {}, {} } },
|
||||
{ "celo", { SoundId::Celo, SoundCategory::Strings, {}, {} } },
|
||||
{ "bandurria", { SoundId::Bandurria, SoundCategory::Strings, { SoundSubCategory::Spanish }, {} } },
|
||||
{ "bandurria-tablature", { SoundId::Bandurria, SoundCategory::Strings, { SoundSubCategory::Spanish }, {} } },
|
||||
{ "laud", { SoundId::Laud, SoundCategory::Strings, { SoundSubCategory::Spanish }, {} } },
|
||||
{ "laud-tablature", { SoundId::Laud, SoundCategory::Strings, { SoundSubCategory::Spanish }, {} } },
|
||||
{ "koto", { SoundId::Koto, SoundCategory::Strings, { SoundSubCategory::Japanese,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "shamisen", { SoundId::Shamisen, SoundCategory::Strings, { SoundSubCategory::Japanese,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "sitar", { SoundId::Sitar, SoundCategory::Strings, { SoundSubCategory::Indian,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "oud", { SoundId::Oud, SoundCategory::Strings, { SoundSubCategory::African,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "prim", { SoundId::Prim, SoundCategory::Strings, { SoundSubCategory::Plucked, }, {} } },
|
||||
{ "brac", { SoundId::Brac, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
{ "bugarija", { SoundId::Bugarija, SoundCategory::Strings, { mpe::SoundSubCategory::Plucked }, {} } },
|
||||
{ "berda", { SoundId::Berda, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
{ "celo", { SoundId::Celo, SoundCategory::Strings, { SoundSubCategory::Plucked }, {} } },
|
||||
{ "bandurria", { SoundId::Bandurria, SoundCategory::Strings, { SoundSubCategory::Spanish,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "bandurria-tablature", { SoundId::Bandurria, SoundCategory::Strings, { SoundSubCategory::Spanish,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "laud", { SoundId::Laud, SoundCategory::Strings, { SoundSubCategory::Spanish,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "laud-tablature", { SoundId::Laud, SoundCategory::Strings, { SoundSubCategory::Spanish,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
|
||||
{ "strings", { SoundId::StringsGroup, SoundCategory::Strings, {}, {} } },
|
||||
{ "double-bass", { SoundId::Contrabass, SoundCategory::Strings, { SoundSubCategory::Orchestral }, {} } },
|
||||
{ "contrabass", { SoundId::Contrabass, SoundCategory::Strings, { SoundSubCategory::Orchestral }, {} } },
|
||||
{ "contrabasses", { SoundId::ContrabassSection, SoundCategory::Strings, { SoundSubCategory::Orchestral }, {} } },
|
||||
{ "contrabasses", { SoundId::Contrabass, SoundCategory::Strings, { SoundSubCategory::Orchestral,
|
||||
SoundSubCategory::Section }, {} } },
|
||||
{ "violin", { SoundId::Violin, SoundCategory::Strings, { SoundSubCategory::Orchestral }, {} } },
|
||||
{ "violins", { SoundId::ViolinSection, SoundCategory::Strings, { SoundSubCategory::Orchestral }, {} } },
|
||||
{ "violins", { SoundId::Violin, SoundCategory::Strings, { SoundSubCategory::Orchestral,
|
||||
SoundSubCategory::Section }, {} } },
|
||||
{ "viola", { SoundId::Viola, SoundCategory::Strings, { SoundSubCategory::Orchestral }, {} } },
|
||||
{ "violas", { SoundId::ViolaSection, SoundCategory::Strings, { SoundSubCategory::Orchestral }, {} } },
|
||||
{ "violas", { SoundId::Viola, SoundCategory::Strings, { SoundSubCategory::Orchestral,
|
||||
SoundSubCategory::Section }, {} } },
|
||||
{ "violoncello", { SoundId::Violoncello, SoundCategory::Strings, { SoundSubCategory::Orchestral }, {} } },
|
||||
{ "violoncellos", { SoundId::VioloncelloSection, SoundCategory::Strings, { SoundSubCategory::Orchestral }, {} } },
|
||||
{ "violoncellos", { SoundId::Violoncello, SoundCategory::Strings, { SoundSubCategory::Orchestral,
|
||||
SoundSubCategory::Section }, {} } },
|
||||
|
||||
{ "treble-viol", { SoundId::Viol, SoundCategory::Strings, {}, {} } },
|
||||
{ "alto-viol", { SoundId::Viol, SoundCategory::Strings, { SoundSubCategory::Alto }, {} } },
|
||||
|
@ -188,7 +262,8 @@ const PlaybackSetupData& StringsSetupDataResolver::doResolve(const Instrument* i
|
|||
{ "nyckelharpa", { SoundId::Nyckelharpa, SoundCategory::Strings, { SoundSubCategory::Swedish }, {} } },
|
||||
|
||||
{ "bass-synthesizer", { SoundId::Synthesizer, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Bass }, {} } },
|
||||
SoundSubCategory::Bass,
|
||||
SoundSubCategory::Plucked }, {} } },
|
||||
{ "bowed-synth", { SoundId::Synthesizer, SoundCategory::Strings, { SoundSubCategory::Electric,
|
||||
SoundSubCategory::Bowed }, {} } },
|
||||
};
|
||||
|
@ -199,5 +274,16 @@ const PlaybackSetupData& StringsSetupDataResolver::doResolve(const Instrument* i
|
|||
return empty;
|
||||
}
|
||||
|
||||
static const std::unordered_set<SoundId> supportPrimaryAndSecondaryCategories {
|
||||
SoundId::Violin
|
||||
};
|
||||
|
||||
if (mu::contains(supportPrimaryAndSecondaryCategories, search->second.id)) {
|
||||
SoundSubCategory category = instrument->isPrimary() ? SoundSubCategory::Primary : SoundSubCategory::Secondary;
|
||||
PlaybackSetupData setupData = search->second;
|
||||
setupData.subCategorySet.insert(category);
|
||||
return setupData;
|
||||
}
|
||||
|
||||
return search->second;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace mu::engraving {
|
|||
class StringsSetupDataResolver : public SetupDataResolverBase<StringsSetupDataResolver>
|
||||
{
|
||||
public:
|
||||
static const mpe::PlaybackSetupData& doResolve(const Instrument* instrument);
|
||||
static mpe::PlaybackSetupData doResolve(const Instrument* instrument);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -25,15 +25,15 @@
|
|||
using namespace mu::engraving;
|
||||
using namespace mu::mpe;
|
||||
|
||||
const PlaybackSetupData& VoicesSetupDataResolver::doResolve(const Instrument* instrument)
|
||||
PlaybackSetupData VoicesSetupDataResolver::doResolve(const Instrument* instrument)
|
||||
{
|
||||
static std::unordered_map<std::string, mpe::PlaybackSetupData> SETUP_DATA_MAP = {
|
||||
static const std::unordered_map<std::string, mpe::PlaybackSetupData> SETUP_DATA_MAP = {
|
||||
{ "boy-soprano", { SoundId::Choir, SoundCategory::Voices, { SoundSubCategory::Soprano,
|
||||
SoundSubCategory::Boy }, {} } },
|
||||
{ "soprano", { SoundId::Choir, SoundCategory::Voices, { SoundSubCategory::Soprano }, {} } },
|
||||
{ "soprano-c-clef", { SoundId::Choir, SoundCategory::Voices, { SoundSubCategory::Soprano }, {} } },
|
||||
{ "mezzo-soprano", { SoundId::Choir, SoundCategory::Voices, { SoundSubCategory::Mezzo_Soprano }, {} } },
|
||||
{ "mezzo-soprano-c-clef", { SoundId::Choir, SoundCategory::Voices, { SoundSubCategory::Mezzo_Soprano }, {} } },
|
||||
{ "mezzo-soprano", { SoundId::Choir, SoundCategory::Voices, { SoundSubCategory::Soprano }, {} } },
|
||||
{ "mezzo-soprano-c-clef", { SoundId::Choir, SoundCategory::Voices, { SoundSubCategory::Soprano }, {} } },
|
||||
{ "countertenor", { SoundId::Choir, SoundCategory::Voices, { SoundSubCategory::Counter_Tenor }, {} } },
|
||||
{ "alto", { SoundId::Choir, SoundCategory::Voices, { SoundSubCategory::Alto }, {} } },
|
||||
{ "alto-c-clef", { SoundId::Choir, SoundCategory::Voices, { SoundSubCategory::Alto }, {} } },
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace mu::engraving {
|
|||
class VoicesSetupDataResolver : public SetupDataResolverBase<VoicesSetupDataResolver>
|
||||
{
|
||||
public:
|
||||
static const mpe::PlaybackSetupData& doResolve(const Instrument* instrument);
|
||||
static mpe::PlaybackSetupData doResolve(const Instrument* instrument);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
using namespace mu::engraving;
|
||||
using namespace mu::mpe;
|
||||
|
||||
const PlaybackSetupData& WindsSetupDataResolver::doResolve(const Instrument* instrument)
|
||||
PlaybackSetupData WindsSetupDataResolver::doResolve(const Instrument* instrument)
|
||||
{
|
||||
static std::unordered_map<std::string, mpe::PlaybackSetupData> SETUP_DATA_MAP = {
|
||||
static const std::unordered_map<std::string, mpe::PlaybackSetupData> SETUP_DATA_MAP = {
|
||||
{ "winds", { SoundId::WindsGroup, SoundCategory::Winds, {}, {} } },
|
||||
{ "eb-piccolo", { SoundId::Piccolo, SoundCategory::Winds, {}, {} } },
|
||||
{ "db-piccolo", { SoundId::Piccolo, SoundCategory::Winds, {}, {} } },
|
||||
|
@ -92,6 +92,8 @@ const PlaybackSetupData& WindsSetupDataResolver::doResolve(const Instrument* ins
|
|||
{ "tenor-gemshorn", { SoundId::Gemshorn, SoundCategory::Winds, { SoundSubCategory::Tenor }, {} } },
|
||||
{ "bass-gemshorn", { SoundId::Gemshorn, SoundCategory::Winds, { SoundSubCategory::Bass }, {} } },
|
||||
|
||||
{ "theremin", { SoundId::Theremin, SoundCategory::Winds, { SoundSubCategory::Electric }, {} } },
|
||||
|
||||
{ "pan-flute", { SoundId::PanFlute, SoundCategory::Winds, {}, {} } },
|
||||
|
||||
{ "quena", { SoundId::Quena, SoundCategory::Winds, {}, {} } },
|
||||
|
@ -161,19 +163,24 @@ const PlaybackSetupData& WindsSetupDataResolver::doResolve(const Instrument* ins
|
|||
|
||||
{ "piccolo-clarinet", { SoundId::Clarinet, SoundCategory::Winds, {}, {} } },
|
||||
{ "soprano-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Sopranino }, {} } },
|
||||
{ "eb-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Sopranino }, {} } },
|
||||
{ "eb-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Sopranino,
|
||||
SoundSubCategory::In_E_flat }, {} } },
|
||||
{ "d-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Sopranino }, {} } },
|
||||
{ "c-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Sopranino }, {} } },
|
||||
{ "bb-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Sopranino }, {} } },
|
||||
{ "bb-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Soprano,
|
||||
SoundSubCategory::In_B_flat }, {} } },
|
||||
{ "clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Soprano }, {} } },
|
||||
{ "a-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Soprano }, {} } },
|
||||
{ "g-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Soprano }, {} } },
|
||||
{ "basset-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Soprano }, {} } },
|
||||
{ "basset-horn", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Soprano }, {} } },
|
||||
{ "alto-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Alto }, {} } },
|
||||
{ "bass-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Bass }, {} } },
|
||||
{ "bb-bass-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Bass }, {} } },
|
||||
{ "bb-bass-clarinet-bass-clef", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Bass }, {} } },
|
||||
{ "bass-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Bass,
|
||||
SoundSubCategory::In_B_flat }, {} } },
|
||||
{ "bb-bass-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Bass,
|
||||
SoundSubCategory::In_B_flat }, {} } },
|
||||
{ "bb-bass-clarinet-bass-clef", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Bass,
|
||||
SoundSubCategory::In_B_flat }, {} } },
|
||||
{ "a-bass-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Bass }, {} } },
|
||||
{ "a-bass-clarinet-bass-clef", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Bass }, {} } },
|
||||
{ "contra-alto-clarinet", { SoundId::Clarinet, SoundCategory::Winds, { SoundSubCategory::Contra_Alto }, {} } },
|
||||
|
@ -262,18 +269,23 @@ const PlaybackSetupData& WindsSetupDataResolver::doResolve(const Instrument* ins
|
|||
|
||||
{ "brass", { SoundId::BrassGroup, SoundCategory::Winds, {}, {} } },
|
||||
|
||||
{ "c-horn-alto", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::Alto }, {} } },
|
||||
{ "bb-horn-alto", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::Alto }, {} } },
|
||||
{ "a-horn", { SoundId::Horn, SoundCategory::Winds, {}, {} } },
|
||||
{ "ab-horn", { SoundId::Horn, SoundCategory::Winds, {}, {} } },
|
||||
{ "g-horn", { SoundId::Horn, SoundCategory::Winds, {}, {} } },
|
||||
{ "e-horn", { SoundId::Horn, SoundCategory::Winds, {}, {} } },
|
||||
{ "eb-horn", { SoundId::Horn, SoundCategory::Winds, {}, {} } },
|
||||
{ "d-horn", { SoundId::Horn, SoundCategory::Winds, {}, {} } },
|
||||
{ "horn", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::French }, {} } },
|
||||
{ "c-horn", { SoundId::Horn, SoundCategory::Winds, {}, {} } },
|
||||
{ "c-horn-bass", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::Bass }, {} } },
|
||||
{ "bb-horn-basso", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::Bass }, {} } },
|
||||
{ "c-horn-alto", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::Alto,
|
||||
SoundSubCategory::In_C }, {} } },
|
||||
{ "bb-horn-alto", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::Alto,
|
||||
SoundSubCategory::In_B_flat }, {} } },
|
||||
{ "a-horn", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::In_A }, {} } },
|
||||
{ "ab-horn", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::In_A_flat }, {} } },
|
||||
{ "g-horn", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::In_G }, {} } },
|
||||
{ "e-horn", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::In_E }, {} } },
|
||||
{ "eb-horn", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::In_E_flat }, {} } },
|
||||
{ "d-horn", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::In_D }, {} } },
|
||||
{ "horn", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::French,
|
||||
SoundSubCategory::In_F }, {} } },
|
||||
{ "c-horn", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::In_C }, {} } },
|
||||
{ "c-horn-bass", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::Bass,
|
||||
SoundSubCategory::In_C }, {} } },
|
||||
{ "bb-horn-basso", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::Bass,
|
||||
SoundSubCategory::In_B_flat }, {} } },
|
||||
{ "vienna-horn", { SoundId::Horn, SoundCategory::Winds, { SoundSubCategory::Vienna }, {} } },
|
||||
|
||||
{ "bb-wagner-tuba", { SoundId::Tuba, SoundCategory::Winds, { SoundSubCategory::Wagner }, {} } },
|
||||
|
@ -402,5 +414,16 @@ const PlaybackSetupData& WindsSetupDataResolver::doResolve(const Instrument* ins
|
|||
return empty;
|
||||
}
|
||||
|
||||
static const std::unordered_set<SoundId> supportPrimaryAndSecondaryCategories {
|
||||
SoundId::Flute,
|
||||
};
|
||||
|
||||
if (mu::contains(supportPrimaryAndSecondaryCategories, search->second.id)) {
|
||||
SoundSubCategory category = instrument->isPrimary() ? SoundSubCategory::Primary : SoundSubCategory::Secondary;
|
||||
PlaybackSetupData setupData = search->second;
|
||||
setupData.subCategorySet.insert(category);
|
||||
return setupData;
|
||||
}
|
||||
|
||||
return search->second;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace mu::engraving {
|
|||
class WindsSetupDataResolver : public SetupDataResolverBase<WindsSetupDataResolver>
|
||||
{
|
||||
public:
|
||||
static const mpe::PlaybackSetupData& doResolve(const Instrument* instrument);
|
||||
static mpe::PlaybackSetupData doResolve(const Instrument* instrument);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -108,8 +108,14 @@ void ChordArticulationsParser::parseSpanners(const Chord* chord, const Rendering
|
|||
continue;
|
||||
}
|
||||
|
||||
if (spanner->part() != chord->part()) {
|
||||
continue;
|
||||
if (SpannerFilter::isMultiStaffSpanner(spanner)) {
|
||||
if (spanner->part() != chord->part()) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (spanner->staffIdx() != chord->staffIdx()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SpannerFilter::isItemPlayable(spanner, ctx)) {
|
||||
|
|
|
@ -68,7 +68,7 @@ void ArpeggioMetaParser::doParse(const EngravingItem* item, const RenderingConte
|
|||
articulationMeta.type = type;
|
||||
articulationMeta.pattern = ctx.profile->pattern(type);
|
||||
articulationMeta.timestamp = ctx.nominalTimestamp;
|
||||
articulationMeta.overallDuration = ctx.nominalDuration;
|
||||
articulationMeta.overallDuration = ctx.nominalDuration * arpeggio->Stretch();
|
||||
|
||||
appendArticulationData(std::move(articulationMeta), result);
|
||||
}
|
||||
|
|
|
@ -35,8 +35,15 @@ void TremoloMetaParser::doParse(const EngravingItem* item, const RenderingContex
|
|||
|
||||
const Tremolo* tremolo = toTremolo(item);
|
||||
|
||||
if (tremolo->twoNotes() && tremolo->chord2()->tick().ticks() == ctx.nominalPositionStartTick) {
|
||||
return;
|
||||
if (tremolo->twoNotes()) {
|
||||
const Chord* chord2 = tremolo->chord2();
|
||||
IF_ASSERT_FAILED(chord2) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (chord2->tick().ticks() == ctx.nominalPositionStartTick) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mpe::ArticulationType type = mpe::ArticulationType::Undefined;
|
||||
|
@ -72,7 +79,7 @@ void TremoloMetaParser::doParse(const EngravingItem* item, const RenderingContex
|
|||
|
||||
int overallDurationTicks = ctx.nominalDurationTicks;
|
||||
if (tremolo->twoNotes() && tremolo->chord1() && tremolo->chord2()) {
|
||||
overallDurationTicks = tremolo->chord1()->ticks().ticks() + tremolo->chord2()->ticks().ticks();
|
||||
overallDurationTicks = tremolo->chord1()->actualTicks().ticks() + tremolo->chord2()->actualTicks().ticks();
|
||||
}
|
||||
|
||||
mpe::ArticulationMeta articulationMeta;
|
||||
|
|
|
@ -126,13 +126,26 @@ void PlaybackContext::updateDynamicMap(const Dynamic* dynamic, const Segment* se
|
|||
return;
|
||||
}
|
||||
|
||||
applyDynamicToNextSegment(segment, prevDynamicLevel);
|
||||
applyDynamicToNextSegment(segment, segmentPositionTick, prevDynamicLevel);
|
||||
return;
|
||||
}
|
||||
|
||||
const DynamicTransition& transition = dynamicTransitionFromType(type);
|
||||
m_dynamicsMap[segmentPositionTick] = dynamicLevelFromType(transition.from);
|
||||
applyDynamicToNextSegment(segment, dynamicLevelFromType(transition.to));
|
||||
const int transitionDuration = dynamic->velocityChangeLength().ticks();
|
||||
|
||||
dynamic_level_t levelFrom = dynamicLevelFromType(transition.from);
|
||||
dynamic_level_t levelTo = dynamicLevelFromType(transition.to);
|
||||
|
||||
dynamic_level_t range = levelTo - levelFrom;
|
||||
|
||||
std::map<int, int> dynamicsCurve = TConv::easingValueCurve(transitionDuration,
|
||||
6 /*stepsCount*/,
|
||||
static_cast<int>(range),
|
||||
ChangeMethod::NORMAL);
|
||||
|
||||
for (const auto& pair : dynamicsCurve) {
|
||||
m_dynamicsMap[segmentPositionTick + pair.first] = levelFrom + pair.second;
|
||||
}
|
||||
}
|
||||
|
||||
void PlaybackContext::updatePlayTechMap(const PlayTechAnnotation* annotation, const int segmentPositionTick)
|
||||
|
@ -146,13 +159,16 @@ void PlaybackContext::updatePlayTechMap(const PlayTechAnnotation* annotation, co
|
|||
m_playTechniquesMap[segmentPositionTick] = articulationFromPlayTechType(type);
|
||||
}
|
||||
|
||||
void PlaybackContext::applyDynamicToNextSegment(const Segment* currentSegment, const mpe::dynamic_level_t dynamicLevel)
|
||||
void PlaybackContext::applyDynamicToNextSegment(const Segment* currentSegment, const int segmentPositionTick,
|
||||
const mpe::dynamic_level_t dynamicLevel)
|
||||
{
|
||||
if (!currentSegment->next()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int nextSegmentPositionTick = currentSegment->next()->tick().ticks();
|
||||
const int tickPositionOffset = segmentPositionTick - currentSegment->tick().ticks();
|
||||
|
||||
int nextSegmentPositionTick = currentSegment->next()->tick().ticks() + tickPositionOffset;
|
||||
m_dynamicsMap[nextSegmentPositionTick] = dynamicLevel;
|
||||
}
|
||||
|
||||
|
@ -181,12 +197,32 @@ void PlaybackContext::handleSpanners(const ID partId, const Score* score, const
|
|||
|
||||
int spannerDurationTicks = spannerTo - spannerFrom;
|
||||
|
||||
if (spannerDurationTicks == 0) {
|
||||
if (spannerDurationTicks <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Hairpin* hairpin = toHairpin(spanner);
|
||||
|
||||
{
|
||||
Dynamic* startDynamic
|
||||
= toDynamic(hairpin->startSegment()->findAnnotation(ElementType::DYNAMIC, hairpin->track(), hairpin->track()));
|
||||
if (startDynamic) {
|
||||
if (startDynamic->dynamicType() != DynamicType::OTHER
|
||||
&& !isOrdinaryDynamicType(startDynamic->dynamicType())
|
||||
&& !isSingleNoteDynamicType(startDynamic->dynamicType())) {
|
||||
// The hairpin starts with a transition dynamic; we should start the hairpin after the transition is complete
|
||||
// This solution should be replaced once we have better infrastructure to see relations between Dynamics and Hairpins.
|
||||
spannerFrom += startDynamic->velocityChangeLength().ticks();
|
||||
|
||||
spannerDurationTicks = spannerTo - spannerFrom;
|
||||
|
||||
if (spannerDurationTicks <= 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DynamicType dynamicTypeFrom = hairpin->dynamicTypeFrom();
|
||||
DynamicType dynamicTypeTo = hairpin->dynamicTypeTo();
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ private:
|
|||
|
||||
void updateDynamicMap(const Dynamic* dynamic, const Segment* segment, const int segmentPositionTick);
|
||||
void updatePlayTechMap(const PlayTechAnnotation* annotation, const int segmentPositionTick);
|
||||
void applyDynamicToNextSegment(const Segment* currentSegment, const mpe::dynamic_level_t dynamicLevel);
|
||||
void applyDynamicToNextSegment(const Segment* currentSegment, const int segmentPositionTick, const mpe::dynamic_level_t dynamicLevel);
|
||||
|
||||
void handleSpanners(const ID partId, const Score* score, const int segmentStartTick, const int segmentEndTick,
|
||||
const int tickPositionOffset);
|
||||
|
|
|
@ -41,6 +41,23 @@
|
|||
using namespace mu::engraving;
|
||||
using namespace mu::mpe;
|
||||
|
||||
static ArticulationMap makeArticulations(ArticulationType persistentArticulationApplied, ArticulationsProfilePtr profile,
|
||||
timestamp_t timestamp, duration_t duration)
|
||||
{
|
||||
ArticulationMeta meta(persistentArticulationApplied,
|
||||
profile->pattern(persistentArticulationApplied),
|
||||
timestamp,
|
||||
duration,
|
||||
0,
|
||||
0);
|
||||
|
||||
ArticulationMap articulations;
|
||||
articulations.emplace(persistentArticulationApplied, mu::mpe::ArticulationAppliedData(std::move(meta), 0, mu::mpe::HUNDRED_PERCENT));
|
||||
articulations.preCalculateAverageData();
|
||||
|
||||
return articulations;
|
||||
}
|
||||
|
||||
void PlaybackEventsRenderer::render(const EngravingItem* item, const dynamic_level_t nominalDynamicLevel,
|
||||
const ArticulationType persistentArticulationApplied,
|
||||
const ArticulationsProfilePtr profile,
|
||||
|
@ -90,7 +107,9 @@ void PlaybackEventsRenderer::render(const EngravingItem* item, const mpe::timest
|
|||
}
|
||||
|
||||
void PlaybackEventsRenderer::renderChordSymbol(const Harmony* chordSymbol,
|
||||
const int ticksPositionOffset, mpe::PlaybackEventsMap& result) const
|
||||
const int ticksPositionOffset,
|
||||
const mpe::ArticulationsProfilePtr profile,
|
||||
mpe::PlaybackEventsMap& result) const
|
||||
{
|
||||
if (!chordSymbol->isRealizable()) {
|
||||
return;
|
||||
|
@ -110,7 +129,8 @@ void PlaybackEventsRenderer::renderChordSymbol(const Harmony* chordSymbol,
|
|||
duration_t duration = durationFromTicks(bps.val, durationTicks);
|
||||
|
||||
voice_layer_idx_t voiceIdx = static_cast<voice_layer_idx_t>(chordSymbol->voice());
|
||||
static ArticulationMap emptyArticulations;
|
||||
|
||||
ArticulationMap articulations = makeArticulations(mpe::ArticulationType::Standard, profile, eventTimestamp, duration);
|
||||
|
||||
for (auto it = notes.cbegin(); it != notes.cend(); ++it) {
|
||||
int octave = playingOctave(it->first, it->second);
|
||||
|
@ -121,13 +141,14 @@ void PlaybackEventsRenderer::renderChordSymbol(const Harmony* chordSymbol,
|
|||
voiceIdx,
|
||||
pitchLevel,
|
||||
dynamicLevelFromType(mpe::DynamicType::Natural),
|
||||
emptyArticulations,
|
||||
articulations,
|
||||
bps.val));
|
||||
}
|
||||
}
|
||||
|
||||
void PlaybackEventsRenderer::renderChordSymbol(const Harmony* chordSymbol, const mpe::timestamp_t actualTimestamp,
|
||||
const mpe::duration_t actualDuration, mpe::PlaybackEventsMap& result) const
|
||||
const mpe::duration_t actualDuration, const ArticulationsProfilePtr profile,
|
||||
mpe::PlaybackEventsMap& result) const
|
||||
{
|
||||
if (!chordSymbol->isRealizable()) {
|
||||
return;
|
||||
|
@ -139,7 +160,8 @@ void PlaybackEventsRenderer::renderChordSymbol(const Harmony* chordSymbol, const
|
|||
PlaybackEventList& events = result[actualTimestamp];
|
||||
|
||||
voice_layer_idx_t voiceIdx = static_cast<voice_layer_idx_t>(chordSymbol->voice());
|
||||
static ArticulationMap emptyArticulations;
|
||||
|
||||
ArticulationMap articulations = makeArticulations(mpe::ArticulationType::Standard, profile, actualTimestamp, actualDuration);
|
||||
|
||||
for (auto it = notes.cbegin(); it != notes.cend(); ++it) {
|
||||
int octave = playingOctave(it->first, it->second);
|
||||
|
@ -150,7 +172,7 @@ void PlaybackEventsRenderer::renderChordSymbol(const Harmony* chordSymbol, const
|
|||
voiceIdx,
|
||||
pitchLevel,
|
||||
dynamicLevelFromType(mpe::DynamicType::Natural),
|
||||
emptyArticulations,
|
||||
articulations,
|
||||
2.0));
|
||||
}
|
||||
}
|
||||
|
@ -212,7 +234,7 @@ void PlaybackEventsRenderer::renderNoteEvents(const Chord* chord, const int tick
|
|||
}
|
||||
|
||||
int chordPosTick = chord->tick().ticks();
|
||||
int chordDurationTicks = chord->durationTypeTicks().ticks();
|
||||
int chordDurationTicks = chord->actualTicks().ticks();
|
||||
|
||||
const Score* score = chord->score();
|
||||
|
||||
|
@ -248,16 +270,7 @@ void PlaybackEventsRenderer::renderFixedNoteEvent(const Note* note, const mpe::t
|
|||
const mpe::ArticulationType persistentArticulationApplied,
|
||||
const mpe::ArticulationsProfilePtr profile, mpe::PlaybackEventList& result) const
|
||||
{
|
||||
ArticulationMeta meta(persistentArticulationApplied,
|
||||
profile->pattern(persistentArticulationApplied),
|
||||
actualTimestamp,
|
||||
actualDuration,
|
||||
0,
|
||||
0);
|
||||
|
||||
ArticulationMap articulations;
|
||||
articulations.emplace(persistentArticulationApplied, mpe::ArticulationAppliedData(std::move(meta), 0, mpe::HUNDRED_PERCENT));
|
||||
articulations.preCalculateAverageData();
|
||||
ArticulationMap articulations = makeArticulations(persistentArticulationApplied, profile, actualDuration, actualTimestamp);
|
||||
|
||||
result.emplace_back(buildFixedNoteEvent(note, actualTimestamp, actualDuration, actualDynamicLevel, articulations));
|
||||
}
|
||||
|
|
|
@ -50,9 +50,10 @@ public:
|
|||
const mpe::dynamic_level_t actualDynamicLevel, const mpe::ArticulationType persistentArticulationApplied,
|
||||
const mpe::ArticulationsProfilePtr profile, mpe::PlaybackEventsMap& result) const;
|
||||
|
||||
void renderChordSymbol(const Harmony* chordSymbol, const int ticksPositionOffset, mpe::PlaybackEventsMap& result) const;
|
||||
void renderChordSymbol(const Harmony* chordSymbol, const mpe::timestamp_t actualTimestamp, const mpe::duration_t actualDuration,
|
||||
void renderChordSymbol(const Harmony* chordSymbol, const int ticksPositionOffset, const mpe::ArticulationsProfilePtr profile,
|
||||
mpe::PlaybackEventsMap& result) const;
|
||||
void renderChordSymbol(const Harmony* chordSymbol, const mpe::timestamp_t actualTimestamp, const mpe::duration_t actualDuration,
|
||||
const mpe::ArticulationsProfilePtr profile, mpe::PlaybackEventsMap& result) const;
|
||||
|
||||
void renderMetronome(const Score* score, const int measureStartTick, const int measureEndTick, const int ticksPositionOffset,
|
||||
mpe::PlaybackEventsMap& result) const;
|
||||
|
|
|
@ -208,17 +208,17 @@ void PlaybackModel::triggerEventsForItems(const std::vector<const EngravingItem*
|
|||
duration_t actualDuration = MScore::defaultPlayDuration * 1000;
|
||||
|
||||
for (const EngravingItem* item : playableItems) {
|
||||
if (item->isHarmony()) {
|
||||
m_renderer.renderChordSymbol(toHarmony(item), actualTimestamp, actualDuration, result);
|
||||
continue;
|
||||
}
|
||||
|
||||
ArticulationsProfilePtr profile = profilesRepository()->defaultProfile(m_playbackDataMap[trackId].setupData.category);
|
||||
ArticulationsProfilePtr profile = defaultActiculationProfile(trackId);
|
||||
if (!profile) {
|
||||
LOGE() << "unsupported instrument family: " << trackId.partId.toUint64();
|
||||
return;
|
||||
}
|
||||
|
||||
if (item->isHarmony()) {
|
||||
m_renderer.renderChordSymbol(toHarmony(item), actualTimestamp, actualDuration, profile, result);
|
||||
continue;
|
||||
}
|
||||
|
||||
int utick = repeatList().tick2utick(item->tick().ticks());
|
||||
const PlaybackContext& ctx = m_playbackCtxMap[trackId];
|
||||
|
||||
|
@ -340,8 +340,14 @@ void PlaybackModel::processSegment(const int tickPositionOffset, const Segment*
|
|||
|
||||
InstrumentTrackId trackId = chordSymbolsTrackId(item->part()->id());
|
||||
|
||||
ArticulationsProfilePtr profile = defaultActiculationProfile(trackId);
|
||||
if (!profile) {
|
||||
LOGE() << "unsupported instrument family: " << item->part()->id();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (chordSymbol->play()) {
|
||||
m_renderer.renderChordSymbol(chordSymbol, tickPositionOffset,
|
||||
m_renderer.renderChordSymbol(chordSymbol, tickPositionOffset, profile,
|
||||
m_playbackDataMap[trackId].originEvents);
|
||||
}
|
||||
|
||||
|
@ -385,7 +391,7 @@ void PlaybackModel::processSegment(const int tickPositionOffset, const Segment*
|
|||
|
||||
const PlaybackContext& ctx = m_playbackCtxMap[trackId];
|
||||
|
||||
ArticulationsProfilePtr profile = profilesRepository()->defaultProfile(m_playbackDataMap[trackId].setupData.category);
|
||||
ArticulationsProfilePtr profile = defaultActiculationProfile(trackId);
|
||||
if (!profile) {
|
||||
LOGE() << "unsupported instrument family: " << item->part()->id();
|
||||
continue;
|
||||
|
@ -570,10 +576,37 @@ void PlaybackModel::clearExpiredContexts(const track_idx_t trackFrom, const trac
|
|||
}
|
||||
}
|
||||
|
||||
void mu::engraving::PlaybackModel::removeEventsFromRange(const track_idx_t trackFrom, const track_idx_t trackTo,
|
||||
const timestamp_t timestampFrom, const timestamp_t timestampTo)
|
||||
{
|
||||
for (const Part* part : m_score->parts()) {
|
||||
if (part->startTrack() > trackTo || part->endTrack() <= trackFrom) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const InstrumentTrackId& trackId : part->instrumentTrackIdSet()) {
|
||||
removeTrackEvents(trackId, timestampFrom, timestampTo);
|
||||
}
|
||||
|
||||
removeTrackEvents(chordSymbolsTrackId(part->id()), timestampFrom, timestampTo);
|
||||
}
|
||||
|
||||
removeTrackEvents(METRONOME_TRACK_ID, timestampFrom, timestampTo);
|
||||
}
|
||||
|
||||
void PlaybackModel::clearExpiredEvents(const int tickFrom, const int tickTo, const track_idx_t trackFrom, const track_idx_t trackTo)
|
||||
{
|
||||
TRACEFUNC;
|
||||
|
||||
if (!m_score || !m_score->lastMeasure()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tickFrom == 0 && m_score->lastMeasure()->endTick().ticks() == tickTo) {
|
||||
removeEventsFromRange(trackFrom, trackTo);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const RepeatSegment* repeatSegment : m_score->repeatList()) {
|
||||
int tickPositionOffset = repeatSegment->utick - repeatSegment->tick;
|
||||
int repeatStartTick = repeatSegment->tick;
|
||||
|
@ -586,19 +619,7 @@ void PlaybackModel::clearExpiredEvents(const int tickFrom, const int tickTo, con
|
|||
timestamp_t timestampFrom = timestampFromTicks(m_score, tickFrom + tickPositionOffset);
|
||||
timestamp_t timestampTo = timestampFromTicks(m_score, tickTo + tickPositionOffset);
|
||||
|
||||
for (const Part* part : m_score->parts()) {
|
||||
if (part->startTrack() > trackTo || part->endTrack() <= trackFrom) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const InstrumentTrackId& trackId : part->instrumentTrackIdSet()) {
|
||||
removeEvents(trackId, timestampFrom, timestampTo);
|
||||
}
|
||||
|
||||
removeEvents(chordSymbolsTrackId(part->id()), timestampFrom, timestampTo);
|
||||
}
|
||||
|
||||
removeEvents(METRONOME_TRACK_ID, timestampFrom, timestampTo);
|
||||
removeEventsFromRange(trackFrom, trackTo, timestampFrom, timestampTo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -635,7 +656,8 @@ void PlaybackModel::notifyAboutChanges(const InstrumentTrackIdSet& oldTracks, co
|
|||
}
|
||||
}
|
||||
|
||||
void PlaybackModel::removeEvents(const InstrumentTrackId& trackId, const mpe::timestamp_t timestampFrom, const mpe::timestamp_t timestampTo)
|
||||
void PlaybackModel::removeTrackEvents(const InstrumentTrackId& trackId, const mpe::timestamp_t timestampFrom,
|
||||
const mpe::timestamp_t timestampTo)
|
||||
{
|
||||
auto search = m_playbackDataMap.find(trackId);
|
||||
|
||||
|
@ -645,6 +667,11 @@ void PlaybackModel::removeEvents(const InstrumentTrackId& trackId, const mpe::ti
|
|||
|
||||
PlaybackData& trackPlaybackData = search->second;
|
||||
|
||||
if (timestampFrom == -1 && timestampTo == -1) {
|
||||
search->second.originEvents.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
PlaybackEventsMap::const_iterator lowerBound;
|
||||
|
||||
if (timestampFrom == 0) {
|
||||
|
@ -750,3 +777,13 @@ InstrumentTrackId PlaybackModel::idKey(const ID& partId, const std::string& inst
|
|||
{
|
||||
return { partId, instrumentId };
|
||||
}
|
||||
|
||||
mpe::ArticulationsProfilePtr PlaybackModel::defaultActiculationProfile(const InstrumentTrackId& trackId) const
|
||||
{
|
||||
auto it = m_playbackDataMap.find(trackId);
|
||||
if (it == m_playbackDataMap.cend()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return profilesRepository()->defaultProfile(it->second.setupData.category);
|
||||
}
|
||||
|
|
|
@ -121,7 +121,10 @@ private:
|
|||
void collectChangesTracks(const InstrumentTrackId& trackId, ChangedTrackIdSet* result);
|
||||
void notifyAboutChanges(const InstrumentTrackIdSet& oldTracks, const InstrumentTrackIdSet& changedTracks);
|
||||
|
||||
void removeEvents(const InstrumentTrackId& trackId, const mpe::timestamp_t timestampFrom, const mpe::timestamp_t timestampTo);
|
||||
void removeEventsFromRange(const track_idx_t trackFrom, const track_idx_t trackTo, const mpe::timestamp_t timestampFrom = -1,
|
||||
const mpe::timestamp_t timestampTo = -1);
|
||||
void removeTrackEvents(const InstrumentTrackId& trackId, const mpe::timestamp_t timestampFrom = -1,
|
||||
const mpe::timestamp_t timestampTo = -1);
|
||||
|
||||
TrackBoundaries trackBoundaries(const ScoreChangesRange& changesRange) const;
|
||||
TickBoundaries tickBoundaries(const ScoreChangesRange& changesRange) const;
|
||||
|
@ -130,6 +133,8 @@ private:
|
|||
|
||||
std::vector<const EngravingItem*> filterPlaybleItems(const std::vector<const EngravingItem*>& items) const;
|
||||
|
||||
mpe::ArticulationsProfilePtr defaultActiculationProfile(const InstrumentTrackId& trackId) const;
|
||||
|
||||
Score* m_score = nullptr;
|
||||
bool m_expandRepeats = true;
|
||||
bool m_playChordSymbols = true;
|
||||
|
|
|
@ -63,7 +63,9 @@ void PlaybackSetupDataResolver::resolveChordSymbolsSetupData(const Instrument* i
|
|||
{
|
||||
if (instrument->hasStrings()) {
|
||||
static const mpe::PlaybackSetupData CHORD_SYMBOLS_SETUP_DATA = {
|
||||
SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic, SoundSubCategory::Nylon }, {}
|
||||
SoundId::Guitar, SoundCategory::Strings, { SoundSubCategory::Acoustic,
|
||||
SoundSubCategory::Nylon,
|
||||
SoundSubCategory::Plucked }, {}
|
||||
};
|
||||
|
||||
result = CHORD_SYMBOLS_SETUP_DATA;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "arpeggiorenderer.h"
|
||||
|
||||
#include "libmscore/chord.h"
|
||||
#include "libmscore/arpeggio.h"
|
||||
|
||||
using namespace mu::engraving;
|
||||
using namespace mu::mpe;
|
||||
|
@ -48,13 +49,18 @@ void ArpeggioRenderer::doRender(const EngravingItem* item, const mpe::Articulati
|
|||
return;
|
||||
}
|
||||
|
||||
const Arpeggio* arpeggio = chord->arpeggio();
|
||||
IF_ASSERT_FAILED(arpeggio) {
|
||||
return;
|
||||
}
|
||||
|
||||
int stepsCount = static_cast<int>(chord->notes().size());
|
||||
mpe::percentage_t percentageStep = mpe::HUNDRED_PERCENT / stepsCount;
|
||||
|
||||
auto buildEvent = [&](NominalNoteCtx& noteCtx, const int stepNumber) {
|
||||
noteCtx.chordCtx.commonArticulations.updateOccupiedRange(preferredType, stepNumber * percentageStep,
|
||||
(stepNumber + 1) * percentageStep);
|
||||
noteCtx.timestamp += timestampOffsetStep(context) * stepNumber;
|
||||
noteCtx.timestamp += timestampOffsetStep(context) * stepNumber * arpeggio->Stretch();
|
||||
result.emplace_back(buildNoteEvent(std::move(noteCtx)));
|
||||
};
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue