mmpSearch/_layouts/projetos.html

582 lines
20 KiB
HTML

---
layout: default
title: "{{ page.file }}"
---
<div class="publication">
<div class="container">
<br />
<div class="tabs is-centered is-boxed is-medium mb-6">
{% include sidebar.html %}
</div>
<div
class="box has-background-white-ter mb-5"
style="
border-top: 4px solid #3273dc;
padding: 8px 16px !important;
display: flex;
align-items: center;
justify-content: space-between;
min-height: unset;
"
>
<div style="display: flex; align-items: center; gap: 15px">
<h1
class="title is-5 m-0 p-0"
style="white-space: nowrap; line-height: 1; margin: 0 !important"
>
<code>{{ page.file }}</code>
</h1>
{% if page.bpm %}
<span
class="tag is-dark is-small"
style="height: 20px; line-height: 20px"
>🎵 {{ page.bpm }}</span
>
{% endif %}
</div>
{% if page.file %}
<div style="display: flex; align-items: center; gap: 15px">
{% assign creation_url = '/mmpSearch/creation.html?project=' | append:
page.file %} {% assign embed_url = creation_url | append: '&embed=true'
%}
<button
class="button is-small is-info is-light js-open-modal"
data-project-title="{{ page.file }}"
data-embed-url="{{ embed_url }}"
style="height: 25px; border-radius: 4px; font-weight: 600"
>
<span class="icon is-small"><i class="fa-solid fa-eye"></i></span>
<span class="is-hidden-mobile">Espiar Editor</span>
</button>
<div style="width: 1px; height: 20px; background-color: #ddd"></div>
<div style="display: flex; align-items: center">
<span
class="is-size-7 mr-2 has-text-grey is-hidden-mobile"
style="margin-bottom: 0 !important"
>Preview:</span
>
<div class="control">
{% assign audio_file_path = '/src_mmpSearch/wav/' | append: page.file |
append: '.wav' %}
<audio
controls
style="
height: 25px;
max-width: 220px;
vertical-align: middle;
margin: 0;
"
>
<source
src="{{ audio_file_path | relative_url }}"
type="audio/wav"
/>
{% assign audio_ogg_path = '/src_mmpSearch/ogg/' | append: page.file |
append: '.ogg' %}
<source
src="{{ audio_ogg_path | relative_url }}"
type="audio/ogg"
/>
</audio>
</div>
</div>
</div>
{% endif %}
</div>
<div class="columns">
<div class="column is-8">
{% if page.tags %} {% assign tags_vazias = true %} {% for categoria in
page.tags %} {% if categoria[1] and categoria[1].size > 0 %}{% assign
tags_vazias = false %}{% endif %} {% endfor %} {% unless tags_vazias %}
<details
class="card mb-4"
open
style="
background-color: #f0f8ff;
border: 1px solid #cfe8fc;
border-radius: 8px;
"
>
<summary
class="card-header"
style="
cursor: pointer;
background-color: #e1f0fa;
border-bottom: 1px solid #cfe8fc;
"
>
<p class="card-header-title" style="color: #205081">
🏷️ Tags do Projeto
</p>
<button class="card-header-icon" aria-label="more options">
<span class="icon" style="color: #205081"
><i class="fa-solid fa-angle-down"></i
></span>
</button>
</summary>
<div class="card-content" style="background-color: transparent">
{% for categoria in page.tags %} {% if categoria[1] and
categoria[1].size > 0 %}
<div class="mb-3">
<strong class="is-size-7 is-uppercase" style="color: #5b7da3"
>{{ categoria[0] }}:</strong
>
<div class="tags mt-2">
{% for valor in categoria[1] %} {% if valor != "" %} {% assign
tag_slug = valor | replace: ' ', '+' %} {% if categoria[0] ==
'bassline' %}
<a
href="{{ '/bassline/?bassline=' | append: tag_slug | relative_url }}"
class="tag is-link is-light"
>{{ valor }}</a
>
{% elsif categoria[0] == 'sample' %}
<a
href="{{ '/sample/?sample=' | append: tag_slug | relative_url }}"
class="tag is-link is-light"
>{{ valor }}</a
>
{% elsif categoria[0] == 'plugin' %}
<a
href="{{ '/plugin/?plugin=' | append: tag_slug | relative_url }}"
class="tag is-link is-light"
>{{ valor }}</a
>
{% elsif categoria[0] == 'automation' %}
<a
href="{{ '/automation/?automation=' | append: tag_slug | relative_url }}"
class="tag is-link is-light"
>{{ valor }}</a
>
{% else %}
<a
href="{{ '/' | append: tag_slug | relative_url }}"
class="tag is-link is-light"
>{{ valor }}</a
>
{% endif %} {% endif %} {% endfor %}
</div>
</div>
{% endif %} {% endfor %}
</div>
</details>
{% endunless %} {% endif %} {% if page.tracks and page.tracks.size > 0
%}
<details
class="card mb-4"
open
style="
background-color: #f0f8ff;
border: 1px solid #cfe8fc;
border-radius: 8px;
"
>
<summary
class="card-header"
style="
cursor: pointer;
background-color: #e1f0fa;
border-bottom: 1px solid #cfe8fc;
"
>
<p class="card-header-title" style="color: #205081">
🎚️ Instrumentos & Padrões
</p>
<button class="card-header-icon" aria-label="more options">
<span class="icon" style="color: #205081"
><i class="fa-solid fa-angle-down"></i
></span>
</button>
</summary>
<div
class="card-content"
style="background-color: transparent; padding: 1.5rem"
>
{% for track in page.tracks %} {% if track.instruments and
track.instruments.size > 0 %}
<div
class="box p-0 shadow-sm"
style="
background-color: #fff;
border: 1px solid #cfe8fc;
border-radius: 8px;
overflow: hidden;
width: 100%;
height: fit-content !important;
"
>
<div
class="px-4 py-3"
style="
background-color: #eef6fc;
border-bottom: 1px solid #cfe8fc;
"
>
<span class="tag is-link is-light" style="font-weight: 600"
>📂 {{ track.bassline_name }}</span
>
</div>
<div class="p-4" style="background-color: #fff">
{% for instrument in track.instruments %}
<div
class="instrument-wrapper box shadow-sm mb-4"
style="
border: 1px solid #eee;
border-left: 5px solid #3298dc;
padding: 1rem;
height: fit-content !important;
"
data-plugin-name="{{ instrument.instrument_name | downcase }}"
data-params="{{ instrument | jsonify | escape }}"
>
{% include _instrument_logic_inline.html %}
</div>
{% endfor %}
</div>
{% elsif track.instrument_name %} {% assign instrument = track %}
<div
class="instrument-wrapper box shadow-sm"
style="
border: 1px solid #cfe8fc;
border-left: 5px solid #3298dc;
padding: 1rem;
width: 100%;
height: fit-content !important;
"
data-plugin-name="{{ instrument.instrument_name | downcase }}"
data-params="{{ instrument | jsonify | escape }}"
>
{% include _instrument_logic_inline.html %}
</div>
{% endif %} {% endfor %}
</div>
</div>
</details>
{% endif %}
</div>
<div class="column is-4">
<div
class="box has-background-info-light"
style="position: sticky; top: 20px"
>
<h3 class="title is-6 has-text-info mb-3">
🛠️ Abra na Criação Colaborativa
</h3>
{% assign creation_url = '/mmpSearch/creation.html?project=' | append:
page.file %}
<a
href="{{ creation_url }}"
target="_blank"
class="button is-info is-fullwidth is-medium mb-4 shadow-sm"
>
<span>Abrir no MMPCreator</span>
<span class="icon"
><i class="fa-solid fa-up-right-from-square"></i
></span>
</a>
<p class="is-size-7 has-text-grey-dark">
O link abrirá o projeto em uma nova aba para edição.
<br />
Arquivo: <code>{{ page.file }}</code>
</p>
<div class="mt-4 is-hidden-mobile">
<hr style="background-color: #a4cbe0; height: 1px" />
<p class="title is-7 has-text-info-dark mb-2">Prévia do Editor:</p>
{% assign embed_url = creation_url | append: '&embed=true' %}
<iframe
src="{{ embed_url }}"
title="Prévia do Projeto"
style="
width: 100%;
height: 300px;
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
"
></iframe>
</div>
</div>
</div>
</div>
<br />
</div>
</div>
{% capture instrument_logic %} {% assign plugin_name =
instrument.instrument_name | downcase %} {% assign is_sample = false %} {%
assign sample_src = "" %} {% if plugin_name == 'audiofileprocessor' or
instrument.audiofileprocessor %} {% assign is_sample = true %} {% assign
sample_src = instrument.audiofileprocessor.src | default: "" | strip %} {% endif
%} {% assign should_open = false %} {% if is_sample == false %} {% assign
should_open = true %} {% elsif is_sample == true and sample_src != "" %} {%
assign should_open = true %} {% endif %}
<div
class="instrument-wrapper mb-4 p-2"
style="border-left: 3px solid #3298dc; background: #fff"
data-plugin-name="{{ plugin_name }}"
data-params="{{ instrument | jsonify | escape }}"
>
<li style="list-style: none">
<details {% if should_open %}open{% endif %}>
<summary style="cursor: pointer; outline: none; margin-bottom: 0.5rem">
<div style="display: inline-flex; align-items: center; gap: 8px">
{% assign display_name = instrument.instrument_name %} {% if is_sample
%} {% if display_name contains "audiofileprocessor" and
instrument.patterns %} {% assign first_pattern_name =
instrument.patterns | map: 'name' | first %} {% if first_pattern_name
and first_pattern_name != empty %} {% assign display_name =
first_pattern_name | remove: ".ogg" | remove: ".wav" | remove: ".flac"
| remove: ".mp3" %} {% elsif instrument.audiofileprocessor.src %} {%
assign src_parts = instrument.audiofileprocessor.src | split: '/' %}
{% assign file_name = src_parts | last %} {% assign display_name =
file_name | remove: ".ogg" | remove: ".wav" | remove: ".flac" |
remove: ".mp3" %} {% endif %} {% endif %} {% endif %} {% assign
instrument_slug = display_name | replace: ' ', '+' %}
<a
href="{{ '/instruments/?instrument=' | append: instrument_slug | relative_url }}"
class="tag is-info is-light"
>
<strong>{{ display_name }}</strong>
{% unless is_sample %}
<span class="ml-1" style="font-size: 0.7em">(Synth 🎹)</span>{%
endunless %}
</a>
</div>
</summary>
{% for pattern in instrument.patterns %} {% assign pattern_steps =
pattern.steps %} {% if pattern_steps and pattern_steps.size > 0 %}
<div
class="mt-2 ml-4"
style="display: flex; align-items: center; gap: 4px"
>
{% assign bassline_index = forloop.index | minus: 1 %} {% if
track.bassline_name %}
<span class="is-size-7 has-text-grey-light" style="min-width: 20px"
>{{ bassline_index }}:</span
>
{% endif %}
<div
class="patterns-container"
style="display: flex; flex-direction: row; flex-wrap: wrap; gap: 4px"
>
{% assign total_steps = pattern_steps.size %} {% assign chunk_size = 4
%} {% assign num_chunks = total_steps | divided_by: chunk_size %} {%
assign remainder = total_steps | modulo: chunk_size %} {% if remainder
> 0 %}{% assign num_chunks = num_chunks | plus: 1 %}{% endif %} {% for
i in (0..num_chunks) %} {% assign start_index = i | times: chunk_size
%} {% assign current_chunk_array = pattern_steps | slice: start_index,
chunk_size %} {% if current_chunk_array.size > 0 %} {% assign
chunk_string = "" %} {% for step in current_chunk_array %} {% if step
== true or step == 'true' or step == 1 %} {% assign chunk_string =
chunk_string | append: '1' %} {% else %} {% assign chunk_string =
chunk_string | append: '0' %} {% endif %} {% endfor %} {% assign
search_url = '/pattern/?p=' | append: chunk_string | relative_url %}
<a
href="{{ search_url }}"
title="Buscar padrão {{ chunk_string }}"
style="display: inline-block"
>
<div
style="
display: flex;
flex-direction: row;
border: 1px solid #ccc;
padding: 2px;
border-radius: 2px;
background-color: #fff;
"
>
{% for step_active in current_chunk_array %} {% assign step_color
= '#e0e0e0' %} {% if step_active == true or step_active == 'true'
or step_active == 1 %} {% assign step_color = '#4caf50' %} {%
endif %}
<div
style="width: 5px; height: 10px; background-color: {{ step_color }}; border-radius: 1px; margin-right: 1px;"
></div>
{% endfor %}
</div>
</a>
{% endif %} {% endfor %}
</div>
</div>
{% endif %} {% endfor %}
</details>
<div class="playback-controls mt-2 pl-4">
{% if is_sample %} {% if sample_src != "" %} {% assign
audio_filename_with_path = 'src/samples/' | append: sample_src %}
<audio
controls
class="js-sample-player"
style="height: 30px; width: 250px"
>
<source
src="{{ audio_filename_with_path | relative_url }}"
type="audio/ogg"
/>
{% assign wav_path = audio_filename_with_path | replace: '.ogg', '.wav'
%}
<source src="{{ wav_path | relative_url }}" type="audio/wav" />
</audio>
{% else %}
<p class="has-text-danger is-size-7">O sample **não foi enviado** 😢</p>
{% endif %} {% else %}
<button class="button is-small is-primary is-outlined js-play-synth-btn">
<span class="icon is-small"><i class="fa-solid fa-play"></i></span>
<span>Testar Plugin</span>
</button>
<span class="is-size-7 has-text-grey ml-2">Via Web Audio API</span>
{% endif %}
</div>
</li>
</div>
{% endcapture %}
<div id="preview-modal" class="modal">
<div class="modal-background"></div>
<div
class="modal-card"
style="width: 90%; max-width: 900px; height: 80vh; max-height: 800px"
>
<header
class="modal-card-head"
style="
background-color: #f0f8ff;
border-bottom: 1px solid #cfe8fc;
padding: 10px 20px;
"
>
<p
class="modal-card-title is-size-6"
id="modal-title"
style="color: #205081; font-weight: bold; margin-bottom: 0"
>
Preview
</p>
<button class="delete" aria-label="close"></button>
</header>
<section
class="modal-card-body p-0"
style="background-color: #000; display: flex"
>
<iframe
id="preview-iframe"
src=""
style="width: 100%; height: 100%; border: none; flex: 1"
></iframe>
</section>
<footer
class="modal-card-foot"
style="
justify-content: flex-end;
background-color: #fff;
border-top: 1px solid #cfe8fc;
padding: 10px 20px;
"
>
<button class="button is-small" id="close-modal-btn">Fechar</button>
<a
href="#"
id="full-edit-btn"
target="_blank"
class="button is-small is-info"
>
<span>Abrir Editor Completo</span>
<span class="icon is-small ml-1"
><i class="fa-solid fa-up-right-from-square"></i
></span>
</a>
</footer>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
// --- LÓGICA DO MODAL DE PREVIEW ---
const modal = document.getElementById("preview-modal");
const iframe = document.getElementById("preview-iframe");
const modalTitle = document.getElementById("modal-title");
const fullEditBtn = document.getElementById("full-edit-btn");
const closeButtons = document.querySelectorAll(
".modal-background, .modal-card-head .delete, #close-modal-btn"
);
function openModal(title, embedUrl) {
if (!modal) return;
modalTitle.textContent = "Espiando: " + title;
iframe.src = embedUrl;
// Ajusta botão de editor completo
const fullUrl = embedUrl.replace("&embed=true", "");
fullEditBtn.href = fullUrl;
modal.classList.add("is-active");
document.documentElement.classList.add("is-clipped");
}
function closeModal() {
if (!modal) return;
modal.classList.remove("is-active");
document.documentElement.classList.remove("is-clipped");
iframe.src = ""; // Limpa iframe
}
// Trigger nos botões
document.querySelectorAll(".js-open-modal").forEach((btn) => {
btn.addEventListener("click", (e) => {
e.preventDefault();
const title = btn.dataset.projectTitle;
const url = btn.dataset.embedUrl;
openModal(title, url);
});
});
// Fechar
closeButtons.forEach((el) => el.addEventListener("click", closeModal));
document.addEventListener("keydown", (e) => {
if (e.key === "Escape") closeModal();
});
});
</script>
<script type="module">
import { InstrumentFactory } from '{{ "/assets/js/audio/InstrumentFactory.js" | relative_url }}';
document.addEventListener("DOMContentLoaded", () => {
const factory = new InstrumentFactory();
const synthButtons = document.querySelectorAll(".js-play-synth-btn");
synthButtons.forEach((btn) => {
btn.addEventListener("click", (e) => {
const wrapper = e.target.closest(".instrument-wrapper");
if (wrapper && wrapper.dataset.params) {
try {
const instrumentData = JSON.parse(wrapper.dataset.params);
factory.play(instrumentData);
} catch (error) {
console.error("Erro audio:", error);
}
}
});
});
});
</script>