/* Public domain */ #ifndef _AGAR_AU_MU_H_ #define _AGAR_AU_MU_H_ #include #include #include #define MU_NODE_ID_MAX (0xffffffff-1) #define MU_CLUSTER_ID_MAX (0xffffffff-1) #define MU_STATUS_MAX 2048 #define MU_PART_NAME_MAX 64 struct mu; struct mu_note; struct mu_constraint; struct mu_group; struct mu_view; struct ag_widget; /* Clef */ enum mu_clef { MU_CLEF_TREBLE, MU_CLEF_TREBLE_8VA, MU_CLEF_TREBLE_15MA, MU_CLEF_TREBLE_8VB, MU_CLEF_BASS, MU_CLEF_BASS_8VB, MU_CLEF_BASS_15MB, MU_CLEF_BARITONE_F, MU_CLEF_SUBBASS, MU_CLEF_SOPRANO_C1, MU_CLEF_MEZZOSOPRANO_C2, MU_CLEF_ALTO_C3, MU_CLEF_TENOR_C4, MU_CLEF_BARITONE_C, MU_CLEF_VIOLIN_G4, MU_CLEF_BASS_F_V8A, MU_CLEF_BASS_F_15MA, MU_CLEF_TABLATURE, MU_CLEF_PERCUSSION, }; /* Key signature */ enum mu_key_signature { MU_C_MAJOR = 0, MU_A_MINOR = 0, MU_F_MAJOR = 1, MU_D_MINOR = 1, /* Bb */ MU_Bb_MAJOR = 2, MU_G_MINOR = 2, /* {BE}b */ MU_Eb_MAJOR = 3, MU_C_MINOR = 3, /* {ABE}b */ MU_Ab_MAJOR = 4, MU_F_MINOR = 4, /* {ABDE}b */ MU_Db_MAJOR = 5, MU_Bb_MINOR = 5, /* {GABDE}b */ MU_Gb_MAJOR = 6, MU_Eb_MINOR = 6, /* {GABCDE}b */ MU_Cb_MAJOR = 7, MU_Ab_MINOR = 7, /* {FGABCDE}b */ /* (15-n) */ MU_Cs_MAJOR = 8, MU_As_MINOR = 8, /* {ABCDEFG}s */ MU_Fs_MAJOR = 9, MU_Ds_MINOR = 9, /* {ACDEFG}s */ MU_B_MAJOR = 10, MU_Gs_MINOR = 10, /* {ACDFG}s */ MU_E_MAJOR = 11, MU_Cs_MINOR = 11, /* {CDFG}s */ MU_A_MAJOR = 12, MU_Fs_MINOR = 12, /* {CFG}s */ MU_D_MAJOR = 13, MU_B_MINOR = 13, /* {CF}s */ MU_G_MAJOR = 14, MU_E_MINOR = 14, /* Fs */ }; /* Constraint solver status */ enum mu_solver_status { MU_INVALID, /* No solutions */ MU_WELL_CONSTRAINED, /* Finite number of solution */ MU_UNDER_CONSTRAINED, /* Infinite number of solutions */ MU_OVER_CONSTRAINED /* Redundant constraints */ }; /* Musical note */ typedef struct mu_note { Uint32 id; /* Unique handle */ Uint flags; #define MU_NOTE_SELECTED 0x01 /* For editor */ #define MU_NOTE_MOUSEOVER 0x02 /* For editor */ #define MU_NOTE_MOVED 0x04 /* For editor */ #define MU_NOTE_SUPCONSTRAINTS 0x08 /* Suppress constraints */ #define MU_NOTE_FIXED 0x10 /* Treat position as known */ #define MU_NOTE_KNOWN 0x20 /* Position found by solver */ #define MU_NOTE_CHECKED 0x40 /* For constrainedness check */ struct mu *mu; /* Back pointer to piece */ struct mu_constraint **cons; /* Constraints / relations */ Uint nCons; Uint nEdges; /* Computed # of edges in graph */ AG_TAILQ_ENTRY(mu_note) notes; /* Entry in measure */ } MU_Note; /* Pair of notes */ typedef struct mu_note_pair { MU_Note *n1; MU_Note *n2; } MU_NotePair; /* Type of constraint between notes */ enum mu_constraint_type { MU_DISTANCE, MU_INCIDENT, /* Translated to DISTANCE(0) */ MU_ANGLE, MU_PERPENDICULAR, /* Translated to ANGLE(90deg) */ MU_PARALLEL, /* Translated to ANGLE(0deg) */ MU_TANGENT, MU_CONSTRAINT_LAST #define MU_CONSTRAINT_ANY MU_CONSTRAINT_LAST }; /* Constraint / relation between two notes */ typedef struct mu_constraint { enum mu_constraint_type uType; /* User-requested constraint type */ enum mu_constraint_type type; /* Effective constraint type */ union { M_Real dist; /* DISTANCE value */ M_Real angle; /* ANGLE value (radians) */ } data; #ifdef _AGAR_AU_INTERNAL # define ct_distance data.dist # define ct_angle data.angle #endif MU_Note *n1; MU_Note *n2; AG_TAILQ_ENTRY(mu_constraint) constraints; } MU_Constraint; /* Rigid cluster of constrained notes */ typedef struct mu_cluster { Uint32 name; AG_TAILQ_HEAD_(mu_constraint) edges; AG_TAILQ_ENTRY(mu_cluster) clusters; } MU_Cluster; /* Placement instruction generated by graph analysis */ typedef struct mu_insn { enum mu_insn_type { MU_COMPOSE_PAIR, /* Find n2 from n1 */ MU_COMPOSE_RING /* Find n3 from n1 and n2, assuming (n1,n2,n3) is a constrained ring */ } type; MU_Note *n[3]; /* Notes (n0 = unknown) */ MU_Constraint *ct01, *ct02; /* Constraints */ AG_TAILQ_ENTRY(mu_insn) insns; } MU_Insn; /* Intersection computation routine between two notes */ typedef struct mu_intersect_fn { const char *type1; const char *type2; void (*fn)(struct mu_group *, void *, void *); } MU_IntersectFn; /* Generic operation on a set of notes */ typedef struct mu_note_fn { const char *name; const char *mask; void (*fn)(struct mu *, int, struct mu_note **); } MU_NoteFn; /* Measure in staff */ typedef struct mu_bar { Uint n; /* Bar number */ char sig[MU_SIGNATURE_MAX]; /* Alt. key signature (or \0) */ AG_TAILQ_HEAD_(mu_note) notes; /* Set of notes */ } MU_Bar; /* Staff in musical part */ typedef struct mu_score { enum mu_clef clef; /* Clef */ MU_Bar *bars; /* Bars (sized to piece) */ Uint nBars; AG_TAILQ_ENTRY(mu_score) scores; /* Staves in part */ } MU_Score; /* Part in musical piece */ typedef struct mu_part { MU *mu; /* Back pointer to piece */ char name[MU_PART_NAME_MAX]; /* Short/abbreviated name */ char nameFull[MU_PART_NAME_MAX]; /* Long name */ AG_Text descr; /* Description / notes */ AG_TAILQ_HEAD_(mu_score) scores; /* Staves in part */ AG_TAILQ_ENTRY(mu_part) parts; /* Parts in piece */ } MU_Part; /* Musical piece */ typedef struct mu { struct ag_object obj; enum mu_key_signature key; /* Key signature */ Uint flags; #define MU_SKIP_UNKNOWN_FEATURES 0x01 /* Skip unimplemented features */ enum mu_solver_status status; /* Solver status code */ char statusText[MU_STATUS_MAX]; /* Solver status text */ Uint nSolutions; /* # of solutions possible */ MU_Cluster ctGraph; /* Original constraint graph */ AG_TAILQ_HEAD_(mu_part) parts; /* Parts */ AG_TAILQ_HEAD_(mu_cluster) clusters; /* Rigid clusters */ AG_TAILQ_HEAD_(mu_insn) insns; /* Construction steps */ } MU; #define MU_FOREACH_NOTE(note, bar, ntype) \ for((note) = AG_TAILQ_FIRST(&(bar)->notes); \ (note) != AG_TAILQ_END(&(bar)->notes); \ (note) = AG_TAILQ_NEXT(note,notes)) __BEGIN_DECLS extern AG_ObjectClass muClass; extern const char *muConstraintNames[]; extern const MU_IntersectFn muIntersectFns[]; extern const Uint muIntersectFnCount; extern const MU_NoteFn muNoteFns[]; extern const Uint muNoteFnCount; void MU_InitSubsystem(void); void MU_DestroySubsystem(void); void *MU_Edit(void *); MU *MU_New(void *, const char *); MU_Part *MU_PartNew(MU *, const char *, const char *); MU_Score *MU_ScoreNew(MU_Part *, enum mu_clef); void MU_NoteInit(void *, const void *, Uint32, Uint); void MU_NoteSetName(void *, const char *, ...); MU_Note *MU_NoteNew(void *); int MU_NoteDel(void *); void MU_NoteAttach(void *, void *); void MU_NoteDetach(void *, void *); void MU_NoteMoveUp(void *); void MU_NoteMoveDown(void *); void MU_NoteMoveHead(void *); void MU_NoteMoveTail(void *); void MU_NoteMoveToParent(void *, void *); int MU_NoteLoadGeneric(MU *, MU_Note **, AG_DataSource *); void MU_GetNoteTransform(void *, M_Matrix44 *); void MU_GetNoteTransformInverse(void *, M_Matrix44 *); void MU_NoteAddReference(void *, void *); void MU_NoteDelReference(void *, void *); void MU_NoteAddConstraint(void *, MU_Constraint *); void MU_NoteDelConstraint(void *, MU_Constraint *); Uint32 MU_GenNoteName(MU *, const char *); Uint32 MU_GenClusterName(MU *); M_Color MU_NoteColor(void *, const M_Color *); void MU_NoteRedraw(void *, struct mu_view *); void *MU_ReadRef(AG_DataSource *, MU *, const char *); void MU_WriteRef(AG_DataSource *, void *); void *MU_ProximitySearch(MU *, const char *, const M_Vector3 *, M_Vector3 *, void *); int MU_Solve(MU *); void MU_FreeClusters(MU *); void MU_FreeInsns(MU *); void MU_InitCluster(MU_Cluster *, Uint32); void MU_FreeCluster(MU_Cluster *); void MU_CopyCluster(const MU_Cluster *, MU_Cluster *); int MU_NoteInCluster(const MU_Note *, const MU_Cluster *); MU_Constraint *MU_AddConstraint(MU_Cluster *, void *, void *, enum mu_constraint_type, ...); MU_Constraint *MU_AddConstraintCopy(MU_Cluster *, const MU_Constraint *); MU_Constraint *MU_DupConstraint(const MU_Constraint *); void MU_DelConstraint(MU_Cluster *, MU_Constraint *); int MU_DelSimilarConstraint(MU_Cluster *, const MU_Constraint *); int MU_CompareConstraints(const MU_Constraint *, const MU_Constraint *); Uint MU_ConstraintsToSubgraph(const MU_Cluster *, const MU_Note *, const MU_Cluster *, MU_Constraint *[2]); MU_Insn *MU_AddInsn(MU *, enum mu_insn_type, ...); int MU_ExecInsn(MU *, const MU_Insn *); int MU_ExecProgram(MU *); void MU_SetStatus(MU *, enum mu_solver_status, const char *, ...); void MU_ClearProgramState(MU *); M_Vector3 MU_NoteDir(void *); void *MU_FindNote(MU *, Uint32, const char *); void *MU_FindNoteByName(MU *, const char *); MU_Cluster *MU_FindCluster(MU *, Uint32); MU_Constraint *MU_FindConstraint(const MU_Cluster *, enum mu_constraint_type, void *, void *); MU_Constraint *MU_FindSimilarConstraint(const MU_Cluster *, const MU_Constraint *); MU_Constraint *MU_ConstrainedNotes(const MU_Cluster *, const MU_Note *, const MU_Note *); Uint MU_NoteConstraintCount(const MU_Cluster *, void *); void MU_ComputeIntersections(MU_Group *, MU_Note *, MU_Note *); void MU_GeometryMenu(struct mu_view *, void *); static __inline__ void MU_Update(MU *mu) { #if 1 if (MU_Solve(mu) != 0) { fprintf(stderr, "%s: Solver failed\n", AGOBJECT(mu)->name); } #else if (MU_Solve(mu) == 0) MU_ExecProgram(mu); #endif } static __inline__ int MU_CompareNotePair(MU_NotePair *pair, void *n1, void *n2) { return ((pair->n1 == n1 && pair->n2 == n2) || (pair->n1 == n2 && pair->n2 == n1)); } __END_DECLS #include #endif /* _AGAR_AU_MU_H_ */